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:

PieceHeadless behavior
InputThe prompt on the flag or file. Piped stdin is **not** the prompt.
Outputstdout. Default is plain text; --output-format json is one object.
PermissionsThere is no TUI to click. Use --always-approve (alias --yolo) in CI, plus --allow / --deny if you need guardrails.
SessionEach run starts a **new** session unless you pass -r / -c.
Exit0 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-approve

Useful 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-approve

CI-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

FlagRole
-p, --singlePrompt text (--print is an alias). Conflicts with --prompt-json / --prompt-file.
--output-format jsonOne result object. Also plain, streaming-json, streaming-messages-json.
--always-approve / --yoloSkip interactive tool prompts. Same idea as --permission-mode bypassPermissions.
-m, --modelModel ID from your Provider.
--cwdWorking directory (also used to find .git as the project root).
--tools / --disallowed-toolsHeadless-only tool allowlist / denylist (internal IDs, for example read_file).
--max-turnsHeadless-only cap on assistant turns.
--allow / --denyPermission rules (Bash(npm*), Edit(src/**), …). Deny wins.
--rulesExtra 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 agent without stdio, and do not pass --grok-ws-url. Bare matcha agent is a different, relay-oriented mode.
  • **Self-update** — --no-auto-update is accepted and does nothing.
  • **Account OAuth** — --oauth / --device-auth fail closed.