ai-session-checkpoint 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 gokks8142
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # ai-session-checkpoint
2
+
3
+ **Never lose AI coding session context again.**
4
+
5
+ When your Claude Code context fills up or your Cursor tab crashes, all the context vanishes. `ai-session-checkpoint` silently saves session state to a folder — so your next session picks up exactly where you left off. Put that folder in Google Drive or iCloud and it syncs across machines automatically.
6
+
7
+ ## Quick Start (30 seconds)
8
+
9
+ ```bash
10
+ cd ~/my-project
11
+
12
+ # Option 1: Shell script (zero dependencies)
13
+ curl -fsSL https://raw.githubusercontent.com/gokks8142/ai-session-checkpoint/main/install.sh | bash
14
+
15
+ # Option 2: npx (Node.js users)
16
+ npx ai-session-checkpoint init
17
+ ```
18
+
19
+ That's it. Open your AI editor, start coding. Checkpoints happen automatically.
20
+
21
+ ## What It Does
22
+
23
+ | Feature | How |
24
+ |---------|-----|
25
+ | **Auto-checkpoint** | Background agent saves every 20 min (Claude Code) |
26
+ | **Manual checkpoint** | Say "checkpoint" in any AI editor |
27
+ | **Session recovery** | New sessions read `.checkpoints/` on start — full context |
28
+ | **Cross-editor** | Same `.checkpoints/` folder works in Claude Code + Cursor |
29
+ | **Cross-machine** | Put checkpoint folder in Google Drive / iCloud — syncs automatically |
30
+ | **Change detection** | Skips if no files changed — no noise from read-only work |
31
+ | **Smart retention** | Keeps recent detail, compresses old history, max 50 files |
32
+
33
+ ## How It Works
34
+
35
+ ```
36
+ my-project/
37
+ ├── .checkpoints/ ← symlink to checkpoint storage
38
+ │ ├── project-state.md ← current project state (always up-to-date)
39
+ │ ├── sessions/
40
+ │ │ ├── 2026-03-21-10-30.md ← auto-checkpoint
41
+ │ │ └── 2026-03-21-11-15.md ← manual checkpoint
42
+ │ ├── decisions.md ← architecture decisions log
43
+ │ └── problems.md ← open issues / blockers
44
+ ├── CLAUDE.md ← tells Claude to read/write .checkpoints/
45
+ └── ... (your code)
46
+ ```
47
+
48
+ 1. **On session start**: AI reads `project-state.md` + latest session file → full context
49
+ 2. **Every 20 min**: Background agent checks `git diff`, writes session snapshot if changes detected
50
+ 3. **On "checkpoint"**: Immediate save with summary confirmation
51
+ 4. **New session**: Reads checkpoints, picks up where you left off
52
+
53
+ ## Storage Options
54
+
55
+ ### Local folder (default)
56
+
57
+ Checkpoints go to `~/.ai-checkpoints/my-project/`. Works immediately, zero setup.
58
+
59
+ ### Cloud sync (Google Drive / iCloud)
60
+
61
+ To sync checkpoints across machines, put the folder in Google Drive or iCloud:
62
+
63
+ ```bash
64
+ # 1. Create a folder in Google Drive (one time)
65
+ mkdir -p ~/Google\ Drive/My\ Drive/ClaudeCode/
66
+
67
+ # 2. Run install.sh from your project and enter the path when prompted
68
+ cd ~/my-project
69
+ curl -fsSL https://raw.githubusercontent.com/gokks8142/ai-session-checkpoint/main/install.sh | bash
70
+
71
+ # When asked "Where should checkpoints be stored?", enter:
72
+ # ~/Google Drive/My Drive/ClaudeCode/
73
+ ```
74
+
75
+ That's it. Checkpoints sync automatically via Google Drive. On your other machine, create the same symlink and you have full context.
76
+
77
+ ### Obsidian (optional bonus)
78
+
79
+ If you already use [Obsidian](https://obsidian.md), you can point your vault at the same Google Drive folder. This gives you search, graph view, and backlinks across your checkpoints — but it's purely optional. The tool works identically with or without Obsidian.
80
+
81
+ ## Link a Project
82
+
83
+ The installer handles this automatically. If you need to do it manually:
84
+
85
+ ```bash
86
+ # Symlink your project to the checkpoint folder
87
+ ln -s ~/Google\ Drive/My\ Drive/ClaudeCode/my-project ~/my-project/.checkpoints
88
+ ```
89
+
90
+ To verify:
91
+ ```bash
92
+ ls -la .checkpoints/
93
+ # Should show: project-state.md, sessions/, decisions.md, problems.md
94
+ ```
95
+
96
+ ## Supported Editors
97
+
98
+ | Editor | Auto-checkpoint | Manual checkpoint | Config file |
99
+ |--------|:-:|:-:|---|
100
+ | Claude Code | ✅ | ✅ | `CLAUDE.md` |
101
+ | Cursor | — | ✅ | `.cursorrules` |
102
+
103
+ The checkpoint format is editor-agnostic — any AI editor that reads files can use it.
104
+
105
+ ## What Gets Saved
106
+
107
+ **Session file** (`sessions/YYYY-MM-DD-HH-MM.md`):
108
+ - Summary of what was accomplished
109
+ - Files changed and why
110
+ - Decisions made
111
+ - Open items and next steps
112
+
113
+ **Project state** (`project-state.md`):
114
+ - What the project is and tech stack
115
+ - What's built and working
116
+ - What's in progress
117
+ - Key files and their purposes
118
+ - Known issues
119
+
120
+ ## Smart Retention
121
+
122
+ Checkpoints don't pile up forever:
123
+
124
+ | Time window | Rule |
125
+ |-------------|------|
126
+ | Last 24 hours | Keep all |
127
+ | Last 7 days | Keep 1 per day |
128
+ | Last 30 days | Keep 1 per week |
129
+ | Older | Delete |
130
+
131
+ Hard cap: **50 files max** (configurable). Oldest deleted on rollover.
132
+
133
+ ## Uninstall
134
+
135
+ ```bash
136
+ rm .checkpoints # Remove symlink
137
+ # Remove checkpoint lines from CLAUDE.md or .cursorrules
138
+ # Optionally delete ~/.ai-checkpoints/my-project/
139
+ ```
140
+
141
+ ## License
142
+
143
+ MIT
package/bin/init.js ADDED
@@ -0,0 +1,315 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ai-session-checkpoint CLI
5
+ *
6
+ * Usage:
7
+ * npx ai-session-checkpoint init # Set up checkpoints for current project
8
+ * npx ai-session-checkpoint migrate --to obsidian # Migrate local → Obsidian
9
+ */
10
+
11
+ const fs = require("fs");
12
+ const path = require("path");
13
+ const { execSync } = require("child_process");
14
+ const readline = require("readline");
15
+
16
+ const VERSION = "1.0.0";
17
+
18
+ // --- Helpers ---
19
+ function ask(question, defaultAnswer) {
20
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
21
+ return new Promise((resolve) => {
22
+ const prompt = defaultAnswer ? `${question} (${defaultAnswer}): ` : `${question}: `;
23
+ rl.question(prompt, (answer) => {
24
+ rl.close();
25
+ resolve(answer.trim() || defaultAnswer || "");
26
+ });
27
+ });
28
+ }
29
+
30
+ function green(t) { return `\x1b[32m${t}\x1b[0m`; }
31
+ function blue(t) { return `\x1b[34m${t}\x1b[0m`; }
32
+ function cyan(t) { return `\x1b[36m${t}\x1b[0m`; }
33
+ function bold(t) { return `\x1b[1m${t}\x1b[0m`; }
34
+ function dim(t) { return `\x1b[2m${t}\x1b[0m`; }
35
+
36
+ function writeIfMissing(filePath, content, label) {
37
+ if (!fs.existsSync(filePath)) {
38
+ fs.writeFileSync(filePath, content, "utf8");
39
+ console.log(` ${green("✓")} Created: ${dim(label)}`);
40
+ return true;
41
+ }
42
+ return false;
43
+ }
44
+
45
+ // No Obsidian-specific detection — user provides custom path if needed
46
+
47
+ // --- Templates ---
48
+ const TEMPLATES = {
49
+ "project-state.md": `# Project State
50
+
51
+ ## What is this project?
52
+ <!-- Brief description -->
53
+
54
+ ## Tech Stack
55
+ <!-- Languages, frameworks, tools -->
56
+
57
+ ## What's Built
58
+ <!-- Completed features and components -->
59
+
60
+ ## In Progress
61
+ <!-- Current work items -->
62
+
63
+ ## Key Files
64
+ <!-- Important files and their purposes -->
65
+
66
+ ## Known Issues
67
+ <!-- Bugs, blockers, open questions -->
68
+ `,
69
+ "decisions.md": `# Architecture Decisions
70
+
71
+ <!-- Format:
72
+ ## YYYY-MM-DD: Decision Title
73
+ **Context:** Why this decision was needed
74
+ **Decision:** What was decided
75
+ **Alternatives:** What else was considered
76
+ -->
77
+ `,
78
+ "problems.md": `# Open Problems
79
+
80
+ <!-- Format:
81
+ ## Problem Title
82
+ **Status:** open | investigating | blocked | resolved
83
+ **Description:** What's happening
84
+ **Impact:** Why it matters
85
+ **Notes:** Investigation progress
86
+ -->
87
+ `,
88
+ };
89
+
90
+ const CHECKPOINT_INSTRUCTIONS = `At session start, read \`.checkpoints/project-state.md\` and the latest file in \`.checkpoints/sessions/\` to pick up context from previous sessions.
91
+
92
+ When the user says "checkpoint" or when you complete a feature/fix, write a session summary to \`.checkpoints/sessions/\` (filename: \`YYYY-MM-DD-HH-MM.md\`) and update \`.checkpoints/project-state.md\`.`;
93
+
94
+ const SKILL_CONTENT = `---
95
+ name: ai-session-checkpoint
96
+ description: Automatically save session context, decisions, and progress so no work is lost when sessions crash or context windows fill up.
97
+ triggers:
98
+ - "checkpoint"
99
+ - "save progress"
100
+ - "save context"
101
+ - "save session"
102
+ ---
103
+
104
+ # ai-session-checkpoint
105
+
106
+ ## On Session Start
107
+
108
+ Read \`.checkpoints/project-state.md\` and the latest file in \`.checkpoints/sessions/\` to pick up context from previous sessions. Briefly summarize what you found so the user knows you have context.
109
+
110
+ ## On "checkpoint" / "save progress" / "save context"
111
+
112
+ 1. **Check for changes**: Run \`git diff --stat\` to see if any files changed. If no changes and no significant decisions were made, tell the user "No changes to checkpoint" and skip.
113
+
114
+ 2. **Write session file**: Create \`.checkpoints/sessions/YYYY-MM-DD-HH-MM.md\` with:
115
+ \`\`\`
116
+ # Session: YYYY-MM-DD HH:MM
117
+
118
+ ## Summary
119
+ - What was accomplished this session (2-5 bullet points)
120
+
121
+ ## Files Changed
122
+ - path/to/file.ts — what changed and why
123
+
124
+ ## Decisions Made
125
+ - Key decisions with brief rationale
126
+
127
+ ## Open Items
128
+ - What's left to do, blockers, next steps
129
+ \`\`\`
130
+
131
+ 3. **Update project state**: Rewrite \`.checkpoints/project-state.md\` with current reality:
132
+ - What the project is
133
+ - Tech stack
134
+ - What's built and working
135
+ - What's in progress
136
+ - Key files and their purposes
137
+ - Known issues
138
+
139
+ 4. **Retention sweep**: Count files in \`.checkpoints/sessions/\`. If more than 50, delete the oldest file(s) to stay at 50.
140
+
141
+ 5. **Confirm**: Tell the user what was saved with a brief summary.
142
+
143
+ ## On Feature/Fix Completion
144
+
145
+ When you complete a significant feature or fix, proactively offer: "Want me to checkpoint this progress?"
146
+ `;
147
+
148
+ // --- Commands ---
149
+ async function init() {
150
+ const projectDir = process.cwd();
151
+ const projectName = path.basename(projectDir);
152
+ const homedir = require("os").homedir();
153
+ const defaultCheckpointDir = path.join(homedir, ".ai-checkpoints");
154
+
155
+ console.log("");
156
+ console.log(`${blue(bold("ai-session-checkpoint"))} ${dim(`v${VERSION}`)}`);
157
+ console.log("");
158
+
159
+ // Step 1: Storage
160
+ let checkpointBase;
161
+ console.log(cyan("? Where should checkpoints be stored?"));
162
+ console.log(` ${bold("1)")} Local folder ${dim(`(${defaultCheckpointDir}/)`)}`);
163
+ console.log(` ${bold("2)")} Custom path ${dim("(Google Drive, iCloud, Dropbox, etc.)")}`);
164
+ const choice = await ask(" Choose [1/2]", "1");
165
+ if (choice === "2") {
166
+ const customPath = await ask(" Enter path", "");
167
+ if (customPath) {
168
+ const resolved = customPath.replace(/^~/, homedir);
169
+ fs.mkdirSync(resolved, { recursive: true });
170
+ checkpointBase = resolved;
171
+ } else {
172
+ checkpointBase = defaultCheckpointDir;
173
+ }
174
+ } else {
175
+ checkpointBase = defaultCheckpointDir;
176
+ }
177
+
178
+ // Step 2: Project name
179
+ const name = await ask(cyan("? Project name?"), projectName);
180
+ const checkpointDir = path.join(checkpointBase, name);
181
+
182
+ // Step 3: Detect editor
183
+ let editorType = "claude-code";
184
+ if (fs.existsSync(path.join(projectDir, ".cursorrules")) && !fs.existsSync(path.join(projectDir, "CLAUDE.md"))) {
185
+ editorType = "cursor";
186
+ }
187
+ console.log(`${dim(" Editor detected: " + editorType)}`);
188
+ console.log("");
189
+
190
+ // Step 4: Create checkpoint folder + templates
191
+ fs.mkdirSync(path.join(checkpointDir, "sessions"), { recursive: true });
192
+
193
+ for (const [filename, content] of Object.entries(TEMPLATES)) {
194
+ writeIfMissing(path.join(checkpointDir, filename), content, filename);
195
+ }
196
+ console.log(` ${green("✓")} Templates: ${dim("project-state.md, decisions.md, problems.md, sessions/")}`);
197
+
198
+ // Step 5: Symlink
199
+ const symlinkPath = path.join(projectDir, ".checkpoints");
200
+ if (fs.existsSync(symlinkPath)) {
201
+ const stat = fs.lstatSync(symlinkPath);
202
+ if (stat.isSymbolicLink()) fs.unlinkSync(symlinkPath);
203
+ }
204
+ if (!fs.existsSync(symlinkPath)) {
205
+ fs.symlinkSync(checkpointDir, symlinkPath);
206
+ console.log(` ${green("✓")} Symlink: ${dim(`.checkpoints → ${checkpointDir}`)}`);
207
+ }
208
+
209
+ // Step 6: Editor config
210
+ if (editorType === "claude-code" || editorType === "both") {
211
+ const claudeMd = path.join(projectDir, "CLAUDE.md");
212
+ if (fs.existsSync(claudeMd)) {
213
+ const existing = fs.readFileSync(claudeMd, "utf8");
214
+ if (!existing.includes(".checkpoints/project-state.md")) {
215
+ fs.appendFileSync(claudeMd, "\n" + CHECKPOINT_INSTRUCTIONS + "\n");
216
+ console.log(` ${green("✓")} CLAUDE.md: ${dim("Added checkpoint instructions")}`);
217
+ }
218
+ } else {
219
+ fs.writeFileSync(claudeMd, CHECKPOINT_INSTRUCTIONS + "\n");
220
+ console.log(` ${green("✓")} CLAUDE.md: ${dim("Created with checkpoint instructions")}`);
221
+ }
222
+ }
223
+
224
+ if (editorType === "cursor" || editorType === "both") {
225
+ const cursorrules = path.join(projectDir, ".cursorrules");
226
+ if (fs.existsSync(cursorrules)) {
227
+ const existing = fs.readFileSync(cursorrules, "utf8");
228
+ if (!existing.includes(".checkpoints/project-state.md")) {
229
+ fs.appendFileSync(cursorrules, "\n" + CHECKPOINT_INSTRUCTIONS + "\n");
230
+ console.log(` ${green("✓")} .cursorrules: ${dim("Added checkpoint instructions")}`);
231
+ }
232
+ } else {
233
+ fs.writeFileSync(cursorrules, CHECKPOINT_INSTRUCTIONS + "\n");
234
+ console.log(` ${green("✓")} .cursorrules: ${dim("Created with checkpoint instructions")}`);
235
+ }
236
+ }
237
+
238
+ // Step 7: Install skill
239
+ if (editorType === "claude-code" || editorType === "both") {
240
+ const skillDir = path.join(homedir, ".claude", "skills", "ai-session-checkpoint");
241
+ fs.mkdirSync(skillDir, { recursive: true });
242
+ fs.writeFileSync(path.join(skillDir, "SKILL.md"), SKILL_CONTENT);
243
+ console.log(` ${green("✓")} Skill: ${dim("~/.claude/skills/ai-session-checkpoint/")}`);
244
+ }
245
+
246
+ // Step 8: .gitignore
247
+ const gitignorePath = path.join(projectDir, ".gitignore");
248
+ if (fs.existsSync(gitignorePath)) {
249
+ const existing = fs.readFileSync(gitignorePath, "utf8");
250
+ if (!existing.includes(".checkpoints")) {
251
+ fs.appendFileSync(gitignorePath, "\n# ai-session-checkpoint\n.checkpoints\n");
252
+ console.log(` ${green("✓")} .gitignore: ${dim("Added .checkpoints")}`);
253
+ }
254
+ }
255
+
256
+ console.log("");
257
+ console.log(`${green(bold("Done!"))} Checkpoints stored in: ${dim(checkpointDir)}`);
258
+ console.log("");
259
+ }
260
+
261
+ async function migrate() {
262
+ const args = process.argv.slice(3);
263
+ if (args[0] !== "--to" || !args[1]) {
264
+ console.log("Usage: ai-session-checkpoint migrate --to <path>");
265
+ console.log("Example: ai-session-checkpoint migrate --to ~/Google\\ Drive/My\\ Drive/ClaudeCode");
266
+ process.exit(1);
267
+ }
268
+
269
+ const projectDir = process.cwd();
270
+ const symlinkPath = path.join(projectDir, ".checkpoints");
271
+ const homedir = require("os").homedir();
272
+
273
+ if (!fs.existsSync(symlinkPath)) {
274
+ console.log("No .checkpoints found in current directory. Run 'init' first.");
275
+ process.exit(1);
276
+ }
277
+
278
+ const currentTarget = fs.readlinkSync(symlinkPath);
279
+ const newBase = args[1].replace(/^~/, homedir);
280
+ const projectName = path.basename(projectDir);
281
+ const newTarget = path.join(newBase, projectName);
282
+
283
+ if (currentTarget === newTarget) {
284
+ console.log("Already using that path. Nothing to migrate.");
285
+ process.exit(0);
286
+ }
287
+
288
+ // Copy files
289
+ fs.mkdirSync(newTarget, { recursive: true });
290
+ execSync(`cp -r "${currentTarget}/"* "${newTarget}/"`, { stdio: "inherit" });
291
+
292
+ // Update symlink
293
+ fs.unlinkSync(symlinkPath);
294
+ fs.symlinkSync(newTarget, symlinkPath);
295
+
296
+ console.log(`${green("✓")} Migrated: ${dim(currentTarget)} → ${dim(newTarget)}`);
297
+ console.log(`${green("✓")} Symlink updated`);
298
+ console.log(`${green("✓")} All session history preserved`);
299
+ }
300
+
301
+ // --- Main ---
302
+ const command = process.argv[2] || "init";
303
+
304
+ switch (command) {
305
+ case "init":
306
+ init().catch(console.error);
307
+ break;
308
+ case "migrate":
309
+ migrate().catch(console.error);
310
+ break;
311
+ default:
312
+ console.log(`Unknown command: ${command}`);
313
+ console.log("Usage: ai-session-checkpoint [init|migrate]");
314
+ process.exit(1);
315
+ }
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: ai-session-checkpoint
3
+ description: Automatically save session context, decisions, and progress so no work is lost when sessions crash or context windows fill up.
4
+ triggers:
5
+ - "checkpoint"
6
+ - "save progress"
7
+ - "save context"
8
+ - "save session"
9
+ ---
10
+
11
+ # ai-session-checkpoint
12
+
13
+ ## On Session Start
14
+
15
+ Read `.checkpoints/project-state.md` and the latest file in `.checkpoints/sessions/` to pick up context from previous sessions. Briefly summarize what you found so the user knows you have context.
16
+
17
+ ## On "checkpoint" / "save progress" / "save context"
18
+
19
+ 1. **Check for changes**: Run `git diff --stat` to see if any files changed. If no changes and no significant decisions were made, tell the user "No changes to checkpoint" and skip.
20
+
21
+ 2. **Write session file**: Create `.checkpoints/sessions/YYYY-MM-DD-HH-MM.md` with:
22
+ ```
23
+ # Session: YYYY-MM-DD HH:MM
24
+
25
+ ## Summary
26
+ - What was accomplished this session (2-5 bullet points)
27
+
28
+ ## Files Changed
29
+ - path/to/file.ts — what changed and why
30
+
31
+ ## Decisions Made
32
+ - Key decisions with brief rationale
33
+
34
+ ## Open Items
35
+ - What's left to do, blockers, next steps
36
+ ```
37
+
38
+ 3. **Update project state**: Rewrite `.checkpoints/project-state.md` with current reality:
39
+ - What the project is
40
+ - Tech stack
41
+ - What's built and working
42
+ - What's in progress
43
+ - Key files and their purposes
44
+ - Known issues
45
+
46
+ 4. **Retention sweep**: Count files in `.checkpoints/sessions/`. If more than 50, delete the oldest file(s) to stay at 50.
47
+
48
+ 5. **Confirm**: Tell the user what was saved with a brief summary.
49
+
50
+ ## On Feature/Fix Completion
51
+
52
+ When you complete a significant feature or fix, proactively offer: "Want me to checkpoint this progress?"
@@ -0,0 +1,3 @@
1
+ At session start, read `.checkpoints/project-state.md` and the latest file in `.checkpoints/sessions/` to pick up context from previous sessions.
2
+
3
+ When the user says "checkpoint" or when you complete a feature/fix, write a session summary to `.checkpoints/sessions/` (filename: `YYYY-MM-DD-HH-MM.md`) and update `.checkpoints/project-state.md`.
@@ -0,0 +1,5 @@
1
+ At session start, read `.checkpoints/project-state.md` and the latest file in `.checkpoints/sessions/` to pick up context from previous sessions.
2
+
3
+ When the user says "checkpoint" or when you complete a feature/fix, write a session summary to `.checkpoints/sessions/` (filename: `YYYY-MM-DD-HH-MM.md`) and update `.checkpoints/project-state.md`.
4
+
5
+ Before ending a long conversation, offer to checkpoint: "Want me to save this session's progress?"
package/install.sh ADDED
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # ai-session-checkpoint installer
4
+ # Zero dependencies — works on any Mac/Linux with bash
5
+ #
6
+ # Usage:
7
+ # curl -fsSL https://raw.githubusercontent.com/gokks8142/ai-session-checkpoint/main/install.sh | bash
8
+ # OR
9
+ # ./install.sh
10
+ #
11
+ set -euo pipefail
12
+
13
+ # --- Colors ---
14
+ RED='\033[0;31m'
15
+ GREEN='\033[0;32m'
16
+ BLUE='\033[0;34m'
17
+ CYAN='\033[0;36m'
18
+ BOLD='\033[1m'
19
+ DIM='\033[2m'
20
+ RESET='\033[0m'
21
+
22
+ # --- Config ---
23
+ VERSION="1.0.0"
24
+ DEFAULT_CHECKPOINT_DIR="$HOME/.ai-checkpoints"
25
+ SKILL_DIR="$HOME/.claude/skills/ai-session-checkpoint"
26
+
27
+ # --- Detect project ---
28
+ PROJECT_DIR="$(pwd)"
29
+ PROJECT_NAME="$(basename "$PROJECT_DIR")"
30
+
31
+ echo ""
32
+ echo -e "${BLUE}${BOLD}ai-session-checkpoint${RESET} ${DIM}v${VERSION}${RESET}"
33
+ echo ""
34
+
35
+ # --- Step 1: Storage location ---
36
+ echo -e "${CYAN}? Where should checkpoints be stored?${RESET}"
37
+ echo -e " ${BOLD}1)${RESET} Local folder (${DIM}${DEFAULT_CHECKPOINT_DIR}/${RESET})"
38
+ echo -e " ${BOLD}2)${RESET} Custom path ${DIM}(Google Drive, iCloud, Dropbox, etc.)${RESET}"
39
+ echo ""
40
+ read -p " Choose [1/2] (default: 1): " STORAGE_CHOICE
41
+ STORAGE_CHOICE="${STORAGE_CHOICE:-1}"
42
+
43
+ if [ "$STORAGE_CHOICE" = "2" ]; then
44
+ read -p " Enter path: " CUSTOM_PATH
45
+ if [ -z "$CUSTOM_PATH" ]; then
46
+ echo -e " ${RED}!${RESET} No path entered. Using local folder."
47
+ CHECKPOINT_BASE="$DEFAULT_CHECKPOINT_DIR"
48
+ else
49
+ # Expand ~ if present
50
+ CUSTOM_PATH="${CUSTOM_PATH/#\~/$HOME}"
51
+ mkdir -p "$CUSTOM_PATH"
52
+ CHECKPOINT_BASE="$CUSTOM_PATH"
53
+ fi
54
+ else
55
+ CHECKPOINT_BASE="$DEFAULT_CHECKPOINT_DIR"
56
+ fi
57
+
58
+ # --- Step 2: Project name ---
59
+ echo ""
60
+ echo -e "${CYAN}? Project name?${RESET} ${DIM}(${PROJECT_NAME})${RESET}"
61
+ read -p " Name: " INPUT_NAME
62
+ PROJECT_NAME="${INPUT_NAME:-$PROJECT_NAME}"
63
+
64
+ CHECKPOINT_DIR="$CHECKPOINT_BASE/$PROJECT_NAME"
65
+
66
+ # --- Step 3: Detect AI editor ---
67
+ EDITOR_TYPE="unknown"
68
+ if [ -f "$PROJECT_DIR/CLAUDE.md" ] || command -v claude &>/dev/null; then
69
+ EDITOR_TYPE="claude-code"
70
+ elif [ -f "$PROJECT_DIR/.cursorrules" ]; then
71
+ EDITOR_TYPE="cursor"
72
+ fi
73
+
74
+ echo ""
75
+ if [ "$EDITOR_TYPE" = "claude-code" ]; then
76
+ echo -e "${CYAN}? AI editor detected: ${BOLD}Claude Code${RESET}"
77
+ elif [ "$EDITOR_TYPE" = "cursor" ]; then
78
+ echo -e "${CYAN}? AI editor detected: ${BOLD}Cursor${RESET}"
79
+ else
80
+ echo -e "${CYAN}? AI editor:${RESET}"
81
+ echo -e " ${BOLD}1)${RESET} Claude Code"
82
+ echo -e " ${BOLD}2)${RESET} Cursor"
83
+ echo -e " ${BOLD}3)${RESET} Both"
84
+ read -p " Choose [1/2/3] (default: 1): " EDITOR_CHOICE
85
+ case "${EDITOR_CHOICE:-1}" in
86
+ 2) EDITOR_TYPE="cursor" ;;
87
+ 3) EDITOR_TYPE="both" ;;
88
+ *) EDITOR_TYPE="claude-code" ;;
89
+ esac
90
+ fi
91
+
92
+ echo ""
93
+
94
+ # --- Step 4: Create checkpoint folder + templates ---
95
+ mkdir -p "$CHECKPOINT_DIR/sessions"
96
+
97
+ # project-state.md
98
+ if [ ! -f "$CHECKPOINT_DIR/project-state.md" ]; then
99
+ cat > "$CHECKPOINT_DIR/project-state.md" << 'TMPL'
100
+ # Project State
101
+
102
+ ## What is this project?
103
+ <!-- Brief description -->
104
+
105
+ ## Tech Stack
106
+ <!-- Languages, frameworks, tools -->
107
+
108
+ ## What's Built
109
+ <!-- Completed features and components -->
110
+
111
+ ## In Progress
112
+ <!-- Current work items -->
113
+
114
+ ## Key Files
115
+ <!-- Important files and their purposes -->
116
+
117
+ ## Known Issues
118
+ <!-- Bugs, blockers, open questions -->
119
+ TMPL
120
+ echo -e " ${GREEN}✓${RESET} Created: ${DIM}project-state.md${RESET}"
121
+ fi
122
+
123
+ # decisions.md
124
+ if [ ! -f "$CHECKPOINT_DIR/decisions.md" ]; then
125
+ cat > "$CHECKPOINT_DIR/decisions.md" << 'TMPL'
126
+ # Architecture Decisions
127
+
128
+ <!-- Format:
129
+ ## YYYY-MM-DD: Decision Title
130
+ **Context:** Why this decision was needed
131
+ **Decision:** What was decided
132
+ **Alternatives:** What else was considered
133
+ -->
134
+ TMPL
135
+ echo -e " ${GREEN}✓${RESET} Created: ${DIM}decisions.md${RESET}"
136
+ fi
137
+
138
+ # problems.md
139
+ if [ ! -f "$CHECKPOINT_DIR/problems.md" ]; then
140
+ cat > "$CHECKPOINT_DIR/problems.md" << 'TMPL'
141
+ # Open Problems
142
+
143
+ <!-- Format:
144
+ ## Problem Title
145
+ **Status:** open | investigating | blocked | resolved
146
+ **Description:** What's happening
147
+ **Impact:** Why it matters
148
+ **Notes:** Investigation progress
149
+ -->
150
+ TMPL
151
+ echo -e " ${GREEN}✓${RESET} Created: ${DIM}problems.md${RESET}"
152
+ fi
153
+
154
+ echo -e " ${GREEN}✓${RESET} Templates: ${DIM}project-state.md, decisions.md, problems.md, sessions/${RESET}"
155
+
156
+ # --- Step 5: Create symlink ---
157
+ SYMLINK_PATH="$PROJECT_DIR/.checkpoints"
158
+
159
+ if [ -L "$SYMLINK_PATH" ]; then
160
+ rm "$SYMLINK_PATH"
161
+ elif [ -e "$SYMLINK_PATH" ]; then
162
+ echo -e " ${RED}!${RESET} .checkpoints already exists and is not a symlink. Skipping."
163
+ echo ""
164
+ else
165
+ true
166
+ fi
167
+
168
+ if [ ! -e "$SYMLINK_PATH" ]; then
169
+ ln -s "$CHECKPOINT_DIR" "$SYMLINK_PATH"
170
+ echo -e " ${GREEN}✓${RESET} Symlink: ${DIM}.checkpoints → ${CHECKPOINT_DIR}${RESET}"
171
+ fi
172
+
173
+ # --- Step 6: Configure AI editor ---
174
+ CHECKPOINT_INSTRUCTIONS='At session start, read `.checkpoints/project-state.md` and the latest file in `.checkpoints/sessions/` to pick up context from previous sessions.
175
+
176
+ When the user says "checkpoint" or when you complete a feature/fix, write a session summary to `.checkpoints/sessions/` (filename: `YYYY-MM-DD-HH-MM.md`) and update `.checkpoints/project-state.md`.'
177
+
178
+ # Claude Code: CLAUDE.md
179
+ if [ "$EDITOR_TYPE" = "claude-code" ] || [ "$EDITOR_TYPE" = "both" ]; then
180
+ CLAUDE_MD="$PROJECT_DIR/CLAUDE.md"
181
+ if [ -f "$CLAUDE_MD" ]; then
182
+ # Check if instructions already exist
183
+ if ! grep -q ".checkpoints/project-state.md" "$CLAUDE_MD" 2>/dev/null; then
184
+ echo "" >> "$CLAUDE_MD"
185
+ echo "$CHECKPOINT_INSTRUCTIONS" >> "$CLAUDE_MD"
186
+ echo -e " ${GREEN}✓${RESET} CLAUDE.md: ${DIM}Added checkpoint instructions${RESET}"
187
+ else
188
+ echo -e " ${DIM} CLAUDE.md already has checkpoint instructions${RESET}"
189
+ fi
190
+ else
191
+ echo "$CHECKPOINT_INSTRUCTIONS" > "$CLAUDE_MD"
192
+ echo -e " ${GREEN}✓${RESET} CLAUDE.md: ${DIM}Created with checkpoint instructions${RESET}"
193
+ fi
194
+ fi
195
+
196
+ # Cursor: .cursorrules
197
+ if [ "$EDITOR_TYPE" = "cursor" ] || [ "$EDITOR_TYPE" = "both" ]; then
198
+ CURSORRULES="$PROJECT_DIR/.cursorrules"
199
+ if [ -f "$CURSORRULES" ]; then
200
+ if ! grep -q ".checkpoints/project-state.md" "$CURSORRULES" 2>/dev/null; then
201
+ echo "" >> "$CURSORRULES"
202
+ echo "$CHECKPOINT_INSTRUCTIONS" >> "$CURSORRULES"
203
+ echo -e " ${GREEN}✓${RESET} .cursorrules: ${DIM}Added checkpoint instructions${RESET}"
204
+ else
205
+ echo -e " ${DIM} .cursorrules already has checkpoint instructions${RESET}"
206
+ fi
207
+ else
208
+ echo "$CHECKPOINT_INSTRUCTIONS" > "$CURSORRULES"
209
+ echo -e " ${GREEN}✓${RESET} .cursorrules: ${DIM}Created with checkpoint instructions${RESET}"
210
+ fi
211
+ fi
212
+
213
+ # --- Step 7: Install Claude Code skill (if applicable) ---
214
+ if [ "$EDITOR_TYPE" = "claude-code" ] || [ "$EDITOR_TYPE" = "both" ]; then
215
+ mkdir -p "$SKILL_DIR"
216
+
217
+ cat > "$SKILL_DIR/SKILL.md" << 'SKILLEOF'
218
+ ---
219
+ name: ai-session-checkpoint
220
+ description: Automatically save session context, decisions, and progress so no work is lost when sessions crash or context windows fill up.
221
+ triggers:
222
+ - "checkpoint"
223
+ - "save progress"
224
+ - "save context"
225
+ - "save session"
226
+ ---
227
+
228
+ # ai-session-checkpoint
229
+
230
+ ## On Session Start
231
+
232
+ Read `.checkpoints/project-state.md` and the latest file in `.checkpoints/sessions/` to pick up context from previous sessions. Briefly summarize what you found so the user knows you have context.
233
+
234
+ ## On "checkpoint" / "save progress" / "save context"
235
+
236
+ 1. **Check for changes**: Run `git diff --stat` to see if any files changed. If no changes and no significant decisions were made, tell the user "No changes to checkpoint" and skip.
237
+
238
+ 2. **Write session file**: Create `.checkpoints/sessions/YYYY-MM-DD-HH-MM.md` with:
239
+ ```
240
+ # Session: YYYY-MM-DD HH:MM
241
+
242
+ ## Summary
243
+ - What was accomplished this session (2-5 bullet points)
244
+
245
+ ## Files Changed
246
+ - path/to/file.ts — what changed and why
247
+
248
+ ## Decisions Made
249
+ - Key decisions with brief rationale
250
+
251
+ ## Open Items
252
+ - What's left to do, blockers, next steps
253
+ ```
254
+
255
+ 3. **Update project state**: Rewrite `.checkpoints/project-state.md` with current reality:
256
+ - What the project is
257
+ - Tech stack
258
+ - What's built and working
259
+ - What's in progress
260
+ - Key files and their purposes
261
+ - Known issues
262
+
263
+ 4. **Retention sweep**: Count files in `.checkpoints/sessions/`. If more than 50, delete the oldest file(s) to stay at 50.
264
+
265
+ 5. **Confirm**: Tell the user what was saved with a brief summary.
266
+
267
+ ## On Feature/Fix Completion
268
+
269
+ When you complete a significant feature or fix, proactively offer: "Want me to checkpoint this progress?"
270
+ SKILLEOF
271
+
272
+ echo -e " ${GREEN}✓${RESET} Skill: ${DIM}Installed to ~/.claude/skills/ai-session-checkpoint/${RESET}"
273
+ fi
274
+
275
+ # --- Step 8: Add .checkpoints to .gitignore ---
276
+ GITIGNORE="$PROJECT_DIR/.gitignore"
277
+ if [ -f "$GITIGNORE" ]; then
278
+ if ! grep -q ".checkpoints" "$GITIGNORE" 2>/dev/null; then
279
+ echo "" >> "$GITIGNORE"
280
+ echo "# ai-session-checkpoint" >> "$GITIGNORE"
281
+ echo ".checkpoints" >> "$GITIGNORE"
282
+ echo -e " ${GREEN}✓${RESET} .gitignore: ${DIM}Added .checkpoints${RESET}"
283
+ fi
284
+ else
285
+ echo "# ai-session-checkpoint" > "$GITIGNORE"
286
+ echo ".checkpoints" >> "$GITIGNORE"
287
+ echo -e " ${GREEN}✓${RESET} .gitignore: ${DIM}Created with .checkpoints${RESET}"
288
+ fi
289
+
290
+ # --- Done ---
291
+ echo ""
292
+ echo -e "${GREEN}${BOLD}Done!${RESET} Checkpoints stored in: ${DIM}${CHECKPOINT_DIR}${RESET}"
293
+ echo ""
294
+ if [ "$EDITOR_TYPE" = "claude-code" ] || [ "$EDITOR_TYPE" = "both" ]; then
295
+ echo -e " Your next Claude Code session will:"
296
+ echo -e " ${DIM} 1. Read .checkpoints/ on start for context${RESET}"
297
+ echo -e " ${DIM} 2. Checkpoint on \"checkpoint\" command${RESET}"
298
+ echo -e " ${DIM} 3. Offer to checkpoint when features are done${RESET}"
299
+ fi
300
+ echo ""
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "ai-session-checkpoint",
3
+ "version": "1.0.0",
4
+ "description": "Never lose AI coding session context again. Auto-checkpoints for Claude Code, Cursor, and any AI editor.",
5
+ "license": "MIT",
6
+ "author": "gokks8142",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/gokks8142/ai-session-checkpoint.git"
10
+ },
11
+ "bin": {
12
+ "ai-session-checkpoint": "bin/init.js"
13
+ },
14
+ "keywords": [
15
+ "ai",
16
+ "claude",
17
+ "cursor",
18
+ "checkpoint",
19
+ "session",
20
+ "context",
21
+ "obsidian",
22
+ "developer-tools"
23
+ ],
24
+ "files": [
25
+ "bin/",
26
+ "editors/",
27
+ "scripts/",
28
+ "templates/",
29
+ "install.sh",
30
+ "LICENSE",
31
+ "README.md"
32
+ ]
33
+ }
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Link an existing project to an Obsidian vault checkpoint folder.
4
+ #
5
+ # Usage:
6
+ # ./link-vault.sh <vault-path> <project-name> [project-dir]
7
+ #
8
+ # Example:
9
+ # ./link-vault.sh ~/GoogleDrive/.../MyVault/Org/ClaudeCode MyProject ~/vibecode/MyProject
10
+ #
11
+ set -euo pipefail
12
+
13
+ VAULT_BASE="${1:?Usage: link-vault.sh <vault-base-path> <project-name> [project-dir]}"
14
+ PROJECT_NAME="${2:?Usage: link-vault.sh <vault-base-path> <project-name> [project-dir]}"
15
+ PROJECT_DIR="${3:-$(pwd)}"
16
+
17
+ CHECKPOINT_DIR="$VAULT_BASE/$PROJECT_NAME"
18
+ SYMLINK_PATH="$PROJECT_DIR/.checkpoints"
19
+
20
+ # Create checkpoint folder if needed
21
+ mkdir -p "$CHECKPOINT_DIR/sessions"
22
+
23
+ # Create symlink
24
+ if [ -L "$SYMLINK_PATH" ]; then
25
+ rm "$SYMLINK_PATH"
26
+ fi
27
+
28
+ ln -s "$CHECKPOINT_DIR" "$SYMLINK_PATH"
29
+ echo "✓ Linked: $SYMLINK_PATH → $CHECKPOINT_DIR"
@@ -0,0 +1,8 @@
1
+ # Architecture Decisions
2
+
3
+ <!-- Format:
4
+ ## YYYY-MM-DD: Decision Title
5
+ **Context:** Why this decision was needed
6
+ **Decision:** What was decided
7
+ **Alternatives:** What else was considered
8
+ -->
@@ -0,0 +1,9 @@
1
+ # Open Problems
2
+
3
+ <!-- Format:
4
+ ## Problem Title
5
+ **Status:** open | investigating | blocked | resolved
6
+ **Description:** What's happening
7
+ **Impact:** Why it matters
8
+ **Notes:** Investigation progress
9
+ -->
@@ -0,0 +1,19 @@
1
+ # Project State
2
+
3
+ ## What is this project?
4
+ <!-- Brief description -->
5
+
6
+ ## Tech Stack
7
+ <!-- Languages, frameworks, tools -->
8
+
9
+ ## What's Built
10
+ <!-- Completed features and components -->
11
+
12
+ ## In Progress
13
+ <!-- Current work items -->
14
+
15
+ ## Key Files
16
+ <!-- Important files and their purposes -->
17
+
18
+ ## Known Issues
19
+ <!-- Bugs, blockers, open questions -->
File without changes