Claude Code Adapter
The Claude Code adapter uses Claude Code's built-in hooks API to emit signals after every tool invocation. It captures all 7 hook event types: PostToolUse, PreToolUse, SessionStart, SessionEnd, Stop, PreCompact, and UserPromptSubmit.
Prerequisites
- Claude Code installed and configured
- FORG CLI installed and activated (
forg statusshows your device) - Claude Code version 1.2.0 or later (hooks API required)
Installation
Run forg connect claude-code to install automatically, or add the following to ~/.claude/settings.json (or a project-level .claude/settings.json):
{
"hooks": {
"PostToolUse": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "forg emit --event PostToolUse" }
]
}
],
"PreToolUse": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "forg emit --event PreToolUse" }
]
}
],
"SessionStart": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "forg emit --event SessionStart" }
]
}
],
"SessionEnd": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "forg emit --event SessionEnd" }
]
}
],
"Stop": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "forg emit --event Stop" }
]
}
],
"PreCompact": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "forg emit --event PreCompact" }
]
}
],
"UserPromptSubmit": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "forg emit --event UserPromptSubmit" }
]
}
]
}
}When Claude Code fires a hook, it pipes a JSON context to stdin. The forg emit command auto-detects piped stdin (no --stdin flag needed) and reads the hook context automatically.
How it works
Claude Code fires the PostToolUse hook after each tool call and passes a JSON context to stdin with fields including:
{
"tool_name": "Bash",
"model": "claude-opus-4-5",
"usage": {
"input_tokens": 1024,
"output_tokens": 512,
"cache_read_input_tokens": 256
},
"cost_usd": 0.0042,
"session_id": "..."
}The FORG agent reads this context, normalizes it to the FORG signal schema, and POSTs it directly to https://engine.forg.pro/signalsigned with the device's HMAC session key.
HMAC session key
Each FORG session has an HMAC session key derived from the device bundle. The engine sets FORG_SESSION_KEY and FORG_SESSION_ID in the hook environment so every forg emit invocation can sign its signal correctly. This prevents spoofed signals from other processes on the same machine.
Verification
# Check that a session is active and adapters are installed:
forg status
# Expected output:
# user_id: usr_...
# device: a3f9e2c1b84d...
# engine: https://engine.forg.pro
# license worker: https://api.forg.pro
#
# session: a3f9e2c1 (active)
#
# Installed adapters:
# ✓ Claude Code (free)Project-level config
To enable FORG only in specific projects, add the hooks config to .claude/settings.json in the project root instead of the global settings. This is useful when you want to track a specific repository separately.
Status bar integration
FORG writes a ~/.claude/statusline.sh script during activation that shows live session metrics in the Claude Code status bar. If you already have a custom statusline.sh, FORG will not overwrite it — a warning is surfaced at activation time instead.
You can also use forg status --inline to get a one-line status string suitable for use in your own status bar script:
forg status --inline
# FORG · a3f9e2c1 · 2 toolsTroubleshooting
| Symptom | Fix |
|---|---|
| No signals appearing after tool calls | Verify ~/.claude/settings.json is valid JSON with correct hook commands. Run forg status to confirm a session is active. |
| Hook fires but signals are rejected (401) | HMAC mismatch. Ensure FORG_SESSION_KEY and FORG_SESSION_ID are set in the hook environment by Claude Code. |
| High latency on tool calls | The hook runs synchronously before the tool result is returned. The emit timeout is 3s. Check network connectivity to engine.forg.pro. |
| Claude Code shows statusline error | If you have a custom statusline.sh, FORG's status indicator won't overwrite it. This is expected behavior. |
Known limitations
- Cost data accuracy depends on Claude Code's reported cost; FORG does not independently price model calls
- Cache token counts (cache_read, cache_write) are tracked separately and included in tokens_in
- SubAgent tool calls inside a session are attributed to the same session_id