Three repositories, one workflow

Three projects, one workflow

You hand a ticket to one command. It reads the issue, explores the code, writes a plan for you to approve, implements it test-first, has three AI models review the result, commits, opens the pull request and reports back. Three repositories make that possible, and each does a completely different job. This page explains which does what, and how they fit together.

3
projects
6
phases
65
commands
253
stack skills
197
device tools
3
CLI hosts
10
sub-agents

01Three projects, three different jobs

Think about how a crew works. There is a process that knows what order the work happens in, there is the craft knowledge of how things are built in this particular shop, and there are the actual tools and eyes on the job. These three repositories are exactly those three things.

multi-agent-pipeline

The process

The part that knows the order and refuses to skip steps. It drives a ticket all the way to a merged pull request: analyse, plan, build, review, commit, report. It knows what needs your approval, what is a hard stop, and where to loop back and try again.

multi-agent-plugins

The craft knowledge

The answer to how we build things here, one answer per stack: iOS, Android, frontend, backend and shared. Folder shape, naming, which layer may know what, how tests are written. The pipeline consults this knowledge while it builds instead of carrying it inside itself.

multi-agent-toolkit-mcp

The hands and eyes

The server that lets the AI actually launch the app, tap a button, take a screenshot, run a build and audit a package. Without it the AI can only read code. With it, it can look at the result of its own work.

Why they are separate

They change at different rates, and each is useful on its own. The process can stay still for months. A stack's conventions change whenever that stack evolves. The toolkit grows when a new device capability appears. If they were one repository, every small convention change would force a release of the whole pipeline. The toolkit in particular stands alone: it gives any AI editor control of a simulator, whether or not the pipeline is involved.

02The big picture

The three repositories at the top. The three command-line tools that run them in the middle. At the bottom, the systems a run talks to and the durable trace it leaves behind.

AUTHOREDmulti-agent-pipelinethe process: 6 phases + 65 commandscommands/ · 65multi-agent-refs/ · lazy-loadedagents/ · 10lib/ · schemas/ · scripts/skills/shared/external · 161multi-agent-pluginsthe craft knowledge: 253 skillsiOS · Android · Frontend · Backendone plugin per stackCommon · Analyst: on everywhereeach: index + reference +workflow + tools + knowledgemulti-agent-toolkit-mcpthe hands and eyes: 197 toolsiOS · 42 Android · 33Web · 35 Design · 7Code · 8 Pass · 4published to npm, own versionv3.22.3generated from the left, version bumped only on changeinstall.js writes three host treesconsumed by all three hostsregistered once per hostRUNS ITClaude Code/multi-agent:<cmd>65 slash commands, lazy refsplugins load natively3 review modelsCopilot CLI/multi-agent-<cmd>65 skills, inlined orchestratorplugins copied in3 review modelsCodex CLI/multi-agent · $multi-agent1 skill, 65 specs as refspersonas generated as TOML3 review modelsone command runs the phasesA RUN0Init1Plan2Dev3Review4Commit5ReportWHAT IT TOUCHESpersistsreads and writesShared state rootall three hosts write here, none retargets the pathagent-state.jsontracker-state.jsonknowledge/ · memory/metrics.jsonla run started on one CLI resumes on anothera run is a file, not a sessionSystems you already useTrackers: Jira · GitHub · BitbucketDocs: Confluence · WikiDesign: FigmaDiagnostics: Graylog · Fortify · Crashlyticshosts come from preferences, tokens from the keychainno address or secret is ever hard-coded
The one-way arrow at the top is the only generated relationship: the marketplace is built from part of the pipeline, never edited by hand. The purple box at the bottom is the single place all three CLIs write to: delivery diverges, state converges. Review is purple because it is the only phase that can move a run backwards.

03What happens when you run one command

6 phases in order. Two of the arrows go backwards, and those two are the reason this is worth drawing rather than listing.

left margin: the two loops back0 · Initreads the ticket, branchesWhich repo, which branch, whose identity, what kind of task. All before any model call.Exit gate: stops unless the task type and design access are on record.1 · Plananalysis, then a planExplores the code in parallel, finds what is affected and what can be reused, then writes a file-level task graph.Approval gate: nothing is written until you approve. You can ask for edits.2 · Devtest first, then the codePer task: write a failing test, make it pass, simplify, build. At most three build retries.Rework from review and fix requests from the user test both come back here.3 · Reviewmodels, triage, your testTwo stages over the logs Dev's exit gate already produced: three models in parallel, then triage.The optional user test sits inside it: the branch is checked out so you can open the app.4 · Commitcommit, push, pull requestA conventional commit carrying the ticket id, then a PR that preserves existing reviewers.Refuses to commit while an accepted blocking finding is unresolved.5 · Reportwhere to tell peoplePR description, Jira comment, Confluence page, wiki. Whichever you pick.Records what it learned, and the next run reads it.reworkfixEvery mode runs its whole phase set. No mode skips review.The rework loop stops after three rounds and hands the problem to you rather than looping forever.the analysis mode: 5 of the same phases, and nothing is written to the repo0 · Initintake1 · Planevidence, synthesis3 · Reviewvalidator4 · Commitpublish, not a commit5 · ReportsummaryNo Dev: phase 4 publishes the document to Local, Confluence or Jira instead of committing code.
The lanes in the left margin are deliberately separated. The dashed one is an optional path: a fix request from the user test that sits inside review. The purple one is the mandatory return from review.

04The pipeline: modes, gates, review

There are not many unrelated modes to memorise. There are two independent switches - where the work happens, and whether anything is confirmed - and the names are just their useful combinations.

local

Your checkout, or a separate one

This is a question too, asked at Phase 0 Step 5b. A separate checkout of the same repository leaves your own working copy untouched and lets two tasks run side by side. Local works in the checkout you are sitting in, which is simpler when you want to watch it happen, and costs the user-test phase - that gate checks the change out of a separate checkout, and there is none. The local entries answer it up front; autopilot resolves it to a separate checkout without asking, because an unattended commit in your own copy is the thing separate checkouts exist to prevent.

base branch

Evidence, then the question

Phase 0 collects the candidate base branches with the evidence behind each one before it asks. An issue carrying a target version, or linking the issue that represents the release, already names the branch on a repo whose release branches encode the version - so that becomes a ranked row whose description says why, beside rows reading "the repository's default" or "you used this last time". Nothing is hardcoded: any issue field whose schema resolves to a version is read whatever the board calls it, and the branch naming convention is inferred from the branches that exist rather than read off a table. A failed fetch degrades loudly - the list falls back to local refs and the question says so, instead of presenting a weeks-old cache as the remote's answer.

maturity

Not ready is a question, not a dead end

Phase 0 scores how ready the issue is before anything is built, and until 17.6.0 it scored and stopped: a blocker ended the run, an unattended queue moved to the next item, and the issue stayed exactly as immature as it was found. It now asks. Interactively, at that step: open the issue and fix it, continue without it - and which gap you waved through is recorded, not just that you continued - or abort. Unattended, on the issue itself, if you turned that on: one comment naming what is missing, then it stops and waits. Never a status change, never an assignee, never a close. Edit the issue and the next scan re-checks it, and if the gap closed development starts on its own - an edit is a reason to look again, never proof, so the check re-runs against the new text and decides. The same question is never asked twice.

autopilot

Asks you, or decides itself

Interactively it stops for the plan, the commit and the pull request. On autopilot it resolves those to sensible defaults, writes down what it chose, works in a separate checkout without asking, and turns on the gates that check its claims. It still stops for a review blocker it cannot fix, a build that will not go green, a circuit-breaker trip and the channel choice at reporting. Under the continuous-mode runner it ends at a draft pull request that a person reviews and merges.

One of those switches is decided purely by which entry you type: whether the run asks you anything. The other is a question the run asks itself at Phase 0, with the evidence it has already gathered in front of you.

Four entry points over one 6-phase contract

You choose how much ceremony a task gets. The full pipeline asks at every step. Autopilot runs the same phases and resolves the defaults itself. Analysis runs 5 of the 6 phases and produces a document instead of code. Every mode runs its whole phase set: no answer during a run adds or removes a phase.

ModePhasesWorktreeAsks youDev model
/multi-agent0 1 2 3 4 5asked at Step 5bat every stepSonnet
:autopilot0 1 2 3 4 5yesonly at reportingSonnet
:analysis0 1 3 4 5noat every stepFable
:resume0 3 4 5inherited from the runat every stepnone when the branch diff is the input
What autopilot never skips. The review phase, the three-attempt build cap, the confirms in front of destructive commands, the circuit breaker, and the channel choice at reporting. Everything else it resolves to a default and logs. It adds checks rather than removing them: the claim gates only run with autopilot on, and nothing it does ends in a merge. Unattended does not mean unchecked.

What stops a run, and what only warns

A check that cannot fail is worse than no check, because the green tick gets read as coverage. So every gate declares which side of the line it is on, and several deliberately stay closed when the evidence is missing.

GatePhaseKindWhat it prevents
Init exit gate0stopsA run entering analysis with no task type or design access on record
Design access0stopsUI derived from a text description instead of the design
Analysis validator1stopsA malformed analysis reaching the planner
Reuse discovery1stopsA second copy of something that already exists
Plan validator and approval1stopsAn unexecutable or unapproved plan reaching the build
Autopilot safety classifier1pausesUnattended execution of a plan that deletes or migrates data
Build queue lock2serializesTwo builds racing on the same output
Build, lint, tests, secrets2stopsSpending review budget on a change that does not compile
Evidence gate2, 4stopsA claim that the build passed with no log that shows it
Test integrity3raises blockersTests weakened or deleted until the suite turns green
Visual conformance3stopsA component drifting away from its design
Diff risk score3advisoryNothing. It routes attention, it is not a gate.
Secret and attribution hooks4stopsCommitting a token, crediting a bot, force-pushing a protected branch

Review: two stages, and one honest asymmetry

Phase 2 exit gate, inherited1 · Parallel review2 · TriageOutcomebuildlinttestssecret scanevidence gateno model runs until all of these passcheap checks reject before costly onesReviewer 1 · security and architecturefable · opus · gpt-5.6 xhighReviewer 2 · edge casesgpt-5.4 · absent on Claude CodeReviewer 3 · correctness and namingsonnet · sonnet · gpt-5.6 medium180 second limit; if none return it retries once, then stopson very small changes it may drop to a single reviewermerge and de-duplicatefilter false positivesconfirm with a failing testpauses if it rejects over 80%fixback to phase 2accepton to phase 4escalateafter three roundsThree reviewers on every host. Only slot 2 differs: Opus on Claude Code, GPT-5.4 elsewhere. Capability, not preference.On Codex all three are from one vendor, so agreement counts as weaker evidence, and the triage note says so.
Reviewer 2 is dashed because it is the only intentional difference between the hosts: every host runs three reviewers, but GPT-5.4 is not reachable from Claude Code, so that slot is filled with Opus there and with GPT-5.4 elsewhere.

10 specialists, three model vocabularies

Each specialist is defined once and states a tier, not a model name. Every CLI maps that tier onto a model it can actually reach, so one definition works in three places.

SpecialistPhaseTierWhat it does
task-clarifier0haikuScores how ambiguous the request is
explorer1sonnetScans the codebase in parallel
ios-architect1fableiOS structural judgement
android-architect1fableAndroid structural judgement
backend-architect1fableAPI and service judgement
plan-critic1fableOne adversarial round on the plan under four lenses, with the quality gates on
dev-critic2.5sonnetCritiques the code before review sees it
code-reviewer3fableMember of the review panel
security-auditor3opusSecurity and store compliance
bulk-readeranyhaikuSummarises one large file so its full text never enters the caller's context

05Autopilot, unattended

Continuous mode lets one machine pick work up on its own. /multi-agent:autopilot-on selects the repositories it watches; labelled GitHub issues and assigned, labelled Jira items then join a queue. A launchd tick takes the head of the queue, runs the whole pipeline on it in a separate checkout, and ends at a draft pull request. A person reviews it and merges it. Nothing in the pipeline merges.

research

Research before asking

A run that parks on a maturity blocker or an open analysis question gets a research pass first. It reads the tracker thread, linked items and documents, similar closed items and the repository. A script closes only the gaps a quoted source or a resolving file:line backs, and the original check re-runs and decides. Whatever is still open parks the run with the candidates found.

draft PR

One outward writer

The session never pushes. Phase 4 writes a request, and the runner, outside the session, re-runs the stack's build and tests itself, re-checks the gate ledger, the secret scan and the outbound gate, pushes from a clean staging repository and opens the pull request as a draft. A check that fails leaves the item marked verification-failed with the verdict on disk.

operations

Operations around a run

A second launchd agent keeps the Mac awake while the mode is on. Every credential a configured repository needs is probed before the schedule is offered and again on every tick. A circuit breaker stops launching after attempts that produced nothing, a cost ceiling caps spend over a rolling 24 hours, a parallel-agent cap limits sessions at once, and a daily cleanup report is written.

security

A guard that fails closed

Under the unattended flag the Bash guard judges a command only when it reduces to simple commands, and refuses anything it cannot parse. On what it can parse: no push, PR, issue or tracker write, no Keychain read, no fetch outside the network allowlist, no package install. Ticket and PR text reaches the model inside untrusted-data delimiters. The boundary itself is a separate non-admin macOS user plus branch rulesets.

gates

Claims are checked, not trusted

Before a commit, a run's claims about the repository are checked: a localization key or endpoint it references exists, open analysis questions are answered or park the run, a triage citation quotes the line it cites, a pre-existing finding points at a line the diff did not touch, and a test pass shows a positive executed count plus a new test that fails without the change. Every verdict goes to a ledger, and the commit hook refuses a commit whose mandatory gates did not pass.

client

A client contract and a phone

Commands and run questions are declared as data. /multi-agent:serve starts a localhost server over the same JSON the CLI prints, with a manifest, types and fixtures a client builds against. Four phone routes read redacted runs, answer a parked question with one of its offered options, and, only when switched on, queue a launch. Every request carries a signature from an enrolled device.

Attended use is unchanged, and nothing is on by default. Every behaviour above keys on the unattended flag or on autopilot mode; without either, no gate writes a ledger entry or parks a run. Installing the package writes no state and schedules nothing, and a gate fails the build if that ever changes. A label is a filter, not a gate: the gate is the repository picker, and it is per machine. autopilot-status shows what runs at which phase, what is queued and which pull requests it opened today; autopilot-off removes the schedule and keeps the selection.

06The plugins: craft knowledge per stack

How you build a screen in an iOS project has nothing to do with how you add an endpoint in a backend. The pipeline does not carry those answers inside itself. It asks that stack's plugin. Six plugins carry 253 skills between them; each versions on its own.

PluginStackCovers
ai-ios-toolkitiOS / SwiftUIArchitecture, code style, file placement, navigation, forms, previews, Figma to component, Code Connect, HIG and design review (Liquid Glass, SF Symbols, app icons, haptics, iPhone Duo), Apple's own Xcode skills first where Xcode provides them, build and test, a new project scaffold
ai-android-toolkitAndroid / ComposeArchitecture, state, navigation, testing, Gradle, a new project scaffold
ai-frontend-toolkitReact / TypeScriptComponents, state, routing, styling, accessibility, a new project scaffold
ai-backend-toolkitPython / NodeCreating and evolving endpoints, auth, data, validation, security, the OpenAPI spec, a new service scaffold
ai-common-toolkitevery stackAccessibility audit, plain-language editing, security review, backlog, decision council
ai-analyst-toolkitevery stackCitable evidence (issues, releases, registries) kept apart from advisory signal (forums)

Every plugin has the same skeleton

index

The router

One entry point that decides which skill should answer a given request.

reference

How this stack is built

Knowledge to read, not steps to run: layers, naming, file placement, which unit may know what.

workflow

What to do, step by step

Create a screen, evolve a component, fix a bug, scaffold a new project, branch and open a PR. Imperative and ordered.

tools

Outside sources

Figma data, Code Connect mappings, component documentation, resource registries.

knowledge

Generated depth

Framework and API depth. Never hand-written here: it is generated from the pipeline, and the next build overwrites it.

The marketplace is an output, not a source. Vendor knowledge is authored once in the pipeline repository. A build script rebuilds each plugin's knowledge tree, regenerates its skill list, and bumps the patch version only when that plugin's skill set actually changed. An unchanged run bumps nothing. Writing directly into a plugin's knowledge folder is a mistake by construction: the next build overwrites it.

07The toolkit: hands and eyes for the AI

A model being able to read code does not mean it knows whether what it wrote works. This server closes that gap: it can launch the app, tap it, take a screenshot, run a build, and audit the package before submission. All 197 tools over a standard MCP connection.

FamilyCountWhat it doesWho uses it
ios_*42Drives the simulator: screenshots, taps, typing, permissions, locale, location, push, appearance; plus a build wrapper and result drill-downDevice checks in review, design check, store readiness
android_*33The same surface for the emulator: install, navigate, permissions, dark mode, font scale, logcat, APK auditThe same consumers, Android side
web_*35A real browser page: navigate, click, type, read text, evaluate, screenshot, an accessibility snapshot whose refs the other tools accept, console and network capture, a bounded crawlFrontend work and verification
design_*7Opens the app in mock mode, enumerates every state, compares it to the Figma variant pixel by pixelThe design check command
agent_*2Runs an array of steps in a single round trip, and queries a large tool result offloaded to a fileMulti-step manual test paths
code_*8Language-server queries: definition, references, hover, workspace and document symbols, diagnosticsNavigating unfamiliar code in Dev and Review
context_*4A local full-text index over repositories and documents: index, search, fetchAnalysis and research without pasting whole files
research_*2Web search and cited answers through a configured providerThe research step in attended runs
security_*2Offline CVSS 3.1 scoring and a lockfile dependency inventoryThe security review command
pass_*4Builds, signs, inspects and validates Apple Wallet passes, and reports the signing identity and its expiryWallet pass work
media_*1Extracts scene-change frames from a videoReading a screen recording attached to a bug
Why the build wrapper matters. Raw build output is thousands of lines and all of it lands in the model's context. The wrapper returns one line instead: pass or fail, how many errors, how many warnings, and an id. The model drills into that id only when it needs to. That is thousands of tokens saved per build cycle, and the context stays available for real work.

The server runs independently of the pipeline. It connects to any MCP client, because it is a plain stdio MCP server. Some pipeline skills declare a minimum version, so when the server moves it has to ship: the sync step has its own gates, from a syntax check to package completeness to the advertised tool count matching the real one.

08Three CLIs, one pipeline

The same tree installs into three places, in three different shapes, because the three hosts disagree about how skills are discovered and how much of a prompt survives.

one authored treecommands/multi-agent/ · 65skills/ · 229agents/ · 10 multi-agent-refs/lib/ · schemas/ · scripts/install.js --claude --copilot --codexClaude Code/multi-agent:<cmd>copied, only its own namespace wipedcommands/multi-agent/ · 65multi-agent-refs/skills/ · 161 agents/*.md · 10a thin router loads one phase at a timethe rules folder is never overwrittenplugins load natively from the marketplaceno path rewriting neededCopilot CLI/multi-agent-<cmd>copied with path rules appliedskills/multi-agent-<cmd> · 65skills/ · plugins copied in agents/*.md · 10no commands tree, no refs treethe orchestrator is one file with all 6 phasesbecause there is no lazy loading hereplugins are copied, prefixed on a name clashrefs resolve from GitHubCodex CLI/multi-agent · $multi-agenttransformed with ordered rulesskills/multi-agent · exactly 1refs/commands/<cmd> · 65refs/skills/specialists are generated as TOML, not copiedplus a router prompt for a real slash commandsub-commands are reference files, not skillsthe reason is in the next sectionOne state root for all threelog, preference and knowledge paths are deliberately left aloneagent-state.json · tracker-state.jsonresume: validate, then re-enter at the next phasework started on one CLI can finish on another
The transform detail sits inside each host box rather than on the arrows, so the arrows only have to carry direction. The three dashed purple arrows converge on one point, because that convergence is the whole idea.

Why Codex gets exactly one skill

Codex collects the name and description of every skill it finds into one block, and silently drops the overflow. It does not warn. This was measured, not assumed.

if each command were its own skillthe skills blockpast the line, entries dropno log, no warningcapacitymeasured on Codex 0.145:142 skills declared75 of them surfacedplus one unrelated skill evictedand plugin skills render with no descriptionso an entry buys nothing even when it fitswhat ships: 1 skill and 65 referencesthe skills blocka single entryread on demandmulti-agent-refs/commands/<cmd>/SKILL.md · 51phases/phase-N-*.md · 8skills/<name>/ · 199located by the recipe carried in AGENTS.mda gate fails if a second pipeline skill ever appearsso the constraint cannot regress unnoticed
Two more silent failures live in the same family: forking with full history while overriding the model discards the override, and there are four concurrency slots, so at most three sub-agents can run. That ceiling is why the Codex review panel is exactly three.

09macOS only

The pipeline supports one operating system, and says so where a machine can act on it. Every credential read goes through the macOS Keychain, every iOS build through xcodebuild, every piece of visual evidence through simctl. A run on another platform would not shrink into a smaller run; it would fail partway through, after creating a worktree and a branch.

WhereWhat it does
package.jsonDeclares os: ["darwin"], so npm refuses a non-macOS install before a single file is written
index.js · installRefuse a non-darwin host with one line naming the requirement; uninstall, help and --version stay available
doctorRuns a host-platform check first, so a wrong host gets one honest line instead of a cascade of failures

Rules that keep the shell honest

  • BSD userland and bash 3.2 are the runtime. GNU-only flags such as grep -P are banned, because BSD grep exits 2 and a silenced error reads as found nothing.
  • Paths are always quoted and always go through the home variable. No absolute user path anywhere.
  • Secrets only ever go through one layer, the credential store in front of the Keychain, and stream over stdin so no token reaches argv.
  • Verification parses every shell script after a sync. Any output at all means a regression.

10Talking to the outside

A task rarely arrives self-contained. Six typed fetchers pull in the surrounding evidence, and six channels write the result where people are already looking. Neither has an address or a secret hard-coded: addresses come from preferences and secrets from a keychain mapping.

SourceWhat it brings inIf it fails
ConfluenceFeature specification pagesThe run continues
Swagger / OpenAPIEndpoint contractsThe run continues
CrashlyticsThe stack trace behind a reported crashThe run continues
GraylogService logs for a transaction idThe run continues, but not silently
FortifySecurity scan findingsA critical finding stops review
FigmaDesign truth: screenshots, tokens, component mappingIf all three tiers fail, the run stops
An unreachable source is announced, not absorbed. Exiting with success is not permission to stay quiet. A network failure has to offer a real choice: refresh the credential, connect the VPN and retry, continue without this source, or abort. Which branch was taken gets recorded. Because I searched the logs and found nothing, and I never reached the log server, are different statements, and only one of them is true.
ChannelWhat it writesThe rule it respects
Pull requestA description with fixed sections: summary, changes, architecture, verification, dependencies, relatedA Bitbucket update must not clear the existing reviewers
JiraOne comment: summary, test scenarios, source referencesIt writes once, no matter how many PRs opened
ConfluenceA page under a parent you chooseDesign frames upload as attachments, never hotlinked
WikiA component page, per-platform sub-pages, screenshots, a status boardIt only opens for component work
GitHub issueA comment plus a progress-flag update in the issue bodyThe issue is never closed, and comment and flags are both or neither
PR reviewOne inline comment per finding, anchored to a line, plus a review stateOne big lumped comment is forbidden

11How it keeps itself honest

Most of what follows exists because the opposite behaviour shipped once and cost something.

No commit without a passing build

And passing means a log that shows it. A self-assertion does not count as a build.

An issue is never closed

Auto-close keywords are forbidden in commits, PR titles and bodies. Closing is a human decision.

Uncommitted work is never removed

The cleanup step has a safe skip path and never force-removes.

A design is never guessed

If a variant, spacing or string is missing, the run stops and asks for the analysis to be regenerated. Substituting something close has cost rebuild rounds.

No AI credit anywhere

Not in commits, not in PR bodies, not in code comments. The author is always the user's identity.

An empty answer is not consent

If a question is submitted blank it is asked again, never resolved to a default.

Counts are derived, not asserted

Every number describing how many commands exist is computed from the tree, and a gate requires the prose to agree.

A test that asserts nothing is rejected

The runner fails a suite that exits successfully having checked nothing. Three suites were doing exactly that.

On top of those sit the smoke suites, a separate parity gate per host, an install fingerprint that catches structural drift, and a registry where a command name may only disappear through a recorded rename.