How It Works
The hook lifecycle, extraction signals, and how claude-smart turns a Claude Code session into injected rules.
How It Works
claude-smart is a thin Claude Code plugin on top of Reflexio. It uses Claude Code's lifecycle hooks to stream session events into Reflexio, which extracts two artifacts — a user profile and a project playbook — and feeds them back into Claude at the start of every new session.
Data Flow
Claude Code session
├─ UserPromptSubmit ─┐
├─ PreToolUse ──────┤ → ~/.claude-smart/sessions/{session_id}.jsonl
├─ PostToolUse ──────┤ │
└─ Stop ──────┘ ▼
reflexio publish_interaction
│
▼
┌──────────────────────────────┐
│ Reflexio extractors │
│ (run via `claude -p`) │
│ → profiles + playbook │
│ → dedupe + archive │
└────────────┬─────────────────┘
▼
~/.reflexio/data/reflexio.db
│
Next session → SessionStart ────┘
→ search_user_playbooks(agent_version=project_id)
→ additionalContext injected into system promptThe Hook Lifecycle
claude-smart registers seven hook handlers with Claude Code. Every local event funnels through one of them.
| Hook | Matcher | What it does | Timeout |
|---|---|---|---|
Setup | * | Runs once on install. Syncs the Python env, seeds ~/.reflexio/.env with provider flags, and prebuilds the dashboard. | 300s |
SessionStart | startup|clear|compact|resume | Starts the Reflexio backend on :8081 and the dashboard on :3001, then queries profiles + playbook and injects them as additionalContext. | 30s |
UserPromptSubmit | * | Appends the user turn to the session JSONL buffer; heuristically flags corrections. | 15s |
PreToolUse | Edit|Write|NotebookEdit|Bash | Records the tool invocation metadata for later extraction. | 10s |
PostToolUse | * | Finalizes tool-use metadata with the result. | 15s |
Stop | * | Publishes the finalized assistant turn (plus any pending user turns and tool calls) to Reflexio. | 30s |
SessionEnd | * | Flushes the remaining buffer with force_extraction=True. | 60s |
Hook handlers are implemented in Python under plugin/src/claude_smart/events/ in the claude-smart repository.
The Local Session Buffer
Every session writes to an append-only JSONL file:
~/.claude-smart/sessions/{session_id}.jsonlEach line is a record tagged by type: User, Assistant, ToolStart, ToolEnd, [correction]. Special {"published_up_to": N} watermark lines mark how far the publisher has advanced. This makes the buffer offline-safe: if the Reflexio backend is down, hooks keep appending and the next successful Stop drains everything past the watermark.
The buffer is safe to inspect and safe to delete — everything before the latest watermark is already in ~/.reflexio/data/reflexio.db.
What Triggers Rule Extraction
Reflexio's playbook extractor only emits rules from two signals:
- Correction SOPs — the user rejected the agent's behavior. claude-smart flags these in two ways:
- Explicit —
/tag [note]marks the previous turn as a correction with your note as the description. - Heuristic —
UserPromptSubmitscans for corrective phrasing ("no, don't", "instead", "that's wrong", etc.) and tags the turn automatically.
- Explicit —
- Success-path recipes — completed tasks that produced concrete values, formulas, or tool sequences. These are preserved so Claude can reuse what already works.
Identity and context facts (e.g. "I'm a data scientist", "we freeze merges Thursdays") route to the profile only — they don't become playbook rules.
Mapping to Reflexio
claude-smart is a thin adapter; everything below is stored in Reflexio's normal data model.
| Reflexio field | claude-smart value | Scope |
|---|---|---|
user_id | Claude Code session_id | Profile scope — current conversation |
agent_version | project_id (git-toplevel basename) | Playbook scope — cross-session, project-wide |
session_id | Claude Code session_id | Used for Reflexio's deferred success evaluation |
Cross-session playbook retrieval uses search_user_playbooks(agent_version=project_id, user_id=None) — so playbook rules written from any prior session in this project surface for every future session.
Embeddings and Search
- Embedder: Chroma's
all-MiniLM-L6-v2(384-dim, zero-padded to Reflexio's 512-dim schema), run in-process viachromadb. Weights are cached at~/.cache/chroma/onnx_models/(~80 MB, downloaded once). - Search: hybrid BM25 + vector similarity. BM25 catches exact-keyword matches; vector similarity catches paraphrases.
- Generation: every LLM call (extraction, dedup, evaluation) subprocesses
claude -p --output-format json, reusing your existing Claude Code auth. No OpenAI or Anthropic API key is required.
Rule Lifecycle
- Dedup — duplicate rules are merged; the stronger one wins.
- Supersede — when a new correction contradicts an existing rule, the old rule is marked
ARCHIVEDand the new one replaces it. - Display —
/showonly printsCURRENTrules, which is exactly what Claude sees.