A feature flag CLI for AI agents
The flagger CLI gives agents and people the same flag commands from a shell: create, set, target, kill, bulk, revert and eval. Every command takes --json and prints one JSON object, with errors as {"error":{"code","message"}}, and exits 0 when done, 2 when a change is waiting for a person's approval and 1 on an error. Agent tokens must give a --note on every write, which lands in the audit log with the run.
Updated
Why agents want a CLI
A coding agent already works in a shell. A CLI that answers in JSON and signals outcomes with exit codes fits the loop it runs: make a change, check the result, decide the next step. The flagger CLI does the same things as Flagger.gg's MCP server and API. Use whichever your agent handles best; many agents use the CLI inside scripts and checks, and MCP in conversation.
Commands: login, logout, whoami, list, get, create, set, target, kill, bulk, revert, eval, requests, request, approve, decline, tokens, import, mcp and version. approve and decline work for people only.
In development Packaged installs of the CLI (npm, Homebrew and go install) are in development. Until then, agents can make the same changes through the hosted MCP server at mcp.flagger.gg or the API at api.flagger.gg.
Ship a change behind a flag from the shell
- Give the agent a token. Create an agent token in the console, scoped to one project, its environments and its actions (
read create target rollout kill request). Set it asFLAGGER_TOKEN, or store it withflagger login --token -, which reads it from stdin.flagger whoamishows what the token can do. - Name the run. Set
FLAGGER_RUNto the agent's thread or job id, optionally followed by a URL, or pass--run. Every change records it. - Create the flag dark. In auto-live mode, the default, a new flag starts on unless it has a not-ready reason, so give one for unfinished work:
flagger create new_checkout --summary "New checkout page" --not-ready "Payment copy not reviewed" --note "Ships the new checkout dark". - Widen it in steps.
flagger set new_checkout admins --note "Admins first", thenflagger set new_checkout percent --percent 10 --note "Checks green". Turning on a flag that has a not-ready reason needs--confirm-not-ready. - Handle approval. If the project has approvals on and the change is wider than the agent may make alone, the CLI exits 2 and prints the request.
flagger request <id> --waitpolls until a person decides. - Kill it if checks fail.
flagger kill new_checkout --note "Error rate up after rollout"turns it off for everyone, works on protected flags and is never rate-limited.flagger revert new_checkoutputs back the state before the latest change.
JSON output and exit codes
With --json, every command prints exactly one JSON object on stdout: the API's answer as it is. Errors keep the same shape everywhere.
$ flagger kill new_checkout --note "Error rate up" --json
{"status":"applied","flag":{"key":"new_checkout","state":"off", …}}
$ flagger set new_checkout on --confirm-not-ready --note "Ready" --json
{"status":"pending_approval","request":{"id":"req_…", …},"url":"…"}
$ echo $?
2
$ flagger set new_checkout sideways --json
{"error":{"code":"invalid_request","message":"state must be one of …"}}
| Exit code | Meaning |
|---|---|
0 | Done. The change is applied, or the read succeeded. |
2 | Waiting for approval. A request was filed for a person to approve. |
1 | Error. The error.code says which, for example not_ready, forbidden, needs_approval or rate_limited. |
Flags on every command
| Flag | Environment variable | Meaning |
|---|---|---|
--project p | FLAGGER_PROJECT | Project slug. Defaults to the token's project. |
--env e | FLAGGER_ENV | Environment. Defaults to production. |
--note text | Why. Required for agent tokens on every write. | |
--run id [url] | FLAGGER_RUN | The agent's thread or run. |
--json | One JSON object on stdout. | |
--url u | FLAGGER_URL | API base URL. Defaults to https://api.flagger.gg. |
The token is FLAGGER_TOKEN, else the one flagger login stored in ~/.config/flagger/credentials.json.
Ask why a flag is on
flagger eval new_checkout --user usr_123 answers whether the flag is on for that user and why, for example bucket 37 ≥ 10%, admin, in targets or anonymous. Add --email, --admin or --workspaces to describe the user. flagger list --not-live shows the flags that aren't on for everyone yet, and flagger get <key> shows a flag with its history and pending requests.
FAQ
Is there a feature flag CLI with JSON output for AI agents?
Yes. Every flagger command takes --json and prints one JSON object, errors included, with exit codes 0 (done), 2 (waiting for approval) and 1 (error).
How does an agent know a change needs a human?
The CLI exits 2 and prints {"status":"pending_approval", …} with the request. The agent can wait with flagger request <id> --wait or move on.
Can an agent approve its own change from the CLI?
No. approve and decline need a person's own sign-in; agent and admin tokens can't approve.
Why does my agent's command fail without --note?
Agent tokens must say why on every write. The note goes into the audit log with the run, so a person can see which agent changed what and why.
Should my agent use the CLI or MCP?
Either. They make the same changes under the same token rules. The CLI suits scripts and CI checks; MCP suits agents that call tools directly.
Ship your next change behind a flag.
Sign up, add an SDK key to your app and give your agent a token.