Howto: Learning Capture for Claude Code
What it does
synonyms:: howto, learning capture claude code, howto learning capture for claude code checklist:: what it does, architecture, prerequisites, setup, how learning capture works, hook script details, key differences from opencode hooks, troubleshooting
Claude Code automatically captures failed bash commands and stores them as learnings. When you run the same failing command again, the pre-tool-use hook warns you. Both Claude Code and opencode share the same learning store.
Architecture
Claude Code hooks (~/.claude/hooks/)
|
|--- PreToolUse (pre_tool_use.sh)
| |---> terraphim-agent guard --json (safety)
| |---> terraphim-agent replace --role ... --json (knowledge graph rewrites)
| |---> terraphim-agent hook --hook-type pre-tool-use (generic pre handler)
|
|--- PostToolUse (post_tool_use.sh)
| |---> terraphim-agent learn hook --format claude (capture failed commands)
| |---> terraphim-agent hook --hook-type post-tool-use (generic post handler)
|
|
v
Shared learning store
(~/.config/terraphim/learnings/)Prerequisites
terraphim-agentinstalled at~/.cargo/bin/terraphim-agent- Claude Code v2.1+ installed (
npm install -g @anthropic-ai/claude-code)
Setup
1. Hook scripts (already installed)
The hook scripts live at:
~/.claude/hooks/pre_tool_use.sh— runs before every Bash tool call~/.claude/hooks/post_tool_use.sh— runs after every Bash tool call
2. Hook registration (already configured)
Hooks can be registered in either ~/.claude/settings.json (shared, version-controlled) or ~/.claude/settings.local.json (personal, git-ignored). This setup uses settings.local.json so per-developer paths do not leak into the repo. On teams that want everyone to share the same hooks, move the block into settings.json.
3. Verify it works
# Simulate what Claude Code sends when a command fails
|
# Check the learning was captured
Expected output:
Learnings matching 'nonexistent-test-cmd'.
[G] [cmd] nonexistent-test-cmd (exit: 127)How learning capture works
Capture (automatic)
When Claude Code runs a Bash command that fails, Claude Code sends JSON to the PostToolUse hook via stdin:
The post_tool_use.sh script:
- Locates
terraphim-agentbinary (4 fallback paths) - Reads JSON from stdin
- Pipes to
terraphim-agent learn hook --format claude - Also runs
terraphim-agent hook --hook-type post-tool-use --json - Always fails open (
|| true) — never blocks Claude Code
Pre-tool-use warnings (automatic)
Before each Bash command, pre_tool_use.sh runs terraphim-agent hook --hook-type pre-tool-use --json which checks the command against past learnings and the role-configured knowledge graph. If it matches a past failure or a recorded correction, the hint is surfaced to the LLM via the hook's structured JSON response — never directly to the user terminal.
Claude Code and opencode now align on the same UX principle: pre-tool-use hints are for LLM consumption only, keeping the user interface clean while still informing the model about past failures and corrections.
Safety guard (automatic)
pre_tool_use.sh also runs terraphim-agent guard which blocks destructive commands like git reset --hard, rm -rf, etc. If blocked, the hook returns:
Correction (manual)
Add corrections to teach the system what to do instead:
# Record that 'npm install' should be 'bun install'
# Record that a specific command has a known fix
# Capture a user correction inline (used in conversation)
Query (manual)
Search past learnings:
# Search by keyword
# Search exactly
# List recent learnings
# Query and see corrections
Hook script details
post_tool_use.sh
stdin -> JSON { tool_name, tool_input, tool_result }
|
v
Find terraphim-agent binary
(~/.cargo/bin/ -> target/release/ -> target/debug/ -> PATH)
|
v
cd ~/.config/terraphim (for KG access)
|
v
terraphim-agent learn hook --format claude (capture failed commands)
|
v
terraphim-agent hook --hook-type post-tool-use --json (generic handler)
|
v
stdout passthrough (always succeeds, || true)pre_tool_use.sh
stdin -> JSON { tool_name, tool_input }
|
v
Filter: only Bash commands
|
v
Step 1: terraphim-agent guard --json (block destructive commands)
| If blocked -> return deny JSON
v
Step 2: terraphim-agent replace --role "Terraphim Engineer" --json
| (knowledge graph text replacement for git commits, package managers)
v
Step 3: terraphim-agent hook --hook-type pre-tool-use --json
(generic pre-tool handler)Key differences from opencode hooks
| Aspect | Claude Code | opencode |
|--------|-------------|----------|
| Hook type | Shell scripts (bash) | JavaScript plugins (Bun) |
| Registration | settings.local.json | Auto-loaded from plugin/ dir |
| Input format | JSON on stdin | JS objects (input, output) |
| Tool name | "Bash" (capital B) | "bash" (lowercase) |
| Exit code | Structured { exit_code: N } | Raw string (parse from output) |
| Blocking | Return permissionDecision: "deny" | throw new Error() |
| Fail-open | \|\| true | catch {} |
Troubleshooting
Learnings not being captured
- Check terraphim-agent is installed:
- Test the hook directly:
|
- Check hook is registered:
| Hook script not executable
Safety guard blocking legitimate commands
The safety guard uses terraphim-agent guard which checks for destructive patterns. If a legitimate command is blocked, the guard can be bypassed by running the command outside Claude Code (directly in terminal).
See also
- Learning Capture for opencode — same learning store, Bun plugin instead of shell scripts
- Command Rewriting How-To — deeper walkthrough of the knowledge-graph-driven
replacepipeline