claude-baton 2.1.5 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,6 +21,11 @@ Save session state before context loss.
21
21
  - **decisions**: key choices made and WHY
22
22
  - **blockers**: anything blocking progress
23
23
  - **plan_reference**: file path and section of the active plan document (e.g. "docs/v2-plan.md Phase 2 Step 3"), or omit if no plan is active
24
+ - **learnings**: review the conversation for corrections, failures, and wrong assumptions. For each, write a short actionable statement. Examples:
25
+ - "User corrected: always run tests before committing"
26
+ - "Assumed API returns array but it returns object"
27
+ - "Build failed because forgot to update imports after rename"
28
+ If nothing went wrong this session, use an empty array.
24
29
 
25
30
  5. Call the `save_checkpoint` MCP tool with all fields:
26
31
  - what_was_built
@@ -32,6 +37,7 @@ Save session state before context loss.
32
37
  - branch (from step 2)
33
38
  - uncommitted_files (array of lines from git status --short)
34
39
  - git_snapshot (from git log --oneline -10)
40
+ - learnings (array of strings from step 4)
35
41
 
36
42
  6. Print structured confirmation:
37
43
 
@@ -0,0 +1,84 @@
1
+ Analyze recent checkpoints to surface learnings and suggest memory updates.
2
+
3
+ Run periodically (weekly or after major milestones) to close the learning loop.
4
+
5
+ ## Steps
6
+
7
+ 1. Detect the project from the current working directory. Construct the project slug by replacing all `/` with `-` in the full path.
8
+
9
+ 2. Call the `list_checkpoints` MCP tool with `limit: 10` (no date) to fetch the 10 most recent checkpoints.
10
+
11
+ 3. Load current memory state:
12
+ - Read all files in `~/.claude/projects/[PROJECT_SLUG]/memory/`
13
+ - Read `MEMORY.md` in the memory directory
14
+ - Read the project's `CLAUDE.md` (in the working directory root)
15
+
16
+ 4. Check git history for correction patterns:
17
+ ```bash
18
+ git log --oneline -30
19
+ ```
20
+ Look for reverts, quick-follow fix commits (e.g., "fix: ..." immediately after a feature commit), and patterns indicating repeated mistakes.
21
+
22
+ 5. Analyze the checkpoint data:
23
+
24
+ **Extract learnings:**
25
+ - Pull the `learnings` array from each checkpoint (may be empty or absent on older checkpoints)
26
+ - Also extract signals from `decisions_made`, `blockers`, and `what_was_built`
27
+
28
+ **Frequency analysis:**
29
+ - Count how many times each learning (or semantically similar learning) appears
30
+ - Single occurrence = note only
31
+ - 2+ occurrences = high confidence, propose as rule
32
+
33
+ **Cross-reference:**
34
+ - Is this learning already captured in a memory file? → skip
35
+ - Is this learning already a CLAUDE.md rule? → skip
36
+ - Is this a correction/preference? → propose as feedback memory
37
+ - Is this about the project? → propose as project memory
38
+
39
+ 6. Present the report:
40
+
41
+ ```
42
+ ## 🔄 Retro — [PROJECT_NAME] — [DATE]
43
+
44
+ ### 🧠 Memory Health
45
+
46
+ - 📁 Total memories: [count of files in memory dir]
47
+ - 📏 MEMORY.md line count: [N]/200 (⚠️ warn if >150)
48
+ - 🪦 Stale memories: [any referencing completed/outdated work]
49
+ - 🔀 Duplicate/overlapping memories: [any found]
50
+
51
+ ### 📚 Learnings Summary
52
+
53
+ **🔁 Recurring (2+ times) — propose as rules:**
54
+
55
+ - [learning] — appeared in [N] checkpoints
56
+ - ...
57
+
58
+ **📌 Single occurrence — note only:**
59
+
60
+ - [learning]
61
+ - ...
62
+
63
+ ### 🔍 Git Correction Patterns
64
+
65
+ [Reverts, quick-follow fixes that indicate recurring mistakes, or "✅ None detected"]
66
+
67
+ ### 🛠️ Proposed Changes
68
+
69
+ **📝 Memory file actions:**
70
+
71
+ - ➕ **Create:** [new memory file if a pattern warrants it, with suggested filename and content]
72
+ - ✏️ **Update:** [existing memory with outdated info]
73
+ - 🔗 **Merge:** [overlapping memories to consolidate]
74
+ - 🗑️ **Prune:** [stale memories to delete]
75
+
76
+ **📐 CLAUDE.md rules** (only for recurring learnings not already captured):
77
+
78
+ 1. Add to section [X]: "[exact rule wording]"
79
+ _Reason: appeared in [N] checkpoints, e.g., [quote from learning]_
80
+ ```
81
+
82
+ 7. Ask: **"Which changes should I apply? (all / list numbers / none)"**
83
+
84
+ Do NOT modify CLAUDE.md, memory files, or any project files without explicit approval.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
- import { initDatabase, getDefaultDbPath, insertCheckpoint, getLatestCheckpoint, getCheckpoint, getCheckpointsByDate, insertDailySummary, countAll, } from "./store.js";
4
+ import { initDatabase, getDefaultDbPath, insertCheckpoint, getLatestCheckpoint, getCheckpoint, getCheckpointsByDate, getRecentCheckpoints, insertDailySummary, countAll, } from "./store.js";
5
5
  import { callClaudeJson } from "./llm.js";
6
6
  import { formatSize, normalizeProjectPath } from "./utils.js";
7
7
  import { readFileSync, statSync } from "fs";
@@ -76,6 +76,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
76
76
  type: "string",
77
77
  description: "Reference to active plan document and section, e.g. 'docs/plan.md Phase 2 Step 3'",
78
78
  },
79
+ learnings: {
80
+ type: "array",
81
+ items: { type: "string" },
82
+ description: "Actionable learnings from the session — corrections, wrong assumptions, failed approaches",
83
+ },
79
84
  source: {
80
85
  type: "string",
81
86
  enum: ["manual", "auto"],
@@ -108,13 +113,17 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
108
113
  },
109
114
  {
110
115
  name: "list_checkpoints",
111
- description: "List all checkpoints for a date",
116
+ description: "List checkpoints by date or most recent",
112
117
  inputSchema: {
113
118
  type: "object",
114
119
  properties: {
115
120
  date: {
116
121
  type: "string",
117
- description: "YYYY-MM-DD (defaults to today)",
122
+ description: "YYYY-MM-DD returns checkpoints for this date. If omitted, returns most recent across all dates.",
123
+ },
124
+ limit: {
125
+ type: "number",
126
+ description: "Max checkpoints to return (default 10). Used when date is omitted.",
118
127
  },
119
128
  project: {
120
129
  type: "string",
@@ -161,6 +170,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
161
170
  uncommittedFiles: a?.uncommitted_files,
162
171
  gitSnapshot: a?.git_snapshot,
163
172
  planReference: a?.plan_reference,
173
+ learnings: a?.learnings,
164
174
  source: a?.source ?? "manual",
165
175
  }, dbPath);
166
176
  return { content: [{ type: "text", text: `Checkpoint saved: ${id}` }] };
@@ -177,14 +187,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
177
187
  };
178
188
  }
179
189
  case "list_checkpoints": {
180
- const cpDate = args?.date ?? new Date().toISOString().slice(0, 10);
181
- const cps = getCheckpointsByDate(db, projectPath, cpDate);
190
+ const cpDate = args?.date;
191
+ const limit = args?.limit ?? 10;
192
+ const cps = cpDate
193
+ ? getCheckpointsByDate(db, projectPath, cpDate)
194
+ : getRecentCheckpoints(db, projectPath, limit);
182
195
  const summary = cps.map((cp) => ({
183
196
  id: cp.id,
184
197
  created_at: cp.created_at,
185
198
  what_was_built: cp.what_was_built,
186
199
  branch: cp.branch,
187
200
  current_state: cp.current_state,
201
+ decisions_made: cp.decisions_made,
202
+ learnings: cp.learnings,
188
203
  }));
189
204
  return {
190
205
  content: [{ type: "text", text: JSON.stringify(summary, null, 2) }],
package/dist/store.d.ts CHANGED
@@ -12,10 +12,12 @@ export declare function insertCheckpoint(db: Database, projectPath: string, sess
12
12
  gitSnapshot?: string;
13
13
  planReference?: string;
14
14
  source?: "manual" | "auto";
15
+ learnings?: string[];
15
16
  }, dbPath?: string): string;
16
17
  export declare function getCheckpoint(db: Database, id: string): Checkpoint | null;
17
18
  export declare function getLatestCheckpoint(db: Database, projectPath: string): Checkpoint | null;
18
19
  export declare function getCheckpointsByDate(db: Database, projectPath: string, date: string): Checkpoint[];
20
+ export declare function getRecentCheckpoints(db: Database, projectPath: string, limit?: number): Checkpoint[];
19
21
  export declare function getAllCheckpoints(db: Database, projectPath?: string): Checkpoint[];
20
22
  export declare function insertDailySummary(db: Database, projectPath: string, date: string, summary: Record<string, unknown>, dbPath?: string): string;
21
23
  export declare function getDailySummary(db: Database, projectPath: string, date: string): DailySummary | null;
package/dist/store.js CHANGED
@@ -88,12 +88,21 @@ export function initSchema(db) {
88
88
  if (!msg.includes("duplicate column"))
89
89
  throw e;
90
90
  }
91
+ // Migration: add learnings column for existing databases
92
+ try {
93
+ db.exec("ALTER TABLE checkpoints ADD COLUMN learnings TEXT DEFAULT '[]'");
94
+ }
95
+ catch (e) {
96
+ const msg = e instanceof Error ? e.message : "";
97
+ if (!msg.includes("duplicate column"))
98
+ throw e;
99
+ }
91
100
  }
92
101
  // --- Checkpoints CRUD ---
93
102
  export function insertCheckpoint(db, projectPath, sessionId, currentState, whatWasBuilt, nextSteps, opts, dbPath) {
94
103
  const id = crypto.randomUUID();
95
- db.run(`INSERT INTO checkpoints (id, project_path, session_id, branch, current_state, what_was_built, next_steps, decisions_made, blockers, uncommitted_files, git_snapshot, plan_reference, source, created_at)
96
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
104
+ db.run(`INSERT INTO checkpoints (id, project_path, session_id, branch, current_state, what_was_built, next_steps, decisions_made, blockers, uncommitted_files, git_snapshot, plan_reference, source, learnings, created_at)
105
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
97
106
  id,
98
107
  projectPath,
99
108
  sessionId,
@@ -107,6 +116,7 @@ export function insertCheckpoint(db, projectPath, sessionId, currentState, whatW
107
116
  opts?.gitSnapshot ?? null,
108
117
  opts?.planReference ?? null,
109
118
  opts?.source ?? "manual",
119
+ JSON.stringify(opts?.learnings ?? []),
110
120
  new Date().toISOString(),
111
121
  ]);
112
122
  if (dbPath)
@@ -137,6 +147,7 @@ function parseCheckpointRow(row) {
137
147
  uncommitted_files: JSON.parse(row.uncommitted_files),
138
148
  git_snapshot: row.git_snapshot ?? null,
139
149
  plan_reference: row.plan_reference ?? null,
150
+ learnings: JSON.parse(row.learnings ?? "[]"),
140
151
  source: row.source ?? "manual",
141
152
  };
142
153
  }
@@ -154,6 +165,16 @@ export function getCheckpointsByDate(db, projectPath, date) {
154
165
  stmt.free();
155
166
  return results;
156
167
  }
168
+ export function getRecentCheckpoints(db, projectPath, limit = 10) {
169
+ const stmt = db.prepare("SELECT * FROM checkpoints WHERE project_path = ? ORDER BY created_at DESC, rowid DESC LIMIT ?");
170
+ stmt.bind([projectPath, limit]);
171
+ const results = [];
172
+ while (stmt.step()) {
173
+ results.push(parseCheckpointRow(stmt.getAsObject()));
174
+ }
175
+ stmt.free();
176
+ return results;
177
+ }
157
178
  export function getAllCheckpoints(db, projectPath) {
158
179
  let sql = "SELECT * FROM checkpoints";
159
180
  const params = [];
package/dist/types.d.ts CHANGED
@@ -12,6 +12,7 @@ export interface Checkpoint {
12
12
  uncommitted_files: string[];
13
13
  git_snapshot: string | null;
14
14
  plan_reference: string | null;
15
+ learnings: string[];
15
16
  source: "manual" | "auto";
16
17
  created_at: string;
17
18
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-baton",
3
- "version": "2.1.5",
3
+ "version": "2.2.0",
4
4
  "description": "Session lifecycle management for Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -19,6 +19,7 @@ Analyze these inputs and produce a JSON object with these fields:
19
19
  - decisions_made: Key decisions made since the previous checkpoint, if any (1-2 sentences, or "None")
20
20
  - blockers: Anything blocking progress, if any (1 sentence, or "None")
21
21
  - plan_reference: If the session references an active plan document (e.g. PLAN.md, docs/plan.md, a spec file), include the file path and the specific section being worked on (e.g. "docs/v2-plan.md Phase 2 Step 3"). Null if no plan document is referenced.
22
+ - learnings: Review the transcript for corrections made by the user, failed approaches, wrong assumptions, or mistakes by Claude. For each, write a short actionable learning statement. Examples: "User corrected: always run tests before committing", "Assumed API returns array but it returns object", "Build failed because forgot to update imports after rename". If nothing went wrong, output an empty array.
22
23
 
23
24
  Rules:
24
25
  - Be concise — each field should be 1-3 sentences max
@@ -40,5 +41,6 @@ Example output:
40
41
  "next_steps": "Wire up login form to POST /auth/login endpoint. Add token refresh middleware.",
41
42
  "decisions_made": "Using bcrypt over argon2 for password hashing due to simpler deployment. Storing refresh tokens in httpOnly cookies.",
42
43
  "blockers": "None",
43
- "plan_reference": "docs/auth-plan.md Phase 2 Step 1"
44
+ "plan_reference": "docs/auth-plan.md Phase 2 Step 1",
45
+ "learnings": ["Assumed bcrypt was already installed but had to add it to dependencies"]
44
46
  }