09. Automation and Editor Integration
Headless and CI
Run Matcha CLI from a script or CI job: one prompt in, a result on stdout, then exit. There is no full-screen TUI and no Matcha-hosted runner.
How headless works
The same matcha binary that opens the TUI can also run a single turn and leave. Headless mode is that one-shot path. You supply a prompt, the assistant uses your configured Provider and local tools, and the process prints the answer, then exits with a status code your pipeline can test.
This is not an editor embed. For a long-lived JSON-RPC server that an editor talks to, use matcha agent stdio. For a shared local backend that several clients attach to, see leader processes.
Passing -p / --single (or --prompt-json / --prompt-file) turns the process into headless mode. The assistant still has tool access. What changes is the contract with you:
| Piece | Headless behavior |
|---|---|
| Input | The prompt on the flag or file. Piped stdin is **not** the prompt. |
| Output | stdout. Default is plain text; --output-format json is one object. |
| Permissions | There is no TUI to click. Use --always-approve (alias --yolo) in CI, plus --allow / --deny if you need guardrails. |
| Session | Each run starts a **new** session unless you pass -r / -c. |
| Exit | 0 on a completed prompt; 1 on auth, network, or runtime failure; 130 on SIGINT; 143 on SIGTERM. |
--output-format values: plain (default), json, streaming-json, streaming-messages-json. For CI, start with json and read text and sessionId.
When to use it
Use this when a human should not sit in the TUI:
- a pre-commit check or PR review bot
- a one-off “summarize this diff” from a Makefile or hook
- a follow-up prompt that resumes yesterday’s session by ID
Headless is local and BYOK. Set a Provider key in the environment (for example XAI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY) or run matcha login --provider <id> --from-env on the machine first. There is no Matcha-hosted runner, no grok.com relay, and no account OAuth for CI.
Run a prompt
Configure a Provider, then run a prompt from the project directory:
export XAI_API_KEY="…" # or OPENAI_API_KEY / ANTHROPIC_API_KEY
matcha -p "List the top-level files and say what this repo is."Machine-readable result (one JSON object after the turn ends):
matcha -p "Summarize this repository in one paragraph." \
--output-format json --always-approveUseful fields on success: text, stopReason, sessionId, requestId. When the prompt reached the model, spend fields (usage, num_turns, modelUsage) may also appear. On failure, stdout is an error object such as {"type":"error","message":"…"} and the process exits non-zero.
Capture the session and continue it
ID=$(matcha -p "Review the staged diff." --output-format json --always-approve \
| jq -r '.sessionId')
matcha -p "Now list only security issues." --resume "$ID" --always-approve-r / --resume takes a session ID (prefer this in scripts) or a title for the current directory. -c / --continue resumes the most recent session for this directory. -s / --session-id only **creates** a new UUID; it does not resume.
Pipes and files
# stdout is the answer — redirect it
matcha -p "Draft a README for this crate." --always-approve > README.md
# stdin is not the prompt; inject context yourself
matcha -p "Write a commit message for:
$(git diff --staged)" --always-approve
matcha --prompt-file ./prompt.txt --always-approveCI-shaped review (--always-approve still honors deny rules and hooks):
matcha -p "Review changes for bugs. Reply OK, or list issues." \
--output-format json --always-approve | jq -r '.text'Common flags
| Flag | Role |
|---|---|
-p, --single | Prompt text (--print is an alias). Conflicts with --prompt-json / --prompt-file. |
--output-format json | One result object. Also plain, streaming-json, streaming-messages-json. |
--always-approve / --yolo | Skip interactive tool prompts. Same idea as --permission-mode bypassPermissions. |
-m, --model | Model ID from your Provider. |
--cwd | Working directory (also used to find .git as the project root). |
--tools / --disallowed-tools | Headless-only tool allowlist / denylist (internal IDs, for example read_file). |
--max-turns | Headless-only cap on assistant turns. |
--allow / --deny | Permission rules (Bash(npm*), Edit(src/**), …). Deny wins. |
--rules | Extra text appended to the system prompt. |
For containers, you can mount ~/.matcha read-only: sessions then stay ephemeral. Do not put API keys in auth.json; that file is metadata. Use the Provider’s official env var.
What is unavailable
- **Matcha-hosted runners** — there is no official cloud job that runs the prompt for you.
- **Product relay** — do not use
matcha agentwithoutstdio, and do not pass--grok-ws-url. Barematcha agentis a different, relay-oriented mode. - **Self-update** —
--no-auto-updateis accepted and does nothing. - **Account OAuth** —
--oauth/--device-authfail closed.