@vibe-x/agent-better-checkpoint 0.2.0 → 0.3.1
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 +29 -3
- package/bin/cli.mjs +187 -59
- package/package.json +1 -1
- package/platform/config.template.yml +16 -0
- package/skill/SKILL.md +16 -29
package/README.md
CHANGED
|
@@ -96,6 +96,23 @@ npx @vibe-x/agent-better-checkpoint --platform cursor
|
|
|
96
96
|
npx @vibe-x/agent-better-checkpoint --platform claude
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
### Project-only Install
|
|
100
|
+
|
|
101
|
+
Install only into your project (no global changes). Uses Cursor's project-level [skills](https://cursor.com/docs/context/skills) and [hooks](https://cursor.com/docs/agent/hooks):
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
cd /path/to/your/project
|
|
105
|
+
npx @vibe-x/agent-better-checkpoint --platform cursor --target .
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Creates: `.cursor/skills/`, `.cursor/hooks.json`, `.vibe-x/agent-better-checkpoint/`. Commit these with your repo.
|
|
109
|
+
|
|
110
|
+
Uninstall project-only:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx @vibe-x/agent-better-checkpoint --uninstall --target .
|
|
114
|
+
```
|
|
115
|
+
|
|
99
116
|
### Via [skills.sh](https://skills.sh)
|
|
100
117
|
|
|
101
118
|
```bash
|
|
@@ -106,14 +123,23 @@ The AI agent will auto-bootstrap the runtime scripts on first use.
|
|
|
106
123
|
|
|
107
124
|
### What Gets Installed
|
|
108
125
|
|
|
126
|
+
**Global** (no `--target`):
|
|
127
|
+
|
|
109
128
|
| Location | Content |
|
|
110
129
|
|----------|---------|
|
|
111
130
|
| `~/.vibe-x/agent-better-checkpoint/scripts/` | Commit script (`checkpoint.sh` / `.ps1`) |
|
|
112
131
|
| `~/.vibe-x/agent-better-checkpoint/hooks/stop/` | Stop hook (`check_uncommitted.sh` / `.ps1`) |
|
|
113
|
-
|
|
|
114
|
-
|
|
|
132
|
+
| `~/.cursor/skills/` or `~/.claude/skills/` | `SKILL.md` — AI agent instructions |
|
|
133
|
+
| `~/.cursor/hooks.json` or `~/.claude/settings.json` | Stop hook registration |
|
|
115
134
|
|
|
116
|
-
|
|
135
|
+
**Project-only** (`--target .`):
|
|
136
|
+
|
|
137
|
+
| Location | Content |
|
|
138
|
+
|----------|---------|
|
|
139
|
+
| `<project>/.cursor/skills/agent-better-checkpoint/` | `SKILL.md` |
|
|
140
|
+
| `<project>/.cursor/hooks.json` | Stop hook (Cursor only) |
|
|
141
|
+
| `<project>/.cursor/hooks/` | `check_uncommitted.sh` |
|
|
142
|
+
| `<project>/.vibe-x/agent-better-checkpoint/` | `checkpoint.sh`, `config.yml` |
|
|
117
143
|
|
|
118
144
|
### Uninstall
|
|
119
145
|
|
package/bin/cli.mjs
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* npx @vibe-x/agent-better-checkpoint --uninstall
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, chmodSync, rmSync, statSync } from 'node:fs';
|
|
15
|
+
import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, chmodSync, rmSync, statSync, readdirSync } from 'node:fs';
|
|
16
16
|
import { join, dirname, resolve } from 'node:path';
|
|
17
17
|
import { homedir, platform } from 'node:os';
|
|
18
18
|
import { fileURLToPath } from 'node:url';
|
|
@@ -31,13 +31,14 @@ const SKILL_NAME = 'agent-better-checkpoint';
|
|
|
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
|
+
const CONFIG_TEMPLATE = join(PLATFORM_DIR, 'config.template.yml');
|
|
34
35
|
|
|
35
36
|
// ============================================================
|
|
36
37
|
// Argument parsing
|
|
37
38
|
// ============================================================
|
|
38
39
|
|
|
39
40
|
function parseArgs(argv) {
|
|
40
|
-
const args = { platform: null, uninstall: false };
|
|
41
|
+
const args = { platform: null, uninstall: false, target: null };
|
|
41
42
|
for (let i = 2; i < argv.length; i++) {
|
|
42
43
|
switch (argv[i]) {
|
|
43
44
|
case '--platform':
|
|
@@ -47,6 +48,13 @@ function parseArgs(argv) {
|
|
|
47
48
|
process.exit(1);
|
|
48
49
|
}
|
|
49
50
|
break;
|
|
51
|
+
case '--target':
|
|
52
|
+
args.target = argv[++i];
|
|
53
|
+
if (!args.target) {
|
|
54
|
+
console.error('Error: --target requires a path argument');
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
50
58
|
case '--uninstall':
|
|
51
59
|
args.uninstall = true;
|
|
52
60
|
break;
|
|
@@ -73,6 +81,7 @@ Usage:
|
|
|
73
81
|
|
|
74
82
|
Options:
|
|
75
83
|
--platform <cursor|claude> Target AI platform (auto-detected if omitted)
|
|
84
|
+
--target <path> Project-only install (no global). Use . for cwd
|
|
76
85
|
--uninstall Remove installed files and hook registrations
|
|
77
86
|
-h, --help Show this help message
|
|
78
87
|
`);
|
|
@@ -144,31 +153,17 @@ function installScripts(osType) {
|
|
|
144
153
|
ensureDir(scriptsDir);
|
|
145
154
|
ensureDir(hooksDir);
|
|
146
155
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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');
|
|
156
|
+
// 双端脚本都安装,方便跨平台使用
|
|
157
|
+
copyFileSafe(join(PLATFORM_DIR, 'unix', 'checkpoint.sh'), join(scriptsDir, 'checkpoint.sh'));
|
|
158
|
+
copyFileSafe(join(PLATFORM_DIR, 'unix', 'check_uncommitted.sh'), join(hooksDir, 'check_uncommitted.sh'));
|
|
159
|
+
setExecutable(join(scriptsDir, 'checkpoint.sh'));
|
|
160
|
+
setExecutable(join(hooksDir, 'check_uncommitted.sh'));
|
|
165
161
|
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
copyFileSafe(join(PLATFORM_DIR, 'win', 'checkpoint.ps1'), join(scriptsDir, 'checkpoint.ps1'));
|
|
163
|
+
copyFileSafe(join(PLATFORM_DIR, 'win', 'check_uncommitted.ps1'), join(hooksDir, 'check_uncommitted.ps1'));
|
|
168
164
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
165
|
+
console.log(` Scripts → ${scriptsDir}/`);
|
|
166
|
+
console.log(` Hooks → ${hooksDir}/`);
|
|
172
167
|
}
|
|
173
168
|
|
|
174
169
|
function installSkill(aiPlatform) {
|
|
@@ -216,12 +211,6 @@ function registerCursorHook(osType) {
|
|
|
216
211
|
hookCmd = `powershell -File "${INSTALL_BASE}\\hooks\\stop\\check_uncommitted.ps1"`;
|
|
217
212
|
}
|
|
218
213
|
|
|
219
|
-
// Check if already registered
|
|
220
|
-
const alreadyRegistered = config.hooks.stop.some(
|
|
221
|
-
h => typeof h === 'object' && h.command && h.command.includes(SKILL_NAME.replace(/-/g, ''))
|
|
222
|
-
);
|
|
223
|
-
|
|
224
|
-
// More precise check: command includes agent-better-checkpoint
|
|
225
214
|
const registered = config.hooks.stop.some(
|
|
226
215
|
h => typeof h === 'object' && h.command && h.command.includes('agent-better-checkpoint')
|
|
227
216
|
);
|
|
@@ -234,6 +223,111 @@ function registerCursorHook(osType) {
|
|
|
234
223
|
console.log(` Config → ${hooksPath}`);
|
|
235
224
|
}
|
|
236
225
|
|
|
226
|
+
// 项目级安装:仅写入 target 目录,不触碰全局
|
|
227
|
+
function installProjectOnly(targetDir, aiPlatform, osType) {
|
|
228
|
+
const root = resolve(targetDir);
|
|
229
|
+
|
|
230
|
+
// .vibe-x/agent-better-checkpoint: checkpoint 脚本 + config
|
|
231
|
+
const vibeXBase = join(root, '.vibe-x', 'agent-better-checkpoint');
|
|
232
|
+
ensureDir(vibeXBase);
|
|
233
|
+
copyFileSafe(join(PLATFORM_DIR, 'unix', 'checkpoint.sh'), join(vibeXBase, 'checkpoint.sh'));
|
|
234
|
+
copyFileSafe(join(PLATFORM_DIR, 'win', 'checkpoint.ps1'), join(vibeXBase, 'checkpoint.ps1'));
|
|
235
|
+
setExecutable(join(vibeXBase, 'checkpoint.sh'));
|
|
236
|
+
const configDest = join(vibeXBase, 'config.yml');
|
|
237
|
+
if (!existsSync(configDest) && existsSync(CONFIG_TEMPLATE)) {
|
|
238
|
+
copyFileSafe(CONFIG_TEMPLATE, configDest);
|
|
239
|
+
}
|
|
240
|
+
console.log(` Config → ${vibeXBase}/`);
|
|
241
|
+
|
|
242
|
+
// Skill: .cursor/skills/ 或 .claude/skills/
|
|
243
|
+
const skillRoot = aiPlatform === 'cursor' ? '.cursor' : '.claude';
|
|
244
|
+
const skillDir = join(root, skillRoot, 'skills', SKILL_NAME);
|
|
245
|
+
copyFileSafe(SKILL_SRC, join(skillDir, 'SKILL.md'));
|
|
246
|
+
console.log(` Skill → ${skillDir}/`);
|
|
247
|
+
|
|
248
|
+
if (aiPlatform === 'cursor') {
|
|
249
|
+
// Cursor 支持项目级 hooks: .cursor/hooks.json + .cursor/hooks/
|
|
250
|
+
const hooksDir = join(root, '.cursor', 'hooks');
|
|
251
|
+
ensureDir(hooksDir);
|
|
252
|
+
copyFileSafe(join(PLATFORM_DIR, 'unix', 'check_uncommitted.sh'), join(hooksDir, 'check_uncommitted.sh'));
|
|
253
|
+
setExecutable(join(hooksDir, 'check_uncommitted.sh'));
|
|
254
|
+
copyFileSafe(join(PLATFORM_DIR, 'win', 'check_uncommitted.ps1'), join(hooksDir, 'check_uncommitted.ps1'));
|
|
255
|
+
const hookCmd = osType === 'unix'
|
|
256
|
+
? 'bash .cursor/hooks/check_uncommitted.sh'
|
|
257
|
+
: `powershell -File ".cursor\\hooks\\check_uncommitted.ps1"`;
|
|
258
|
+
const hooksPath = join(root, '.cursor', 'hooks.json');
|
|
259
|
+
let config = readJsonFile(hooksPath) || { version: 1, hooks: {} };
|
|
260
|
+
if (!config.hooks) config.hooks = {};
|
|
261
|
+
if (!config.hooks.stop) config.hooks.stop = [];
|
|
262
|
+
const registered = config.hooks.stop.some(
|
|
263
|
+
h => typeof h === 'object' && h.command && h.command.includes('check_uncommitted')
|
|
264
|
+
);
|
|
265
|
+
if (!registered) {
|
|
266
|
+
config.hooks.stop.push({ command: hookCmd });
|
|
267
|
+
}
|
|
268
|
+
writeJsonFile(hooksPath, config);
|
|
269
|
+
console.log(` Hooks → ${hooksPath}`);
|
|
270
|
+
} else {
|
|
271
|
+
// Claude Code: settings.json 为全局,无项目级 hooks,仅安装 skill 和脚本
|
|
272
|
+
console.log(` Hooks → (Claude stop hook is global-only, skipped for project install)`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function uninstallProjectOnly(targetDir, aiPlatform) {
|
|
277
|
+
const root = resolve(targetDir);
|
|
278
|
+
|
|
279
|
+
const vibeXBase = join(root, '.vibe-x', 'agent-better-checkpoint');
|
|
280
|
+
const skillRoot = aiPlatform === 'cursor' ? '.cursor' : '.claude';
|
|
281
|
+
const skillDir = join(root, skillRoot, 'skills', SKILL_NAME);
|
|
282
|
+
if (existsSync(vibeXBase)) {
|
|
283
|
+
rmSync(vibeXBase, { recursive: true, force: true });
|
|
284
|
+
console.log(` Removed ${vibeXBase}`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (existsSync(skillDir)) {
|
|
288
|
+
rmSync(skillDir, { recursive: true, force: true });
|
|
289
|
+
console.log(` Removed ${skillDir}`);
|
|
290
|
+
}
|
|
291
|
+
// 移除空的 .cursor/skills 或 .claude/skills 父目录
|
|
292
|
+
const skillsParent = join(root, skillRoot, 'skills');
|
|
293
|
+
if (existsSync(skillsParent)) {
|
|
294
|
+
try {
|
|
295
|
+
if (readdirSync(skillsParent).length === 0) {
|
|
296
|
+
rmSync(skillsParent, { recursive: true, force: true });
|
|
297
|
+
}
|
|
298
|
+
} catch {
|
|
299
|
+
// ignore
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (aiPlatform === 'cursor') {
|
|
304
|
+
const hooksPath = join(root, '.cursor', 'hooks.json');
|
|
305
|
+
if (existsSync(hooksPath)) {
|
|
306
|
+
const config = readJsonFile(hooksPath);
|
|
307
|
+
if (config?.hooks?.stop) {
|
|
308
|
+
config.hooks.stop = config.hooks.stop.filter(
|
|
309
|
+
h => !(typeof h === 'object' && h.command && h.command.includes('check_uncommitted'))
|
|
310
|
+
);
|
|
311
|
+
if (config.hooks.stop.length === 0) delete config.hooks.stop;
|
|
312
|
+
if (Object.keys(config.hooks || {}).length === 0) {
|
|
313
|
+
rmSync(hooksPath, { force: true });
|
|
314
|
+
} else {
|
|
315
|
+
writeJsonFile(hooksPath, config);
|
|
316
|
+
}
|
|
317
|
+
console.log(` Cleaned ${hooksPath}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const hooksDir = join(root, '.cursor', 'hooks');
|
|
321
|
+
const shPath = join(hooksDir, 'check_uncommitted.sh');
|
|
322
|
+
const ps1Path = join(hooksDir, 'check_uncommitted.ps1');
|
|
323
|
+
if (existsSync(shPath)) rmSync(shPath, { force: true });
|
|
324
|
+
if (existsSync(ps1Path)) rmSync(ps1Path, { force: true });
|
|
325
|
+
if (existsSync(hooksDir) && readdirSync(hooksDir).length === 0) {
|
|
326
|
+
rmSync(hooksDir, { recursive: true, force: true });
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
237
331
|
function registerClaudeHook(osType) {
|
|
238
332
|
const settingsPath = join(homedir(), '.claude', 'settings.json');
|
|
239
333
|
let settings = readJsonFile(settingsPath) || {};
|
|
@@ -268,6 +362,12 @@ function registerClaudeHook(osType) {
|
|
|
268
362
|
// Uninstall logic
|
|
269
363
|
// ============================================================
|
|
270
364
|
|
|
365
|
+
function hasInstallation(platform) {
|
|
366
|
+
const home = homedir();
|
|
367
|
+
const skillDir = join(home, platform === 'cursor' ? '.cursor' : '.claude', 'skills', SKILL_NAME);
|
|
368
|
+
return existsSync(skillDir);
|
|
369
|
+
}
|
|
370
|
+
|
|
271
371
|
function uninstallScripts() {
|
|
272
372
|
if (existsSync(INSTALL_BASE)) {
|
|
273
373
|
rmSync(INSTALL_BASE, { recursive: true, force: true });
|
|
@@ -331,8 +431,9 @@ function main() {
|
|
|
331
431
|
const args = parseArgs(process.argv);
|
|
332
432
|
const osType = getOSType();
|
|
333
433
|
const aiPlatform = args.platform || detectAIPlatform();
|
|
434
|
+
const projectTargetDir = args.target ? resolve(args.target) : null;
|
|
334
435
|
|
|
335
|
-
if (!aiPlatform) {
|
|
436
|
+
if (!aiPlatform && !projectTargetDir && !args.uninstall) {
|
|
336
437
|
console.error(
|
|
337
438
|
'Error: could not detect AI platform.\n' +
|
|
338
439
|
'Please specify: npx @vibe-x/agent-better-checkpoint --platform cursor|claude'
|
|
@@ -341,38 +442,65 @@ function main() {
|
|
|
341
442
|
}
|
|
342
443
|
|
|
343
444
|
if (args.uninstall) {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
445
|
+
if (projectTargetDir) {
|
|
446
|
+
// 优先从项目目录检测平台(与安装时一致),否则用 --platform 或全局检测
|
|
447
|
+
let platform = args.platform;
|
|
448
|
+
if (!platform) {
|
|
449
|
+
const cursorSkill = join(projectTargetDir, '.cursor', 'skills', SKILL_NAME);
|
|
450
|
+
const claudeSkill = join(projectTargetDir, '.claude', 'skills', SKILL_NAME);
|
|
451
|
+
if (existsSync(cursorSkill)) platform = 'cursor';
|
|
452
|
+
else if (existsSync(claudeSkill)) platform = 'claude';
|
|
453
|
+
}
|
|
454
|
+
if (!platform) platform = aiPlatform;
|
|
455
|
+
if (!platform) {
|
|
456
|
+
console.error('Error: --target uninstall requires --platform cursor|claude (or project must have skill installed)');
|
|
457
|
+
process.exit(1);
|
|
458
|
+
}
|
|
459
|
+
console.log(`\n[Project-local] Uninstalling from ${projectTargetDir}...`);
|
|
460
|
+
uninstallProjectOnly(projectTargetDir, platform);
|
|
350
461
|
} else {
|
|
351
|
-
|
|
352
|
-
|
|
462
|
+
const platforms = args.platform
|
|
463
|
+
? [args.platform]
|
|
464
|
+
: ['cursor', 'claude'].filter(p => hasInstallation(p));
|
|
465
|
+
for (const p of platforms) {
|
|
466
|
+
console.log(`\n[${p === 'cursor' ? 'Cursor' : 'Claude Code'}] Uninstalling...`);
|
|
467
|
+
if (p === 'cursor') {
|
|
468
|
+
uninstallCursorSkill();
|
|
469
|
+
unregisterCursorHook();
|
|
470
|
+
} else {
|
|
471
|
+
uninstallClaudeSkill();
|
|
472
|
+
unregisterClaudeHook();
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
if (platforms.length > 0) uninstallScripts();
|
|
476
|
+
if (platforms.length === 0) console.log('\nNo global installation found.');
|
|
353
477
|
}
|
|
354
|
-
|
|
355
|
-
uninstallScripts();
|
|
356
|
-
console.log(`\n✅ Uninstallation complete!`);
|
|
478
|
+
console.log('\n✅ Uninstallation complete!');
|
|
357
479
|
} else {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
480
|
+
if (projectTargetDir) {
|
|
481
|
+
if (!aiPlatform) {
|
|
482
|
+
console.error('Error: --target requires --platform cursor|claude');
|
|
483
|
+
process.exit(1);
|
|
484
|
+
}
|
|
485
|
+
console.log(`\n[Project-local] Installing to ${projectTargetDir}... (OS: ${osType})`);
|
|
486
|
+
installProjectOnly(projectTargetDir, aiPlatform, osType);
|
|
487
|
+
console.log('\n✅ Installation complete! (project-only, no global changes)');
|
|
366
488
|
} else {
|
|
367
|
-
|
|
489
|
+
console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Installing... (OS: ${osType})`);
|
|
490
|
+
installScripts(osType);
|
|
491
|
+
installSkill(aiPlatform);
|
|
492
|
+
if (aiPlatform === 'cursor') {
|
|
493
|
+
registerCursorHook(osType);
|
|
494
|
+
} else {
|
|
495
|
+
registerClaudeHook(osType);
|
|
496
|
+
}
|
|
497
|
+
console.log('\n✅ Installation complete!');
|
|
498
|
+
console.log('\nInstalled components:');
|
|
499
|
+
console.log(` 📜 Checkpoint script → ~/.vibe-x/agent-better-checkpoint/scripts/ (.sh + .ps1)`);
|
|
500
|
+
console.log(` 🔒 Stop hook → ~/.vibe-x/agent-better-checkpoint/hooks/stop/ (.sh + .ps1)`);
|
|
501
|
+
console.log(` 📖 SKILL.md → ${aiPlatform === 'cursor' ? '~/.cursor/skills/' : '~/.claude/skills/'}${SKILL_NAME}/`);
|
|
368
502
|
}
|
|
369
|
-
|
|
370
|
-
console.log(`\n✅ Installation complete!`);
|
|
371
|
-
console.log(`\nInstalled components:`);
|
|
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}/`);
|
|
375
|
-
console.log(`\nThe AI agent will now auto-commit with semantic messages. Happy coding! 🎉`);
|
|
503
|
+
console.log('\nThe AI agent will now auto-commit with semantic messages. Happy coding! 🎉');
|
|
376
504
|
}
|
|
377
505
|
}
|
|
378
506
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Checkpoint commit trigger conditions
|
|
2
|
+
#
|
|
3
|
+
# Controls when stop hook (check_uncommitted) triggers commit reminder.
|
|
4
|
+
# Affects only stop hook detection, not checkpoint.sh commit behavior.
|
|
5
|
+
|
|
6
|
+
# Trigger reminder if ANY condition met (OR)
|
|
7
|
+
# Empty/commented = condition disabled
|
|
8
|
+
trigger_if_any:
|
|
9
|
+
# min_changed_files: 3 # At least N active files changed
|
|
10
|
+
min_changed_lines: 5 # At least N lines changed
|
|
11
|
+
|
|
12
|
+
# Passive file patterns — matched files do not trigger reminder alone
|
|
13
|
+
passive_patterns:
|
|
14
|
+
- ".discuss/**"
|
|
15
|
+
- ".vibe-x/**"
|
|
16
|
+
- ".DS_Store"
|
package/skill/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: agent-better-checkpoint
|
|
|
3
3
|
description: "Automatically creates semantic Git checkpoint commits during AI coding sessions. Replaces opaque platform checkpoints with transparent, queryable Git commits using Conventional Commits format with Git Trailers. You MUST follow this skill whenever you make code changes — commit after each meaningful edit."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.3.1"
|
|
7
7
|
author: "alienzhou"
|
|
8
8
|
category: "version-control"
|
|
9
9
|
---
|
|
@@ -20,16 +20,18 @@ You are an AI coding assistant with **checkpoint awareness**. Every meaningful e
|
|
|
20
20
|
|
|
21
21
|
Before your first commit, verify the checkpoint scripts are available:
|
|
22
22
|
|
|
23
|
-
**Project-local (preferred
|
|
24
|
-
**Global fallback:** Check if `~/.vibe-x/agent-better-checkpoint/scripts/checkpoint.sh`
|
|
23
|
+
**Project-local (preferred):** Check if `.vibe-x/agent-better-checkpoint/checkpoint.sh` (or `.ps1`) exists in the workspace.
|
|
24
|
+
**Global fallback:** Check if `~/.vibe-x/agent-better-checkpoint/scripts/checkpoint.sh` (or `.ps1`) exists.
|
|
25
|
+
|
|
26
|
+
Both `.sh` and `.ps1` are always installed regardless of current OS.
|
|
25
27
|
|
|
26
28
|
If neither exists, run:
|
|
27
29
|
|
|
28
30
|
```bash
|
|
29
|
-
npx @vibe-x/agent-better-checkpoint@0.
|
|
31
|
+
npx @vibe-x/agent-better-checkpoint@0.3.1
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
Without `--target`: installs globally. With `--target .`: project-only (skill + hooks in `.cursor/`, scripts in `.vibe-x/`), no global changes.
|
|
33
35
|
|
|
34
36
|
---
|
|
35
37
|
|
|
@@ -94,29 +96,14 @@ Switch to flex-column layout with collapsible sidebar.
|
|
|
94
96
|
|
|
95
97
|
## 🛠️ How to Commit
|
|
96
98
|
|
|
97
|
-
Call the checkpoint script after composing your message.
|
|
98
|
-
|
|
99
|
-
**Prefer project-local when present** (`.vibe-x/agent-better-checkpoint/` committed with project):
|
|
100
|
-
|
|
101
|
-
**macOS/Linux:**
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
# Project-local (if .vibe-x/agent-better-checkpoint/ exists)
|
|
105
|
-
.vibe-x/agent-better-checkpoint/checkpoint.sh "<commit-message>" "<user-prompt>"
|
|
106
|
-
|
|
107
|
-
# Or global fallback
|
|
108
|
-
~/.vibe-x/agent-better-checkpoint/scripts/checkpoint.sh "<commit-message>" "<user-prompt>"
|
|
109
|
-
```
|
|
99
|
+
Call the checkpoint script after composing your message. Both `.sh` and `.ps1` are always available — pick the one matching the current OS.
|
|
110
100
|
|
|
111
|
-
**
|
|
101
|
+
**Prefer project-local when present**, fall back to global:
|
|
112
102
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
# Or global fallback
|
|
118
|
-
powershell -File "$env:USERPROFILE/.vibe-x/agent-better-checkpoint/scripts/checkpoint.ps1" "<commit-message>" "<user-prompt>"
|
|
119
|
-
```
|
|
103
|
+
| OS | Project-local | Global fallback |
|
|
104
|
+
|----|--------------|-----------------|
|
|
105
|
+
| macOS/Linux | `.vibe-x/agent-better-checkpoint/checkpoint.sh` | `~/.vibe-x/agent-better-checkpoint/scripts/checkpoint.sh` |
|
|
106
|
+
| Windows | `powershell -File ".vibe-x\agent-better-checkpoint\checkpoint.ps1"` | `powershell -File "$env:USERPROFILE\.vibe-x\agent-better-checkpoint\scripts\checkpoint.ps1"` |
|
|
120
107
|
|
|
121
108
|
### Parameters:
|
|
122
109
|
|
|
@@ -129,7 +116,7 @@ powershell -File "$env:USERPROFILE/.vibe-x/agent-better-checkpoint/scripts/check
|
|
|
129
116
|
### Example (macOS/Linux):
|
|
130
117
|
|
|
131
118
|
```bash
|
|
132
|
-
|
|
119
|
+
.vibe-x/agent-better-checkpoint/checkpoint.sh \
|
|
133
120
|
"checkpoint(auth): add JWT token refresh logic
|
|
134
121
|
|
|
135
122
|
Implement automatic token refresh when access token expires.
|
|
@@ -140,7 +127,7 @@ Uses refresh token rotation for security." \
|
|
|
140
127
|
### Example (Windows):
|
|
141
128
|
|
|
142
129
|
```powershell
|
|
143
|
-
powershell -File "
|
|
130
|
+
powershell -File ".vibe-x\agent-better-checkpoint\checkpoint.ps1" `
|
|
144
131
|
"checkpoint(auth): add JWT token refresh logic`n`nImplement automatic token refresh when access token expires.`nUses refresh token rotation for security." `
|
|
145
132
|
"帮我实现 token 刷新机制"
|
|
146
133
|
```
|
|
@@ -177,4 +164,4 @@ This should feel natural — commit as you go, like any good developer.
|
|
|
177
164
|
|
|
178
165
|
---
|
|
179
166
|
|
|
180
|
-
**Version**: 0.
|
|
167
|
+
**Version**: 0.3.1
|