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

  1. 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 as FLAGGER_TOKEN, or store it with flagger login --token -, which reads it from stdin. flagger whoami shows what the token can do.
  2. Name the run. Set FLAGGER_RUN to the agent's thread or job id, optionally followed by a URL, or pass --run. Every change records it.
  3. 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".
  4. Widen it in steps. flagger set new_checkout admins --note "Admins first", then flagger set new_checkout percent --percent 10 --note "Checks green". Turning on a flag that has a not-ready reason needs --confirm-not-ready.
  5. 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> --wait polls until a person decides.
  6. 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_checkout puts 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 codeMeaning
0Done. The change is applied, or the read succeeded.
2Waiting for approval. A request was filed for a person to approve.
1Error. The error.code says which, for example not_ready, forbidden, needs_approval or rate_limited.

Flags on every command

FlagEnvironment variableMeaning
--project pFLAGGER_PROJECTProject slug. Defaults to the token's project.
--env eFLAGGER_ENVEnvironment. Defaults to production.
--note textWhy. Required for agent tokens on every write.
--run id [url]FLAGGER_RUNThe agent's thread or run.
--jsonOne JSON object on stdout.
--url uFLAGGER_URLAPI 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.

Sign up