Everything core from cicero-pas's .task-manager, with instance data reduced to skeleton: empty stage directories, the task template, empty local/ scaffolding, and a README covering install (clone into .task-manager/, vendored on purpose) and update (update.sh replaces core wholesale; local/ and tasks/ survive). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Agent adapters
An adapter makes the task manager work with a particular coding agent.
Core never speaks any vendor's language — it launches jobs and ingests
normalized events; adapters translate at the edge. claude/ ships as the
default. Select with BOARD_AGENT_ADAPTER in local/.env; a directory of
the same name under local/adapters/ overrides the core one.
The contract
An adapter is a directory with two executables:
run — execute one headless job to completion
- env in:
AGENT_PROMPT(the full prompt),AGENT_MODE(work= may mutate the checkout,review= read-only — map this intent to whatever permission mechanism your agent has),AGENT_CWD, and theBOARD_*passthrough (BOARD_AGENT_ID,BOARD_TASK,BOARD_PORT) which your event bridge must forward with every event. - stdout is captured by the board as the job log. The prompts instruct the
agent to end with marker lines (
NOT READY:,RELEVANCE REVIEW:,PR REVIEW:,ADDRESSED:) — the board parses them from this output, so the agent's final text must reach stdout. - exit 0 = completed; anything else = failed.
wire — wire live-session visibility into the host project
Called by install.py with the project root as argv[1] (plus --dry-run).
Idempotently make the project's own interactive sessions report events —
however your platform allows (Claude Code: hooks; opencode: a plugin
subscribing to its event bus). Print a report; exit 0 on ok/fixed. If the
platform has no way to observe sessions, be a no-op with an honest message:
the board still runs headless jobs via run, you just lose the live
play-by-play.
Events — the normalized schema (v1)
POST to http://127.0.0.1:$BOARD_PORT/api/events:
{"v": 1, "session": str, "kind": str, "summary": str,
"file"?: str, "cmd"?: str, "detail"?: str, "ok"?: bool,
"running"?: bool, "agent"?: $BOARD_AGENT_ID, "task"?: $BOARD_TASK}
kinds: session end idle edit read search command test check git plan subagent web other. running: true marks an in-flight action (shown as
the live line, not appended to the timeline); follow it with the completed
event. kind: idle = finished responding; kind: end = session over.
Classification happens in YOUR emitter — core never sees vendor payloads.
Writing one (e.g. for opencode)
run:opencode run "$AGENT_PROMPT"with its permission config mapped fromAGENT_MODE; make sure the final output lands on stdout.wire: drop a plugin into the project that subscribes to tool events and POSTs the normalized schema with theBOARD_*env forwarded.- Events beat perfection: start with
session/endplus a genericcommandper tool call, refine kinds later.