@a5c-ai/babysitter-codex 0.1.11-staging.fd3ab4c2 → 5.0.1-staging.08b18580

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.
@@ -41,7 +41,7 @@
41
41
  ],
42
42
  "brandColor": "#0F766E",
43
43
  "composerIcon": "./assets/icon.svg",
44
- "logo": "./assets/logo.svg",
44
+ "logo": "./assets/logo.png",
45
45
  "screenshots": []
46
46
  }
47
47
  }
package/README.md CHANGED
@@ -10,9 +10,10 @@ This package ships a real Codex plugin bundle:
10
10
  - `hooks/`
11
11
 
12
12
  It still uses the Babysitter SDK CLI and the shared `~/.a5c` process-library
13
- state. The installer registers the plugin bundle and also materializes the
14
- active Codex `skills/`, `hooks/`, and `hooks.json` surface at the selected
15
- scope so Codex can execute the Babysitter commands and hook scripts directly.
13
+ state. Global install writes the plugin bundle to `~/.agents/plugins/babysitter`
14
+ and updates `~/.agents/plugins/marketplace.json` so Codex can load the plugin
15
+ through its marketplace surface. Workspace install continues to materialize a
16
+ workspace-local Codex surface for team setup.
16
17
 
17
18
  ## Installation
18
19
 
@@ -25,8 +26,8 @@ npm install -g @a5c-ai/babysitter-sdk
25
26
  clone the repo and install the plugin globally:
26
27
 
27
28
  ```bash
28
- git clone https://github.com/a5c-ai/babysitter.git
29
- cd babysitter
29
+ npx -y @a5c-ai/babysitter-codex install --global
30
+
30
31
  codex
31
32
 
32
33
  > /plugins
@@ -34,6 +35,10 @@ codex
34
35
 
35
36
  then navigate to the 'babysitter' entry and select 'Install'.
36
37
 
38
+ If Codex was already open when you ran `install --global`, start a new thread
39
+ after installing from `/plugins` before expecting `babysitter:*` skills such as
40
+ `$babysitter:babysit` or `$babysitter:call` to appear in the mention picker.
41
+
37
42
  ## Integration Model
38
43
 
39
44
  The plugin provides:
@@ -50,9 +55,9 @@ The process library is fetched and bound through the SDK CLI in
50
55
 
51
56
  After `install --workspace`, the important files are:
52
57
 
53
- - `plugins/babysitter/.codex-plugin/plugin.json`
54
- - `plugins/babysitter/skills/babysit/SKILL.md`
55
- - `plugins/babysitter/hooks.json`
58
+ - `.agents/plugins/babysitter/.codex-plugin/plugin.json`
59
+ - `.agents/plugins/babysitter/skills/babysit/SKILL.md`
60
+ - `.agents/plugins/babysitter/hooks.json`
56
61
  - `.codex/skills/`
57
62
  - `.codex/hooks/`
58
63
  - `.codex/hooks.json`
@@ -67,13 +72,10 @@ Verify the installed plugin bundle:
67
72
 
68
73
  ```bash
69
74
  npm ls -g @a5c-ai/babysitter-codex --depth=0
70
- test -f ~/.codex/plugins/babysitter/.codex-plugin/plugin.json
71
- test -f ~/.codex/plugins/babysitter/hooks.json
72
- test -f ~/.codex/plugins/babysitter/hooks/babysitter-stop-hook.sh
73
- test -f ~/.codex/plugins/babysitter/skills/babysit/SKILL.md
74
- test -f ~/.codex/hooks.json
75
- test -f ~/.codex/hooks/babysitter-stop-hook.sh
76
- test -f ~/.codex/skills/babysit/SKILL.md
75
+ test -f ~/.agents/plugins/babysitter/.codex-plugin/plugin.json
76
+ test -f ~/.agents/plugins/babysitter/hooks.json
77
+ test -f ~/.agents/plugins/babysitter/hooks/babysitter-stop-hook.sh
78
+ test -f ~/.agents/plugins/babysitter/skills/babysit/SKILL.md
77
79
  test -f ~/.agents/plugins/marketplace.json
78
80
  ```
79
81
 
@@ -83,9 +85,10 @@ Verify the active shared process-library binding:
83
85
  babysitter process-library:active --json
84
86
  ```
85
87
 
86
- On native Windows, Codex currently does not execute hooks. The plugin still
87
- installs correctly, but the lifecycle hooks will not fire until Codex enables
88
- Windows hook execution.
88
+ On native Windows, Codex hooks require **Codex CLI >= 0.119.0** (released
89
+ 2026-04-10, [openai/codex#17268](https://github.com/openai/codex/pull/17268)).
90
+ Older Codex versions silently skipped hook execution on Windows. If hooks do
91
+ not fire after install, run `codex --version` and upgrade if needed.
89
92
 
90
93
  ## License
91
94
 
Binary file
@@ -7,6 +7,7 @@ const { spawnSync } = require('child_process');
7
7
 
8
8
  const PLUGIN_NAME = 'babysitter';
9
9
  const PLUGIN_CATEGORY = 'Coding';
10
+ const LEGACY_MARKETPLACE_PLUGIN_NAMES = ['babysitter-codex'];
10
11
  const LEGACY_SKILL_NAMES = [
11
12
  'babysit',
12
13
  'babysitter-codex',
@@ -58,12 +59,13 @@ const DEFAULT_MARKETPLACE = {
58
59
  };
59
60
  const PLUGIN_BUNDLE_ENTRIES = [
60
61
  '.codex-plugin',
61
- '.app.json',
62
62
  'assets',
63
63
  'hooks',
64
64
  'hooks.json',
65
65
  'skills',
66
- 'babysitter.lock.json',
66
+ '.app.json',
67
+ 'plugin.lock.json',
68
+ 'README.md',
67
69
  ];
68
70
 
69
71
  function getCodexHome() {
@@ -88,7 +90,7 @@ function getHomePluginRoot() {
88
90
  if (process.env.BABYSITTER_CODEX_PLUGIN_DIR) {
89
91
  return path.resolve(process.env.BABYSITTER_CODEX_PLUGIN_DIR, PLUGIN_NAME);
90
92
  }
91
- return path.join(getCodexHome(), 'plugins', PLUGIN_NAME);
93
+ return path.join(getUserHome(), '.agents', 'plugins', PLUGIN_NAME);
92
94
  }
93
95
 
94
96
  function getHomeMarketplacePath() {
@@ -315,13 +317,21 @@ function ensureExecutable(filePath) {
315
317
  }
316
318
  }
317
319
 
320
+ function getMarketplaceRootDir(marketplacePath) {
321
+ const pluginsDir = path.dirname(marketplacePath);
322
+ const dotAgentsDir = path.dirname(pluginsDir);
323
+ return path.dirname(dotAgentsDir);
324
+ }
325
+
318
326
  function normalizeMarketplaceSourcePath(marketplacePath, pluginSourcePath) {
319
- let next = pluginSourcePath;
320
- if (path.isAbsolute(next)) {
321
- next = path.relative(path.dirname(marketplacePath), next);
322
- }
327
+ let next = path.relative(getMarketplaceRootDir(marketplacePath), pluginSourcePath);
323
328
  next = String(next || '').replace(/\\/g, '/');
324
- if (!next.startsWith('./') && !next.startsWith('../')) {
329
+ if (!next || next === '.' || next.startsWith('../')) {
330
+ throw new Error(
331
+ `Plugin source path must live under ${getMarketplaceRootDir(marketplacePath)} so Codex can load it via a ./-prefixed marketplace entry.`,
332
+ );
333
+ }
334
+ if (!next.startsWith('./')) {
325
335
  next = `./${next}`;
326
336
  }
327
337
  return next;
@@ -347,15 +357,15 @@ function ensureMarketplaceEntry(marketplacePath, pluginSourcePath) {
347
357
  },
348
358
  category: PLUGIN_CATEGORY,
349
359
  };
350
- const existingIndex = Array.isArray(marketplace.plugins)
351
- ? marketplace.plugins.findIndex((entry) => entry && entry.name === PLUGIN_NAME)
352
- : -1;
353
360
  if (!Array.isArray(marketplace.plugins)) {
354
361
  marketplace.plugins = [nextEntry];
355
- } else if (existingIndex >= 0) {
356
- marketplace.plugins[existingIndex] = nextEntry;
357
362
  } else {
358
- marketplace.plugins.push(nextEntry);
363
+ const sanitized = marketplace.plugins.filter((entry) => (
364
+ entry &&
365
+ entry.name !== PLUGIN_NAME &&
366
+ !LEGACY_MARKETPLACE_PLUGIN_NAMES.includes(entry.name)
367
+ ));
368
+ marketplace.plugins = [...sanitized, nextEntry];
359
369
  }
360
370
  writeJson(marketplacePath, marketplace);
361
371
  return nextEntry;
@@ -369,7 +379,11 @@ function removeMarketplaceEntry(marketplacePath) {
369
379
  if (!Array.isArray(marketplace.plugins)) {
370
380
  return;
371
381
  }
372
- marketplace.plugins = marketplace.plugins.filter((entry) => entry && entry.name !== PLUGIN_NAME);
382
+ marketplace.plugins = marketplace.plugins.filter((entry) => (
383
+ entry &&
384
+ entry.name !== PLUGIN_NAME &&
385
+ !LEGACY_MARKETPLACE_PLUGIN_NAMES.includes(entry.name)
386
+ ));
373
387
  writeJson(marketplacePath, marketplace);
374
388
  }
375
389
 
@@ -489,8 +503,11 @@ function warnWindowsHooks() {
489
503
  if (process.platform !== 'win32') {
490
504
  return;
491
505
  }
492
- console.warn('[babysitter] Warning: Codex hooks are currently disabled on native Windows.');
493
- console.warn('[babysitter] The plugin will install correctly, but SessionStart/UserPromptSubmit/Stop hooks will not fire until Codex enables Windows hook execution.');
506
+ // Codex enabled Windows hooks in v0.119.0 (2026-04-10, openai/codex#17268).
507
+ // Older Codex CLIs still skip hook execution on Windows; warn so users on
508
+ // pinned/older versions know to upgrade.
509
+ console.warn('[babysitter] Note: Codex hooks on Windows require Codex CLI >= 0.119.0.');
510
+ console.warn('[babysitter] If hooks do not fire, run `codex --version` and upgrade if you are below 0.119.0.');
494
511
  }
495
512
 
496
513
  module.exports = {
package/bin/install.js CHANGED
@@ -9,7 +9,6 @@ const {
9
9
  getCodexHome,
10
10
  getHomeMarketplacePath,
11
11
  getHomePluginRoot,
12
- installCodexSurface,
13
12
  mergeCodexConfigFile,
14
13
  warnWindowsHooks,
15
14
  } = require('./install-shared');
@@ -27,7 +26,6 @@ function main() {
27
26
  copyPluginBundle(PACKAGE_ROOT, pluginRoot);
28
27
  ensureMarketplaceEntry(marketplacePath, pluginRoot);
29
28
  mergeCodexConfigFile(path.join(codexHome, 'config.toml'));
30
- installCodexSurface(PACKAGE_ROOT, codexHome);
31
29
 
32
30
  const active = ensureGlobalProcessLibrary(PACKAGE_ROOT);
33
31
  console.log(`[babysitter] marketplace: ${marketplacePath}`);
@@ -38,7 +36,8 @@ function main() {
38
36
  console.log(`[babysitter] process library state: ${active.stateFile}`);
39
37
  warnWindowsHooks();
40
38
  console.log('[babysitter] Installation complete!');
41
- console.log('[babysitter] Restart Codex to pick up the installed plugin and config changes.');
39
+ console.log('[babysitter] Restart Codex to pick up the installed plugin and config changes, then run Codex and install Babysitter from `/plugins`.');
40
+ console.log('[babysitter] If Codex was already open, start a new thread after install before expecting `babysitter:*` skills such as `$babysitter:babysit` or `$babysitter:call` to appear.');
42
41
  } catch (err) {
43
42
  console.error(`[babysitter] Failed to install plugin: ${err.message}`);
44
43
  process.exitCode = 1;
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env bash
2
+ # Unified Session Start Hook - routes through hooks-proxy for all hook execution.
3
+ #
4
+ # Ensures the babysitter CLI and hooks-proxy are installed (from versions.json
5
+ # sdkVersion), then delegates to the TypeScript handler via hooks-proxy.
6
+ set -euo pipefail
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
10
+ GLOBAL_ROOT="${BABYSITTER_GLOBAL_STATE_DIR:-$HOME/.a5c}"
11
+ STATE_DIR="${BABYSITTER_STATE_DIR:-${GLOBAL_ROOT}/state}"
12
+ LOG_DIR="${BABYSITTER_LOG_DIR:-${GLOBAL_ROOT}/logs}"
13
+ LOG_FILE="$LOG_DIR/babysitter-session-start-hook.log"
14
+ SDK_MARKER_FILE="${PLUGIN_ROOT}/.babysitter-install-attempted"
15
+ PROXY_MARKER_FILE="${PLUGIN_ROOT}/.hooks-proxy-install-attempted"
16
+
17
+ export CODEX_PLUGIN_ROOT="${CODEX_PLUGIN_ROOT:-${PLUGIN_ROOT}}"
18
+ export BABYSITTER_STATE_DIR="${STATE_DIR}"
19
+
20
+ mkdir -p "$LOG_DIR" 2>/dev/null
21
+
22
+ blog() {
23
+ local msg="$1"
24
+ local ts
25
+ ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
26
+ echo "[INFO] $ts $msg" >> "$LOG_FILE" 2>/dev/null
27
+ if command -v babysitter &>/dev/null; then
28
+ babysitter log --type hook --label "hook:session-start" --message "$msg" --source shell-hook 2>/dev/null || true
29
+ fi
30
+ }
31
+
32
+ blog "Unified hook script invoked"
33
+ blog "PLUGIN_ROOT=$PLUGIN_ROOT"
34
+ blog "STATE_DIR=$STATE_DIR"
35
+
36
+ # Get required SDK version from versions.json (used for both SDK and hooks-proxy)
37
+ SDK_VERSION=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('${PLUGIN_ROOT}/versions.json','utf8')).sdkVersion||'latest')}catch{console.log('latest')}" 2>/dev/null || echo "latest")
38
+
39
+ # ---------------------------------------------------------------------------
40
+ # SDK install/upgrade
41
+ # ---------------------------------------------------------------------------
42
+
43
+ install_sdk() {
44
+ local target_version="$1"
45
+ if npm i -g "@a5c-ai/babysitter-sdk@${target_version}" --loglevel=error 2>/dev/null; then
46
+ blog "Installed SDK globally (${target_version})"
47
+ return 0
48
+ else
49
+ if npm i -g "@a5c-ai/babysitter-sdk@${target_version}" --prefix "$HOME/.local" --loglevel=error 2>/dev/null; then
50
+ export PATH="$HOME/.local/bin:$PATH"
51
+ blog "Installed SDK to user prefix (${target_version})"
52
+ return 0
53
+ fi
54
+ fi
55
+ return 1
56
+ }
57
+
58
+ NEEDS_SDK_INSTALL=false
59
+ if command -v babysitter &>/dev/null; then
60
+ CURRENT_VERSION=$(babysitter --version 2>/dev/null || echo "unknown")
61
+ if [ "$CURRENT_VERSION" != "$SDK_VERSION" ]; then
62
+ blog "SDK version mismatch: installed=${CURRENT_VERSION}, required=${SDK_VERSION}"
63
+ NEEDS_SDK_INSTALL=true
64
+ else
65
+ blog "SDK version OK: ${CURRENT_VERSION}"
66
+ fi
67
+ else
68
+ blog "SDK CLI not found, will install"
69
+ NEEDS_SDK_INSTALL=true
70
+ fi
71
+
72
+ if [ "$NEEDS_SDK_INSTALL" = true ] && [ ! -f "$SDK_MARKER_FILE" ]; then
73
+ install_sdk "$SDK_VERSION"
74
+ echo "$SDK_VERSION" > "$SDK_MARKER_FILE" 2>/dev/null
75
+ fi
76
+
77
+ if ! command -v babysitter &>/dev/null; then
78
+ blog "CLI not found after install, using npx fallback"
79
+ babysitter() { npx -y "@a5c-ai/babysitter-sdk@${SDK_VERSION}" "$@"; }
80
+ export -f babysitter
81
+ fi
82
+
83
+ # ---------------------------------------------------------------------------
84
+ # Hooks-proxy install/upgrade (same pattern as SDK)
85
+ # ---------------------------------------------------------------------------
86
+
87
+ install_hooks_proxy() {
88
+ local target_version="$1"
89
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --loglevel=error 2>/dev/null; then
90
+ blog "Installed hooks-proxy globally (${target_version})"
91
+ return 0
92
+ else
93
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --prefix "$HOME/.local" --loglevel=error 2>/dev/null; then
94
+ export PATH="$HOME/.local/bin:$PATH"
95
+ blog "Installed hooks-proxy to user prefix (${target_version})"
96
+ return 0
97
+ fi
98
+ fi
99
+ return 1
100
+ }
101
+
102
+ NEEDS_PROXY_INSTALL=false
103
+ if command -v a5c-hooks-proxy &>/dev/null; then
104
+ PROXY_VERSION=$(a5c-hooks-proxy --version 2>/dev/null || echo "unknown")
105
+ if [ "$PROXY_VERSION" != "$SDK_VERSION" ]; then
106
+ blog "hooks-proxy version mismatch: installed=${PROXY_VERSION}, required=${SDK_VERSION}"
107
+ NEEDS_PROXY_INSTALL=true
108
+ else
109
+ blog "hooks-proxy version OK: ${PROXY_VERSION}"
110
+ fi
111
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
112
+ export PATH="$HOME/.local/bin:$PATH"
113
+ PROXY_VERSION=$(a5c-hooks-proxy --version 2>/dev/null || echo "unknown")
114
+ if [ "$PROXY_VERSION" != "$SDK_VERSION" ]; then
115
+ blog "hooks-proxy version mismatch: installed=${PROXY_VERSION}, required=${SDK_VERSION}"
116
+ NEEDS_PROXY_INSTALL=true
117
+ else
118
+ blog "hooks-proxy version OK: ${PROXY_VERSION}"
119
+ fi
120
+ else
121
+ blog "hooks-proxy not found, will install"
122
+ NEEDS_PROXY_INSTALL=true
123
+ fi
124
+
125
+ if [ "$NEEDS_PROXY_INSTALL" = true ] && [ ! -f "$PROXY_MARKER_FILE" ]; then
126
+ install_hooks_proxy "$SDK_VERSION"
127
+ echo "$SDK_VERSION" > "$PROXY_MARKER_FILE" 2>/dev/null
128
+ fi
129
+
130
+ # Resolve hooks-proxy binary (npx fallback if still not found)
131
+ PROXY=""
132
+ if command -v a5c-hooks-proxy &>/dev/null; then
133
+ PROXY="a5c-hooks-proxy"
134
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
135
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
136
+ fi
137
+
138
+ if [ -z "$PROXY" ]; then
139
+ blog "hooks-proxy not found after install, using npx fallback"
140
+ PROXY="npx -y @a5c-ai/hooks-proxy-cli@${SDK_VERSION} "
141
+ fi
142
+
143
+ # ---------------------------------------------------------------------------
144
+ # Capture stdin and delegate to hooks-proxy
145
+ # ---------------------------------------------------------------------------
146
+
147
+ INPUT_FILE=$(mktemp 2>/dev/null || echo "/tmp/codex-session-start-hook-$$.json")
148
+ cat > "$INPUT_FILE"
149
+
150
+ blog "Hook input received ($(wc -c < "$INPUT_FILE") bytes)"
151
+
152
+ STDERR_LOG="$LOG_DIR/babysitter-session-start-hook-stderr.log"
153
+
154
+ blog "Using hooks-proxy: $PROXY"
155
+ RESULT=$($PROXY invoke \
156
+ --adapter codex \
157
+ --handler "babysitter hook:run --harness unified --hook-type session-start --plugin-root ${CODEX_PLUGIN_ROOT} --state-dir ${BABYSITTER_STATE_DIR}" \
158
+ --json \
159
+ < "$INPUT_FILE" 2>"$STDERR_LOG")
160
+ EXIT_CODE=$?
161
+
162
+ blog "CLI exit code=$EXIT_CODE"
163
+
164
+ rm -f "$INPUT_FILE" 2>/dev/null
165
+ printf '%s\n' "$RESULT"
166
+ exit $EXIT_CODE
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env bash
2
+ # Unified Stop Hook - routes through hooks-proxy for all hook execution.
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
7
+ GLOBAL_ROOT="${BABYSITTER_GLOBAL_STATE_DIR:-$HOME/.a5c}"
8
+ STATE_DIR="${BABYSITTER_STATE_DIR:-${GLOBAL_ROOT}/state}"
9
+ LOG_DIR="${BABYSITTER_LOG_DIR:-${GLOBAL_ROOT}/logs}"
10
+ LOG_FILE="$LOG_DIR/babysitter-stop-hook.log"
11
+ PROXY_MARKER_FILE="${PLUGIN_ROOT}/.hooks-proxy-install-attempted"
12
+
13
+ export CODEX_PLUGIN_ROOT="${CODEX_PLUGIN_ROOT:-${PLUGIN_ROOT}}"
14
+ export BABYSITTER_STATE_DIR="${STATE_DIR}"
15
+
16
+ mkdir -p "$LOG_DIR" 2>/dev/null
17
+
18
+ blog() {
19
+ local msg="$1"
20
+ local ts
21
+ ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
22
+ echo "[INFO] $ts $msg" >> "$LOG_FILE" 2>/dev/null
23
+ if command -v babysitter &>/dev/null; then
24
+ babysitter log --type hook --label "hook:stop" --message "$msg" --source shell-hook 2>/dev/null || true
25
+ fi
26
+ }
27
+
28
+ blog "Unified hook script invoked"
29
+ blog "PLUGIN_ROOT=$PLUGIN_ROOT"
30
+ blog "STATE_DIR=$STATE_DIR"
31
+
32
+ # Get required version from versions.json (used for hooks-proxy)
33
+ SDK_VERSION=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('${PLUGIN_ROOT}/versions.json','utf8')).sdkVersion||'latest')}catch{console.log('latest')}" 2>/dev/null || echo "latest")
34
+
35
+ # ---------------------------------------------------------------------------
36
+ # Hooks-proxy install (same pattern as SDK install in session-start)
37
+ # ---------------------------------------------------------------------------
38
+
39
+ install_hooks_proxy() {
40
+ local target_version="$1"
41
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --loglevel=error 2>/dev/null; then
42
+ blog "Installed hooks-proxy globally (${target_version})"
43
+ return 0
44
+ else
45
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --prefix "$HOME/.local" --loglevel=error 2>/dev/null; then
46
+ export PATH="$HOME/.local/bin:$PATH"
47
+ blog "Installed hooks-proxy to user prefix (${target_version})"
48
+ return 0
49
+ fi
50
+ fi
51
+ return 1
52
+ }
53
+
54
+ # Resolve hooks-proxy binary
55
+ PROXY=""
56
+ if command -v a5c-hooks-proxy &>/dev/null; then
57
+ PROXY="a5c-hooks-proxy"
58
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
59
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
60
+ fi
61
+
62
+ # Install if not found (only attempt once per plugin version)
63
+ if [ -z "$PROXY" ] && [ ! -f "$PROXY_MARKER_FILE" ]; then
64
+ blog "hooks-proxy not found, attempting install"
65
+ install_hooks_proxy "$SDK_VERSION"
66
+ echo "$SDK_VERSION" > "$PROXY_MARKER_FILE" 2>/dev/null
67
+ if command -v a5c-hooks-proxy &>/dev/null; then
68
+ PROXY="a5c-hooks-proxy"
69
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
70
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
71
+ fi
72
+ fi
73
+
74
+ # npx fallback if still not found
75
+ if [ -z "$PROXY" ]; then
76
+ blog "hooks-proxy not found after install, using npx fallback"
77
+ PROXY="npx -y @a5c-ai/hooks-proxy-cli@${SDK_VERSION} "
78
+ fi
79
+
80
+ # ---------------------------------------------------------------------------
81
+ # Capture stdin and delegate to hooks-proxy
82
+ # ---------------------------------------------------------------------------
83
+
84
+ INPUT_FILE=$(mktemp 2>/dev/null || echo "/tmp/codex-stop-hook-$$.json")
85
+ cat > "$INPUT_FILE"
86
+
87
+ blog "Hook input received ($(wc -c < "$INPUT_FILE") bytes)"
88
+
89
+ STDERR_LOG="$LOG_DIR/babysitter-stop-hook-stderr.log"
90
+
91
+ blog "Using hooks-proxy: $PROXY"
92
+ RESULT=$($PROXY invoke \
93
+ --adapter codex \
94
+ --handler "babysitter hook:run --harness unified --hook-type stop --plugin-root ${CODEX_PLUGIN_ROOT} --state-dir ${BABYSITTER_STATE_DIR}" \
95
+ --json \
96
+ < "$INPUT_FILE" 2>"$STDERR_LOG")
97
+ EXIT_CODE=$?
98
+
99
+ blog "CLI exit code=$EXIT_CODE"
100
+
101
+ rm -f "$INPUT_FILE" 2>/dev/null
102
+ printf '%s\n' "$RESULT"
103
+ exit $EXIT_CODE
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env bash
2
+ # Unified UserPromptSubmit Hook - routes through hooks-proxy for all hook execution.
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
7
+ GLOBAL_ROOT="${BABYSITTER_GLOBAL_STATE_DIR:-$HOME/.a5c}"
8
+ STATE_DIR="${BABYSITTER_STATE_DIR:-${GLOBAL_ROOT}/state}"
9
+ LOG_DIR="${BABYSITTER_LOG_DIR:-${GLOBAL_ROOT}/logs}"
10
+ PROXY_MARKER_FILE="${PLUGIN_ROOT}/.hooks-proxy-install-attempted"
11
+
12
+ export CODEX_PLUGIN_ROOT="${CODEX_PLUGIN_ROOT:-${PLUGIN_ROOT}}"
13
+ export BABYSITTER_STATE_DIR="${STATE_DIR}"
14
+
15
+ mkdir -p "$LOG_DIR" 2>/dev/null
16
+
17
+ # Get required version from versions.json (used for hooks-proxy)
18
+ SDK_VERSION=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('${PLUGIN_ROOT}/versions.json','utf8')).sdkVersion||'latest')}catch{console.log('latest')}" 2>/dev/null || echo "latest")
19
+
20
+ # ---------------------------------------------------------------------------
21
+ # Hooks-proxy install (same pattern as SDK install in session-start)
22
+ # ---------------------------------------------------------------------------
23
+
24
+ install_hooks_proxy() {
25
+ local target_version="$1"
26
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --loglevel=error 2>/dev/null; then
27
+ return 0
28
+ else
29
+ if npm i -g "@a5c-ai/hooks-proxy-cli@${target_version}" --prefix "$HOME/.local" --loglevel=error 2>/dev/null; then
30
+ export PATH="$HOME/.local/bin:$PATH"
31
+ return 0
32
+ fi
33
+ fi
34
+ return 1
35
+ }
36
+
37
+ # Resolve hooks-proxy binary
38
+ PROXY=""
39
+ if command -v a5c-hooks-proxy &>/dev/null; then
40
+ PROXY="a5c-hooks-proxy"
41
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
42
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
43
+ fi
44
+
45
+ # Install if not found (only attempt once per plugin version)
46
+ if [ -z "$PROXY" ] && [ ! -f "$PROXY_MARKER_FILE" ]; then
47
+ install_hooks_proxy "$SDK_VERSION"
48
+ echo "$SDK_VERSION" > "$PROXY_MARKER_FILE" 2>/dev/null
49
+ if command -v a5c-hooks-proxy &>/dev/null; then
50
+ PROXY="a5c-hooks-proxy"
51
+ elif [ -f "$HOME/.local/bin/a5c-hooks-proxy" ]; then
52
+ PROXY="$HOME/.local/bin/a5c-hooks-proxy"
53
+ fi
54
+ fi
55
+
56
+ # npx fallback if still not found
57
+ if [ -z "$PROXY" ]; then
58
+ PROXY="npx -y @a5c-ai/hooks-proxy-cli@${SDK_VERSION} "
59
+ fi
60
+
61
+ # ---------------------------------------------------------------------------
62
+ # Capture stdin and delegate to hooks-proxy
63
+ # ---------------------------------------------------------------------------
64
+
65
+ INPUT_FILE=$(mktemp 2>/dev/null || echo "/tmp/codex-user-prompt-submit-hook-$$.json")
66
+ cat > "$INPUT_FILE"
67
+
68
+ if command -v babysitter &>/dev/null; then
69
+ babysitter log --type hook --label "hook:user-prompt-submit" --message "Unified hook invoked" --source shell-hook 2>/dev/null || true
70
+ fi
71
+
72
+ STDERR_LOG="$LOG_DIR/babysitter-user-prompt-submit-hook-stderr.log"
73
+
74
+ RESULT=$($PROXY invoke \
75
+ --adapter codex \
76
+ --handler "babysitter hook:run --harness unified --hook-type user-prompt-submit --plugin-root ${CODEX_PLUGIN_ROOT} --state-dir ${BABYSITTER_STATE_DIR}" \
77
+ --json \
78
+ < "$INPUT_FILE" 2>"$STDERR_LOG")
79
+ EXIT_CODE=$?
80
+
81
+ if command -v babysitter &>/dev/null; then
82
+ babysitter log --type hook --label "hook:user-prompt-submit" --message "CLI exit code=$EXIT_CODE" --source shell-hook 2>/dev/null || true
83
+ fi
84
+
85
+ rm -f "$INPUT_FILE" 2>/dev/null
86
+ if [ -n "$RESULT" ]; then
87
+ printf '%s\n' "$RESULT"
88
+ fi
89
+ exit $EXIT_CODE
@@ -3,8 +3,9 @@ set -euo pipefail
3
3
 
4
4
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
5
  PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
6
- STATE_DIR="${BABYSITTER_STATE_DIR:-${PWD}/.a5c}"
7
- LOG_DIR="${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}"
6
+ GLOBAL_ROOT="${BABYSITTER_GLOBAL_STATE_DIR:-$HOME/.a5c}"
7
+ STATE_DIR="${BABYSITTER_STATE_DIR:-${GLOBAL_ROOT}/state}"
8
+ LOG_DIR="${BABYSITTER_LOG_DIR:-${GLOBAL_ROOT}/logs}"
8
9
  LOG_FILE="$LOG_DIR/babysitter-session-start-hook.log"
9
10
 
10
11
  export CODEX_PLUGIN_ROOT="${CODEX_PLUGIN_ROOT:-${PLUGIN_ROOT}}"
@@ -3,8 +3,9 @@ set -euo pipefail
3
3
 
4
4
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
5
  PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
6
- STATE_DIR="${BABYSITTER_STATE_DIR:-${PWD}/.a5c}"
7
- LOG_DIR="${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}"
6
+ GLOBAL_ROOT="${BABYSITTER_GLOBAL_STATE_DIR:-$HOME/.a5c}"
7
+ STATE_DIR="${BABYSITTER_STATE_DIR:-${GLOBAL_ROOT}/state}"
8
+ LOG_DIR="${BABYSITTER_LOG_DIR:-${GLOBAL_ROOT}/logs}"
8
9
  LOG_FILE="$LOG_DIR/babysitter-stop-hook.log"
9
10
 
10
11
  export CODEX_PLUGIN_ROOT="${CODEX_PLUGIN_ROOT:-${PLUGIN_ROOT}}"
@@ -0,0 +1,38 @@
1
+ {
2
+ "_comment": "NOT ACTIVE — Alternative hooks.json using per-hook unified scripts with hooks-proxy support. To activate, replace hooks.json with this file.",
3
+ "hooks": {
4
+ "SessionStart": [
5
+ {
6
+ "matcher": ".*",
7
+ "hooks": [
8
+ {
9
+ "type": "command",
10
+ "command": "./hooks/babysitter-proxied-session-start.sh"
11
+ }
12
+ ]
13
+ }
14
+ ],
15
+ "UserPromptSubmit": [
16
+ {
17
+ "matcher": ".*",
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "./hooks/babysitter-proxied-user-prompt-submit.sh"
22
+ }
23
+ ]
24
+ }
25
+ ],
26
+ "Stop": [
27
+ {
28
+ "matcher": ".*",
29
+ "hooks": [
30
+ {
31
+ "type": "command",
32
+ "command": "./hooks/babysitter-proxied-stop-hook.sh"
33
+ }
34
+ ]
35
+ }
36
+ ]
37
+ }
38
+ }
@@ -3,8 +3,9 @@ set -euo pipefail
3
3
 
4
4
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
5
  PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
6
- STATE_DIR="${BABYSITTER_STATE_DIR:-${PWD}/.a5c}"
7
- LOG_DIR="${BABYSITTER_LOG_DIR:-$HOME/.a5c/logs}"
6
+ GLOBAL_ROOT="${BABYSITTER_GLOBAL_STATE_DIR:-$HOME/.a5c}"
7
+ STATE_DIR="${BABYSITTER_STATE_DIR:-${GLOBAL_ROOT}/state}"
8
+ LOG_DIR="${BABYSITTER_LOG_DIR:-${GLOBAL_ROOT}/logs}"
8
9
 
9
10
  export CODEX_PLUGIN_ROOT="${CODEX_PLUGIN_ROOT:-${PLUGIN_ROOT}}"
10
11
  export BABYSITTER_STATE_DIR="${STATE_DIR}"
package/hooks.json CHANGED
@@ -2,33 +2,33 @@
2
2
  "hooks": {
3
3
  "SessionStart": [
4
4
  {
5
- "matcher": "*",
5
+ "matcher": ".*",
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
9
- "command": "./hooks/babysitter-session-start.sh"
9
+ "command": "./hooks/babysitter-proxied-session-start.sh"
10
10
  }
11
11
  ]
12
12
  }
13
13
  ],
14
14
  "UserPromptSubmit": [
15
15
  {
16
- "matcher": "*",
16
+ "matcher": ".*",
17
17
  "hooks": [
18
18
  {
19
19
  "type": "command",
20
- "command": "./hooks/user-prompt-submit.sh"
20
+ "command": "./hooks/babysitter-proxied-user-prompt-submit.sh"
21
21
  }
22
22
  ]
23
23
  }
24
24
  ],
25
25
  "Stop": [
26
26
  {
27
- "matcher": "*",
27
+ "matcher": ".*",
28
28
  "hooks": [
29
29
  {
30
30
  "type": "command",
31
- "command": "./hooks/babysitter-stop-hook.sh"
31
+ "command": "./hooks/babysitter-proxied-stop-hook.sh"
32
32
  }
33
33
  ]
34
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a5c-ai/babysitter-codex",
3
- "version": "0.1.11-staging.fd3ab4c2",
3
+ "version": "5.0.1-staging.08b18580",
4
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
5
  "scripts": {
6
6
  "test": "node test/integration.test.js && node test/packaged-install.test.js",
@@ -17,14 +17,15 @@
17
17
  },
18
18
  "files": [
19
19
  ".codex-plugin/",
20
- ".app.json",
21
20
  "assets/",
22
21
  "hooks/",
23
22
  "hooks.json",
24
23
  "skills/",
24
+ ".app.json",
25
25
  "bin/",
26
26
  "scripts/",
27
- "babysitter.lock.json"
27
+ "plugin.lock.json",
28
+ "README.md"
28
29
  ],
29
30
  "keywords": [
30
31
  "babysitter",
@@ -45,6 +46,6 @@
45
46
  },
46
47
  "homepage": "https://github.com/a5c-ai/babysitter/tree/main/plugins/babysitter-codex#readme",
47
48
  "dependencies": {
48
- "@a5c-ai/babysitter-sdk": "0.0.188-staging.fd3ab4c2"
49
+ "@a5c-ai/babysitter-sdk": "5.0.1-staging.08b18580"
49
50
  }
50
51
  }
@@ -0,0 +1,153 @@
1
+ {
2
+ "lockVersion": 1,
3
+ "pluginId": "ai.a5c.babysitter",
4
+ "pluginVersion": "0.1.5",
5
+ "generatedBy": "@a5c-ai/babysitter-codex",
6
+ "generatedAt": "2026-03-11T00:00:00.000Z",
7
+ "skills": [
8
+ {
9
+ "id": "assimilate",
10
+ "vendoredPath": "skills/assimilate",
11
+ "source": {
12
+ "type": "local",
13
+ "path": "skills/assimilate"
14
+ }
15
+ },
16
+ {
17
+ "id": "babysit",
18
+ "vendoredPath": "skills/babysit",
19
+ "source": {
20
+ "type": "local",
21
+ "path": "skills/babysit"
22
+ }
23
+ },
24
+ {
25
+ "id": "call",
26
+ "vendoredPath": "skills/call",
27
+ "source": {
28
+ "type": "local",
29
+ "path": "skills/call"
30
+ }
31
+ },
32
+ {
33
+ "id": "doctor",
34
+ "vendoredPath": "skills/doctor",
35
+ "source": {
36
+ "type": "local",
37
+ "path": "skills/doctor"
38
+ }
39
+ },
40
+ {
41
+ "id": "forever",
42
+ "vendoredPath": "skills/forever",
43
+ "source": {
44
+ "type": "local",
45
+ "path": "skills/forever"
46
+ }
47
+ },
48
+ {
49
+ "id": "help",
50
+ "vendoredPath": "skills/help",
51
+ "source": {
52
+ "type": "local",
53
+ "path": "skills/help"
54
+ }
55
+ },
56
+ {
57
+ "id": "issue",
58
+ "vendoredPath": "skills/issue",
59
+ "source": {
60
+ "type": "local",
61
+ "path": "skills/issue"
62
+ }
63
+ },
64
+ {
65
+ "id": "model",
66
+ "vendoredPath": "skills/model",
67
+ "source": {
68
+ "type": "local",
69
+ "path": "skills/model"
70
+ }
71
+ },
72
+ {
73
+ "id": "observe",
74
+ "vendoredPath": "skills/observe",
75
+ "source": {
76
+ "type": "local",
77
+ "path": "skills/observe"
78
+ }
79
+ },
80
+ {
81
+ "id": "plan",
82
+ "vendoredPath": "skills/plan",
83
+ "source": {
84
+ "type": "local",
85
+ "path": "skills/plan"
86
+ }
87
+ },
88
+ {
89
+ "id": "project-install",
90
+ "vendoredPath": "skills/project-install",
91
+ "source": {
92
+ "type": "local",
93
+ "path": "skills/project-install"
94
+ }
95
+ },
96
+ {
97
+ "id": "resume",
98
+ "vendoredPath": "skills/resume",
99
+ "source": {
100
+ "type": "local",
101
+ "path": "skills/resume"
102
+ }
103
+ },
104
+ {
105
+ "id": "retrospect",
106
+ "vendoredPath": "skills/retrospect",
107
+ "source": {
108
+ "type": "local",
109
+ "path": "skills/retrospect"
110
+ }
111
+ },
112
+ {
113
+ "id": "team-install",
114
+ "vendoredPath": "skills/team-install",
115
+ "source": {
116
+ "type": "local",
117
+ "path": "skills/team-install"
118
+ }
119
+ },
120
+ {
121
+ "id": "user-install",
122
+ "vendoredPath": "skills/user-install",
123
+ "source": {
124
+ "type": "local",
125
+ "path": "skills/user-install"
126
+ }
127
+ },
128
+ {
129
+ "id": "yolo",
130
+ "vendoredPath": "skills/yolo",
131
+ "source": {
132
+ "type": "local",
133
+ "path": "skills/yolo"
134
+ }
135
+ }
136
+ ],
137
+ "metadata": {
138
+ "runtime": {
139
+ "name": "@a5c/babysitter-codex-runtime",
140
+ "version": "0.1.4"
141
+ },
142
+ "content": {
143
+ "name": "@a5c/babysitter-codex-content",
144
+ "version": "0.1.4",
145
+ "processLibrary": {
146
+ "repo": "https://github.com/a5c-ai/babysitter.git",
147
+ "processSubpath": "library",
148
+ "referenceSubpath": "library/reference",
149
+ "snapshotCommit": "unknown"
150
+ }
151
+ }
152
+ }
153
+ }
@@ -32,7 +32,7 @@ function main() {
32
32
  const args = parseArgs(process.argv);
33
33
  const packageRoot = path.resolve(process.env.BABYSITTER_PACKAGE_ROOT || path.join(__dirname, '..'));
34
34
  const workspaceRoot = args.workspace;
35
- const workspacePluginRoot = path.join(workspaceRoot, 'plugins', 'babysitter');
35
+ const workspacePluginRoot = path.join(workspaceRoot, '.agents', 'plugins', 'babysitter');
36
36
  const workspaceMarketplacePath = path.join(workspaceRoot, '.agents', 'plugins', 'marketplace.json');
37
37
  const workspaceConfigPath = path.join(workspaceRoot, '.codex', 'config.toml');
38
38
 
@@ -81,6 +81,7 @@ function main() {
81
81
 
82
82
  warnWindowsHooks();
83
83
  console.log('[team-install] complete');
84
+ console.log('[team-install] If Codex was already open, start a new thread before expecting `babysitter:*` skills such as `$babysitter:babysit` or `$babysitter:call` to appear.');
84
85
  }
85
86
 
86
87
  main();
@@ -18,6 +18,8 @@ Read the SDK version from `versions.json` to ensure version compatibility:
18
18
 
19
19
  ```bash
20
20
  SDK_VERSION=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('${CODEX_PLUGIN_ROOT}/versions.json','utf8')).sdkVersion||'latest')}catch{console.log('latest')}")
21
+ npm i -g @a5c-ai/babysitter-sdk@$SDK_VERSION
22
+
21
23
  CLI="npx -y @a5c-ai/babysitter-sdk@$SDK_VERSION"
22
24
  ```
23
25
 
@@ -1,18 +0,0 @@
1
- {
2
- "version": 1,
3
- "generatedAt": "2026-03-11T00:00:00.000Z",
4
- "runtime": {
5
- "name": "@a5c/babysitter-codex-runtime",
6
- "version": "0.1.4"
7
- },
8
- "content": {
9
- "name": "@a5c/babysitter-codex-content",
10
- "version": "0.1.4",
11
- "processLibrary": {
12
- "repo": "https://github.com/a5c-ai/babysitter.git",
13
- "processSubpath": "library",
14
- "referenceSubpath": "library/reference",
15
- "snapshotCommit": "unknown"
16
- }
17
- }
18
- }