@a5c-ai/babysitter-codex 0.1.6-staging.060a3463
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/.codex/config.toml +24 -0
- package/.codex/hooks/babysitter-session-start.sh +15 -0
- package/.codex/hooks/babysitter-stop-hook.sh +15 -0
- package/.codex/hooks/user-prompt-submit.sh +15 -0
- package/.codex/hooks.json +37 -0
- package/.codex/skills/babysit/SKILL.md +110 -0
- package/README.md +156 -0
- package/SKILL.md +111 -0
- package/agents/openai.yaml +4 -0
- package/babysitter.lock.json +18 -0
- package/bin/postinstall.js +415 -0
- package/bin/uninstall.js +80 -0
- package/package.json +46 -0
- package/prompts/README.md +28 -0
- package/prompts/assimilate.md +9 -0
- package/prompts/call.md +12 -0
- package/prompts/doctor.md +9 -0
- package/prompts/forever.md +8 -0
- package/prompts/help.md +8 -0
- package/prompts/issue.md +9 -0
- package/prompts/model.md +8 -0
- package/prompts/observe.md +8 -0
- package/prompts/plan.md +11 -0
- package/prompts/project-install.md +8 -0
- package/prompts/resume.md +8 -0
- package/prompts/retrospect.md +8 -0
- package/prompts/team-install.md +8 -0
- package/prompts/user-install.md +8 -0
- package/prompts/yolo.md +8 -0
- package/scripts/team-install.js +439 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* postinstall.js
|
|
6
|
+
*
|
|
7
|
+
* Installs the Codex-facing Babysitter skill bundle globally under CODEX_HOME,
|
|
8
|
+
* installs optional mode prompt aliases such as `/call` and `/plan`,
|
|
9
|
+
* clones/updates the process library into ~/.a5c via the SDK CLI, and
|
|
10
|
+
* optionally onboards the current workspace when npm was run from inside a
|
|
11
|
+
* repo.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const os = require('os');
|
|
17
|
+
const { spawnSync } = require('child_process');
|
|
18
|
+
|
|
19
|
+
const SKILL_NAME = 'babysit';
|
|
20
|
+
const LEGACY_SKILL_NAME = 'babysitter-codex';
|
|
21
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
22
|
+
const IS_WIN = process.platform === 'win32';
|
|
23
|
+
const INSTALL_ENTRIES = [
|
|
24
|
+
{ source: 'SKILL.md', required: true },
|
|
25
|
+
{ source: 'README.md', required: true },
|
|
26
|
+
{ source: 'agents', required: true },
|
|
27
|
+
{ source: 'prompts', required: true },
|
|
28
|
+
{ source: '.codex', required: true },
|
|
29
|
+
{ source: 'scripts', required: true },
|
|
30
|
+
{ source: 'babysitter.lock.json', required: true },
|
|
31
|
+
];
|
|
32
|
+
const LEGACY_PROMPT_NAMES = ['babysit.md'];
|
|
33
|
+
|
|
34
|
+
function getCodexHome() {
|
|
35
|
+
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
36
|
+
return path.join(os.homedir(), '.codex');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getGlobalStateDir() {
|
|
40
|
+
if (process.env.BABYSITTER_GLOBAL_STATE_DIR) {
|
|
41
|
+
return path.resolve(process.env.BABYSITTER_GLOBAL_STATE_DIR);
|
|
42
|
+
}
|
|
43
|
+
return path.join(os.homedir(), '.a5c');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function readJson(filePath) {
|
|
47
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function writeFileIfChanged(filePath, contents) {
|
|
51
|
+
if (fs.existsSync(filePath)) {
|
|
52
|
+
const current = fs.readFileSync(filePath, 'utf8');
|
|
53
|
+
if (current === contents) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
58
|
+
fs.writeFileSync(filePath, contents, 'utf8');
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function copyRecursive(src, dest) {
|
|
63
|
+
const stat = fs.statSync(src);
|
|
64
|
+
if (stat.isDirectory()) {
|
|
65
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
66
|
+
for (const entry of fs.readdirSync(src)) {
|
|
67
|
+
if (['node_modules', '.a5c', '.git', 'test', '.gitignore'].includes(entry)) continue;
|
|
68
|
+
copyRecursive(path.join(src, entry), path.join(dest, entry));
|
|
69
|
+
}
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (path.basename(src) === 'SKILL.md') {
|
|
74
|
+
const file = fs.readFileSync(src);
|
|
75
|
+
const hasBom = file.length >= 3 && file[0] === 0xef && file[1] === 0xbb && file[2] === 0xbf;
|
|
76
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
77
|
+
fs.writeFileSync(dest, hasBom ? file.subarray(3) : file);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
82
|
+
fs.copyFileSync(src, dest);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function listPromptEntries() {
|
|
86
|
+
const promptsDir = path.join(PACKAGE_ROOT, 'prompts');
|
|
87
|
+
if (!fs.existsSync(promptsDir)) {
|
|
88
|
+
throw new Error(`required prompt alias directory is missing: ${promptsDir}`);
|
|
89
|
+
}
|
|
90
|
+
return fs
|
|
91
|
+
.readdirSync(promptsDir)
|
|
92
|
+
.filter((name) => name.endsWith('.md') && name.toLowerCase() !== 'readme.md')
|
|
93
|
+
.sort()
|
|
94
|
+
.map((name) => ({
|
|
95
|
+
source: path.join('prompts', name),
|
|
96
|
+
targetName: name,
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function resolveBabysitterCommand(packageRoot) {
|
|
101
|
+
if (process.env.BABYSITTER_SDK_CLI) {
|
|
102
|
+
return {
|
|
103
|
+
command: process.execPath,
|
|
104
|
+
argsPrefix: [path.resolve(process.env.BABYSITTER_SDK_CLI)],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
return {
|
|
109
|
+
command: process.execPath,
|
|
110
|
+
argsPrefix: [
|
|
111
|
+
require.resolve('@a5c-ai/babysitter-sdk/dist/cli/main.js', {
|
|
112
|
+
paths: [packageRoot],
|
|
113
|
+
}),
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
} catch {
|
|
117
|
+
return {
|
|
118
|
+
command: 'babysitter',
|
|
119
|
+
argsPrefix: [],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function resolveLocalSdkCli(packageRoot) {
|
|
125
|
+
if (process.env.BABYSITTER_SDK_CLI) {
|
|
126
|
+
return path.resolve(process.env.BABYSITTER_SDK_CLI);
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
return require.resolve('@a5c-ai/babysitter-sdk/dist/cli/main.js', {
|
|
130
|
+
paths: [packageRoot],
|
|
131
|
+
});
|
|
132
|
+
} catch {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function runBabysitterCli(packageRoot, cliArgs, options = {}) {
|
|
138
|
+
const resolved = resolveBabysitterCommand(packageRoot);
|
|
139
|
+
const result = spawnSync(resolved.command, [...resolved.argsPrefix, ...cliArgs], {
|
|
140
|
+
cwd: options.cwd || process.cwd(),
|
|
141
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
142
|
+
encoding: 'utf8',
|
|
143
|
+
env: {
|
|
144
|
+
...process.env,
|
|
145
|
+
...(options.env || {}),
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
if (result.status !== 0) {
|
|
149
|
+
const stderr = (result.stderr || '').trim();
|
|
150
|
+
const stdout = (result.stdout || '').trim();
|
|
151
|
+
throw new Error(
|
|
152
|
+
`babysitter ${cliArgs.join(' ')} failed` +
|
|
153
|
+
(stderr ? `: ${stderr}` : stdout ? `: ${stdout}` : ''),
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
return result.stdout;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function resolveProcessLibrarySpec(packageRoot) {
|
|
160
|
+
const lock = readJson(path.join(packageRoot, 'babysitter.lock.json'));
|
|
161
|
+
const processLibraryConfig =
|
|
162
|
+
(lock && lock.content && (lock.content.processLibrary || lock.content.upstream)) || {};
|
|
163
|
+
const repo = process.env.BABYSITTER_PROCESS_LIBRARY_REPO || processLibraryConfig.repo;
|
|
164
|
+
if (!repo) {
|
|
165
|
+
throw new Error('missing process-library repo configuration in babysitter.lock.json');
|
|
166
|
+
}
|
|
167
|
+
const ref = process.env.BABYSITTER_PROCESS_LIBRARY_REF || processLibraryConfig.ref || '';
|
|
168
|
+
const stateDir = getGlobalStateDir();
|
|
169
|
+
const cloneDir = path.join(stateDir, 'process-library', 'babysitter-repo');
|
|
170
|
+
const processSubpath =
|
|
171
|
+
process.env.BABYSITTER_PROCESS_LIBRARY_SUBPATH ||
|
|
172
|
+
processLibraryConfig.processSubpath ||
|
|
173
|
+
'library';
|
|
174
|
+
return {
|
|
175
|
+
repo,
|
|
176
|
+
ref: ref || undefined,
|
|
177
|
+
stateDir,
|
|
178
|
+
cloneDir,
|
|
179
|
+
processRoot: path.join(cloneDir, ...processSubpath.split('/')),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function ensureGlobalProcessLibrary(packageRoot) {
|
|
184
|
+
const spec = resolveProcessLibrarySpec(packageRoot);
|
|
185
|
+
const cloneExists = fs.existsSync(path.join(spec.cloneDir, '.git'));
|
|
186
|
+
const cloneArgs = cloneExists
|
|
187
|
+
? ['process-library:update', '--dir', spec.cloneDir, '--json']
|
|
188
|
+
: ['process-library:clone', '--repo', spec.repo, '--dir', spec.cloneDir, '--json'];
|
|
189
|
+
if (spec.ref) {
|
|
190
|
+
cloneArgs.splice(cloneExists ? 3 : 5, 0, '--ref', spec.ref);
|
|
191
|
+
}
|
|
192
|
+
runBabysitterCli(packageRoot, cloneArgs, { cwd: packageRoot });
|
|
193
|
+
if (!fs.existsSync(spec.processRoot)) {
|
|
194
|
+
throw new Error(`fetched process library root is missing: ${spec.processRoot}`);
|
|
195
|
+
}
|
|
196
|
+
runBabysitterCli(
|
|
197
|
+
packageRoot,
|
|
198
|
+
['process-library:use', '--dir', spec.processRoot, '--state-dir', spec.stateDir, '--json'],
|
|
199
|
+
{ cwd: packageRoot },
|
|
200
|
+
);
|
|
201
|
+
const active = JSON.parse(
|
|
202
|
+
runBabysitterCli(
|
|
203
|
+
packageRoot,
|
|
204
|
+
['process-library:active', '--state-dir', spec.stateDir, '--json'],
|
|
205
|
+
{ cwd: packageRoot },
|
|
206
|
+
),
|
|
207
|
+
);
|
|
208
|
+
console.log(`[babysitter-codex] process library: ${spec.processRoot}`);
|
|
209
|
+
console.log(`[babysitter-codex] process library state: ${active.stateFile}`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function mergeCodexHomeConfig(codexHome) {
|
|
213
|
+
const configPath = path.join(codexHome, 'config.toml');
|
|
214
|
+
const featureLines = [
|
|
215
|
+
'[features]',
|
|
216
|
+
'codex_hooks = true',
|
|
217
|
+
'multi_agent = true',
|
|
218
|
+
];
|
|
219
|
+
|
|
220
|
+
if (!fs.existsSync(configPath)) {
|
|
221
|
+
writeFileIfChanged(
|
|
222
|
+
configPath,
|
|
223
|
+
[
|
|
224
|
+
'approval_policy = "on-request"',
|
|
225
|
+
'sandbox_mode = "workspace-write"',
|
|
226
|
+
'',
|
|
227
|
+
...featureLines,
|
|
228
|
+
'',
|
|
229
|
+
].join('\n'),
|
|
230
|
+
);
|
|
231
|
+
console.log(`[babysitter-codex] wrote ${configPath}`);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let content = fs.readFileSync(configPath, 'utf8');
|
|
236
|
+
if (!/^\s*codex_hooks\s*=.*$/m.test(content)) {
|
|
237
|
+
if (/^\[features\]\s*$/m.test(content)) {
|
|
238
|
+
content = content.replace(
|
|
239
|
+
/^\[features\]\s*$/m,
|
|
240
|
+
['[features]', 'codex_hooks = true', 'multi_agent = true'].join('\n'),
|
|
241
|
+
);
|
|
242
|
+
} else {
|
|
243
|
+
content = [content.trimEnd(), '', ...featureLines, ''].join('\n');
|
|
244
|
+
}
|
|
245
|
+
} else if (!/^\s*multi_agent\s*=.*$/m.test(content) && /^\[features\]\s*$/m.test(content)) {
|
|
246
|
+
content = content.replace(
|
|
247
|
+
/^\[features\]\s*$/m,
|
|
248
|
+
['[features]', 'multi_agent = true'].join('\n'),
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (writeFileIfChanged(configPath, content)) {
|
|
253
|
+
console.log(`[babysitter-codex] merged ${configPath}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function removeLegacySkillDir(codexHome) {
|
|
258
|
+
const legacyDir = path.join(codexHome, 'skills', LEGACY_SKILL_NAME);
|
|
259
|
+
if (!fs.existsSync(legacyDir)) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
fs.rmSync(legacyDir, { recursive: true, force: true });
|
|
263
|
+
console.log(`[babysitter-codex] removed legacy skill ${legacyDir}`);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function removeLegacyPrompts(codexHome) {
|
|
267
|
+
for (const promptName of LEGACY_PROMPT_NAMES) {
|
|
268
|
+
const promptPath = path.join(codexHome, 'prompts', promptName);
|
|
269
|
+
if (!fs.existsSync(promptPath)) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
fs.rmSync(promptPath, { force: true });
|
|
273
|
+
console.log(`[babysitter-codex] removed legacy prompt ${promptPath}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function shouldAutoOnboardWorkspace(skillDir) {
|
|
278
|
+
const initCwd = process.env.INIT_CWD;
|
|
279
|
+
if (!initCwd) return null;
|
|
280
|
+
|
|
281
|
+
const resolved = path.resolve(initCwd);
|
|
282
|
+
if (!fs.existsSync(resolved)) return null;
|
|
283
|
+
if (!fs.statSync(resolved).isDirectory()) return null;
|
|
284
|
+
|
|
285
|
+
const normalizedWorkspace = resolved.toLowerCase();
|
|
286
|
+
const normalizedPackageRoot = PACKAGE_ROOT.toLowerCase();
|
|
287
|
+
const normalizedSkillDir = skillDir.toLowerCase();
|
|
288
|
+
if (normalizedWorkspace === normalizedPackageRoot || normalizedWorkspace === normalizedSkillDir) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return resolved;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function autoOnboardWorkspace(skillDir) {
|
|
296
|
+
const workspace = shouldAutoOnboardWorkspace(skillDir);
|
|
297
|
+
if (!workspace) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const scriptPath = path.join(skillDir, 'scripts', 'team-install.js');
|
|
302
|
+
if (!fs.existsSync(scriptPath)) {
|
|
303
|
+
console.warn('[babysitter-codex] WARNING: team-install.js is missing; skipping workspace hook onboarding');
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const result = spawnSync(process.execPath, [scriptPath, '--workspace', workspace], {
|
|
308
|
+
cwd: workspace,
|
|
309
|
+
stdio: 'pipe',
|
|
310
|
+
encoding: 'utf8',
|
|
311
|
+
env: {
|
|
312
|
+
...process.env,
|
|
313
|
+
BABYSITTER_PACKAGE_ROOT: skillDir,
|
|
314
|
+
...(resolveLocalSdkCli(PACKAGE_ROOT)
|
|
315
|
+
? { BABYSITTER_SDK_CLI: resolveLocalSdkCli(PACKAGE_ROOT) }
|
|
316
|
+
: {}),
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
if (result.status !== 0) {
|
|
321
|
+
console.warn(`[babysitter-codex] WARNING: workspace onboarding failed for ${workspace}`);
|
|
322
|
+
if (result.stdout) console.warn(result.stdout.trim());
|
|
323
|
+
if (result.stderr) console.warn(result.stderr.trim());
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
console.log(`[babysitter-codex] onboarded workspace hooks/config at ${workspace}`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function installEntry(skillDir, entry) {
|
|
331
|
+
const src = path.join(PACKAGE_ROOT, entry.source);
|
|
332
|
+
const dest = path.join(skillDir, entry.source);
|
|
333
|
+
if (!fs.existsSync(src)) {
|
|
334
|
+
if (entry.required) {
|
|
335
|
+
throw new Error(`required install payload is missing: ${src}`);
|
|
336
|
+
}
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
copyRecursive(src, dest);
|
|
340
|
+
console.log(`[babysitter-codex] ${entry.source}${fs.statSync(src).isDirectory() ? '/' : ''}`);
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function installPromptEntry(codexHome, entry) {
|
|
345
|
+
const src = path.join(PACKAGE_ROOT, entry.source);
|
|
346
|
+
if (!fs.existsSync(src)) {
|
|
347
|
+
throw new Error(`required prompt payload is missing: ${src}`);
|
|
348
|
+
}
|
|
349
|
+
const dest = path.join(codexHome, 'prompts', entry.targetName);
|
|
350
|
+
copyRecursive(src, dest);
|
|
351
|
+
console.log(`[babysitter-codex] prompts/${entry.targetName}`);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function verifyInstalledPayload(skillDir, codexHome) {
|
|
355
|
+
const promptEntries = listPromptEntries();
|
|
356
|
+
const missing = INSTALL_ENTRIES
|
|
357
|
+
.map((entry) => entry.source)
|
|
358
|
+
.filter((source) => !fs.existsSync(path.join(skillDir, source)));
|
|
359
|
+
if (missing.length > 0) {
|
|
360
|
+
throw new Error(`installed skill is incomplete; missing: ${missing.join(', ')}`);
|
|
361
|
+
}
|
|
362
|
+
for (const entry of promptEntries) {
|
|
363
|
+
if (!fs.existsSync(path.join(codexHome, 'prompts', entry.targetName))) {
|
|
364
|
+
throw new Error(`installed prompt is missing: ${entry.targetName}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function main() {
|
|
370
|
+
const codexHome = getCodexHome();
|
|
371
|
+
const skillDir = path.join(codexHome, 'skills', SKILL_NAME);
|
|
372
|
+
const promptEntries = listPromptEntries();
|
|
373
|
+
|
|
374
|
+
console.log(`[babysitter-codex] Installing skill to ${skillDir}`);
|
|
375
|
+
|
|
376
|
+
try {
|
|
377
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
378
|
+
|
|
379
|
+
for (const entry of INSTALL_ENTRIES) {
|
|
380
|
+
installEntry(skillDir, entry);
|
|
381
|
+
}
|
|
382
|
+
for (const entry of promptEntries) {
|
|
383
|
+
installPromptEntry(codexHome, entry);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
verifyInstalledPayload(skillDir, codexHome);
|
|
387
|
+
removeLegacySkillDir(codexHome);
|
|
388
|
+
removeLegacyPrompts(codexHome);
|
|
389
|
+
mergeCodexHomeConfig(codexHome);
|
|
390
|
+
|
|
391
|
+
if (!IS_WIN) {
|
|
392
|
+
const hookDir = path.join(skillDir, '.codex', 'hooks');
|
|
393
|
+
if (fs.existsSync(hookDir)) {
|
|
394
|
+
for (const name of fs.readdirSync(hookDir)) {
|
|
395
|
+
const hookPath = path.join(hookDir, name);
|
|
396
|
+
if (name.endsWith('.sh') && fs.statSync(hookPath).isFile()) {
|
|
397
|
+
fs.chmodSync(hookPath, 0o755);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
console.log('[babysitter-codex] +x hooks/*.sh');
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
ensureGlobalProcessLibrary(PACKAGE_ROOT);
|
|
405
|
+
autoOnboardWorkspace(skillDir);
|
|
406
|
+
|
|
407
|
+
console.log('[babysitter-codex] Installation complete!');
|
|
408
|
+
console.log('[babysitter-codex] Restart Codex to pick up the updated skill and hook config.');
|
|
409
|
+
} catch (err) {
|
|
410
|
+
console.error(`[babysitter-codex] Failed to install skill files: ${err.message}`);
|
|
411
|
+
process.exitCode = 1;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
main();
|
package/bin/uninstall.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* uninstall.js
|
|
6
|
+
*
|
|
7
|
+
* Removes the globally installed Codex Babysitter skill and its optional
|
|
8
|
+
* prompt alias. The globally cloned process library is intentionally kept.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const os = require('os');
|
|
14
|
+
|
|
15
|
+
const SKILL_NAMES = ['babysit', 'babysitter-codex'];
|
|
16
|
+
const PROMPT_NAMES = [
|
|
17
|
+
'assimilate.md',
|
|
18
|
+
'call.md',
|
|
19
|
+
'doctor.md',
|
|
20
|
+
'forever.md',
|
|
21
|
+
'help.md',
|
|
22
|
+
'issue.md',
|
|
23
|
+
'model.md',
|
|
24
|
+
'observe.md',
|
|
25
|
+
'plan.md',
|
|
26
|
+
'project-install.md',
|
|
27
|
+
'resume.md',
|
|
28
|
+
'retrospect.md',
|
|
29
|
+
'team-install.md',
|
|
30
|
+
'user-install.md',
|
|
31
|
+
'yolo.md',
|
|
32
|
+
'babysit.md',
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
function getCodexHome() {
|
|
36
|
+
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
37
|
+
return path.join(os.homedir(), '.codex');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function main() {
|
|
41
|
+
const codexHome = getCodexHome();
|
|
42
|
+
let removedAny = false;
|
|
43
|
+
|
|
44
|
+
for (const skillName of SKILL_NAMES) {
|
|
45
|
+
const skillDir = path.join(codexHome, 'skills', skillName);
|
|
46
|
+
if (!fs.existsSync(skillDir)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
51
|
+
console.log(`[babysitter-codex] Removed ${skillDir}`);
|
|
52
|
+
removedAny = true;
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.warn(`[babysitter-codex] Warning: Could not remove skill directory ${skillDir}: ${err.message}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (const promptName of PROMPT_NAMES) {
|
|
59
|
+
const promptPath = path.join(codexHome, 'prompts', promptName);
|
|
60
|
+
if (!fs.existsSync(promptPath)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
fs.rmSync(promptPath, { force: true });
|
|
65
|
+
console.log(`[babysitter-codex] Removed ${promptPath}`);
|
|
66
|
+
removedAny = true;
|
|
67
|
+
} catch (err) {
|
|
68
|
+
console.warn(`[babysitter-codex] Warning: Could not remove prompt ${promptPath}: ${err.message}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!removedAny) {
|
|
73
|
+
console.log('[babysitter-codex] Skill directory not found, nothing to remove.');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log('[babysitter-codex] Restart Codex to complete uninstallation.');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@a5c-ai/babysitter-codex",
|
|
3
|
+
"version": "0.1.6-staging.060a3463",
|
|
4
|
+
"description": "Babysitter Codex skill bundle and integration package for OpenAI Codex CLI with SDK-managed process-library bootstrapping, 15 orchestration modes, and BOM-safe SKILL installation",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "node test/integration.test.js && node test/packaged-install.test.js",
|
|
7
|
+
"test:integration": "node test/integration.test.js",
|
|
8
|
+
"team:install": "node scripts/team-install.js",
|
|
9
|
+
"lint": "node -e \"const fs=require('fs'); const path=require('path'); const cp=require('child_process'); const walk=(dir)=>{for(const entry of fs.readdirSync(dir)){const file=path.join(dir, entry); const stat=fs.statSync(file); if(stat.isDirectory()) walk(file); else if(file.endsWith('.js')) cp.execFileSync(process.execPath,['--check',file],{stdio:'inherit'});}}; ['.codex','bin','scripts','test'].forEach((dir)=>{if(fs.existsSync(dir)) walk(dir);});\"",
|
|
10
|
+
"deploy": "npm publish --access public",
|
|
11
|
+
"deploy:staging": "npm publish --access public --tag staging",
|
|
12
|
+
"postinstall": "node bin/postinstall.js",
|
|
13
|
+
"preuninstall": "node bin/uninstall.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"SKILL.md",
|
|
17
|
+
"README.md",
|
|
18
|
+
"agents/",
|
|
19
|
+
"prompts/",
|
|
20
|
+
".codex/",
|
|
21
|
+
"bin/",
|
|
22
|
+
"scripts/",
|
|
23
|
+
"babysitter.lock.json"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"babysitter",
|
|
27
|
+
"codex",
|
|
28
|
+
"orchestration",
|
|
29
|
+
"ai-agent",
|
|
30
|
+
"sdk-integration",
|
|
31
|
+
"codex-skill"
|
|
32
|
+
],
|
|
33
|
+
"author": "a5c.ai",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/a5c-ai/babysitter"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/a5c-ai/babysitter/tree/main/plugins/babysitter-codex#readme",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@a5c-ai/babysitter-sdk": "0.0.183-staging.060a3463"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Prompt Aliases
|
|
2
|
+
|
|
3
|
+
This folder is the source for the optional Codex prompt aliases that get
|
|
4
|
+
installed into `~/.codex/prompts/`.
|
|
5
|
+
|
|
6
|
+
These are not native Codex commands. Each file should act as a thin prompt
|
|
7
|
+
alias that forwards into the `babysit` skill for the matching mode.
|
|
8
|
+
|
|
9
|
+
Use `$babysit` as the primary integration surface. Use `/call`, `/plan`,
|
|
10
|
+
`/resume`, `/yolo`, and the rest only as optional convenience aliases.
|
|
11
|
+
|
|
12
|
+
## Prompt Files
|
|
13
|
+
|
|
14
|
+
- [call](./call.md)
|
|
15
|
+
- [yolo](./yolo.md)
|
|
16
|
+
- [resume](./resume.md)
|
|
17
|
+
- [plan](./plan.md)
|
|
18
|
+
- [forever](./forever.md)
|
|
19
|
+
- [doctor](./doctor.md)
|
|
20
|
+
- [observe](./observe.md)
|
|
21
|
+
- [retrospect](./retrospect.md)
|
|
22
|
+
- [model](./model.md)
|
|
23
|
+
- [issue](./issue.md)
|
|
24
|
+
- [help](./help.md)
|
|
25
|
+
- [project-install](./project-install.md)
|
|
26
|
+
- [team-install](./team-install.md)
|
|
27
|
+
- [user-install](./user-install.md)
|
|
28
|
+
- [assimilate](./assimilate.md)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Assimilate external methodology/spec into babysitter process patterns.
|
|
3
|
+
argument-hint: Target repo/spec/reference
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use the installed `babysit` skill in `assimilate` mode.
|
|
7
|
+
|
|
8
|
+
Treat everything after `/assimilate` as the target repo, methodology, spec, or
|
|
9
|
+
reference to assimilate.
|
package/prompts/call.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Start an interactive babysitter orchestration run.
|
|
3
|
+
argument-hint: Specific instructions for the run
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use the installed `babysit` skill in `call` mode.
|
|
7
|
+
|
|
8
|
+
Treat everything after `/call` as the Babysitter request for a new interactive
|
|
9
|
+
orchestration run.
|
|
10
|
+
|
|
11
|
+
If no request was provided, ask one concise clarification question before
|
|
12
|
+
continuing.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Define or continue a recurring babysitter workflow.
|
|
3
|
+
argument-hint: Specific instructions for recurring workflow
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use the installed `babysit` skill in `forever` mode.
|
|
7
|
+
|
|
8
|
+
Treat everything after `/forever` as the recurring workflow request.
|
package/prompts/help.md
ADDED
package/prompts/issue.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Start from a GitHub issue and prepare execution/apply flow.
|
|
3
|
+
argument-hint: <issue-number|url> [--repo owner/name] [--apply]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use the installed `babysit` skill in `issue` mode.
|
|
7
|
+
|
|
8
|
+
Treat everything after `/issue` as the issue selector and any extra issue-mode
|
|
9
|
+
arguments.
|
package/prompts/model.md
ADDED
package/prompts/plan.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Plan a workflow without executing it.
|
|
3
|
+
argument-hint: Specific instructions for the plan
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use the installed `babysit` skill in `plan` mode.
|
|
7
|
+
|
|
8
|
+
Treat everything after `/plan` as the planning request.
|
|
9
|
+
|
|
10
|
+
Do not execute the work unless the skill guidance explicitly requires it for a
|
|
11
|
+
planning-quality gate.
|