The Contract
- JSON without asking. When stdout is not a terminal (which is every agent), commands print the exact API response as one JSON line. Errors are JSON envelopes on stderr with stable
codefields and arequestId. - Semantic exit codes.
0success,1API or runtime error,2usage error,3authentication error,4confirmation required,130/143interrupted by SIGINT / SIGTERM. Unknown commands fail hard with no fuzzy “did you mean” to misread. - Never hangs. Nothing waits on stdin unless it is a real terminal, and missing input is an immediate exit 2 with the fix in the message. Every request is bounded, response body included:
--timeout <duration>(90s,1500ms,5m) caps the whole command, retries and pages included, so it fits a tool-call budget. Long-running commands such asemails generatedefault to their own budget. SIGINT or SIGTERM stops the request in flight. - Stable surface. Commands and flags are additive across releases, and the manifest describes the installed build exactly.
Replaying an Unknown Outcome
The API keeps working after the CLI disconnects. So a write that ends inCLI_TIMEOUT, CLI_CONNECTION, CLI_INTERRUPTED or a 5xx may still complete. Its error envelope carries the idempotencyKey it was sent with and a retryCommand that re-runs it with that key, so the API returns the first attempt’s result instead of doing the work twice:
retryCommand; never re-run the original command with a fresh key. A 409 IDEMPOTENCY_IN_PROGRESS means the first attempt is still running (the API holds its key for up to 15 minutes): wait, then run retryCommand again. A read that fails this way changed nothing and simply re-runs.
The replay needs the API’s idempotency store. While it is degraded, a send refuses with a retryable 503 rather than risk sending twice, but other writes run without the guarantee. So for a write that must not happen twice (creating a brand, say), pass --max-retries 0, and check whether it landed before you run retryCommand.
The Confirmation Protocol
Irreversible commands (campaign sends, deletes, trigger fires, cancels) do not execute in a non-interactive session. They exit with code 4 and print an envelope:summary to your human, and only run the confirmCommand after they approve. Passing --yes yourself is reserved for actions the user already asked for explicitly. Test sends (emails send --test --to you@example.com) are the safe lane and skip the gate.
Discovery for Agents
brew-cli docs api (the live GET /v1/help catalog) and the served agent guide at https://brew.new/api/v1/llms.txt.
The repo also ships a ready-made skill at skills/brew-cli/SKILL.md that teaches Claude Code and compatible harnesses this whole contract in about fifty lines.
A Typical Agent Session
Need Help?
Our team is ready to support you at every step of your journey with Brew. Choose the option that works best for you:- Self-Service Tools
- Talk to Our Team
Search Documentation
Type in the “Ask any question” search bar at the top left to instantly find relevant documentation pages.
ChatGPT/Claude Integration
Click “Open in ChatGPT” at the top right of any page to explore it further with ChatGPT or Claude.