Command line
Give bots work from scripts, CI, or other agents with the brainwritebot command.
The brainwritebot command drives a running Brainwrite workspace without its screen: give a bot a job, wait until it and every teammate it asked are done, keep what they made, and set up teams from a file. Every command can print one JSON document, and its exit code says how things went.
Install it with npm install -g brainwritebot, or run it without installing as npx brainwritebot. It needs Node 24 or later. Run brainwritebot help VERB (or VERB --help) for any command's own help.
Which workspace
With Brainwrite open on this computer, the command finds it by itself and acts as its owner; no token is needed.
To reach a workspace on another computer, name it with --url URL (or the BRAINWRITE_URL environment variable). Its address must use https://. Such a workspace needs a token:
brainwritebot connect https://brain.example.com --code CODE --out ~/.brainwrite-token
brainwritebot doctor --url https://brain.example.com --token-file ~/.brainwrite-tokenconnect turns a pairing code from that workspace (in its app, Settings → Remote access → Pair a device) into a token and saves it to a file only you can read; it never prints the token. Codes are single use and expire after five minutes. --client asks for a token that can chat and answer approvals but not change settings. Pass the token with --token-file FILE or the BRAINWRITE_TOKEN environment variable; there is no flag that takes the token itself.
Commands
A TARGET is a bot or group chat by name or id, or --bot ID, --channel ID or --thread ID. --task ID picks one of its conversations. A message can be the next word, --text TEXT, --message-file FILE, or - to read it from standard input.
| Command | What it does |
|---|---|
doctor [--wait 2m] | Checks the workspace answers, is new enough, who you are to it, and that an engine is ready. --wait keeps checking until it is ready. |
bots, channels, models | Your bots and what each is doing, your group chats and who is in them, and the engines with the models each offers. |
messages TARGET [--limit 30] | The latest messages of a conversation, at most 200. |
send TARGET TEXT | Sends one message and returns at once. The same --send-id ID never sends twice. --dry-run sends nothing. |
run TARGET TEXT | Gives a bot or group chat one job and waits until it is done (below). |
wait TARGET | Waits on work already running. If nothing is running, it returns at once. |
interrupt TARGET [--tree] | Presses Stop. --tree also stops every teammate still working on its job. |
export TARGET --out DIR | Writes a conversation's job to a folder (below). |
events | The workspace's live events, one JSON line each (below). |
team apply FILE, team export --out FILE | Makes the workspace match a team file, or writes one (below). |
engine set KIND, engine list | Gives the workspace an engine key without opening the app (below). |
connect [URL] | Gets a token for a workspace (above). |
new-bot, new-channel, set-model, edit | Make a bot or a group chat, change an idle bot's model, or rewrite an earlier message of yours and have the bot answer again from there. |
run and wait
brainwritebot run "Room Lead" --message-file brief.md --timeout 45m --export ./outrun starts a new conversation, titled by --title or the message's first line, unless --task current or --task ID says otherwise. It prints progress to standard error, then the final reply and the files it links.
--wait job(the default) waits for the bot and every teammate it asked;--wait turnonly for the bot's own turn;--wait nonesends and returns.--timeoutis 30 minutes unless you set it, such as90s,5mor2h.--on-input exit(the default) stops waiting when someone must answer a question or an approval;waitkeeps waiting for the answer;stopstops the job.--on-timeout leave(the default) leaves the work running;stopstops it.--strictfails the run if any teammate's part failed.--export DIRwrites the job toDIRonce it ends.DIRmust be new or empty, which is checked before anything is sent;--forcewrites into a folder that already has files.
wait TARGET takes the same waiting options, plus --for job|turn. run prints a --since value; wait --since with it keeps watching the same job, so a job that ended meanwhile reports how it ended. Ctrl-C stops waiting, but the work keeps running.
export
export TARGET --out DIR writes a conversation's job to a folder: the job tree, every transcript with secrets removed, the files its replies link to, and screen captures. --root ID keeps one job. Limits default to --max-files 200, --max-screens 100 and --max-bytes 500MB; anything past them is skipped and listed. A folder that already has files is refused unless --force.
events
events prints the workspace's live events as JSON lines: messages, threads, bots and group chats. --thread ID (repeatable) keeps one conversation's events. --job THREAD_ID follows every conversation of one job, and --until-settled ends when that job does. --kind names the kinds to print, and --screens adds live screen frames.
Teams from a file
team apply FILE makes the workspace match a team file written in YAML or JSON: teams and their shared instructions, bots, skills, Chiefs, group chats and engines. It prints its plan, then applies it; a second apply prints No changes..
--dry-runonly prints the plan;--checkexits with code 6 if anything would change.--prunedeletes bots and group chats the file leaves out, only in teams the file marksprune: true.- A key already set is kept unless
--rotate-secrets. - A bot in the middle of a turn is changed once it is idle, waiting up to
--wait-idle(2 minutes).
team export [--team NAME]… --out FILE writes the workspace, or some of its teams, as a team file. Skills go beside it. Engine keys are written as { env: SET_ME }: set them before you apply the file elsewhere.
Engine keys
engine set KIND gives the workspace an engine key from an environment variable (--key-env VAR) or a file (--key-file FILE). KIND is claude, openai, openrouter, openai-compatible, xai, groq, mistral or cerebras. The key is never printed, and one already set is kept unless --rotate. --base-url URL sets the service's address for claude, xai and groq, and is required for openai-compatible. --install installs the engine's command if it is missing. For claude, the key runs every Claude bot; --only-claude-api keeps it to Claude (API key) bots. engine list shows the engines, whether each is ready, and which keys are set, never their values.
Output and exit codes
Without --json you get plain lines. With --json you get one JSON document, failures included. Progress goes to standard error; --quiet drops it.
| Exit code | Meaning |
|---|---|
| 0 | Done |
| 1 | Failed or stopped |
| 2 | The command line or a file is wrong |
| 3 | Someone must answer a question or an approval |
| 4 | Timed out; the work keeps running |
| 5 | Cannot reach the workspace, not allowed, or the workspace is too old |
| 6 | team apply --check found changes |
| 130 | Ctrl-C; the work keeps running |