Built specifically for Claude Code.
Claude Code is stateless. Claude Reforge isn't.
Every session, Claude starts from zero.
It doesn't know that you spent 3 hours on that timeout bug last week.
It doesn't know that webpack.config.js needs the alias or the build breaks.
It doesn't know that in your project, the obvious solution is wrong.
So it makes the same mistakes. Again. And again.
Until now.
Claude Reforge breaks that loop.
This is not RAG. It does not retrieve knowledge.
It learns from what actually happened and uses that to guide decisions and prevent repeated failures.
This is not a prompt. Not a config file. Not documentation.
It's experience.
| Without Claude Reforge | With Claude Reforge | |
|---|---|---|
| Debugging | Repeats the same paths | Reuses proven fixes instantly |
| Known failures | Tries fixes that already failed | Avoids known bad paths |
| Project knowledge | Resets every session | Knows your project's history |
| Speed | Same on day 1 and day 100 | Gets faster every session |
npm install -g claude-reforge
claude-reforge initRestart Claude Code. That's it.
You're debugging something. Before Claude starts, it already knows:
[claude-reforge: 2 relevant past experiences]
3 weeks ago — same error, this project:
Error: error TS2345 — type 'string' not assignable to 'number'
What worked: Number() cast at the call site
What didn't: changing the function signature (broke 4 other things)
Learned rule: In this codebase, type mismatches in API handlers
→ fix the call site, never the function signature
Claude doesn't rediscover this. It already knows what worked.
Every fix becomes future context. Every session adds to what Claude knows about your project. Every error resolved makes the next one faster.
The more you use it, the less Claude has to guess.
Claude Reforge installs four hooks into Claude Code's lifecycle. They run silently. You never interact with them directly.
Session opens
└─ SessionStart hook
Queries the database for rules and facts learned in this project.
If found, injects them into Claude's context before anything else.
Every tool use (Edit, Write, Bash, Task...)
└─ PreToolUse hook
On first real tool use: builds a query from the task context,
retrieves the most relevant past episodes and injects them (once per session).
Injection is capped: max 3 episodes + max 3 rules. No more.
On every tool use: runs the prevention engine.
Extracts the semantic intent of the current action (not the raw string):
"edit handler.js" → api:file
"git push --force" → git:force_push
"change function params" → code:signature_change
Matches intent against past failures (bad_hit_count ≥ 2).
If a strong match is found, injects exactly 1 warning before execution:
[claude-reforge: prevention warning — failed 3 times]
Error: Cannot read properties of undefined (reading 'map')
What failed: edited src/api/handler.js, ran: npm run build
What worked instead: Modified utils/safeMap.js
During the session
└─ PostToolUse hook (runs after every tool)
Bash output → scans for error patterns, captures the command
Edit / Write → records which files were changed
Errors are tracked with timestamps so order matters.
Session ends
└─ Stop hook
Reads the first user message from the transcript for the task name.
Determines outcome: did errors get resolved? Were files changed after them?
If the session is worth saving, writes an episode to the database.
Runs rule extraction: if 2+ episodes share the same error signature,
a rule is generated automatically.
| Type | What it stores | When it's used |
|---|---|---|
| Episodic | task → error → solution → outcome |
Injected when task context matches |
| Semantic | Stable project facts (file types, stack) | Injected at session start |
| Rules | Patterns extracted from repeated errors | Injected at session start + on match |
| Prevention | Semantic intent of failed actions (git:force_push, code:signature_change, ...) |
Max 1 warning per tool call, only on strong match |
No embeddings. No API calls. No external dependencies.
Retrieval uses a composite score: BM25 keyword match × time decay × importance × outcome weight × reuse bonus × project affinity × folder affinity. Injection is deliberately capped: top 3 episodes + top 3 rules + max 1 prevention warning. Less is more — too much context hurts more than it helps.
Score factors:
- BM25 — keyword relevance between query and episode text
- Time decay —
< 1w → 1.0/< 1mo → 0.85/< 3mo → 0.65/< 6mo → 0.45/ older →0.25 - Outcome — resolved errors score
1.2×, known failures0.75×(still injected as negative examples) - Feedback loop — every time a memory is shown and the session succeeds,
hit_countincreases and the episode scores higher on reuse; if the session fails after injection,bad_hit_countincreases and the episode is penalized up to0.3×— the system learns what actually helps - Project affinity — same-project episodes score
1.3×, cross-project0.85× - Language affinity — cross-language episodes score
0.3×(e.g. a Python episode in a TypeScript project) - Folder affinity — episodes from the same directory tree score
1.1×, cross-folder0.7× - Confidence — rules are scored as
success_rate × occurrence_count; below0.5they are never injected; shown ashigh confidence(≥ 0.8) /medium confidence(≥ 0.6) /emerging pattern(< 0.6)
Everything lives at ~/.claude-reforge/:
~/.claude-reforge/
├── memory.db SQLite database (Node.js built-in, no compilation)
└── sessions/ Temporary session state (deleted after Stop hook)
└── {session_id}.json
Database tables:
episodes task, error, tried_actions, solution, outcome, importance, hit_count, file_types, folders
semantic_facts project-scoped key/value facts (primary_file_types, primary_folders, ...)
rules condition → action, confidence, hit_count
injections audit log of every memory injection (for stats)- Node.js ≥ 22.5
- Claude Code CLI
- macOS / Linux / Windows
No native compilation. No build tools. No dependencies. Uses the SQLite engine built into Node.js itself.
npm install -g claude-reforge
claude-reforge init- Creates
~/.claude-reforge/and initializes the SQLite database - Adds 4 hooks to
~/.claude/settings.json:
"hooks": {
"SessionStart": [{ "hooks": [{ "type": "command", "command": "node \"/path/to/session-start.js\"" }] }],
"PreToolUse": [{ "matcher": ".*", "hooks": [{ "type": "command", "command": "node \"/path/to/pre-tool.js\"" }] }],
"PostToolUse": [{ "matcher": ".*", "hooks": [{ "type": "command", "command": "node \"/path/to/post-tool.js\"" }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "node \"/path/to/stop.js\"" }] }]
}Existing hooks are preserved. Running init twice is safe.
Shows what has been learned: episodes, rules, project facts.
claude-reforge show # this project only
claude-reforge show --all # all projectsclaude-reforge — 12 total episode(s)
Learned Rules
─────────────────────────────────────────────
[×5] Error: error TS2345 string not assignable to number
→ Solution: Number() cast at call site
Recent Episodes (this project)
─────────────────────────────────────────────
#7 ✓ 3w ago ★★★★☆
Task : Fix TypeScript error in auth handler
Error : error TS2345: Argument of type string...
Solution : Number() cast at call site
Impact metrics: errors avoided, fixes reused, learning rate.
claude-reforge stats
Impact
─────────────────────────────────────────────
Errors avoided 18 (3 this week)
Fixes reused 11 (2 this week)
Sessions with memory 24 (4 this week)
Learning
─────────────────────────────────────────────
Episodes saved 31 (4 this week)
Success rate 87%
Rules extracted 5
Learning rate 2.8 ep/wk
Most Reused Fix
─────────────────────────────────────────────
[×7] Fix TS2345 type mismatch in auth handler
Number() cast at call site
Preview exactly what would be injected into Claude's context right now.
claude-reforge explain
claude-reforge explain "fix webpack module not found"claude-reforge forget 12 # delete episode #12
claude-reforge forget --all # clear everything (asks for confirmation)Removes all hooks from ~/.claude/settings.json.
Memory data at ~/.claude-reforge/ is kept unless you also run forget --all.
- All data is stored locally at
~/.claude-reforge/memory.db - No conversations are saved — only tool calls, errors, and outcomes
- No network requests, no cloud, no telemetry
- Delete everything:
claude-reforge forget --all
MIT
