@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 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
- | Platform skill directory | `SKILL.md` — AI agent instructions |
114
- | Platform hook config | Stop hook registration |
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
- > **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.
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
- 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');
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
- copyFileSafe(checkpointSrc, checkpointDest);
167
- copyFileSafe(hookSrc, hookDest);
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
- console.log(` Scripts → ${scriptsDir}\\checkpoint.ps1`);
170
- console.log(` Hooks → ${hooksDir}\\check_uncommitted.ps1`);
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
- // Uninstall flow
345
- console.log(`\n[${aiPlatform === 'cursor' ? 'Cursor' : 'Claude Code'}] Uninstalling...`);
346
-
347
- if (aiPlatform === 'cursor') {
348
- uninstallCursorSkill();
349
- unregisterCursorHook();
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
- uninstallClaudeSkill();
352
- unregisterClaudeHook();
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
- // 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);
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
- registerClaudeHook(osType);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-x/agent-better-checkpoint",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
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.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, committed with project):** Check if `.vibe-x/agent-better-checkpoint/checkpoint.sh` exists in the workspace.
24
- **Global fallback:** Check if `~/.vibe-x/agent-better-checkpoint/scripts/checkpoint.sh` exists (macOS/Linux) or `$env:USERPROFILE/.vibe-x/agent-better-checkpoint/scripts/checkpoint.ps1` (Windows).
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.2.0
31
+ npx @vibe-x/agent-better-checkpoint@0.3.1
30
32
  ```
31
33
 
32
- This installs the global scripts and stop hook. Projects can also commit `.vibe-x/agent-better-checkpoint/` (config + scripts) for self-contained setup.
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. Determine the OS and use the appropriate command.
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
- **Windows (PowerShell):**
101
+ **Prefer project-local when present**, fall back to global:
112
102
 
113
- ```powershell
114
- # Project-local (if .vibe-x/agent-better-checkpoint/ exists)
115
- powershell -File ".\.vibe-x\agent-better-checkpoint\checkpoint.ps1" "<commit-message>" "<user-prompt>"
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
- ~/.vibe-x/agent-better-checkpoint/scripts/checkpoint.sh \
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 "$env:USERPROFILE/.vibe-x/agent-better-checkpoint/scripts/checkpoint.ps1" `
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.2.0
167
+ **Version**: 0.3.1