- CLI surface:
subagentTyper commands for config/registry, controller ownership, worker lifecycle, and turn operations. - Local control plane:
subagentdprocess for bootstrap/status, heartbeat, worker runtime health checks, and auto-restart attempts. - Runtime state: sqlite-backed
StateStorefor controllers, controller instances, workers, event journal, approval requests, and handoff snapshots. - Runtime adapter: per-worker ACP runtime process (
subagent.worker_runtime) with unix-socket IPC (runtime_service). - Config registry: loader for
launchers/roleHints/roleDefaults/defaultsfrom config.
config:init(user/project config template generation)launcher/role:list,showlauncher:probeprompt:render(manager)controller:init,attach,status,recover,releaseworker:start,list,show,inspect,stop,handoff,continue- turn operations:
send,watch,wait,approve,cancel subagentd:run,status- normalized event journal and approval queue
- default
config inittemplate includes ACP launchers forcodex,claude-code,gemini,opencode,cline,github-copilot,kiro - persistent
acp-stdioworker runtime:worker startlaunches runtime (initialize->session/new)- restart path attempts
session/loadusing storedsessionId, then falls back tosession/new senduses runtime IPC to executesession/promptcancelpropagates to runtime (session/cancel)- live permission flow pauses on
session/request_permissionand resumes viaapprove - runtime IPC retries once with auto-restart when runtime socket is unreachable
- explicit local simulation mode (
--debug-modeor--request-approval) - handoff store with
handoff.md+checkpoint.json --inputJSON contract (major commands) with duplicate-field rejection- owner handle model:
controllerId + epoch + token - workspace-scoped runtime state by default:
<workspace-root>/.subagent/state(orSUBAGENT_STATE_DIRoverride) - project-local hint:
<workspace>/.subagent/controller.json - versioned envelope for JSON responses
- local single-host control plane only (no multi-host orchestration/scheduling)
- no queued turn execution;
sendis rejected while worker is busy - session resume is best-effort (
session/loadfallback tosession/new, no guaranteed bit-perfect resurrection) - commands that need implicit state path fail with
WORKSPACE_ROOT_NOT_FOUNDwhen workspace root cannot be inferred