@a5c-ai/babysitter-cursor 5.0.1-staging.f6432257 → 5.0.1-staging.ff2c19f9

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.
Files changed (39) hide show
  1. package/bin/cli.js +8 -16
  2. package/bin/install-shared.js +236 -120
  3. package/bin/install.js +12 -28
  4. package/bin/uninstall.js +12 -27
  5. package/commands/doctor.md +5 -5
  6. package/commands/help.md +245 -244
  7. package/commands/observe.md +12 -12
  8. package/hooks/babysitter-proxied-session-start.ps1 +10 -194
  9. package/hooks/babysitter-proxied-session-start.sh +7 -170
  10. package/hooks/babysitter-proxied-stop.ps1 +12 -0
  11. package/hooks/babysitter-proxied-stop.sh +3 -0
  12. package/hooks/hooks-cursor.json +2 -2
  13. package/hooks.json +2 -2
  14. package/package.json +18 -20
  15. package/plugin.json +7 -5
  16. package/scripts/team-install.js +14 -72
  17. package/skills/cleanup/SKILL.md +21 -0
  18. package/skills/contrib/SKILL.md +34 -0
  19. package/skills/doctor/SKILL.md +5 -5
  20. package/skills/forever/SKILL.md +8 -0
  21. package/skills/help/SKILL.md +3 -2
  22. package/skills/observe/SKILL.md +1 -1
  23. package/skills/plugins/SKILL.md +257 -0
  24. package/skills/project-install/SKILL.md +18 -0
  25. package/skills/resume/SKILL.md +1 -1
  26. package/skills/retrospect/SKILL.md +48 -48
  27. package/skills/user-install/SKILL.md +3 -3
  28. package/skills/yolo/SKILL.md +8 -0
  29. package/versions.json +1 -1
  30. package/.cursor-plugin/plugin.json +0 -22
  31. package/.cursorrules +0 -55
  32. package/hooks/babysitter-proxied-stop-hook.ps1 +0 -125
  33. package/hooks/babysitter-proxied-stop-hook.sh +0 -112
  34. package/hooks/hooks-cursor.json.legacy +0 -21
  35. package/hooks/proxied-hooks.json +0 -22
  36. package/hooks/session-start.ps1 +0 -116
  37. package/hooks/session-start.sh +0 -106
  38. package/hooks/stop-hook.ps1 +0 -73
  39. package/hooks/stop-hook.sh +0 -61
package/bin/cli.js CHANGED
@@ -5,6 +5,8 @@ const path = require('path');
5
5
  const { spawnSync } = require('child_process');
6
6
 
7
7
  const PACKAGE_ROOT = path.resolve(__dirname, '..');
8
+ let shared;
9
+ try { shared = require('./install-shared'); } catch {}
8
10
 
9
11
  function printUsage() {
10
12
  console.error([
@@ -23,16 +25,10 @@ function parseInstallArgs(argv) {
23
25
  for (let i = 0; i < argv.length; i += 1) {
24
26
  const arg = argv[i];
25
27
  if (arg === '--global') {
26
- if (scope === 'workspace') {
27
- throw new Error('install accepts either --global or --workspace, not both');
28
- }
29
28
  scope = 'global';
30
29
  continue;
31
30
  }
32
31
  if (arg === '--workspace') {
33
- if (scope === 'global' && workspace !== null) {
34
- throw new Error('install accepts either --global or --workspace, not both');
35
- }
36
32
  scope = 'workspace';
37
33
  const next = argv[i + 1];
38
34
  if (next && !next.startsWith('-')) {
@@ -46,21 +42,14 @@ function parseInstallArgs(argv) {
46
42
  passthrough.push(arg);
47
43
  }
48
44
 
49
- return {
50
- scope,
51
- workspace,
52
- passthrough,
53
- };
45
+ return { scope, workspace, passthrough };
54
46
  }
55
47
 
56
48
  function runNodeScript(scriptPath, args, extraEnv = {}) {
57
49
  const result = spawnSync(process.execPath, [scriptPath, ...args], {
58
50
  cwd: process.cwd(),
59
51
  stdio: 'inherit',
60
- env: {
61
- ...process.env,
62
- ...extraEnv,
63
- },
52
+ env: { ...process.env, ...extraEnv },
64
53
  });
65
54
  process.exitCode = result.status ?? 1;
66
55
  }
@@ -74,6 +63,9 @@ function main() {
74
63
  }
75
64
 
76
65
  if (command === 'install') {
66
+ if (shared && typeof shared.harnessCliRoute === 'function' && shared.harnessCliRoute(rest, PACKAGE_ROOT, runNodeScript)) {
67
+ return;
68
+ }
77
69
  const parsed = parseInstallArgs(rest);
78
70
  if (parsed.scope === 'workspace') {
79
71
  const args = [];
@@ -84,7 +76,7 @@ function main() {
84
76
  runNodeScript(
85
77
  path.join(PACKAGE_ROOT, 'scripts', 'team-install.js'),
86
78
  args,
87
- { BABYSITTER_PACKAGE_ROOT: PACKAGE_ROOT },
79
+ { PLUGIN_PACKAGE_ROOT: PACKAGE_ROOT },
88
80
  );
89
81
  return;
90
82
  }
@@ -5,14 +5,205 @@ const os = require('os');
5
5
  const path = require('path');
6
6
  const { spawnSync } = require('child_process');
7
7
 
8
- const PLUGIN_NAME = 'babysitter';
8
+ const PLUGIN_NAME = "babysitter";
9
9
  const PLUGIN_CATEGORY = 'Coding';
10
+
11
+ function getUserHome() {
12
+ return os.homedir();
13
+ }
14
+
15
+ function getHarnessHome() {
16
+ return path.join(os.homedir(), '.cursor');
17
+ }
18
+
19
+ function getHomePluginRoot(scope) {
20
+ if (scope === 'workspace') return path.join(process.cwd(), '.a5c', 'plugins', PLUGIN_NAME);
21
+ return path.join(path.join(getHarnessHome(), 'plugins'), PLUGIN_NAME);
22
+ }
23
+
24
+ function getHomeMarketplacePath() {
25
+ return path.join(getHarnessHome(), 'plugins', 'marketplace.json');
26
+ }
27
+
28
+ function writeFileIfChanged(filePath, contents) {
29
+ try {
30
+ const existing = fs.readFileSync(filePath, 'utf8');
31
+ if (existing === contents) return false;
32
+ } catch {}
33
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
34
+ fs.writeFileSync(filePath, contents);
35
+ return true;
36
+ }
37
+
38
+ function copyRecursive(src, dest) {
39
+ fs.mkdirSync(dest, { recursive: true });
40
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
41
+ if (entry.name === 'node_modules' || entry.name === '.git') continue;
42
+ const s = path.join(src, entry.name);
43
+ const d = path.join(dest, entry.name);
44
+ if (entry.isDirectory()) {
45
+ copyRecursive(s, d);
46
+ } else {
47
+ fs.copyFileSync(s, d);
48
+ }
49
+ }
50
+ }
51
+
52
+ function copyPluginBundle(packageRoot, pluginRoot) {
53
+ const bundleEntries = fs.readdirSync(packageRoot).filter(
54
+ e => !['node_modules', '.git', 'test', 'dist'].includes(e)
55
+ );
56
+ fs.mkdirSync(pluginRoot, { recursive: true });
57
+ for (const entry of bundleEntries) {
58
+ const src = path.join(packageRoot, entry);
59
+ const dest = path.join(pluginRoot, entry);
60
+ const stat = fs.statSync(src);
61
+ if (stat.isDirectory()) {
62
+ copyRecursive(src, dest);
63
+ } else {
64
+ fs.copyFileSync(src, dest);
65
+ }
66
+ }
67
+ }
68
+
69
+ function readJson(filePath) {
70
+ try {
71
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
72
+ } catch {
73
+ return null;
74
+ }
75
+ }
76
+
77
+ function writeJson(filePath, value) {
78
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
79
+ fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\n');
80
+ }
81
+
82
+ function ensureExecutable(filePath) {
83
+ try {
84
+ fs.chmodSync(filePath, 0o755);
85
+ } catch {}
86
+ }
87
+
88
+ function normalizeMarketplaceSourcePath(source, marketplacePath) {
89
+ if (typeof source === 'string') {
90
+ return path.relative(path.dirname(marketplacePath), source).replace(/\\/g, '/');
91
+ }
92
+ return source;
93
+ }
94
+
95
+ function ensureMarketplaceEntry(marketplacePath, pluginRoot) {
96
+ let marketplace = readJson(marketplacePath) || {
97
+ name: "a5c.ai",
98
+ plugins: [],
99
+ };
100
+ if (!Array.isArray(marketplace.plugins)) marketplace.plugins = [];
101
+ const idx = marketplace.plugins.findIndex(p => p.name === PLUGIN_NAME);
102
+ const relSource = './' + normalizeMarketplaceSourcePath(pluginRoot, marketplacePath);
103
+ const entry = {
104
+ name: PLUGIN_NAME,
105
+ source: relSource,
106
+ description: "Orchestrate complex, multi-step workflows with event-sourced state management, hook-based extensibility, and human-in-the-loop approval",
107
+ version: "5.0.0",
108
+ author: { name: "a5c.ai" },
109
+ };
110
+ if (idx >= 0) marketplace.plugins[idx] = entry;
111
+ else marketplace.plugins.push(entry);
112
+ writeJson(marketplacePath, marketplace);
113
+ }
114
+
115
+ function removeMarketplaceEntry(marketplacePath) {
116
+ const marketplace = readJson(marketplacePath);
117
+ if (!marketplace || !Array.isArray(marketplace.plugins)) return;
118
+ marketplace.plugins = marketplace.plugins.filter(p => p.name !== PLUGIN_NAME);
119
+ writeJson(marketplacePath, marketplace);
120
+ }
121
+
122
+ function warnWindowsHooks() {
123
+ if (process.platform === 'win32') {
124
+ console.warn('[' + PLUGIN_NAME + '] Windows detected — shell hooks (.sh) require Git Bash or WSL.');
125
+ }
126
+ }
127
+
128
+ function runPostInstall(pluginRoot) {
129
+ const postInstall = path.join(pluginRoot, 'scripts', 'post-install.js');
130
+ if (fs.existsSync(postInstall)) {
131
+ spawnSync(process.execPath, [postInstall], {
132
+ cwd: pluginRoot, stdio: 'inherit',
133
+ env: { ...process.env, PLUGIN_ROOT: pluginRoot },
134
+ });
135
+ }
136
+ }
137
+
138
+ function getGlobalStateDir() {
139
+ return process.env.BABYSITTER_GLOBAL_STATE_DIR || path.join(getUserHome(), '.a5c');
140
+ }
141
+
142
+ function resolveCliCommand(packageRoot) {
143
+ try {
144
+ const result = spawnSync('babysitter', ['--version'], { stdio: 'pipe', timeout: 10000 });
145
+ if (result.status === 0) return 'babysitter';
146
+ } catch {}
147
+ const versionsPath = path.join(packageRoot, 'versions.json');
148
+ const versions = readJson(versionsPath) || {};
149
+ const ver = versions.sdkVersion || 'latest';
150
+ return `npx -y @a5c-ai/babysitter-sdk@${ver}`;
151
+ }
152
+
153
+ function runCli(packageRoot, cliArgs, options = {}) {
154
+ const cmd = resolveCliCommand(packageRoot);
155
+ const parts = cmd.split(' ');
156
+ const result = spawnSync(parts[0], [...parts.slice(1), ...cliArgs], {
157
+ stdio: options.stdio || 'inherit',
158
+ timeout: options.timeout || 120000,
159
+ cwd: options.cwd || process.cwd(),
160
+ env: { ...process.env, ...options.env },
161
+ });
162
+ return result;
163
+ }
164
+
165
+ function ensureGlobalProcessLibrary(packageRoot) {
166
+ const stateDir = getGlobalStateDir();
167
+ const activeFile = path.join(stateDir, 'active', 'process-library.json');
168
+ let active = readJson(activeFile);
169
+ if (active && active.binding && active.binding.dir) {
170
+ return active;
171
+ }
172
+ const defaultSpec = readJson(path.join(stateDir, 'process-library-defaults.json'));
173
+ const cloneDir = defaultSpec && defaultSpec.cloneDir
174
+ ? defaultSpec.cloneDir
175
+ : path.join(stateDir, 'process-library', PLUGIN_NAME + '-repo');
176
+ runCli(packageRoot, [
177
+ 'process-library:clone',
178
+ '--dir', cloneDir,
179
+ '--state-dir', stateDir,
180
+ '--json',
181
+ ], { stdio: 'pipe' });
182
+ runCli(packageRoot, [
183
+ 'process-library:use',
184
+ '--dir', cloneDir,
185
+ '--state-dir', stateDir,
186
+ '--json',
187
+ ], { stdio: 'pipe' });
188
+ active = readJson(activeFile);
189
+ return {
190
+ binding: active && active.binding ? active.binding : { dir: cloneDir },
191
+ defaultSpec: defaultSpec || { cloneDir },
192
+ stateFile: activeFile,
193
+ };
194
+ }
195
+
196
+
197
+ // Cursor-specific install surface.
198
+ // Appended after the compiler base and SDK surface — can override base functions.
199
+
10
200
  const HOOK_SCRIPT_NAMES = [
11
- 'session-start.sh',
12
- 'session-start.ps1',
13
- 'stop-hook.sh',
14
- 'stop-hook.ps1',
201
+ 'babysitter-proxied-session-start.sh',
202
+ 'babysitter-proxied-session-start.ps1',
203
+ 'babysitter-proxied-stop.sh',
204
+ 'babysitter-proxied-stop.ps1',
15
205
  ];
206
+
16
207
  const DEFAULT_MARKETPLACE = {
17
208
  name: 'local-plugins',
18
209
  interface: {
@@ -20,10 +211,12 @@ const DEFAULT_MARKETPLACE = {
20
211
  },
21
212
  plugins: [],
22
213
  };
214
+
23
215
  const MANAGED_HOOKS_CONFIG_PATHS = [
24
216
  path.join('hooks', 'hooks-cursor.json'),
25
217
  'hooks.json',
26
218
  ];
219
+
27
220
  const PLUGIN_BUNDLE_ENTRIES = [
28
221
  '.cursor-plugin',
29
222
  'plugin.json',
@@ -40,19 +233,6 @@ function getCursorHome() {
40
233
  return path.join(os.homedir(), '.cursor');
41
234
  }
42
235
 
43
- function getUserHome() {
44
- if (process.env.USERPROFILE) return path.resolve(process.env.USERPROFILE);
45
- if (process.env.HOME) return path.resolve(process.env.HOME);
46
- return os.homedir();
47
- }
48
-
49
- function getGlobalStateDir() {
50
- if (process.env.BABYSITTER_GLOBAL_STATE_DIR) {
51
- return path.resolve(process.env.BABYSITTER_GLOBAL_STATE_DIR);
52
- }
53
- return path.join(getUserHome(), '.a5c');
54
- }
55
-
56
236
  function getHomePluginRoot() {
57
237
  if (process.env.BABYSITTER_CURSOR_PLUGIN_DIR) {
58
238
  return path.resolve(process.env.BABYSITTER_CURSOR_PLUGIN_DIR, PLUGIN_NAME);
@@ -67,18 +247,6 @@ function getHomeMarketplacePath() {
67
247
  return path.join(getUserHome(), '.agents', 'plugins', 'marketplace.json');
68
248
  }
69
249
 
70
- function writeFileIfChanged(filePath, contents) {
71
- if (fs.existsSync(filePath)) {
72
- const current = fs.readFileSync(filePath, 'utf8');
73
- if (current === contents) {
74
- return false;
75
- }
76
- }
77
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
78
- fs.writeFileSync(filePath, contents, 'utf8');
79
- return true;
80
- }
81
-
82
250
  function copyRecursive(src, dest) {
83
251
  const stat = fs.statSync(src);
84
252
  if (stat.isDirectory()) {
@@ -90,6 +258,7 @@ function copyRecursive(src, dest) {
90
258
  return;
91
259
  }
92
260
 
261
+ // Strip UTF-8 BOM from SKILL.md files
93
262
  if (path.basename(src) === 'SKILL.md') {
94
263
  const file = fs.readFileSync(src);
95
264
  const hasBom = file.length >= 3 && file[0] === 0xef && file[1] === 0xbb && file[2] === 0xbf;
@@ -116,14 +285,6 @@ function copyPluginBundle(packageRoot, pluginRoot) {
116
285
  }
117
286
  }
118
287
 
119
- function ensureExecutable(filePath) {
120
- try {
121
- fs.chmodSync(filePath, 0o755);
122
- } catch {
123
- // Best-effort only. Windows and some filesystems may ignore mode changes.
124
- }
125
- }
126
-
127
288
  function normalizeMarketplaceSourcePath(marketplacePath, pluginSourcePath) {
128
289
  let next = pluginSourcePath;
129
290
  if (path.isAbsolute(next)) {
@@ -136,24 +297,6 @@ function normalizeMarketplaceSourcePath(marketplacePath, pluginSourcePath) {
136
297
  return next;
137
298
  }
138
299
 
139
- function readJson(filePath) {
140
- return JSON.parse(fs.readFileSync(filePath, 'utf8'));
141
- }
142
-
143
- function getManagedHooksConfigPath(packageRoot) {
144
- for (const relativePath of MANAGED_HOOKS_CONFIG_PATHS) {
145
- const candidate = path.join(packageRoot, relativePath);
146
- if (fs.existsSync(candidate)) {
147
- return candidate;
148
- }
149
- }
150
- return null;
151
- }
152
-
153
- function writeJson(filePath, value) {
154
- writeFileIfChanged(filePath, `${JSON.stringify(value, null, 2)}\n`);
155
- }
156
-
157
300
  function normalizeMarketplaceName(name) {
158
301
  const raw = String(name || '').trim();
159
302
  const sanitized = raw
@@ -208,6 +351,16 @@ function removeMarketplaceEntry(marketplacePath) {
208
351
  writeJson(marketplacePath, marketplace);
209
352
  }
210
353
 
354
+ function getManagedHooksConfigPath(packageRoot) {
355
+ for (const relativePath of MANAGED_HOOKS_CONFIG_PATHS) {
356
+ const candidate = path.join(packageRoot, relativePath);
357
+ if (fs.existsSync(candidate)) {
358
+ return candidate;
359
+ }
360
+ }
361
+ return null;
362
+ }
363
+
211
364
  function mergeManagedHooksConfig(packageRoot, cursorHome) {
212
365
  const hooksJsonPath = getManagedHooksConfigPath(packageRoot);
213
366
  if (!hooksJsonPath) return;
@@ -313,62 +466,6 @@ function installCursorSurface(packageRoot, cursorHome) {
313
466
  }
314
467
  }
315
468
 
316
- function resolveBabysitterCommand(packageRoot) {
317
- if (process.env.BABYSITTER_SDK_CLI) {
318
- return {
319
- command: process.execPath,
320
- argsPrefix: [path.resolve(process.env.BABYSITTER_SDK_CLI)],
321
- };
322
- }
323
- try {
324
- return {
325
- command: process.execPath,
326
- argsPrefix: [
327
- require.resolve('@a5c-ai/babysitter-sdk/dist/cli/main.js', {
328
- paths: [packageRoot],
329
- }),
330
- ],
331
- };
332
- } catch {
333
- return {
334
- command: 'babysitter',
335
- argsPrefix: [],
336
- };
337
- }
338
- }
339
-
340
- function runBabysitterCli(packageRoot, cliArgs, options = {}) {
341
- const resolved = resolveBabysitterCommand(packageRoot);
342
- const result = spawnSync(resolved.command, [...resolved.argsPrefix, ...cliArgs], {
343
- cwd: options.cwd || process.cwd(),
344
- stdio: ['ignore', 'pipe', 'pipe'],
345
- encoding: 'utf8',
346
- env: {
347
- ...process.env,
348
- ...(options.env || {}),
349
- },
350
- });
351
- if (result.status !== 0) {
352
- const stderr = (result.stderr || '').trim();
353
- const stdout = (result.stdout || '').trim();
354
- throw new Error(
355
- `babysitter ${cliArgs.join(' ')} failed` +
356
- (stderr ? `: ${stderr}` : stdout ? `: ${stdout}` : ''),
357
- );
358
- }
359
- return result.stdout;
360
- }
361
-
362
- function ensureGlobalProcessLibrary(packageRoot) {
363
- return JSON.parse(
364
- runBabysitterCli(
365
- packageRoot,
366
- ['process-library:active', '--state-dir', getGlobalStateDir(), '--json'],
367
- { cwd: packageRoot },
368
- ),
369
- );
370
- }
371
-
372
469
  function warnWindowsHooks() {
373
470
  if (process.platform !== 'win32') {
374
471
  return;
@@ -377,18 +474,37 @@ function warnWindowsHooks() {
377
474
  console.warn(`[${PLUGIN_NAME}] Both bash (.sh) and PowerShell (.ps1) hook scripts are included.`);
378
475
  }
379
476
 
477
+
380
478
  module.exports = {
381
- copyPluginBundle,
479
+ PLUGIN_NAME,
480
+ PLUGIN_CATEGORY,
481
+ getUserHome,
482
+ getHarnessHome,
483
+ writeFileIfChanged,
484
+ readJson,
485
+ writeJson,
486
+ ensureExecutable,
487
+ runPostInstall,
488
+ getGlobalStateDir,
489
+ resolveCliCommand,
490
+ runCli,
382
491
  ensureGlobalProcessLibrary,
383
- ensureMarketplaceEntry,
384
- getManagedHooksConfigPath,
492
+ HOOK_SCRIPT_NAMES,
493
+ DEFAULT_MARKETPLACE,
494
+ MANAGED_HOOKS_CONFIG_PATHS,
495
+ PLUGIN_BUNDLE_ENTRIES,
385
496
  getCursorHome,
386
- getHomeMarketplacePath,
387
497
  getHomePluginRoot,
388
- installCursorSurface,
389
- removeManagedHooks,
498
+ getHomeMarketplacePath,
499
+ copyRecursive,
500
+ copyPluginBundle,
501
+ normalizeMarketplaceSourcePath,
502
+ normalizeMarketplaceName,
503
+ ensureMarketplaceEntry,
390
504
  removeMarketplaceEntry,
505
+ getManagedHooksConfigPath,
506
+ mergeManagedHooksConfig,
507
+ removeManagedHooks,
508
+ installCursorSurface,
391
509
  warnWindowsHooks,
392
- writeJson,
393
- normalizeMarketplaceName,
394
510
  };
package/bin/install.js CHANGED
@@ -2,43 +2,27 @@
2
2
  'use strict';
3
3
 
4
4
  const path = require('path');
5
- const {
6
- copyPluginBundle,
7
- ensureGlobalProcessLibrary,
8
- ensureMarketplaceEntry,
9
- getCursorHome,
10
- getHomeMarketplacePath,
11
- getHomePluginRoot,
12
- installCursorSurface,
13
- warnWindowsHooks,
14
- } = require('./install-shared');
5
+ const shared = require('./install-shared');
15
6
 
16
7
  const PACKAGE_ROOT = path.resolve(__dirname, '..');
17
8
 
18
9
  function main() {
19
- const cursorHome = getCursorHome();
20
- const pluginRoot = getHomePluginRoot();
21
- const marketplacePath = getHomeMarketplacePath();
10
+ const pluginRoot = shared.getHomePluginRoot();
11
+ const marketplacePath = shared.getHomeMarketplacePath();
22
12
 
23
- console.log(`[babysitter] Installing plugin to ${pluginRoot}`);
13
+ console.log(`[${shared.PLUGIN_NAME}] Installing plugin to ${pluginRoot}`);
24
14
 
25
15
  try {
26
- copyPluginBundle(PACKAGE_ROOT, pluginRoot);
27
- ensureMarketplaceEntry(marketplacePath, pluginRoot);
28
- installCursorSurface(PACKAGE_ROOT, cursorHome);
29
-
30
- const active = ensureGlobalProcessLibrary(PACKAGE_ROOT);
31
- console.log(`[babysitter] marketplace: ${marketplacePath}`);
32
- console.log(`[babysitter] process library: ${active.binding?.dir}`);
33
- if (active.defaultSpec?.cloneDir) {
34
- console.log(`[babysitter] process library clone: ${active.defaultSpec.cloneDir}`);
16
+ shared.copyPluginBundle(PACKAGE_ROOT, pluginRoot);
17
+ shared.ensureMarketplaceEntry(marketplacePath, pluginRoot);
18
+ if (typeof shared.harnessInstall === 'function') {
19
+ shared.harnessInstall(PACKAGE_ROOT, pluginRoot);
35
20
  }
36
- console.log(`[babysitter] process library state: ${active.stateFile}`);
37
- warnWindowsHooks();
38
- console.log('[babysitter] Installation complete!');
39
- console.log('[babysitter] Restart Cursor to pick up the installed plugin and config changes.');
21
+ shared.runPostInstall && shared.runPostInstall(pluginRoot);
22
+ console.log(`[${shared.PLUGIN_NAME}] Installation complete!`);
23
+ console.log(`[${shared.PLUGIN_NAME}] Restart your IDE/CLI to pick up the plugin.`);
40
24
  } catch (err) {
41
- console.error(`[babysitter] Failed to install plugin: ${err.message}`);
25
+ console.error(`[${shared.PLUGIN_NAME}] Failed to install: ${err.message}`);
42
26
  process.exitCode = 1;
43
27
  }
44
28
  }
package/bin/uninstall.js CHANGED
@@ -1,40 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
+ const path = require('path');
4
5
  const fs = require('fs');
5
- const {
6
- getCursorHome,
7
- getHomeMarketplacePath,
8
- getHomePluginRoot,
9
- removeManagedHooks,
10
- removeMarketplaceEntry,
11
- } = require('./install-shared');
6
+ const shared = require('./install-shared');
12
7
 
13
8
  function main() {
14
- const cursorHome = getCursorHome();
15
- const pluginRoot = getHomePluginRoot();
16
- const marketplacePath = getHomeMarketplacePath();
17
- let removedPlugin = false;
9
+ const pluginRoot = shared.getHomePluginRoot();
18
10
 
19
- if (fs.existsSync(pluginRoot)) {
20
- try {
21
- fs.rmSync(pluginRoot, { recursive: true, force: true });
22
- console.log(`[babysitter] Removed ${pluginRoot}`);
23
- removedPlugin = true;
24
- } catch (err) {
25
- console.warn(`[babysitter] Warning: Could not remove plugin directory ${pluginRoot}: ${err.message}`);
26
- }
27
- }
28
-
29
- removeMarketplaceEntry(marketplacePath);
30
- removeManagedHooks(cursorHome);
31
-
32
- if (!removedPlugin) {
33
- console.log('[babysitter] Plugin directory not found, config and hooks cleaned if present.');
11
+ if (!fs.existsSync(pluginRoot)) {
12
+ console.log(`[${shared.PLUGIN_NAME}] Plugin not installed at ${pluginRoot}`);
34
13
  return;
35
14
  }
36
15
 
37
- console.log('[babysitter] Restart Cursor to complete uninstallation.');
16
+ try {
17
+ fs.rmSync(pluginRoot, { recursive: true, force: true });
18
+ console.log(`[${shared.PLUGIN_NAME}] Uninstalled from ${pluginRoot}`);
19
+ } catch (err) {
20
+ console.error(`[${shared.PLUGIN_NAME}] Failed to uninstall: ${err.message}`);
21
+ process.exitCode = 1;
22
+ }
38
23
  }
39
24
 
40
25
  main();
@@ -362,13 +362,13 @@ Mark as FAIL if:
362
362
  - Parse the output and inspect the `resolvedFrom` field. Classify as follows:
363
363
  - `resolvedFrom: "pid-marker"` → mark as PASS ("Session ID derives from the live Claude Code ancestor process -- authoritative").
364
364
  - `resolvedFrom: "env-file"` → mark as PASS with a note ("CLAUDE_ENV_FILE was used; typically healthy").
365
- - `resolvedFrom: "env-var"` → mark as WARN ("`BABYSITTER_SESSION_ID` is set without a corroborating PID marker. Likely stale from a prior Claude Code session -- see GitHub issue #130").
366
- - Remediation: run `babysitter session:cleanup` and start a fresh Claude Code session, or `unset BABYSITTER_SESSION_ID` before invoking babysitter.
365
+ - `resolvedFrom: "env-var"` → mark as WARN ("`AGENT_SESSION_ID` is set without a corroborating PID marker. Likely stale from a prior Claude Code session -- see GitHub issue #130").
366
+ - Remediation: run `babysitter session:cleanup` and start a fresh Claude Code session, or `unset AGENT_SESSION_ID` before invoking babysitter.
367
367
  - `resolvedFrom: "none"` → mark as ERROR ("No session ID resolvable. Either no session-start hook fired, or the ancestor walk failed").
368
368
 
369
369
  **Env-var shadow check:**
370
370
  - Independently inspect `envVarPresent` and `envVarMatches` in the output.
371
- - If `envVarPresent && !envVarMatches`, mark as WARN ("`BABYSITTER_SESSION_ID` in env does not match the resolved session ID; a stale value is shadowing the authoritative one. Unset the env var").
371
+ - If `envVarPresent && !envVarMatches`, mark as WARN ("`AGENT_SESSION_ID` in env does not match the resolved session ID; a stale value is shadowing the authoritative one. Unset the env var").
372
372
 
373
373
  ---
374
374
 
@@ -390,7 +390,7 @@ Mark as FAIL if:
390
390
 
391
391
  - Enumerate files in `~/.a5c/` matching the pattern `current-session-*-pid-*`.
392
392
  - Count markers per harness (derived from the filename).
393
- - If more than one live marker exists for the same harness, mark as INFO ("Multiple live Claude Code / harness sessions detected; ensure each shell scopes `BABYSITTER_SESSION_ID` appropriately -- the PID marker handles this automatically").
393
+ - If more than one live marker exists for the same harness, mark as INFO ("Multiple live Claude Code / harness sessions detected; ensure each shell scopes `AGENT_SESSION_ID` appropriately -- the PID marker handles this automatically").
394
394
  - Otherwise mark as PASS.
395
395
 
396
396
  ---
@@ -501,7 +501,7 @@ babysitter session:cleanup --dry-run # preview
501
501
  babysitter session:cleanup # apply
502
502
 
503
503
  # 2. Unset a stale env var
504
- unset BABYSITTER_SESSION_ID
504
+ unset AGENT_SESSION_ID
505
505
 
506
506
  # 3. Re-bind a run explicitly if needed
507
507
  babysitter session:resume --session-id <fresh-id> --state-dir ~/.a5c --run-id <runId> --runs-dir .a5c/runs