Capturing the "why" behind every Claude Code commit: building a memory layer with MCP and hooks
Architecting Persistent Reasoning: A Pattern for Capturing AI Decision History with Hooks and MCP
Current Situation Analysis
Modern AI coding agents operate with high velocity, frequently generating dozens of commits daily. While the code artifacts persist in the repository, the cognitive trail—the rationale behind specific architectural choices, the alternatives evaluated, and the constraints considered—dissipates the moment the session terminates.
This creates a critical gap in the development lifecycle. Version control systems excel at tracking state mutations. Git provides an immutable log of diffs, but it remains agnostic to intent. The "why" has historically been carried by the developer's memory or scattered across issue trackers and chat logs. When an agent generates code, the human is no longer the primary decision-maker; the agent is. However, the agent's context window is ephemeral. Once a session closes, the reasoning evaporates.
This problem is often misunderstood as a documentation failure. Engineers attempt to manually annotate commits or maintain external notes. This approach does not scale. With AI-augmented workflows producing 30+ commits per day, manual curation becomes a bottleneck that developers inevitably abandon. The result is a codebase that is technically functional but cognitively opaque. Six months later, the team faces "archaeology" sessions to reverse-engineer decisions, or worse, they rewrite working code because the original intent is lost.
The industry lacks a standardized mechanism to persist agent reasoning alongside code. Without this layer, AI adoption introduces a new form of technical debt: decision debt. Teams accumulate code they cannot fully explain, and new sessions start from zero, repeating past evaluations and potentially reintroducing rejected approaches.
WOW Moment: Key Findings
The implementation of a persistent reasoning layer fundamentally shifts how AI agents interact with project history. By capturing not just the outcome but the decision process, teams unlock capabilities that standard workflows cannot support.
The following comparison illustrates the operational impact of integrating a reasoning capture architecture versus a traditional Git-only workflow:
| Dimension | Traditional Git Workflow | Reasoning-Augmented Architecture |
|---|---|---|
| Context Retention | Ephemeral; bound to active session | Persistent; survives session termination |
| Decision Visibility | Implicit; requires inference from diffs | Explicit; structured intent and rationale |
| Rejected Alternatives | Lost; only the winning path is recorded | Preserved; prevents regression to bad patterns |
| Onboarding Cost | High; requires manual knowledge transfer | Low; context injection accelerates ramp-up |
| Stakeholder Access | Engineering-only; diffs are opaque to non-tech | Cross-functional; prose summaries for PM/Design |
| Agent Intelligence | Stateless; each session starts from scratch | Stateful; accumulates team decision history |
The most significant finding is the value of rejected alternatives. Teams often assume they need better commit summaries. In practice, knowing what the agent did not do, and why, provides higher signal than the chosen path. This data enables "Context Injection," where a new session can load the reasoning of a previous session, allowing the agent to build upon past decisions rather than re-evaluating them. This breaks the zero-state problem and allows the AI to become smarter through the team's actual usage history.
Core Solution
The architecture for persistent reasoning relies on three distinct layers: event-driven capture via hooks, structured retrieval via the Model Context Protocol (MCP), and a backend service for storage and synchronization. This separation ensures that capture is passive and non-blocking, retrieval is active and structured, and storage is durable and queryable.
Layer 1: Event-Driven Capture via Hooks
Hooks provide the mechanism to intercept lifecycle events within the AI agent environment. The goal is to trigger capture scripts without interrupting the developer's flow. The system attaches to specific events: commit completion, user prompt submission, and session termination.
Implementation Strategy: Instead of embedding logic directly in shell scripts, a TypeScript configuration defines the capture rules. This allows for cross-platform compatibility and structured event handling.
// hooks.config.ts
import { HookDefinition, EventType } from '@ai-reasoning/hooks';
export const reasoningHooks: HookDefinition[] = [
{
event: EventType.PostToolUse,
matcher: (tool) => tool.name === 'Bash' && tool.input.includes('git commit'),
handler: async (context) => {
const commitHash = await context.git.getHeadHash();
const sessionPrompts = context.session.getAccumulatedPrompts();
// Request structured summary from the agent
const decisionLog = await context.agent.summarizeDecision({
commitHash,
prompts: sessionPrompts,
includeAlternatives: true
});
// Persist asynchronously to avoid blocking the commit
await context.backend.pushDecision(decisionLog);
}
},
{
event: EventType.SessionEnd,
handler: async (context) => {
await context.backend.finalizeSession(context.session.id);
}
}
];
Rationale:
- Async Processing: The hook handler must offload persistence to a background process. Blocking the commit flow degrades the developer experience.
- Structured Summarization: The agent is asked to produce a structured output (JSON) containing intent, alternatives, and rationale, rather than free-form text. This ensures the data is machine-readable for future injection.
- Event Granularity: Capturing on
PostToolUsefor git commits ensures the reasoning is tied to a specific state change. Capturing onSessionEndensures no data is lost if a session closes unexpectedly.
Layer 2: MCP Server for Structured Retrieval
The MCP server acts as the bridge between the agent and the reasoning backend. It exposes tools that allow the agent to query past decisions and save new reports. This layer enforces a separation of concerns: the LLM generates the prose and analysis, while the MCP server handles data transport and validation.
Implementation Strategy: The server exposes a symmetric set of tools for fetching and saving reasoning data. This symmetry supports both passive capture and active retrieval.
// reasoning-mcp-server.ts
import { McpServer } from '@modelcontextprotocol/sdk';
import { DecisionStore } from './decision-store';
const server = new McpServer({
name: 'reasoning-bridge',
version: '1.0.0'
});
server.tool(
'fetch_decision_context',
'Retrieve reasoning history for a specific commit or session',
{ sessionId: z.string(), commitHash: z.string().optional() },
async ({ sessionId, commitHash }) => {
const context = await DecisionStore.getContext(sessionId, commitHash);
return {
content: [{ type: 'text', text: JSON.stringify(context) }]
};
}
);
server.tool(
'persist_session_report',
'Save a structured decision report generated by the agent',
{ report: z.object({ intent: z.string(), alternatives: z.array(z.string()), rationale: z.string() }) },
async ({ report }) => {
await DecisionStore.saveReport(report);
return { content: [{ type: 'text', text: 'Report persisted successfully' }] };
}
);
Rationale:
- Tool Symmetry: Providing both
fetchandpersisttools allows the agent to participate in the loop. It can retrieve context to inform its current work and save its own summaries. - Schema Enforcement: The MCP tools validate the structure of the data. This prevents the backend from receiving malformed reasoning data.
- Stdio Transport: The server runs as a local process spawned per session, ensuring low latency and secure access to local git state.
Layer 3: Backend Storage and Hierarchy
The backend stores the reasoning data and powers the shared timeline. It must support hierarchical scoping (Organization → Team → Project) and provide efficient retrieval for context injection.
Technical Stack:
- Runtime: Kotlin 2.2 with Spring Boot 4.0 and Java 21. Virtual threads handle high-concurrency ingestion from hooks.
- Storage: PostgreSQL 16 for durable storage of decision entries. Redis 7 for session caching and rapid context retrieval.
- Frontend: Next.js 16 with React 19, Tailwind 4, and Zustand. Server components render SEO-friendly timeline pages; client components handle the interactive dashboard.
- Auth: JWT for web console access; HMAC-SHA256 API keys for CLI and MCP authentication.
Schema Design:
The core entity is the DecisionEntry. It links to a commit and stores the reasoning payload.
@Entity
@Table(name = "decision_entries")
class DecisionEntry(
@Id val id: UUID,
val sessionId: String,
val commitHash: String,
val projectId: UUID,
@Column(columnDefinition = "jsonb")
val reasoningPayload: ReasoningPayload,
val createdAt: Instant,
val createdBy: String
) {
data class ReasoningPayload(
val intent: String,
val alternatives: List<Alternative>,
val selectedPath: String,
val constraints: List<String>
)
data class Alternative(
val description: String,
val rejectionReason: String
)
}
Rationale:
- JSONB for Payload: Using JSONB in PostgreSQL allows flexible storage of the reasoning payload while still enabling indexing on specific fields if needed.
- Hierarchical Scoping: The
projectIdand RBAC tables ensure that reasoning data is isolated per project and accessible only to authorized team members. - Virtual Threads: Java 21 virtual threads allow the backend to handle bursty ingestion from multiple agents without thread pool exhaustion.
Context Injection: Closing the Loop
The most powerful capability of this architecture is context injection. When a developer starts a new session, they can invoke a command to load reasoning from a previous session.
/inject-reasoning <session-id>
The MCP server fetches the DecisionEntry for that session and injects the structured reasoning into the new session's context window. The agent now understands the historical decisions, the rejected paths, and the constraints before generating any code. This prevents the agent from suggesting previously rejected approaches and allows it to build incrementally on past work.
Pitfall Guide
Building a reasoning capture system introduces unique challenges. The following pitfalls are derived from production experience with AI agent integrations.
| Pitfall | Explanation | Fix |
|---|---|---|
| Context Window Overflow | Injecting full reasoning history can exceed token limits, causing the agent to truncate critical instructions. | Implement relevance filtering. Only inject reasoning related to the files currently being edited. Use summarization for older sessions. |
| Hook Latency Blocking Flow | If the hook waits for the backend response before returning, the developer experiences lag during commits. | Ensure hooks are fire-and-forget. Use a local queue or async worker to handle persistence. The hook should return immediately. |
| Hallucinated Rationale | The agent may fabricate reasoning that doesn't match its actual tool usage, especially if asked to summarize without grounding. | Ground the summary in actual tool outputs. Provide the agent with the transcript of tool calls and prompts, not just the final code. |
| Secret Leakage in Hooks | Hooks run in the agent's environment and may inadvertently capture environment variables or secrets in the reasoning payload. | Implement a redaction pipeline in the capture layer. Scan payloads for known secret patterns before persisting. |
| MCP Tool Bloat | Exposing too many tools can confuse the agent, leading to tool selection errors or degraded performance. | Group tools logically and limit the surface area. Use clear descriptions and only expose tools relevant to the current project scope. |
| Data Silos | Storing reasoning only locally prevents team collaboration and knowledge sharing. | Deploy a centralized backend with RBAC. Ensure the MCP server can authenticate and sync with the shared store. |
| Ignoring Rejected Paths | Focusing only on the chosen solution loses valuable information about why certain approaches were discarded. | Explicitly model rejectedAlternatives in the schema. Encourage the agent to document rejection reasons during summarization. |
Production Bundle
This section provides actionable resources for deploying a reasoning capture architecture in a production environment.
Action Checklist
- Define Hook Triggers: Configure hooks to capture on
PostToolUsefor git commits andSessionEndevents. - Implement Async Capture: Ensure the hook handler offloads persistence to a background process to avoid blocking the commit flow.
- Design Reasoning Schema: Define a structured schema for
intent,alternatives,rationale, andconstraintsto ensure machine-readable data. - Deploy MCP Server: Set up the MCP server with symmetric
fetchandpersisttools for reasoning data. - Configure Context Injection: Implement the injection mechanism with token limits and relevance filtering to prevent context overflow.
- Set Up RBAC: Configure role-based access control in the backend to restrict reasoning data access to authorized team members.
- Enable Redaction: Add a redaction pipeline to the capture layer to prevent secrets from being stored in the reasoning log.
- Monitor Ingestion: Set up observability (OpenTelemetry) to track hook latency, capture success rates, and backend ingestion throughput.
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|---|---|---|
| Solo Developer | Local SQLite + MCP Server | Low overhead, no infrastructure required. Reasoning is persistent across sessions but not shared. | Minimal; runs locally. |
| Small Team | PostgreSQL + MCP + Shared Backend | Enables team visibility and context sharing. Relational storage supports hierarchy and RBAC. | Moderate; requires database hosting. |
| Enterprise | Kotlin/Spring Boot + Redis + OTel + RBAC | High compliance, auditability, and scalability. Virtual threads handle high concurrency. OTel provides deep observability. | Higher; requires ops resources and cloud infrastructure. |
| High-Security Env | On-Prem Backend + Air-Gapped MCP | Keeps reasoning data within the corporate firewall. Prevents leakage of sensitive decision logic. | High; requires dedicated infrastructure. |
Configuration Template
MCP Server Configuration (.mcp.json):
{
"mcpServers": {
"reasoning-bridge": {
"command": "node",
"args": ["./dist/reasoning-mcp-server.js"],
"env": {
"BACKEND_URL": "https://api.reasoning-bridge.internal",
"API_KEY": "${REASONING_API_KEY}"
}
}
}
}
Hook Configuration (hooks.config.ts):
import { defineHooks } from '@ai-reasoning/hooks';
export default defineHooks({
triggers: [
{
event: 'post_tool_use',
filter: { tool: 'Bash', pattern: 'git commit' },
action: 'capture_commit_reasoning'
},
{
event: 'session_end',
action: 'finalize_session'
}
],
capture: {
includeAlternatives: true,
maxPromptHistory: 50,
redactSecrets: true
}
});
Quick Start Guide
Install the MCP Server: Run the installer script to place the MCP server and hook configurations into your project directory.
curl -sSL https://install.reasoning-bridge.dev | shConfigure Environment: Set the
REASONING_API_KEYandBACKEND_URLin your environment. If running locally, start the backend service using Docker Compose.Initialize the Agent: Launch your AI coding agent. The hooks will automatically attach to the lifecycle events. Verify that the MCP server is connected by running a test command.
Generate Reasoning: Make a commit using the agent. The hook will capture the reasoning and persist it to the backend. Check the timeline view to verify the entry.
Test Context Injection: Start a new session and run
/inject-reasoning <session-id>to load the previous session's context. Verify that the agent acknowledges the historical decisions.
Mid-Year Sale — Unlock Full Article
Base plan from just $4.99/mo or $49/yr
Sign in to read the full article and unlock all tutorials.
Sign In / Register — Start Free Trial7-day free trial · Cancel anytime · 30-day money-back
