Discuss it first. Then let the agents build it.
Crewmate sits between you and your coding agents. You explain what you want built. Crewmate turns that into a clear brief, looks through your codebase for the relevant patterns, discuss for the best outcome with you, splits the work into ordered tasks, then hands those tasks to agents that can run several at once without stepping on each other.
crewmate is the command-line tool that makes this work. It keeps track of briefs, tasks, file locks, and notes from past work, so the agent guiding your project can spend its time making calls, not doing bookkeeping.
A coding agent is good at building things. Point it at a big, vague request, though, and it will start writing code before anyone has agreed on what "done" means.
Before real work can start, something has to pin down what's actually being asked for, look through the existing code for the patterns already in use, break the work into steps that don't collide with each other, and stop two agents from editing the same file at once. Once work is done, whatever got learned along the way needs to stick around for later — not vanish when the conversation ends.
Crewmate takes care of that planning and bookkeeping layer. Frontman, the agent you talk to, stays focused on decisions and coordination and never touches your files directly. Reading the codebase, planning the work, and writing the code happen in separate agents built for exactly those jobs.
You'll need Node.js 20 or newer.
Install the CLI:
git clone https://github.com/errevion/crewmate
cd crewmate
npm install
npm run build
npm linknpm link puts crewmate on your PATH so you can run it from any project.
Then, inside the project you want to work on:
cd ~/my-project
crewmate init --harness opencodeThis adds a few files under .opencode/:
plugins/crewmate.ts— hooks Crewmate's tools into OpenCodecommands/workflow.md— the/workflowcommand that executes graph workflowsagents/frontman.md— the supervisor's promptagents/scout.md— the read-only codebase explorer's promptagents/planner.md— the task-breakdown agent's promptagents/executor.md— the implementer's prompt
Crewmate keeps its own state in .crewmate/crewmate.db (SQLite) and records file checksums in .crewmate/manifest.json. Add .crewmate/ to your .gitignore. It doesn't need to be checked in.
When you update your crewmate CLI to a newer version, you can seamlessly update integration files, agent prompts, and plugins in your existing projects:
cd ~/my-project
crewmate update- Custom prompt protection: If you modified agent prompts or plugins,
crewmate updateautomatically creates a timestamped backup in.crewmate/backups/before applying the latest template updates. - Dependency sync: It updates plugin dependencies in
.opencode/package.jsonwhile preserving your custom dependencies. - Dry run: Preview changes before applying them with
crewmate update --dry-run. - Skip backups: Pass
--no-backupif you don't need backup copies of modified files.
The typical workflow uses the /workflow command inside OpenCode (or prompting Frontman directly) to run customizable, graph-based multi-stage workflows. You can also drive the CLI directly via crewmate workflow start.
flowchart LR
user["You"] --> frontman["Frontman"]
frontman --> scout["Scout"]
frontman --> planner["Planner"]
scout --> facts["What the codebase looks like"]
planner --> dag["Ordered list of tasks"]
dag --> exec1["Executor"]
dag --> exec2["Executor"]
exec1 --> result1["Finished work + notes"]
exec2 --> result2["Finished work + notes"]
Run /workflow in OpenCode (or prompt Frontman directly with your request):
- Workflow initialization — Frontman checks for an active workflow run (
crewmate_workflow_status), initializing a brief session record (crewmate_create_brief) and workflow run (crewmate_workflow_start) if none exists. - Dynamic stage execution — Frontman dynamically inspects the active stage's definition, objectives, and graph nodes:
- In Discussion / Planning stages: Frontman gathers requirements conversationally, dispatches Scout for codebase discovery, and dispatches Planner to decompose requirements into a DAG of implementation tasks.
- In Execution stages: Frontman coordinates parallel Executor subagents across ready tasks with file locking (
crewmate_acquire_lock) and incremental knowledge recording (crewmate_add_artifact). - In Custom stages: Frontman follows the stage graph topology, evaluating conditions, transformations, or custom agent dispatches.
- Stage advancement — Frontman advances through stages via
crewmate_workflow_advanceuntil workflow completion.
If you prefer driving the CLI directly:
# Start a workflow run
crewmate workflow start
# Or set custom brief fields directly
crewmate brief init
crewmate brief set workType software
crewmate brief set goal "Add GitHub OAuth authentication"
crewmate brief set scope '{"included":["authentication","oauth flow"],"excluded":["admin panel"]}'
crewmate brief completeWhile agents are working, crewmate watch opens a live terminal dashboard that refreshes automatically:
crewmate watchThe dashboard has four sections:
| Section | What it shows |
|---|---|
| Header | Brief ID, status (draft/complete), goal text, progress bar, running task count |
| Task board | Every task with a status marker — [✓] completed, [→] running (animated spinner), [ ] pending — plus blocking dependencies and ready-to-run indicators |
| Event feed | Last 12 lifecycle events with timestamp, actor, type, and message |
| Activity graph | Animated visualization of Frontman dispatching work to Scout, Planner, and Executors, with color-coded agent nodes |
| Key | Action |
|---|---|
b |
Toggle full brief details overlay (scope, requirements, stack, constraints, etc.) |
t |
Open interactive task selector list |
Enter |
View full details of the selected task in the task list |
↑ / ↓ or j / k |
Navigate task list or scroll open detail overlay |
PgUp / PgDn |
Fast scroll in detail overlays |
Escape |
Close overlay (task detail → task list → dashboard) or exit dashboard |
q / Ctrl-C |
Exit dashboard |
The dashboard cleanly restores your terminal state upon exit.
| Flag | Default | Description |
|---|---|---|
--brief <id> |
latest brief | Monitor a specific brief instead of the most recent one |
--interval <ms> |
500 |
Database poll interval in milliseconds |
--once |
— | Print a single JSON snapshot to stdout and exit |
When stdout is not a TTY, or when you pass --once, the dashboard skips the TUI and prints structured JSON:
crewmate watch --once | jq .snapshot.tasksThis is useful for CI checks, scripting, or feeding state into other tools.
By default the activity graph uses Unicode box-drawing characters. Set the CREWMATE_GRAPH_RENDERER environment variable to ascii to fall back to plain ASCII, which is useful in terminals without full Unicode support (e.g. Windows CMD without Windows Terminal):
export CREWMATE_GRAPH_RENDERER=ascii # Linux/macOS
set CREWMATE_GRAPH_RENDERER=ascii # Windows
crewmate watchWorkflow lifecycle events are emitted by agents during execution and displayed in the watch dashboard. You can also record or query them manually:
crewmate event add \
--actor executor \
--type completed \
--message "OAuth token storage implemented" \
--task <taskId>
crewmate event list --brief <briefId> --limit 20Actors: frontman, scout, planner, executor
Event types: dispatched, started, locked, artifact, completed, error
Filters (--brief, --task, --actor, --type, --limit) can be combined.
Frontman's current operational state is tracked separately from events and powers the activity graph in crewmate watch:
crewmate activity set orchestrating --message "Dispatching auth tasks"
crewmate activity get
crewmate activity clear
crewmate activity list --limit 50Activity types: idle, questioning, awaiting_response, analyzing, planning, orchestrating, reviewing
All activity subcommands accept --brief <id> to target a specific brief (defaults to latest).
The brief is the one source of truth Frontman and every downstream agent work from. Five fields are required before Crewmate will let you mark it complete:
| Field | Type | Example |
|---|---|---|
workType |
enum | "software", "infrastructure", "data", "documentation", "audit" |
goal |
string | "Build real-time chat feature" |
scope |
JSON | {included: ["messaging"], excluded: ["voice"]} |
functionalRequirements |
JSON array | ["user-messages", "read-receipts"] |
acceptanceCriteria |
JSON array | ["Messages persist", "Files < 25MB"] |
You can also set technicalStack, constraints, existingCodebase, referenceMaterials, qualityStandards, dependencies, risks, and deliverables. These add context but aren't required.
Each agent gets only the context it needs for its own job, not the full history of the conversation.
| Agent | Job | What it can touch |
|---|---|---|
| Frontman | Runs the show. Delegates work, keeps state up to date | Nothing directly. It never reads or edits code itself. |
| Scout | Looks through the codebase and reports back what's actually there | Read-only. Reports facts, doesn't make calls. |
| Planner | Turns a completed brief into an ordered list of concrete tasks | The brief and Scout's findings. |
| Executor | Does the actual implementation work | Its assigned task, under a file lock. |
When more than one Executor is running at the same time, file locks stop them from touching the same files:
crewmate lock acquire <taskId> --files src/auth/github.ts src/auth/session.ts
crewmate lock list
crewmate lock release <taskId>If a task can't get a lock because another task already holds it, the Executor stops right away instead of guessing and risking a broken merge.
Executors write down what they find as they go, so later tasks don't have to rediscover it:
| Type | What it holds |
|---|---|
fact |
Something true about the system right now |
decision |
A design or architecture choice that was made |
api_contract |
A route signature, interface, or schema |
constraint |
A rule later tasks need to respect |
note |
A general observation |
log |
A record of what happened during execution |
These stick around independent of any conversation, so a task started next week can build on what a task from today already figured out.
Tasks form a dependency graph rather than a flat list, a DAG, in the usual sense: each task can name other tasks it depends on, and nothing runs before its dependencies finish. Frontman looks for every task that's pending with all its dependencies completed, then dispatches as many of those in parallel as the file locks will allow.
Everything is stored in SQLite, at .crewmate/crewmate.db:
- briefs — project definitions, with every field saved as JSON
- tasks — linked to a brief, with dependency edges between them
- artifacts — the knowledge Executors have written down
- locks — which files are currently claimed, and by which task
- events — lifecycle events from each agent (dispatched, started, completed, errors)
- activities — Frontman's operational state history
This survives between sessions. Point Crewmate at a project that already has a .crewmate folder and it picks up right where it left off.
Crewmate talks to AI coding harnesses through an adapter, so the core logic doesn't need to know which harness it's running under. OpenCode is supported today; Claude Code, Codex, and Cursor are reasonable candidates for future adapters. See src/harness/README.md for adapter architecture details and instructions on adding new harness adapters.
Every command prints structured JSON to stdout, so it's easy to script against or feed back to an agent.
| Command | What it does |
|---|---|
crewmate init |
Set up the integration files for a harness |
crewmate update |
Update integration files, prompts, and plugins with automatic backups |
crewmate brief init |
Start a new draft brief |
crewmate brief set <field> <value> |
Set one field on the brief |
crewmate brief get <field> |
Read one field back |
crewmate brief show |
Show the whole brief |
crewmate brief status |
Check which required fields are still missing |
crewmate brief complete |
Mark the brief as done |
crewmate task add <briefId> |
Add a task (--title, --description, --dependencies, --field) |
crewmate task list --brief <id> |
List every task under a brief |
crewmate task update <id> --status <s> |
Change a task's status (pending, in_progress, completed) |
crewmate task remove <id> |
Delete a task |
crewmate lock acquire <taskId> |
Claim files for a task (--files) |
crewmate lock release <taskId> |
Release a task's locks |
crewmate lock list |
Show every active lock |
crewmate artifact add <taskId> |
Record an artifact (--type, --content) |
crewmate artifact list |
List artifacts, filterable by --brief, --task, --type |
crewmate event add |
Record a lifecycle event (--actor, --type, --message, --task, --brief) |
crewmate event list |
List events, filterable by --brief, --task, --actor, --type, --limit |
crewmate activity set <type> |
Set Frontman's current activity state (--message, --metadata, --brief) |
crewmate activity get |
Get the current Frontman activity |
crewmate activity clear |
Clear (end) the current activity |
crewmate activity list |
List recent activities (--brief, --limit) |
crewmate watch |
Live dashboard showing brief, tasks, events, and activity graph |
Run crewmate <command> --help for detailed usage and all available flags.
A typical session, watching a brief through to completion:
BRIEF_ID=$(crewmate brief init | jq -r '.id')
crewmate brief set workType software
crewmate brief set goal "Add GitHub OAuth login"
crewmate brief set scope '{"included":["auth"],"excluded":["admin"]}'
crewmate brief set functionalRequirements '["GitHub OAuth 2.0","Token storage"]'
crewmate brief set acceptanceCriteria '["Users can log in","Tokens persist"]'
crewmate brief complete
# watch the live dashboard in another terminal
crewmate watch --brief $BRIEF_ID
# or pull a snapshot for scripting
crewmate watch --once --brief $BRIEF_ID | jq .snapshot.tasks
# query individual components
crewmate task list --brief $BRIEF_ID
crewmate lock list
crewmate artifact list --brief $BRIEF_ID
crewmate event list --brief $BRIEF_ID --limit 20
crewmate activity list --brief $BRIEF_ID
# if something's stuck
crewmate brief status # see which required fields are missing
crewmate task remove <id> # remove a task that's stuck- Node.js 20 or newer
- A project directory, new or existing
- OpenCode installed (the only supported harness for now)
- Windows only: Visual Studio Build Tools with the "Desktop development with C++" workload and a Windows SDK component (required by
better-sqlite3's native compilation vianode-gyp)
git clone https://github.com/errevion/crewmate
cd crewmate
npm install
npm run build # build with tsup
npm run dev # build in watch mode
npm test # unit tests
npm run test:e2e # build, then run end-to-end tests
npm run test:coverage # unit test coverage (v8)
npm run typecheck # type-check without emitting
npm run lint # lint and auto-fix
npm run format # format with Prettiersrc/
commands/ CLI command handlers (init, brief, task, lock, artifact, event, activity, watch)
db/ SQLite layer — connection, migrations, repositories
harness/ Harness adapters (OpenCode today)
adapters/opencode/
templates/ Agent prompts and plugin templates
models/ Data models, constants, field definitions
utils/ Validation and error handling
tests/
e2e/ End-to-end CLI tests
validation.spec.ts
harness.spec.ts
lock.spec.ts
artifact.spec.ts

