subagent-auto-manager
v0.1.28
Published
Codex subagent ledger CLI and hooks backed by SQLite.
Maintainers
Readme
subagent-auto-manager
Small Codex hook + CLI for tracking subagents in a project-local SQLite ledger.
It records SubagentStart, SubagentStop, and selected PostToolUse payloads, then lets you quickly see which subagents are still running, finished, or closed for the current Codex session.
Useful when a long Codex task fans out into multiple subagents and you want a compact per-session ledger without reading rollout logs.
Run
npx -y subagent-auto-manager@latestNode.js 22.14.0 or newer is required because the package uses the built-in node:sqlite module.
Hook Setup
Add this to Codex hooks config, for example project .codex/hooks.json:
{
"hooks": {
"SubagentStart": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "$codexPid=(Get-Process -Id $PID).Parent.Id; npx -y subagent-auto-manager@latest hook --codex-pid $codexPid",
"statusMessage": "Recording subagent start"
}
]
}
],
"SubagentStop": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "$codexPid=(Get-Process -Id $PID).Parent.Id; npx -y subagent-auto-manager@latest hook --codex-pid $codexPid",
"statusMessage": "Recording subagent stop"
}
]
}
],
"PostToolUse": [
{
"matcher": "(close_agent|resume_agent)$",
"hooks": [
{
"type": "command",
"command": "$codexPid=(Get-Process -Id $PID).Parent.Id; npx -y subagent-auto-manager@latest hook --codex-pid $codexPid",
"statusMessage": "Recording subagent close/resume"
}
]
}
]
}
}The command reads Codex JSON from stdin and writes {} to stdout so Codex can continue normally. SubagentStart and SubagentStop payloads are stored in full. The hook records one meaningful process identity: the Codex session PID. Hook recording requires either --codex-pid <pid> or a valid CODEX_PID environment variable; the Windows PowerShell example above passes the parent PID of Codex's hook shell explicitly with --codex-pid. For schema compatibility this PID is still exposed through legacy hook_parent_pid / hook_session_pid fields, but both represent the same Codex session PID for new records and public output. If a SubagentStart or CLI query for the same session_id sees a different identified Codex session PID, prior running runs for that session are treated as stale after a shutdown and automatically marked closed with stopReason: "pid-change". Wrapper parent PIDs from shell, npm, or npx are ignored. PostToolUse tracks close_agent and resume_agent, including Codex multi-agent v1 names such as multi_agent_v1close_agent, multi_agent_v1__close_agent, or multi_agent_v1.close_agent, which are the available signal for whether the parent closed or reopened a subagent thread.
For a global install, put the same hooks block in ~/.codex/hooks.json. On Windows this is typically:
C:\Users\Misty\.codex\hooks.jsonAfter changing a non-managed hook, open /hooks in Codex and trust the updated hook definitions if Codex marks them for review.
Usage
List currently running, not-closed subagents for the current Codex thread:
npx -y subagent-auto-manager@latestList currently running subagent ids:
npx -y subagent-auto-manager@latest --runningFilter list output to one subagent:
npx -y subagent-auto-manager@latest --agent 019e87b0-d695-7902-96e1-9672e0a12db6List only stopped, not-closed subagents:
npx -y subagent-auto-manager@latest --status stoppedBroad historical queries are intended for manual debugging only and require --human:
npx -y subagent-auto-manager@latest --status all --human
npx -y subagent-auto-manager@latest --status closed --human
npx -y subagent-auto-manager@latest --after-timestamp 1780531200 --human--all, list, and --closed are shorthand for these broad/debug filters and also require --human.
List only stopped, not-closed subagents:
npx -y subagent-auto-manager@latest --stoppedList only closed subagent threads for manual debugging:
npx -y subagent-auto-manager@latest --closed --humanMark all stopped, not-closed subagents as closed:
npx -y subagent-auto-manager@latest resetMark all running and stopped, not-closed subagents as closed:
npx -y subagent-auto-manager@latest reset --full --humanClear one closed mark for manual debugging:
npx -y subagent-auto-manager@latest reset --agent 019e87b0-d695-7902-96e1-9672e0a12db6 --humanWait until every listed subagent has emitted SubagentStop:
npx -y subagent-auto-manager@latest wait 019e87b0-d695-7902-96e1-9672e0a12db6 019e87b0-9c23-72d9-bcb1-4907652aa0abThe built-in Codex subagent wait tool returns when one target completes. This CLI command polls the hook ledger and returns only when all requested targets are stopped by SubagentStop. While waiting, each newly stopped agent id is streamed to stderr; stdout stays reserved for the final JSON/YAML/text result. It exits non-zero on timeout and reports targets that did not emit SubagentStop. JSON/YAML output includes an incompleteTargets array; text output prints Pending for targets that started but have not returned yet, Closed for targets closed by stale PID reconcile or close tracking, and Miss for targets with no matching ledger row. On timeout, each incomplete target is also streamed to stderr as [subagent-auto-manager] wait timeout ..., including Closed and Miss targets:
npx -y subagent-auto-manager@latest wait --agent 019e87b0-d695-7902-96e1-9672e0a12db6 --agent 019e87b0-9c23-72d9-bcb1-4907652aa0ab --timeout-ms 600000 --textIf no explicit targets are provided, wait snapshots the current running, not-closed agents for the session and waits for that set:
npx -y subagent-auto-manager@latest wait --timeout-ms 600000Use an explicit session or project directory when needed:
npx -y subagent-auto-manager@latest --session 019e87b0-d695-7902-96e1-9672e0a12db6 --cwd /path/to/projectWith no list or filter arguments, JSON/YAML output returns only the summary and hides runs.
With list or filter arguments, default JSON/YAML output keeps each run compact: agentId, state, and stopReason when the run is stopped or closed. --agent filters by agentId, subagentId, full runKey, or <session>:<agent-id>. stopReason is hook for a recorded SubagentStop and pid-change when an older running row was closed as stale after the identified Codex session process changed. running, list, wait, and debug reconcile stale running rows before reading the ledger when the current Codex session PID can be identified.
Rows closed with pid-change are stale markers, not raw SubagentStop records. Full output keeps stopPayload as null for those rows.
{
"summary": {
"running": 1,
"stopped": 1,
"closed": 0,
"total": 2,
"shown": 1
},
"runs": [
{
"agentId": "agent-running",
"state": "running"
},
{
"agentId": "agent-stopped",
"state": "stopped",
"stopReason": "hook"
}
]
}YAML output is available with --yaml:
npx -y subagent-auto-manager@latest --yamlMedium-detail output is available with --medium. It includes recall fields such as prompt, timing, model, cwd, and parsed startArgs.
Full-detail output is available with --full or --detail full. It includes every stored run field plus parsed startArgs and raw start/stop/close hook payloads:
npx -y subagent-auto-manager@latest --yaml --fullCompact text output is also available with --text. Text output prints full session and agent ids so same-prefix agents remain distinguishable.
Hints are written to stderr. They summarize the active filter/format/detail settings and suggest useful next commands, while stdout remains parseable JSON/YAML/text.
For human diagnostics of stale-run PID detection, use debug --human:
npx -y subagent-auto-manager@latest debug --human --textThe report includes CODEX_PID, current pid/ppid, recursive process lineage, Codex process matches, resolved codexSessionPid, session summary, recent ledger rows, and grouped ledger Codex session PID values. Legacy hookParentPid / hookSessionPid fields are retained in JSON for compatibility.
Storage
Each project stores its ledger below:
<project>/.codex/subagent_auto_manager.db/ledger.sqlite3The CLI isolates sessions with CODEX_THREAD_ID by default. Hooks use the session_id from the Codex hook JSON.
The database stores queryable columns for common Codex hook fields such as session_id, legacy PID columns hook_parent_pid / hook_session_pid, turn_id, agent_id, agent_type, cwd, model, permission_mode, transcript_path, agent_transcript_path, prompt, last_assistant_message, start_args_json, stop_hook_active, tool_name, tool_use_id, and close_target, plus the complete raw payload JSON for every event. The legacy PID columns hold the Codex session PID for new records. start_args_json is a compact JSON snapshot derived from SubagentStart: it keeps launch parameters such as agent type, model, reasoning effort, sandbox or approval settings, fork flags, custom fields, and prompt, while excluding lifecycle metadata such as hook event name, session id, turn id, and transcript paths.
Publishing
This package is published through GitHub Actions trusted publishing. Future releases should be made from GitHub releases or manual workflow dispatch, not local npm publish.
