@a5c-ai/babysitter-cursor 0.1.5-staging.fd3ab4c2 → 5.0.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.
Files changed (46) 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 +11 -27
  5. package/commands/call.md +7 -7
  6. package/commands/contrib.md +31 -31
  7. package/commands/doctor.md +5 -5
  8. package/commands/forever.md +6 -6
  9. package/commands/help.md +245 -244
  10. package/commands/observe.md +12 -12
  11. package/commands/plan.md +7 -7
  12. package/commands/plugins.md +249 -249
  13. package/commands/project-install.md +10 -10
  14. package/commands/resume.md +8 -8
  15. package/commands/retrospect.md +55 -55
  16. package/commands/user-install.md +10 -10
  17. package/commands/yolo.md +7 -7
  18. package/hooks/babysitter-proxied-session-start.ps1 +12 -0
  19. package/hooks/babysitter-proxied-session-start.sh +11 -0
  20. package/hooks/babysitter-proxied-stop.ps1 +12 -0
  21. package/hooks/babysitter-proxied-stop.sh +3 -0
  22. package/hooks/hooks-cursor.json +4 -4
  23. package/hooks.json +4 -4
  24. package/package.json +20 -21
  25. package/plugin.json +7 -5
  26. package/scripts/create-release-tag.mjs +18 -0
  27. package/scripts/publish-from-tag.mjs +12 -0
  28. package/scripts/team-install.js +14 -72
  29. package/skills/babysit/SKILL.md +2 -0
  30. package/skills/cleanup/SKILL.md +21 -0
  31. package/skills/contrib/SKILL.md +34 -0
  32. package/skills/doctor/SKILL.md +5 -5
  33. package/skills/forever/SKILL.md +8 -0
  34. package/skills/help/SKILL.md +3 -2
  35. package/skills/observe/SKILL.md +1 -1
  36. package/skills/plugins/SKILL.md +257 -0
  37. package/skills/project-install/SKILL.md +18 -0
  38. package/skills/yolo/SKILL.md +8 -0
  39. package/versions.json +2 -1
  40. package/.cursor-plugin/plugin.json +0 -22
  41. package/.cursorrules +0 -55
  42. package/hooks/session-start.ps1 +0 -115
  43. package/hooks/session-start.sh +0 -105
  44. package/hooks/stop-hook.ps1 +0 -72
  45. package/hooks/stop-hook.sh +0 -64
  46. package/scripts/sync-command-surfaces.js +0 -62
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,
492
+ PLUGIN_BUNDLE_ENTRIES,
493
+ copyRecursive,
494
+ copyPluginBundle,
495
+ DEFAULT_MARKETPLACE,
496
+ normalizeMarketplaceSourcePath,
497
+ normalizeMarketplaceName,
383
498
  ensureMarketplaceEntry,
384
- getManagedHooksConfigPath,
499
+ removeMarketplaceEntry,
500
+ mergeManagedHooksConfig,
501
+ warnWindowsHooks,
502
+ HOOK_SCRIPT_NAMES,
503
+ MANAGED_HOOKS_CONFIG_PATHS,
385
504
  getCursorHome,
386
- getHomeMarketplacePath,
387
505
  getHomePluginRoot,
388
- installCursorSurface,
506
+ getHomeMarketplacePath,
507
+ getManagedHooksConfigPath,
389
508
  removeManagedHooks,
390
- removeMarketplaceEntry,
391
- warnWindowsHooks,
392
- writeJson,
393
- normalizeMarketplaceName,
509
+ installCursorSurface,
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
@@ -2,39 +2,23 @@
2
2
  'use strict';
3
3
 
4
4
  const fs = require('fs');
5
- const {
6
- getCursorHome,
7
- getHomeMarketplacePath,
8
- getHomePluginRoot,
9
- removeManagedHooks,
10
- removeMarketplaceEntry,
11
- } = require('./install-shared');
5
+ const shared = require('./install-shared');
12
6
 
13
7
  function main() {
14
- const cursorHome = getCursorHome();
15
- const pluginRoot = getHomePluginRoot();
16
- const marketplacePath = getHomeMarketplacePath();
17
- let removedPlugin = false;
8
+ const pluginRoot = shared.getHomePluginRoot();
18
9
 
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.');
10
+ if (!fs.existsSync(pluginRoot)) {
11
+ console.log(`[${shared.PLUGIN_NAME}] Plugin not installed at ${pluginRoot}`);
34
12
  return;
35
13
  }
36
14
 
37
- console.log('[babysitter] Restart Cursor to complete uninstallation.');
15
+ try {
16
+ fs.rmSync(pluginRoot, { recursive: true, force: true });
17
+ console.log(`[${shared.PLUGIN_NAME}] Uninstalled from ${pluginRoot}`);
18
+ } catch (err) {
19
+ console.error(`[${shared.PLUGIN_NAME}] Failed to uninstall: ${err.message}`);
20
+ process.exitCode = 1;
21
+ }
38
22
  }
39
23
 
40
24
  main();
package/commands/call.md CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- description: Orchestrate a babysitter run. use this command to start babysitting a complex workflow.
3
- argument-hint: Specific instructions for the run.
4
- allowed-tools: Read, Grep, Write, Task, Bash, Edit, Grep, Glob, WebFetch, WebSearch, Search, AskUserQuestion, TodoWrite, TodoRead, Skill, BashOutput, KillShell, MultiEdit, LS
5
- ---
6
-
7
- Invoke the babysitter:babysit skill (using the Skill tool) and follow its instructions (SKILL.md).
1
+ ---
2
+ description: Orchestrate a babysitter run. use this command to start babysitting a complex workflow.
3
+ argument-hint: Specific instructions for the run.
4
+ allowed-tools: Read, Grep, Write, Task, Bash, Edit, Grep, Glob, WebFetch, WebSearch, Search, AskUserQuestion, TodoWrite, TodoRead, Skill, BashOutput, KillShell, MultiEdit, LS
5
+ ---
6
+
7
+ Invoke the babysitter:babysit skill (using the Skill tool) and follow its instructions (SKILL.md).
@@ -1,33 +1,33 @@
1
- ---
2
- description: Submit feedback or contribute to babysitter project
3
- argument-hint: Specific instructions for the run.
4
- allowed-tools: Read, Grep, Write, Task, Bash, Edit, Grep, Glob, WebFetch, WebSearch, Search, AskUserQuestion, TodoWrite, TodoRead, Skill, BashOutput, KillShell, MultiEdit, LS
5
- ---
6
-
7
- Invoke the babysitter:babysit skill (using the Skill tool) and follow its instructions (SKILL.md).
8
-
9
- ## Process Routing
10
-
1
+ ---
2
+ description: Submit feedback or contribute to babysitter project
3
+ argument-hint: Specific instructions for the run.
4
+ allowed-tools: Read, Grep, Write, Task, Bash, Edit, Grep, Glob, WebFetch, WebSearch, Search, AskUserQuestion, TodoWrite, TodoRead, Skill, BashOutput, KillShell, MultiEdit, LS
5
+ ---
6
+
7
+ Invoke the babysitter:babysit skill (using the Skill tool) and follow its instructions (SKILL.md).
8
+
9
+ ## Process Routing
10
+
11
11
  Contribution processes live under the active process library's `cradle/` directory. Resolve the active library root with `babysitter process-library:active --json` and route based on arguments:
12
-
13
- ### Issue-based (opens a GitHub issue in a5c-ai/babysitter)
14
- * **Bug report** → `cradle/bug-report.js#process` — Report a bug in the SDK, CLI, process library, etc.
15
- * **Feature request** → `cradle/feature-request.js#process` — Request a new feature or enhancement
16
- * **Documentation question** → `cradle/documentation-question.js#process` — Ask about undocumented behavior or missing docs
17
-
18
- ### PR-based (forks repo, creates branch, submits PR to a5c-ai/babysitter)
19
- * **Bugfix** → `cradle/bugfix.js#process` — User already has the fix for a bug
20
- * **Feature implementation** → `cradle/feature-implementation-contribute.js#process` — User already has a feature implementation
21
- * **Harness integration** → `cradle/feature-harness-integration-contribute.js#process` — User has a harness (CI/CD, IDE, editor) integration
22
- * **Library contribution** → `cradle/library-contribution.js#process` — New or improved process/skill/subagent for the library
23
- * **Documentation answer** → `cradle/documentation-contribute-answer.js#process` — User has an answer for an unanswered docs question
24
-
25
- ### Router (when arguments are empty or general)
26
- * **Contribute** → `cradle/contribute.js#process` — Explains contribution types and routes to the specific process
27
-
28
- ## Contribution Rules
29
-
30
- * PR-based contributions: fork the babysitter repo (a5c-ai/babysitter) for the user, ask to star if not already starred, perform changes, submit PR
31
- * Issue-based contributions: gather details, search for duplicates, review, then open an issue in a5c-ai/babysitter
32
- * Add breakpoints (permissions) before ALL gh actions (fork, star, submit PR/issue) to allow user review and cancellation
12
+
13
+ ### Issue-based (opens a GitHub issue in a5c-ai/babysitter)
14
+ * **Bug report** → `cradle/bug-report.js#process` — Report a bug in the SDK, CLI, process library, etc.
15
+ * **Feature request** → `cradle/feature-request.js#process` — Request a new feature or enhancement
16
+ * **Documentation question** → `cradle/documentation-question.js#process` — Ask about undocumented behavior or missing docs
17
+
18
+ ### PR-based (forks repo, creates branch, submits PR to a5c-ai/babysitter)
19
+ * **Bugfix** → `cradle/bugfix.js#process` — User already has the fix for a bug
20
+ * **Feature implementation** → `cradle/feature-implementation-contribute.js#process` — User already has a feature implementation
21
+ * **Harness integration** → `cradle/feature-harness-integration-contribute.js#process` — User has a harness (CI/CD, IDE, editor) integration
22
+ * **Library contribution** → `cradle/library-contribution.js#process` — New or improved process/skill/subagent for the library
23
+ * **Documentation answer** → `cradle/documentation-contribute-answer.js#process` — User has an answer for an unanswered docs question
24
+
25
+ ### Router (when arguments are empty or general)
26
+ * **Contribute** → `cradle/contribute.js#process` — Explains contribution types and routes to the specific process
27
+
28
+ ## Contribution Rules
29
+
30
+ * PR-based contributions: fork the babysitter repo (a5c-ai/babysitter) for the user, ask to star if not already starred, perform changes, submit PR
31
+ * Issue-based contributions: gather details, search for duplicates, review, then open an issue in a5c-ai/babysitter
32
+ * Add breakpoints (permissions) before ALL gh actions (fork, star, submit PR/issue) to allow user review and cancellation
33
33
  * If arguments are empty: use the `contribute.js` router process to show options and route accordingly