@vibe-x/agent-better-checkpoint 0.1.0 → 0.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.
- package/README.md +20 -3
- package/bin/cli.mjs +31 -32
- package/package.json +1 -1
- package/platform/unix/check_uncommitted.sh +263 -52
- package/platform/unix/checkpoint.sh +13 -13
- package/platform/win/check_uncommitted.ps1 +278 -57
- package/platform/win/checkpoint.ps1 +13 -13
- package/skill/SKILL.md +23 -13
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Agent Better Checkpoint
|
|
1
|
+
# Agent Better Checkpoint (ABC)
|
|
2
2
|
|
|
3
3
|
**One-line install, zero config.** Turns AI agent edits into transparent, queryable Git commits.
|
|
4
4
|
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
npx @vibe-x/agent-better-checkpoint
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
+

|
|
10
|
+
|
|
9
11
|
That's it. Your AI coding assistant (Cursor, Claude Code) will now auto-commit every meaningful edit with semantic messages and structured metadata — no more opaque checkpoints.
|
|
10
12
|
|
|
11
13
|
---
|
|
@@ -40,6 +42,19 @@ git log --format="%(trailers:key=Agent,valueonly)" # by agent
|
|
|
40
42
|
git log --grep="User-Prompt:.*registration" # by prompt keyword
|
|
41
43
|
```
|
|
42
44
|
|
|
45
|
+
### Works with Your Favorite Git Tools
|
|
46
|
+
|
|
47
|
+
Since every checkpoint is a standard Git commit, the entire Git ecosystem is at your disposal — what was once a hidden, platform-specific checkpoint becomes a first-class citizen you can browse, search, diff, and rebase.
|
|
48
|
+
|
|
49
|
+
| Tool | Type | What You Get |
|
|
50
|
+
|------|------|-------------|
|
|
51
|
+
| [GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) | VS Code / Cursor Extension | Inline blame, file history, visual commit graph, interactive rebase — see *who* (you or the AI) changed *what* and *when*, right in the editor |
|
|
52
|
+
| [lazygit](https://github.com/jesseduffield/lazygit) | Terminal UI | Fast keyboard-driven staging, diff browsing, cherry-pick, and rebase across checkpoint commits |
|
|
53
|
+
| [tig](https://github.com/jonas/tig) | Terminal UI | Lightweight ncurses Git log viewer, great for quickly scanning checkpoint history |
|
|
54
|
+
| [GitHub / GitLab Web UI](https://github.com) | Web | Browse, compare, and share checkpoint history online after pushing |
|
|
55
|
+
|
|
56
|
+
For example, with **GitLens in Cursor** you can hover any line to see which checkpoint introduced it and the original user prompt, view all checkpoints for a file in a timeline, or search commits by `checkpoint(` prefix and `User-Prompt` trailer content.
|
|
57
|
+
|
|
43
58
|
---
|
|
44
59
|
|
|
45
60
|
## How It Works
|
|
@@ -93,11 +108,13 @@ The AI agent will auto-bootstrap the runtime scripts on first use.
|
|
|
93
108
|
|
|
94
109
|
| Location | Content |
|
|
95
110
|
|----------|---------|
|
|
96
|
-
| `~/.agent-better-checkpoint/scripts/` | Commit script (`checkpoint.sh` / `.ps1`) |
|
|
97
|
-
| `~/.agent-better-checkpoint/hooks/stop/` | Stop hook (`check_uncommitted.sh` / `.ps1`) |
|
|
111
|
+
| `~/.vibe-x/agent-better-checkpoint/scripts/` | Commit script (`checkpoint.sh` / `.ps1`) |
|
|
112
|
+
| `~/.vibe-x/agent-better-checkpoint/hooks/stop/` | Stop hook (`check_uncommitted.sh` / `.ps1`) |
|
|
98
113
|
| Platform skill directory | `SKILL.md` — AI agent instructions |
|
|
99
114
|
| Platform hook config | Stop hook registration |
|
|
100
115
|
|
|
116
|
+
> **Project-local mode**: Projects can also commit `.vibe-x/agent-better-checkpoint/` (config + scripts) for self-contained setup. When present, the global hook delegates to the project-local scripts automatically.
|
|
117
|
+
|
|
101
118
|
### Uninstall
|
|
102
119
|
|
|
103
120
|
```bash
|
package/bin/cli.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* agent-better-checkpoint
|
|
4
|
+
* agent-better-checkpoint installer (Node.js)
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* One-click install via npx: checkpoint scripts, stop hook, and SKILL.md to user env.
|
|
7
|
+
* Deploys platform-specific scripts (macOS/Linux vs Windows).
|
|
8
8
|
*
|
|
9
9
|
* Usage:
|
|
10
10
|
* npx @vibe-x/agent-better-checkpoint
|
|
@@ -18,22 +18,22 @@ import { homedir, platform } from 'node:os';
|
|
|
18
18
|
import { fileURLToPath } from 'node:url';
|
|
19
19
|
|
|
20
20
|
// ============================================================
|
|
21
|
-
//
|
|
21
|
+
// Path constants
|
|
22
22
|
// ============================================================
|
|
23
23
|
|
|
24
24
|
const __filename = fileURLToPath(import.meta.url);
|
|
25
25
|
const __dirname = dirname(__filename);
|
|
26
26
|
const PKG_ROOT = resolve(__dirname, '..');
|
|
27
27
|
|
|
28
|
-
const INSTALL_BASE = join(homedir(), '.agent-better-checkpoint');
|
|
28
|
+
const INSTALL_BASE = join(homedir(), '.vibe-x', 'agent-better-checkpoint');
|
|
29
29
|
const SKILL_NAME = 'agent-better-checkpoint';
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// In-package source paths
|
|
32
32
|
const PLATFORM_DIR = join(PKG_ROOT, 'platform');
|
|
33
33
|
const SKILL_SRC = join(PKG_ROOT, 'skill', 'SKILL.md');
|
|
34
34
|
|
|
35
35
|
// ============================================================
|
|
36
|
-
//
|
|
36
|
+
// Argument parsing
|
|
37
37
|
// ============================================================
|
|
38
38
|
|
|
39
39
|
function parseArgs(argv) {
|
|
@@ -79,12 +79,12 @@ Options:
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// ============================================================
|
|
82
|
-
//
|
|
82
|
+
// Platform detection
|
|
83
83
|
// ============================================================
|
|
84
84
|
|
|
85
85
|
function detectAIPlatform() {
|
|
86
86
|
const home = homedir();
|
|
87
|
-
//
|
|
87
|
+
// Prefer Claude (if both exist, user can override with --platform)
|
|
88
88
|
if (existsSync(join(home, '.claude'))) return 'claude';
|
|
89
89
|
if (existsSync(join(home, '.cursor'))) return 'cursor';
|
|
90
90
|
return null;
|
|
@@ -97,7 +97,7 @@ function getOSType() {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
// ============================================================
|
|
100
|
-
//
|
|
100
|
+
// File operation helpers
|
|
101
101
|
// ============================================================
|
|
102
102
|
|
|
103
103
|
function ensureDir(dir) {
|
|
@@ -116,7 +116,7 @@ function setExecutable(filepath) {
|
|
|
116
116
|
const st = statSync(filepath);
|
|
117
117
|
chmodSync(filepath, st.mode | 0o111);
|
|
118
118
|
} catch {
|
|
119
|
-
//
|
|
119
|
+
// chmod may be ineffective on Windows, ignore
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
|
|
@@ -134,7 +134,7 @@ function writeJsonFile(filepath, data) {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
// ============================================================
|
|
137
|
-
//
|
|
137
|
+
// Install logic
|
|
138
138
|
// ============================================================
|
|
139
139
|
|
|
140
140
|
function installScripts(osType) {
|
|
@@ -176,7 +176,7 @@ function installSkill(aiPlatform) {
|
|
|
176
176
|
let skillDest;
|
|
177
177
|
|
|
178
178
|
if (aiPlatform === 'cursor') {
|
|
179
|
-
//
|
|
179
|
+
// Check skills.sh install path
|
|
180
180
|
const skillsShPath = join(homedir(), '.cursor', 'skills', SKILL_NAME, 'SKILL.md');
|
|
181
181
|
if (existsSync(skillsShPath)) {
|
|
182
182
|
console.log(` Skill → already installed at ${skillsShPath} (skipped)`);
|
|
@@ -186,16 +186,15 @@ function installSkill(aiPlatform) {
|
|
|
186
186
|
skillDir = join(homedir(), '.cursor', 'skills', SKILL_NAME);
|
|
187
187
|
skillDest = join(skillDir, 'SKILL.md');
|
|
188
188
|
} else if (aiPlatform === 'claude') {
|
|
189
|
-
// Claude Code:
|
|
190
|
-
const
|
|
191
|
-
|
|
189
|
+
// Claude Code: install to standard skills directory
|
|
190
|
+
const skillsRootDir = join(homedir(), '.claude', 'skills');
|
|
191
|
+
skillDir = join(skillsRootDir, SKILL_NAME);
|
|
192
|
+
skillDest = join(skillDir, 'SKILL.md');
|
|
192
193
|
|
|
193
194
|
if (existsSync(skillDest)) {
|
|
194
195
|
console.log(` Skill → already installed at ${skillDest} (skipped)`);
|
|
195
196
|
return;
|
|
196
197
|
}
|
|
197
|
-
|
|
198
|
-
skillDir = commandsDir;
|
|
199
198
|
}
|
|
200
199
|
|
|
201
200
|
copyFileSafe(SKILL_SRC, skillDest);
|
|
@@ -209,7 +208,7 @@ function registerCursorHook(osType) {
|
|
|
209
208
|
if (!config.hooks) config.hooks = {};
|
|
210
209
|
if (!config.hooks.stop) config.hooks.stop = [];
|
|
211
210
|
|
|
212
|
-
//
|
|
211
|
+
// Build hook command
|
|
213
212
|
let hookCmd;
|
|
214
213
|
if (osType === 'unix') {
|
|
215
214
|
hookCmd = `bash ${INSTALL_BASE}/hooks/stop/check_uncommitted.sh`;
|
|
@@ -217,12 +216,12 @@ function registerCursorHook(osType) {
|
|
|
217
216
|
hookCmd = `powershell -File "${INSTALL_BASE}\\hooks\\stop\\check_uncommitted.ps1"`;
|
|
218
217
|
}
|
|
219
218
|
|
|
220
|
-
//
|
|
219
|
+
// Check if already registered
|
|
221
220
|
const alreadyRegistered = config.hooks.stop.some(
|
|
222
221
|
h => typeof h === 'object' && h.command && h.command.includes(SKILL_NAME.replace(/-/g, ''))
|
|
223
222
|
);
|
|
224
223
|
|
|
225
|
-
//
|
|
224
|
+
// More precise check: command includes agent-better-checkpoint
|
|
226
225
|
const registered = config.hooks.stop.some(
|
|
227
226
|
h => typeof h === 'object' && h.command && h.command.includes('agent-better-checkpoint')
|
|
228
227
|
);
|
|
@@ -266,7 +265,7 @@ function registerClaudeHook(osType) {
|
|
|
266
265
|
}
|
|
267
266
|
|
|
268
267
|
// ============================================================
|
|
269
|
-
//
|
|
268
|
+
// Uninstall logic
|
|
270
269
|
// ============================================================
|
|
271
270
|
|
|
272
271
|
function uninstallScripts() {
|
|
@@ -287,10 +286,10 @@ function uninstallCursorSkill() {
|
|
|
287
286
|
}
|
|
288
287
|
|
|
289
288
|
function uninstallClaudeSkill() {
|
|
290
|
-
const
|
|
291
|
-
if (existsSync(
|
|
292
|
-
rmSync(
|
|
293
|
-
console.log(` Removed
|
|
289
|
+
const skillDir = join(homedir(), '.claude', 'skills', SKILL_NAME);
|
|
290
|
+
if (existsSync(skillDir)) {
|
|
291
|
+
rmSync(skillDir, { recursive: true, force: true });
|
|
292
|
+
console.log(` Removed skill: ${skillDir}`);
|
|
294
293
|
}
|
|
295
294
|
}
|
|
296
295
|
|
|
@@ -325,7 +324,7 @@ function unregisterClaudeHook() {
|
|
|
325
324
|
}
|
|
326
325
|
|
|
327
326
|
// ============================================================
|
|
328
|
-
//
|
|
327
|
+
// Main entry
|
|
329
328
|
// ============================================================
|
|
330
329
|
|
|
331
330
|
function main() {
|
|
@@ -342,7 +341,7 @@ function main() {
|
|
|
342
341
|
}
|
|
343
342
|
|
|
344
343
|
if (args.uninstall) {
|
|
345
|
-
//
|
|
344
|
+
// Uninstall flow
|
|
346
345
|
console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Uninstalling...`);
|
|
347
346
|
|
|
348
347
|
if (aiPlatform === 'cursor') {
|
|
@@ -356,7 +355,7 @@ function main() {
|
|
|
356
355
|
uninstallScripts();
|
|
357
356
|
console.log(`\n✅ Uninstallation complete!`);
|
|
358
357
|
} else {
|
|
359
|
-
//
|
|
358
|
+
// Install flow
|
|
360
359
|
console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Installing... (OS: ${osType})`);
|
|
361
360
|
|
|
362
361
|
installScripts(osType);
|
|
@@ -370,9 +369,9 @@ function main() {
|
|
|
370
369
|
|
|
371
370
|
console.log(`\n✅ Installation complete!`);
|
|
372
371
|
console.log(`\nInstalled components:`);
|
|
373
|
-
console.log(` 📜 Checkpoint script → ~/.agent-better-checkpoint/scripts/`);
|
|
374
|
-
console.log(` 🔒 Stop hook → ~/.agent-better-checkpoint/hooks/stop/`);
|
|
375
|
-
console.log(` 📖 SKILL.md → ${aiPlatform === 'cursor' ? '~/.cursor/skills/' : '~/.claude/
|
|
372
|
+
console.log(` 📜 Checkpoint script → ~/.vibe-x/agent-better-checkpoint/scripts/`);
|
|
373
|
+
console.log(` 🔒 Stop hook → ~/.vibe-x/agent-better-checkpoint/hooks/stop/`);
|
|
374
|
+
console.log(` 📖 SKILL.md → ${aiPlatform === 'cursor' ? '~/.cursor/skills/' : '~/.claude/skills/'}${SKILL_NAME}/`);
|
|
376
375
|
console.log(`\nThe AI agent will now auto-commit with semantic messages. Happy coding! 🎉`);
|
|
377
376
|
}
|
|
378
377
|
}
|