@vibe-x/agent-better-checkpoint 0.1.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 Alien ZHOU
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,124 @@
1
+ # Agent Better Checkpoint
2
+
3
+ **One-line install, zero config.** Turns AI agent edits into transparent, queryable Git commits.
4
+
5
+ ```bash
6
+ npx @vibe-x/agent-better-checkpoint
7
+ ```
8
+
9
+ 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
+
11
+ ---
12
+
13
+ ## The Problem
14
+
15
+ AI coding assistants create "checkpoints" as you work, but these are black-box snapshots:
16
+ - **Unreadable** — no meaningful commit messages
17
+ - **Unnavigable** — can't browse or diff individual changes
18
+ - **Unqueryable** — no way to filter, search, or trace back
19
+
20
+ ## The Solution
21
+
22
+ Agent Better Checkpoint replaces them with real Git commits:
23
+
24
+ ```
25
+ checkpoint(api): add user registration endpoint
26
+
27
+ Implement POST /api/users with email/password validation.
28
+ Includes bcrypt hashing and duplicate email check.
29
+
30
+ Agent: cursor
31
+ Checkpoint-Type: auto
32
+ User-Prompt: 帮我实现用户注册接口,需要邮...要密码加密
33
+ ```
34
+
35
+ Each commit follows [Conventional Commits](https://www.conventionalcommits.org/) and carries structured metadata via [Git Trailers](https://git-scm.com/docs/git-interpret-trailers) — queryable with standard Git tools:
36
+
37
+ ```bash
38
+ git log --grep="^checkpoint(" # all checkpoints
39
+ git log --format="%(trailers:key=Agent,valueonly)" # by agent
40
+ git log --grep="User-Prompt:.*registration" # by prompt keyword
41
+ ```
42
+
43
+ ---
44
+
45
+ ## How It Works
46
+
47
+ Three components, fully automatic after install:
48
+
49
+ | Component | What it does |
50
+ |-----------|-------------|
51
+ | **SKILL.md** | Instructs the AI to commit after each meaningful edit, with proper format |
52
+ | **Commit Script** | Appends Git Trailers (agent, type, user prompt) and runs `git commit` |
53
+ | **Stop Hook** | Safety net — reminds the AI to commit if anything is left uncommitted |
54
+
55
+ ```
56
+ User gives task → AI edits code → AI calls checkpoint script → Git commit with trailers
57
+
58
+ Conversation ends → Stop hook checks for uncommitted changes
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Installation
64
+
65
+ ### Prerequisites
66
+
67
+ - Git ≥ 2.0
68
+ - Node.js ≥ 18 (only needed for installation)
69
+ - [Cursor](https://cursor.com) or [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
70
+
71
+ ### Quick Install
72
+
73
+ ```bash
74
+ npx @vibe-x/agent-better-checkpoint
75
+ ```
76
+
77
+ Auto-detects your OS and AI platform. Or specify explicitly:
78
+
79
+ ```bash
80
+ npx @vibe-x/agent-better-checkpoint --platform cursor
81
+ npx @vibe-x/agent-better-checkpoint --platform claude
82
+ ```
83
+
84
+ ### Via [skills.sh](https://skills.sh)
85
+
86
+ ```bash
87
+ npx skills add alienzhou/agent-better-checkpoint
88
+ ```
89
+
90
+ The AI agent will auto-bootstrap the runtime scripts on first use.
91
+
92
+ ### What Gets Installed
93
+
94
+ | Location | Content |
95
+ |----------|---------|
96
+ | `~/.agent-better-checkpoint/scripts/` | Commit script (`checkpoint.sh` / `.ps1`) |
97
+ | `~/.agent-better-checkpoint/hooks/stop/` | Stop hook (`check_uncommitted.sh` / `.ps1`) |
98
+ | Platform skill directory | `SKILL.md` — AI agent instructions |
99
+ | Platform hook config | Stop hook registration |
100
+
101
+ ### Uninstall
102
+
103
+ ```bash
104
+ npx @vibe-x/agent-better-checkpoint --uninstall
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Platform Support
110
+
111
+ | Platform | OS | Status |
112
+ |----------|----|--------|
113
+ | Cursor | macOS, Linux, Windows | ✅ |
114
+ | Claude Code | macOS, Linux, Windows | ✅ |
115
+
116
+ ---
117
+
118
+ ## Contributing
119
+
120
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, testing, and publishing instructions.
121
+
122
+ ## License
123
+
124
+ [MIT](LICENSE)
package/bin/cli.mjs ADDED
@@ -0,0 +1,380 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * agent-better-checkpoint 安装器 (Node.js)
5
+ *
6
+ * 通过 npx 一键安装 checkpoint 脚本、stop hook 和 SKILL.md 到用户环境。
7
+ * 按平台(macOS/Linux vs Windows)选择性部署对应脚本。
8
+ *
9
+ * Usage:
10
+ * npx @vibe-x/agent-better-checkpoint
11
+ * npx @vibe-x/agent-better-checkpoint --platform cursor
12
+ * npx @vibe-x/agent-better-checkpoint --uninstall
13
+ */
14
+
15
+ import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, chmodSync, rmSync, statSync } from 'node:fs';
16
+ import { join, dirname, resolve } from 'node:path';
17
+ import { homedir, platform } from 'node:os';
18
+ import { fileURLToPath } from 'node:url';
19
+
20
+ // ============================================================
21
+ // 路径常量
22
+ // ============================================================
23
+
24
+ const __filename = fileURLToPath(import.meta.url);
25
+ const __dirname = dirname(__filename);
26
+ const PKG_ROOT = resolve(__dirname, '..');
27
+
28
+ const INSTALL_BASE = join(homedir(), '.agent-better-checkpoint');
29
+ const SKILL_NAME = 'agent-better-checkpoint';
30
+
31
+ // 包内源文件路径
32
+ const PLATFORM_DIR = join(PKG_ROOT, 'platform');
33
+ const SKILL_SRC = join(PKG_ROOT, 'skill', 'SKILL.md');
34
+
35
+ // ============================================================
36
+ // 参数解析
37
+ // ============================================================
38
+
39
+ function parseArgs(argv) {
40
+ const args = { platform: null, uninstall: false };
41
+ for (let i = 2; i < argv.length; i++) {
42
+ switch (argv[i]) {
43
+ case '--platform':
44
+ args.platform = argv[++i];
45
+ if (!['cursor', 'claude'].includes(args.platform)) {
46
+ console.error(`Error: unsupported platform "${args.platform}". Use "cursor" or "claude".`);
47
+ process.exit(1);
48
+ }
49
+ break;
50
+ case '--uninstall':
51
+ args.uninstall = true;
52
+ break;
53
+ case '--help':
54
+ case '-h':
55
+ printHelp();
56
+ process.exit(0);
57
+ break;
58
+ default:
59
+ console.error(`Unknown option: ${argv[i]}`);
60
+ printHelp();
61
+ process.exit(1);
62
+ }
63
+ }
64
+ return args;
65
+ }
66
+
67
+ function printHelp() {
68
+ console.log(`
69
+ agent-better-checkpoint — Semantic Git Checkpoint Installer
70
+
71
+ Usage:
72
+ npx @vibe-x/agent-better-checkpoint [options]
73
+
74
+ Options:
75
+ --platform <cursor|claude> Target AI platform (auto-detected if omitted)
76
+ --uninstall Remove installed files and hook registrations
77
+ -h, --help Show this help message
78
+ `);
79
+ }
80
+
81
+ // ============================================================
82
+ // 平台检测
83
+ // ============================================================
84
+
85
+ function detectAIPlatform() {
86
+ const home = homedir();
87
+ // 优先 Claude(如果两者都存在,用户可以用 --platform 覆盖)
88
+ if (existsSync(join(home, '.claude'))) return 'claude';
89
+ if (existsSync(join(home, '.cursor'))) return 'cursor';
90
+ return null;
91
+ }
92
+
93
+ function getOSType() {
94
+ const p = platform();
95
+ if (p === 'win32') return 'win';
96
+ return 'unix'; // darwin, linux, freebsd, etc.
97
+ }
98
+
99
+ // ============================================================
100
+ // 文件操作辅助
101
+ // ============================================================
102
+
103
+ function ensureDir(dir) {
104
+ if (!existsSync(dir)) {
105
+ mkdirSync(dir, { recursive: true });
106
+ }
107
+ }
108
+
109
+ function copyFileSafe(src, dest) {
110
+ ensureDir(dirname(dest));
111
+ copyFileSync(src, dest);
112
+ }
113
+
114
+ function setExecutable(filepath) {
115
+ try {
116
+ const st = statSync(filepath);
117
+ chmodSync(filepath, st.mode | 0o111);
118
+ } catch {
119
+ // Windows 下 chmod 可能无效,忽略
120
+ }
121
+ }
122
+
123
+ function readJsonFile(filepath) {
124
+ try {
125
+ return JSON.parse(readFileSync(filepath, 'utf-8'));
126
+ } catch {
127
+ return null;
128
+ }
129
+ }
130
+
131
+ function writeJsonFile(filepath, data) {
132
+ ensureDir(dirname(filepath));
133
+ writeFileSync(filepath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
134
+ }
135
+
136
+ // ============================================================
137
+ // 安装逻辑
138
+ // ============================================================
139
+
140
+ function installScripts(osType) {
141
+ const scriptsDir = join(INSTALL_BASE, 'scripts');
142
+ const hooksDir = join(INSTALL_BASE, 'hooks', 'stop');
143
+
144
+ ensureDir(scriptsDir);
145
+ ensureDir(hooksDir);
146
+
147
+ if (osType === 'unix') {
148
+ const checkpointSrc = join(PLATFORM_DIR, 'unix', 'checkpoint.sh');
149
+ const hookSrc = join(PLATFORM_DIR, 'unix', 'check_uncommitted.sh');
150
+ const checkpointDest = join(scriptsDir, 'checkpoint.sh');
151
+ const hookDest = join(hooksDir, 'check_uncommitted.sh');
152
+
153
+ copyFileSafe(checkpointSrc, checkpointDest);
154
+ copyFileSafe(hookSrc, hookDest);
155
+ setExecutable(checkpointDest);
156
+ setExecutable(hookDest);
157
+
158
+ console.log(` Scripts → ${scriptsDir}/checkpoint.sh`);
159
+ console.log(` Hooks → ${hooksDir}/check_uncommitted.sh`);
160
+ } else {
161
+ const checkpointSrc = join(PLATFORM_DIR, 'win', 'checkpoint.ps1');
162
+ const hookSrc = join(PLATFORM_DIR, 'win', 'check_uncommitted.ps1');
163
+ const checkpointDest = join(scriptsDir, 'checkpoint.ps1');
164
+ const hookDest = join(hooksDir, 'check_uncommitted.ps1');
165
+
166
+ copyFileSafe(checkpointSrc, checkpointDest);
167
+ copyFileSafe(hookSrc, hookDest);
168
+
169
+ console.log(` Scripts → ${scriptsDir}\\checkpoint.ps1`);
170
+ console.log(` Hooks → ${hooksDir}\\check_uncommitted.ps1`);
171
+ }
172
+ }
173
+
174
+ function installSkill(aiPlatform) {
175
+ let skillDir;
176
+ let skillDest;
177
+
178
+ if (aiPlatform === 'cursor') {
179
+ // 检查 skills.sh 安装路径
180
+ const skillsShPath = join(homedir(), '.cursor', 'skills', SKILL_NAME, 'SKILL.md');
181
+ if (existsSync(skillsShPath)) {
182
+ console.log(` Skill → already installed at ${skillsShPath} (skipped)`);
183
+ return;
184
+ }
185
+
186
+ skillDir = join(homedir(), '.cursor', 'skills', SKILL_NAME);
187
+ skillDest = join(skillDir, 'SKILL.md');
188
+ } else if (aiPlatform === 'claude') {
189
+ // Claude Code: 作为 slash command 安装
190
+ const commandsDir = join(homedir(), '.claude', 'commands');
191
+ skillDest = join(commandsDir, `${SKILL_NAME}.md`);
192
+
193
+ if (existsSync(skillDest)) {
194
+ console.log(` Skill → already installed at ${skillDest} (skipped)`);
195
+ return;
196
+ }
197
+
198
+ skillDir = commandsDir;
199
+ }
200
+
201
+ copyFileSafe(SKILL_SRC, skillDest);
202
+ console.log(` Skill → ${skillDest}`);
203
+ }
204
+
205
+ function registerCursorHook(osType) {
206
+ const hooksPath = join(homedir(), '.cursor', 'hooks.json');
207
+ let config = readJsonFile(hooksPath) || { version: 1, hooks: {} };
208
+
209
+ if (!config.hooks) config.hooks = {};
210
+ if (!config.hooks.stop) config.hooks.stop = [];
211
+
212
+ // 构建 hook 命令
213
+ let hookCmd;
214
+ if (osType === 'unix') {
215
+ hookCmd = `bash ${INSTALL_BASE}/hooks/stop/check_uncommitted.sh`;
216
+ } else {
217
+ hookCmd = `powershell -File "${INSTALL_BASE}\\hooks\\stop\\check_uncommitted.ps1"`;
218
+ }
219
+
220
+ // 检查是否已注册
221
+ const alreadyRegistered = config.hooks.stop.some(
222
+ h => typeof h === 'object' && h.command && h.command.includes(SKILL_NAME.replace(/-/g, ''))
223
+ );
224
+
225
+ // 用更精确的检测:检查命令中是否包含 agent-better-checkpoint
226
+ const registered = config.hooks.stop.some(
227
+ h => typeof h === 'object' && h.command && h.command.includes('agent-better-checkpoint')
228
+ );
229
+
230
+ if (!registered) {
231
+ config.hooks.stop.push({ command: hookCmd });
232
+ }
233
+
234
+ writeJsonFile(hooksPath, config);
235
+ console.log(` Config → ${hooksPath}`);
236
+ }
237
+
238
+ function registerClaudeHook(osType) {
239
+ const settingsPath = join(homedir(), '.claude', 'settings.json');
240
+ let settings = readJsonFile(settingsPath) || {};
241
+
242
+ if (!settings.hooks) settings.hooks = {};
243
+ if (!settings.hooks.Stop) settings.hooks.Stop = [];
244
+
245
+ let hookCmd;
246
+ if (osType === 'unix') {
247
+ hookCmd = `bash ${INSTALL_BASE}/hooks/stop/check_uncommitted.sh`;
248
+ } else {
249
+ hookCmd = `powershell -File "${INSTALL_BASE}\\hooks\\stop\\check_uncommitted.ps1"`;
250
+ }
251
+
252
+ const registered = settings.hooks.Stop.some(
253
+ h => typeof h === 'object' &&
254
+ JSON.stringify(h).includes('agent-better-checkpoint')
255
+ );
256
+
257
+ if (!registered) {
258
+ settings.hooks.Stop.push({
259
+ matcher: '',
260
+ hooks: [{ type: 'command', command: hookCmd }]
261
+ });
262
+ }
263
+
264
+ writeJsonFile(settingsPath, settings);
265
+ console.log(` Config → ${settingsPath}`);
266
+ }
267
+
268
+ // ============================================================
269
+ // 卸载逻辑
270
+ // ============================================================
271
+
272
+ function uninstallScripts() {
273
+ if (existsSync(INSTALL_BASE)) {
274
+ rmSync(INSTALL_BASE, { recursive: true, force: true });
275
+ console.log(` Removed ${INSTALL_BASE}`);
276
+ } else {
277
+ console.log(` ${INSTALL_BASE} not found, nothing to remove`);
278
+ }
279
+ }
280
+
281
+ function uninstallCursorSkill() {
282
+ const skillDir = join(homedir(), '.cursor', 'skills', SKILL_NAME);
283
+ if (existsSync(skillDir)) {
284
+ rmSync(skillDir, { recursive: true, force: true });
285
+ console.log(` Removed skill: ${skillDir}`);
286
+ }
287
+ }
288
+
289
+ function uninstallClaudeSkill() {
290
+ const cmdFile = join(homedir(), '.claude', 'commands', `${SKILL_NAME}.md`);
291
+ if (existsSync(cmdFile)) {
292
+ rmSync(cmdFile, { force: true });
293
+ console.log(` Removed command: ${cmdFile}`);
294
+ }
295
+ }
296
+
297
+ function unregisterCursorHook() {
298
+ const hooksPath = join(homedir(), '.cursor', 'hooks.json');
299
+ if (!existsSync(hooksPath)) return;
300
+
301
+ const config = readJsonFile(hooksPath);
302
+ if (!config || !config.hooks || !config.hooks.stop) return;
303
+
304
+ config.hooks.stop = config.hooks.stop.filter(
305
+ h => !(typeof h === 'object' && h.command && h.command.includes('agent-better-checkpoint'))
306
+ );
307
+
308
+ writeJsonFile(hooksPath, config);
309
+ console.log(` Cleaned config: ${hooksPath}`);
310
+ }
311
+
312
+ function unregisterClaudeHook() {
313
+ const settingsPath = join(homedir(), '.claude', 'settings.json');
314
+ if (!existsSync(settingsPath)) return;
315
+
316
+ const settings = readJsonFile(settingsPath);
317
+ if (!settings || !settings.hooks || !settings.hooks.Stop) return;
318
+
319
+ settings.hooks.Stop = settings.hooks.Stop.filter(
320
+ h => !JSON.stringify(h).includes('agent-better-checkpoint')
321
+ );
322
+
323
+ writeJsonFile(settingsPath, settings);
324
+ console.log(` Cleaned config: ${settingsPath}`);
325
+ }
326
+
327
+ // ============================================================
328
+ // 主入口
329
+ // ============================================================
330
+
331
+ function main() {
332
+ const args = parseArgs(process.argv);
333
+ const osType = getOSType();
334
+ const aiPlatform = args.platform || detectAIPlatform();
335
+
336
+ if (!aiPlatform) {
337
+ console.error(
338
+ 'Error: could not detect AI platform.\n' +
339
+ 'Please specify: npx @vibe-x/agent-better-checkpoint --platform cursor|claude'
340
+ );
341
+ process.exit(1);
342
+ }
343
+
344
+ if (args.uninstall) {
345
+ // 卸载流程
346
+ console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Uninstalling...`);
347
+
348
+ if (aiPlatform === 'cursor') {
349
+ uninstallCursorSkill();
350
+ unregisterCursorHook();
351
+ } else {
352
+ uninstallClaudeSkill();
353
+ unregisterClaudeHook();
354
+ }
355
+
356
+ uninstallScripts();
357
+ console.log(`\n✅ Uninstallation complete!`);
358
+ } else {
359
+ // 安装流程
360
+ console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Installing... (OS: ${osType})`);
361
+
362
+ installScripts(osType);
363
+ installSkill(aiPlatform);
364
+
365
+ if (aiPlatform === 'cursor') {
366
+ registerCursorHook(osType);
367
+ } else {
368
+ registerClaudeHook(osType);
369
+ }
370
+
371
+ console.log(`\n✅ Installation complete!`);
372
+ 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/commands/'}${SKILL_NAME}/`);
376
+ console.log(`\nThe AI agent will now auto-commit with semantic messages. Happy coding! 🎉`);
377
+ }
378
+ }
379
+
380
+ main();
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@vibe-x/agent-better-checkpoint",
3
+ "version": "0.1.0",
4
+ "description": "Semantic Git checkpoint commits for AI coding sessions",
5
+ "type": "module",
6
+ "bin": {
7
+ "agent-better-checkpoint": "./bin/cli.mjs"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "platform/",
12
+ "skill/",
13
+ "LICENSE"
14
+ ],
15
+ "keywords": [
16
+ "ai",
17
+ "agent",
18
+ "git",
19
+ "checkpoint",
20
+ "cursor",
21
+ "claude",
22
+ "conventional-commits",
23
+ "skills-sh"
24
+ ],
25
+ "license": "MIT",
26
+ "author": "alienzhou",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/alienzhou/agent-better-checkpoint.git"
30
+ },
31
+ "engines": {
32
+ "node": ">=18"
33
+ }
34
+ }