Misar IO Docs

Hook System

Lifecycle shell scripts that run at key points in every agent session — inject context, block dangerous tools, or log activity automatically.

Overview

Hooks are plain shell scripts placed in .misar/hooks/. The agent runtime executes them at defined lifecycle events, letting you extend agent behaviour without modifying any extension settings.

.misar/
└── hooks/
    ├── session-start.sh    # Runs once when a session begins
    ├── pre-tool-use.sh     # Runs before every tool call
    └── post-tool-use.sh    # Runs after every tool call

All scripts must be executable:

chmod +x .misar/hooks/*.sh

Hook Reference

| Hook | Trigger | Can block? | Timeout | |------|---------|------------|---------| | session-start.sh | Extension activation, new session, clear, compact | No | None | | pre-tool-use.sh | Before each tool call | Yes (exit 1) | 5 seconds | | post-tool-use.sh | After each tool call | No | Fire-and-forget |

session-start.sh

Runs once at the beginning of a session. Stdout is injected directly into the agent's system context.

Arguments:

  • $1 — event type: startup | resume | clear | compact

Environment variables:

  • MISAR_SESSION_EVENT — same value as $1
  • MISAR_WORKSPACE — absolute path to the current workspace
#!/bin/bash
# .misar/hooks/session-start.sh
# Inject dynamic project context at session start

echo "Branch: $(git branch --show-current 2>/dev/null || echo 'unknown')"
echo "Uncommitted files: $(git status --short 2>/dev/null | wc -l | tr -d ' ')"
echo "Node version: $(node --version 2>/dev/null || echo 'not installed')"
echo "Last deployment: $(cat .misar/last-deploy.txt 2>/dev/null || echo 'none')"

On compact events the session context has been summarised. Use this to re-inject any critical facts that may have been trimmed.

pre-tool-use.sh

Runs before every tool call. You control whether the tool is allowed to execute.

Arguments:

  • $1 — tool name (e.g. run_command, write_file, bash)

Stdin: JSON payload with tool arguments.

Exit codes:

  • 0 — allow the tool call to proceed
  • 1 — block the tool call; stderr is shown to the agent as the reason

Stdout: Optional JSON with additionalContext injected into the agent's next message:

{ "additionalContext": "extra context for agent" }
#!/bin/bash
# .misar/hooks/pre-tool-use.sh
TOOL=$1
ARGS=$(cat)

# Block rm -rf on production paths
if [ "$TOOL" = "run_command" ]; then
  CMD=$(echo "$ARGS" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('command',''))" 2>/dev/null)
  if echo "$CMD" | grep -qE "rm\s+-rf\s+/"; then
    echo "Blocked: recursive delete from root is not allowed." >&2
    exit 1
  fi
fi

# Inject lint status before any file write
if [ "$TOOL" = "write_file" ] || [ "$TOOL" = "edit_file" ]; then
  LINT=$(pnpm lint --silent 2>&1 | tail -5)
  echo "{\"additionalContext\": \"Current lint status: $LINT\"}"
fi

exit 0

The 5-second timeout applies to the entire hook execution. Keep pre-tool-use hooks fast to avoid slowing down the agent loop.

post-tool-use.sh

Runs after every tool call. Fire-and-forget — the agent does not wait for it and it cannot affect the result.

Arguments:

  • $1 — tool name

Stdin: JSON payload with tool name, arguments, and result.

#!/bin/bash
# .misar/hooks/post-tool-use.sh
TOOL=$1
PAYLOAD=$(cat)

# Auto-lint after file writes
if [ "$TOOL" = "write_file" ] || [ "$TOOL" = "edit_file" ]; then
  FILE=$(echo "$PAYLOAD" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('path',''))" 2>/dev/null)
  if [ -n "$FILE" ]; then
    pnpm eslint --fix "$FILE" > /dev/null 2>&1 &
  fi
fi

# Log tool usage to a local audit file
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) $TOOL" >> .misar/tool-log.txt

Use Cases

Inject Git Context

Surface the current branch, recent commits, or diff stats into every session automatically.

Block Dangerous Commands

Intercept run_command calls and block patterns like rm -rf, force push, or production database writes.

Auto-lint on Write

Run your formatter or linter after every file edit so code is always clean without manual runs.

Audit Trail

Log every tool call with timestamp to a local file for compliance or debugging purposes.

Debugging Hooks

If a hook behaves unexpectedly, run it manually with the expected arguments:

# Test session-start with a startup event
bash .misar/hooks/session-start.sh startup

# Test pre-tool-use with a synthetic payload
echo '{"command": "ls -la"}' | bash .misar/hooks/pre-tool-use.sh run_command
echo $?   # 0 = allowed, 1 = blocked

Hook errors are surfaced in the VS Code Output panel under Misar Code. If pre-tool-use.sh exits non-zero unexpectedly, the tool call is blocked and the agent reports the stderr message.