@vibe-x/agent-better-checkpoint 0.2.0 → 0.3.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 CHANGED
@@ -96,6 +96,28 @@ npx @vibe-x/agent-better-checkpoint --platform cursor
96
96
  npx @vibe-x/agent-better-checkpoint --platform claude
97
97
  ```
98
98
 
99
+ ### Project-local Install
100
+
101
+ Install scripts into your project for self-contained setup (commit with repo):
102
+
103
+ ```bash
104
+ cd /path/to/your/project
105
+ npx @vibe-x/agent-better-checkpoint --target .
106
+ ```
107
+
108
+ Or specify a target directory:
109
+
110
+ ```bash
111
+ npx @vibe-x/agent-better-checkpoint --target /path/to/your/project
112
+ ```
113
+
114
+ Uninstall project-local only:
115
+
116
+ ```bash
117
+ npx @vibe-x/agent-better-checkpoint --uninstall --target .
118
+ npx @vibe-x/agent-better-checkpoint --uninstall --target /path/to/project
119
+ ```
120
+
99
121
  ### Via [skills.sh](https://skills.sh)
100
122
 
101
123
  ```bash
package/bin/cli.mjs CHANGED
@@ -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> Install to specified project directory (. for cwd)
76
85
  --uninstall Remove installed files and hook registrations
77
86
  -h, --help Show this help message
78
87
  `);
@@ -234,6 +243,37 @@ function registerCursorHook(osType) {
234
243
  console.log(` Config → ${hooksPath}`);
235
244
  }
236
245
 
246
+ function installProjectLocal(targetDir, osType) {
247
+ const projectBase = join(resolve(targetDir), '.vibe-x', 'agent-better-checkpoint');
248
+ ensureDir(projectBase);
249
+
250
+ if (osType === 'unix') {
251
+ copyFileSafe(join(PLATFORM_DIR, 'unix', 'checkpoint.sh'), join(projectBase, 'checkpoint.sh'));
252
+ copyFileSafe(join(PLATFORM_DIR, 'unix', 'check_uncommitted.sh'), join(projectBase, 'check_uncommitted.sh'));
253
+ setExecutable(join(projectBase, 'checkpoint.sh'));
254
+ setExecutable(join(projectBase, 'check_uncommitted.sh'));
255
+ }
256
+ copyFileSafe(join(PLATFORM_DIR, 'win', 'checkpoint.ps1'), join(projectBase, 'checkpoint.ps1'));
257
+ copyFileSafe(join(PLATFORM_DIR, 'win', 'check_uncommitted.ps1'), join(projectBase, 'check_uncommitted.ps1'));
258
+
259
+ const configDest = join(projectBase, 'config.yml');
260
+ if (!existsSync(configDest) && existsSync(CONFIG_TEMPLATE)) {
261
+ copyFileSafe(CONFIG_TEMPLATE, configDest);
262
+ }
263
+
264
+ console.log(` Project → ${projectBase}/`);
265
+ }
266
+
267
+ function uninstallProjectLocal(targetDir) {
268
+ const projectBase = join(resolve(targetDir), '.vibe-x', 'agent-better-checkpoint');
269
+ if (existsSync(projectBase)) {
270
+ rmSync(projectBase, { recursive: true, force: true });
271
+ console.log(` Removed project-local: ${projectBase}`);
272
+ } else {
273
+ console.log(` ${projectBase} not found, nothing to remove`);
274
+ }
275
+ }
276
+
237
277
  function registerClaudeHook(osType) {
238
278
  const settingsPath = join(homedir(), '.claude', 'settings.json');
239
279
  let settings = readJsonFile(settingsPath) || {};
@@ -268,6 +308,12 @@ function registerClaudeHook(osType) {
268
308
  // Uninstall logic
269
309
  // ============================================================
270
310
 
311
+ function hasInstallation(platform) {
312
+ const home = homedir();
313
+ const skillDir = join(home, platform === 'cursor' ? '.cursor' : '.claude', 'skills', SKILL_NAME);
314
+ return existsSync(skillDir);
315
+ }
316
+
271
317
  function uninstallScripts() {
272
318
  if (existsSync(INSTALL_BASE)) {
273
319
  rmSync(INSTALL_BASE, { recursive: true, force: true });
@@ -331,8 +377,9 @@ function main() {
331
377
  const args = parseArgs(process.argv);
332
378
  const osType = getOSType();
333
379
  const aiPlatform = args.platform || detectAIPlatform();
380
+ const projectTargetDir = args.target ? resolve(args.target) : null;
334
381
 
335
- if (!aiPlatform) {
382
+ if (!aiPlatform && !projectTargetDir && !args.uninstall) {
336
383
  console.error(
337
384
  'Error: could not detect AI platform.\n' +
338
385
  'Please specify: npx @vibe-x/agent-better-checkpoint --platform cursor|claude'
@@ -341,38 +388,72 @@ function main() {
341
388
  }
342
389
 
343
390
  if (args.uninstall) {
344
- // Uninstall flow
345
- console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Uninstalling...`);
391
+ if (projectTargetDir) {
392
+ console.log('\n[Project-local] Uninstalling...');
393
+ uninstallProjectLocal(projectTargetDir);
394
+ }
346
395
 
347
- if (aiPlatform === 'cursor') {
348
- uninstallCursorSkill();
349
- unregisterCursorHook();
350
- } else {
351
- uninstallClaudeSkill();
352
- unregisterClaudeHook();
396
+ // 指定 --platform 时只清该平台;未指定时清理所有已安装的平台
397
+ const platforms = args.platform
398
+ ? [args.platform]
399
+ : ['cursor', 'claude'].filter(p => hasInstallation(p));
400
+
401
+ if (!projectTargetDir || args.platform) {
402
+ for (const p of platforms) {
403
+ console.log(`\n[${p === 'cursor' ? 'Cursor' : 'Claude Code'}] Uninstalling...`);
404
+ if (p === 'cursor') {
405
+ uninstallCursorSkill();
406
+ unregisterCursorHook();
407
+ } else {
408
+ uninstallClaudeSkill();
409
+ unregisterClaudeHook();
410
+ }
411
+ }
412
+ if (platforms.length > 0) {
413
+ uninstallScripts();
414
+ }
353
415
  }
354
416
 
355
- uninstallScripts();
356
- console.log(`\n✅ Uninstallation complete!`);
417
+ if (platforms.length === 0 && !projectTargetDir) {
418
+ console.log('\nNo installation found for any platform.');
419
+ }
420
+ console.log('\n✅ Uninstallation complete!');
357
421
  } else {
358
- // Install flow
359
- console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Installing... (OS: ${osType})`);
360
-
361
- installScripts(osType);
362
- installSkill(aiPlatform);
363
-
364
- if (aiPlatform === 'cursor') {
365
- registerCursorHook(osType);
422
+ if (projectTargetDir) {
423
+ if (!aiPlatform) {
424
+ console.error('Error: --target requires AI platform for global hook. Specify --platform cursor|claude');
425
+ process.exit(1);
426
+ }
427
+ console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Installing... (OS: ${osType})`);
428
+ installScripts(osType);
429
+ installSkill(aiPlatform);
430
+ if (aiPlatform === 'cursor') {
431
+ registerCursorHook(osType);
432
+ } else {
433
+ registerClaudeHook(osType);
434
+ }
435
+ installProjectLocal(projectTargetDir, osType);
366
436
  } else {
367
- registerClaudeHook(osType);
437
+ console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Installing... (OS: ${osType})`);
438
+ installScripts(osType);
439
+ installSkill(aiPlatform);
440
+ if (aiPlatform === 'cursor') {
441
+ registerCursorHook(osType);
442
+ } else {
443
+ registerClaudeHook(osType);
444
+ }
368
445
  }
369
446
 
370
- console.log(`\n✅ Installation complete!`);
371
- console.log(`\nInstalled components:`);
447
+ console.log('\n✅ Installation complete!');
448
+ console.log('\nInstalled components:');
372
449
  console.log(` 📜 Checkpoint script → ~/.vibe-x/agent-better-checkpoint/scripts/`);
373
450
  console.log(` 🔒 Stop hook → ~/.vibe-x/agent-better-checkpoint/hooks/stop/`);
374
451
  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! 🎉`);
452
+ if (projectTargetDir) {
453
+ const projectBase = join(resolve(projectTargetDir), '.vibe-x', 'agent-better-checkpoint');
454
+ console.log(` 📁 Project-local → ${projectBase}/`);
455
+ }
456
+ console.log('\nThe AI agent will now auto-commit with semantic messages. Happy coding! 🎉');
376
457
  }
377
458
  }
378
459
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-x/agent-better-checkpoint",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Semantic Git checkpoint commits for AI coding sessions",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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.2.0"
6
+ version: "0.3.0"
7
7
  author: "alienzhou"
8
8
  category: "version-control"
9
9
  ---
@@ -26,10 +26,10 @@ Before your first commit, verify the checkpoint scripts are available:
26
26
  If neither exists, run:
27
27
 
28
28
  ```bash
29
- npx @vibe-x/agent-better-checkpoint@0.2.0
29
+ npx @vibe-x/agent-better-checkpoint@0.3.0
30
30
  ```
31
31
 
32
- This installs the global scripts and stop hook. Projects can also commit `.vibe-x/agent-better-checkpoint/` (config + scripts) for self-contained setup.
32
+ This installs the global scripts and stop hook. For self-contained setup (commit with project), add `--target .` or `--target <path>`.
33
33
 
34
34
  ---
35
35
 
@@ -177,4 +177,4 @@ This should feel natural — commit as you go, like any good developer.
177
177
 
178
178
  ---
179
179
 
180
- **Version**: 0.2.0
180
+ **Version**: 0.3.0