@mychiefmind/ai-maestro
How AI Maestro works
AI Maestro conducts a roster of AI coding agents against a work board. You describe the project once and keep a board of tickets; the orchestrator picks the next unblocked ticket, runs it through a pipeline of specialised agents in an isolated git worktree, gates it, and lands it.
The idea
The board is the source of truth, not the chat
A conversation is lost on the next context reset. A board is not. Work lives in
board/data.json, so a run can be interrupted, resumed, handed to a different
model, or split across parallel sessions without losing where things stand. Every ticket
carries the information needed to execute it — which agents touch it, on which model tier,
and what must be true before it can start.
You maintain two files
config.json (roster, skills, areas, model policy) and context.md
(the brief every agent reads). Plus the board itself.
Everything else is generated
Claude's .claude//CLAUDE.md and Codex's
.agents//.codex//AGENTS.md are rendered from those
files plus the kit. Never hand-edit them — change the source and re-render.
How a ticket runs
Plan once, then one ticket per run
archive.json, remove the worktree.
A ticket names its own pipeline in agent_plan, e.g.
["pe","backend","qa","merge"]. You cannot skip review by omission: whatever you
write, qa and merge are always appended if absent, and
pd is added automatically when the ticket is multi-agent or carries
a human_gate.
The board is never hand-edited
Every write goes through maestro ticket — locked, validated, atomic.
add files one ticket; import lands a whole planned board in a
single write and only ever adds, so it cannot overwrite work already there.
retrace fixes a ticket the scope gate refused; drop retires
one that will never be done, recording why.
How the levels nest
Project plan the boundary — nothing outside it may run └── Initiative an independently valuable outcome, several epics — OPTIONAL └── Epic a demonstrable delivery outcome, made of tickets └── Ticket the executable, independently verifiable unit
Initiatives are optional, and most projects should not use them. Reach for them only when a project holds several outcomes that are each independently worth shipping and each need multiple epics. Then each initiative owns its own slice of the plan's requirements; anything that applies to all of them stays project-wide. An epic belongs to one initiative and a ticket derives its initiative through its epic — never storing one of its own. A project that defines none behaves exactly as it did before the layer existed.
Two commands do almost everything
/project-plan writes the project plan, then turns it into epics and
dependency-ordered tickets, stopping for your review at each step.
/orchestrator runs one ticket — and refuses any ticket the plan doesn't
cover. That is the loop. /plan-update fills the plan in later, section by
section.
Layout
What you own, and what is generated
my-app/ src/ … your application code — never touched maestro/ the kit + your settings config.json roster, skills, areas, model policy context.md the brief every agent reads board/ data.json live epics + tickets archive.json completed tickets + evidence specs/<id>.md long-form spec for a ticket reports/ generated reports, shown in the web dashboard custom/ YOUR agents & skills — never touched by an update agents/*.md skills/<name>/SKILL.md agents/ skills/ render/ … kit files — replaced wholesale on update .claude/ + CLAUDE.md GENERATED — Claude agents, skills & guidance .agents/ + .codex/ + AGENTS.md GENERATED — Codex skills, subagents & guidance .maestro.lock content hashes of everything generated
The lock file is what makes the renderer safe: it records exactly which files this tool
produced, so it only ever removes its own. Unmanaged runtime files are either adopted
into custom/ or left alone — never silently overwritten.
The board
Anatomy of a ticket
| Field | What it drives |
|---|---|
| id required | Unique across data.json and archive.json. |
| status required | backlog → todo → in-progress → review → done, plus blocked. |
| epicId | Groups the ticket under an epic. |
| desc | The short source of truth. Anything longer belongs in board/specs/<id>.md. |
| area | backend / frontend / infra / docs… Selects the area's model floor and test command. |
| depends_on | The ticket is eligible only when every id listed is done. |
| agent_plan | The ordered pipeline of agent codes. Terminal gates are appended if absent. |
| model | haiku / sonnet / opus. The run uses the stronger of this and the area floor; Codex maps them to low / medium / high reasoning effort. |
| execution_mode | multi-agent runs the full gated pipeline; single-agent a lighter path. |
| human_gate | When set, the orchestrator never auto-picks it — a person must clear it first. |
| testCmd | Overrides the area's default test command for this ticket only. |
| evidence | Recorded when the ticket lands: commit SHA, test output, what was verified. |
Check the board's integrity any time with maestro validate. It verifies the
schema, the dependency graph, agent codes against the roster, status consistency, and id
uniqueness across both files.
The roster
Agents
Each agent is one role with one handoff contract. agent_plan routes by the
short code, which is not always the filename — that mapping is the one
thing worth memorising.
| Code | File | Role |
|---|---|---|
| orchestrator | orchestrator.md | Runs the loop: reads the board, picks the next unblocked ticket, dispatches, gates, lands or files a blocker. |
| pe | principal-engineer.md | The planning agent. Turns a ticket into an implementation plan. |
| backend | backend-developer.md | Server-side, data-layer and API work, in an isolated worktree. |
| frontend | frontend-developer.md | UI and client work. |
| pipeline | pipeline-developer.md | Data-pipeline jobs, extraction schemas, scoring, migrations. Holds the idempotency invariant. |
| devops | devops.md | Infrastructure, CI, build and release tooling. |
| docs | technical-writer.md | User-facing documentation: guides, READMEs, references, runbooks. |
| qa | qa.md | Independent review gate. Returns a pass or a specific list of defects — never rubber-stamps. |
| pd | principal-delivery.md | Final delivery gate before a change lands. |
| repo-audit | repo-audit.md | Audits one repo per run and writes a graded Security / Gaps / Improvements report. Not a pipeline stage. |
The code is board data
Renaming an agent changes how every ticket routes. If a plan names a code with no agent
behind it, maestro validate rejects the board rather than letting the run
fail mid-dispatch.
The toolkit
Skills
Skills are procedures an agent (or you) invokes by name — several are also slash commands in your coding tool. Agents are who; skills are how.
| Skill | What it does |
|---|---|
| project-plan | Writes the project plan from a brief (goal, scope, deliverables, use cases, functional and non-functional requirements), then turns it into 3–6 epics and 5–15 dependency-ordered tickets that each trace to a plan item. Stops for review at each step. |
| release-gate (invariants) | Runs the enforce command of every plan item the ticket traces to. A non-zero exit is a hard no-go — the difference between a rule agents are asked to honour and one they cannot violate. |
| plan-update | Fills in the project plan section by section as a conversation, and triages the gaps other skills raised. Raises the plan's completeness percentage. |
| orchestrator | Starts a board run: pre-flights the board and working tree, then hands off to the orchestrator agent. |
| board-validate | Checks the board for structural and logical integrity. |
| delivery-hygiene | Keeps the board small, clear, and close to the real delivery shape. |
| release-gate | The gate a ticket must pass to land. Fails closed — a red or placeholder gate blocks. |
| security-review | A focused security pass over a change, with concrete findings at file:line. |
| test-coverage | Confirms the change is actually covered; blocks on untested critical paths. |
| frontend-quality | Build + lint always; Lighthouse, accessibility and bundle budgets when the project declares them. |
| pipeline-quality | Pipeline tests, stage idempotency, extraction fixtures, schema coverage, migration safety. |
| git-branch | Branch conventions for ticket work. |
| worktree-cleanup | Creates and tears down per-ticket worktrees so parallel work never collides. |
| land-and-archive | Merge, record evidence, move the ticket to the archive, clean up. |
| gc | Git catch-up — sync a stale checkout before trusting what it says. |
| dev-setup | Bootstraps a repo for local development from a clean checkout. |
| dev-report | Read-only status snapshot across repos and worktrees, correlated against the board. |
| orchestration-health | Diagnoses a stuck run: phantom in-progress tickets, orphaned worktrees, unknown codes. |
| repo-audit | Audits one repo and writes a graded report under the board. |
Making it yours
Three ways to customise — and what each costs
Everything of your own lives in maestro/custom/. It is not a kit folder, so an
update cannot reach it. What differs between the three options is what happens to your work
the next time the kit improves.
Add your own
custom/agents/my-agent.md
A name the kit doesn't ship. Renders alongside the kit roster, is never filtered by
roster, and nothing can collide with it. No cost.
Extend a kit agent
custom/agents/qa.overlay.md
Appended to the kit's agent under a ## Project overlay heading. The kit's
half keeps updating; your half is never touched. No cost — prefer this.
Replace a kit agent
custom/agents/qa.md
Your file wins entirely. Right when you genuinely want a different agent — but this project then stops receiving kit improvements to that name. Cost: a permanent fork.
sync reports these separately — N added, N replacing a kit agent,
N extended — and warns on each replacement, because a replacement is invisible in the
output afterwards: it looks exactly like a kit agent.
Already using Claude Code or Codex before installing?
Your existing .claude/agents and .claude/skills are adopted,
not overwritten. On the first render they move into maestro/custom/,
which both preserves them and keeps them the thing that renders — so your setup behaves
after the install exactly as it did before. Your own CLAUDE.md is kept in
place untouched. Existing unmanaged Codex files under .agents/skills and
.codex/agents are likewise preserved in place.
Lifecycle
Install, render, update
# set up in your repo — asks a short questionnaire and renders Claude + Codex targets npx @mychiefmind/ai-maestro setup # re-render after editing config.json or context.md (from the maestro/ folder) npm run sync # bring the kit up to date; your config, context, board and custom/ are kept npx @mychiefmind/ai-maestro@latest update # check the board maestro validate # change the board — locked, validated, atomic. Never edit data.json by hand. maestro ticket set-status T-010 in-progress maestro ticket archive T-010 --evidence "merged abc123: suite green"
Why a command and not an editor: reading data.json, changing a
ticket and writing the file back destroys any change another writer made in between —
silently, with no conflict and no error, leaving valid JSON that passes validation.
maestro ticket applies the change to the file as it is at write time, under a
lock. Exit 2 means someone beat you to it: run the same command again.
What an update touches: only the kit's own folders. Anything of yours it
finds among them — an agent you added, or a kit file you hand-edited — is moved into
custom/ and named in the output before anything is replaced. Nothing is ever
deleted.
Keeping generated files honest
sync --check exits non-zero if committed generated runtime files no longer
matches what would be rendered. Useful in a pre-commit hook or CI so generated files
can't go stale.
Scale
Many repos, and groups of repos
A registry lists the projects that cross-project commands operate on. It replaces "the repos that happen to sit in the same parent folder" with an explicit list — and it is the allowlist: a tool may only touch a project named in it.
// maestro-registry.json { "projects": [ { "name": "my-app", "path": "~/code/my-app" }, { "name": "platform", "path": "~/code/platform", "kind": "ops" }, { "name": "old-tool", "path": "~/code/old-tool", "status": "parked" }, { "registry": "./labs/maestro-registry.json" } ← a group of groups ] }
status: parkedkeeps a repo on the list but out of every sweep — use it instead of deleting the entry, so "deliberately not being worked" stays recorded.kind: opsmarks portfolio tooling that has no delivery pipeline of its own.- An entry with
registryincludes another registry, resolved relative to the file naming it. Names must be unique across the whole tree; cycles are reported with the chain that formed them.
maestro drift --registry maestro-registry.json version + hand-edit report per project maestro update --all --registry maestro-registry.json update every project (--dry-run to preview) node maestro/render/sync.mjs --all --registry maestro-registry.json --check
Each project runs in its own subprocess, so one broken project reports and the batch continues. A repo that hasn't adopted the kit is skipped, not counted as a failure.
When something looks wrong
Troubleshooting
| Symptom | Cause & fix |
|---|---|
| Orchestrator reports idle | No ticket is eligible: every todo ticket has an unmet depends_on or a human_gate. Run maestro validate — it prints the eligible count. |
| A ticket routes nowhere | Its agent_plan names a code with no agent behind it. Check the code table above — the code is not always the filename. |
| My agent isn't rendering | If it's a kit agent, add it to roster in config.json. Your own agents in custom/ are never roster-filtered and always render. |
| An edit to a generated runtime folder disappeared | Put the change in maestro/custom/ — as an .overlay.md if you only wanted to add rules — and re-render. |
sync --check reports drift | A generated file was edited, or config.json/context.md changed without re-rendering. Run sync without --check. |
| An agent stopped improving with the kit | You have a full replacement for it in custom/. sync names these under "replacing a kit agent". Convert it to an .overlay.md to get updates back. |
| A stuck or suspicious run | Use the orchestration-health skill — it finds phantom in-progress tickets, orphaned worktrees and unresolved dependencies. |