Agents & MCP
Drive the AirStrings CLI from scripts and AI agents: JSON output, exit codes, env-var auth, paging, and the MCP server.
The CLI is built to be driven by scripts and AI agents: every command has structured output, stable exit codes, and a headless auth path. This page is the contract.
Prompt, don't type
Once a workspace exists (airstrings init, once, at the repo root), you don't run these commands yourself. You describe the change and let your agent drive the CLI. A real Claude Code session, given only this prompt:
We're adding a free-trial CTA button to the pricing section. Add the string
pricing.cta_trialwith en="Start your free trial" plus translations for all our locales, using the airstrings CLI. Don't publish yet.
The agent first read the project's existing strings to match each locale's register (informal in Italian, German, and Spanish; formal vous in French), then set all five locales in one command:
airstrings strings set pricing.cta_trial --format text --push \
en="Start your free trial" it="Inizia la tua prova gratuita" \
de="Starte deine kostenlose Testphase" es="Empieza tu prueba gratuita" \
fr="Commencez votre essai gratuit"✓ Set pricing.cta_trial — 5 locale(s) [text] (pushed)and verified its own work before reporting back:
airstrings strings get pricing.cta_trialKey: pricing.cta_trial
Format: text
Values:
de: Starte deine kostenlose Testphase
en: Start your free trial
es: Empieza tu prueba gratuita
fr: Commencez votre essai gratuit
it: Inizia la tua prova gratuitaThe contract on the rest of this page is what makes sessions like this converge instead of flail. In the same session, the agent's first set attempt omitted --format: the CLI exited 2 with --format is required — must be 'text' or 'icu', and the agent fixed the command on the next try. A deterministic error costs one correction, not a guessing loop.
To make this the default way strings get edited in your repo, add one line to your project's CLAUDE.md or AGENTS.md:
All user-visible copy lives in AirStrings — manage it with
`airstrings strings set <key> --format text|icu --push`. Never hardcode strings.After that, "using the airstrings CLI" in the prompt becomes optional: the workspace and the agent file carry the context.
Structured output
Add --json to any command for machine-readable stdout. Human-readable text goes to stdout; errors and progress go to stderr. With --json, an error is one JSON object on stderr:
{"error":{"message":"publish: API error 403: Production is protected: changes reach it only by promotion.","next_step":"Publish to staging, then ask a human to promote: https://app.airstrings.com/projects/…/promote","exit_code":7}}next_step is the single action that unblocks you. MCP tool errors carry the same message and Next step: text.
airstrings strings ls --json
airstrings project --json | jq '.name'Exit codes
Branch on the exit code, not on message text:
| Code | Meaning | Retry? |
|---|---|---|
| 0 | ok | n/a |
| 1 | generic error | no |
| 2 | usage / bad input | no, fix the command |
| 3 | auth: bad or expired key, read key used for a write, or no key in this workspace for an open environment | no, fix credentials |
| 4 | not found | no |
| 5 | network | yes, with backoff |
| 6 | rate limited | yes, with backoff |
| 7 | environment protected | no, publish to staging; a human promotes |
| 8 | plan limit reached | no, a human upgrades |
| 9 | login pending | yes, after the user approves the printed URL |
Only 5 and 6 are retryable; everything else is deterministic and will fail the same way again.
Login from an agent
airstrings init --json with no key opens the browser and waits up to 90 seconds for an owner of the organization to approve, then finishes. With --no-browser or CI set, or if nobody approves in time, it exits 9 and prints:
{"status":"pending","verification_uri_complete":"https://app.airstrings.com/cli/approve?code=BCDF-GHJK","user_code":"BCDF-GHJK","expires_in":600,"next_step":"Approve in the browser at https://app.airstrings.com/cli/approve?code=BCDF-GHJK, then run the same command again"}Give the URL to the user, then re-run the same command; the re-run waits up to 90 seconds for the approval. On success the org key is stored in ~/.config/airstrings/credentials.json, a project named after the folder is created (never reused by name) and staging becomes the active environment.
Staging active, protected production
Production is protected, so an agent publishes to staging:
- To ship, write and
publishto staging, runairstrings promote preview, and hand the printed Apply in the dashboard link to a human. A full-power org key can apply it itself:airstrings promote --to production. - For SDK setup,
airstrings sdk-config --env productionreturns production's IDs and public key with any key of the project.
Env-var auth (headless / CI)
For ephemeral agents and CI, skip init entirely and authenticate with environment variables. They override any workspace credentials.
| Variable | Purpose |
|---|---|
AIRSTRINGS_ORG_API_KEY | Org key; wins over every other key. For CI across several projects, use a gated (non-full-power) org key created in the dashboard |
AIRSTRINGS_API_KEY | Project key (as_proj_…); preferred in CI, create one on the dashboard's API Keys page |
AIRSTRINGS_PROJECT_ID | Optional: skips project lookup (one fewer round-trip) |
AIRSTRINGS_ENV_ID | Optional: skips environment lookup |
AIRSTRINGS_BASE_URL | Optional: overrides the default base URL |
AIRSTRINGS_NO_BROWSER | Optional: print the login URL without opening a browser |
The CLI uses the first key it finds: AIRSTRINGS_ORG_API_KEY, AIRSTRINGS_API_KEY, the workspace key, then the stored login. A project key resolves its project; staging is used when it is open, otherwise the default environment. An org key needs a workspace or --project <id|name>. Legacy 64-hex environment keys keep working for their one environment.
Confirm what you are pointed at any time with airstrings status --json, which returns source ("workspace" or "env"), project_id, env_id, base_url, protection ("protected", "open" or "unknown"), key_scope ("read", "write" or "unknown"), key_type ("org", "project", "environment" or "none"), key_source, hint ({message, next_step}), stored_keys (masked keys stored in the workspace; [] when it uses the login), and the available environments.
Paging large lists
strings ls --json returns { "data": [...], "pagination": { "has_more": bool, "next_cursor": string } }. Loop by passing next_cursor back via --cursor until has_more is false.
airstrings strings ls --limit 50 --json
airstrings strings ls --cursor <next_cursor> --json
airstrings strings ls --key-prefix home. --jsonPrefer --limit/--cursor or a --key-prefix filter over an unbounded ls so results stay small.
Typical agent flow
airstrings init --json # browser opens, user approves; on exit 9 re-run
airstrings status --json
airstrings strings set welcome.title en="Welcome" --format text --push
airstrings strings ls --key-prefix welcome. --json
airstrings publish en --jsonMCP server
airstrings-mcp is a separate stdio binary that exposes workspace operations as MCP tools, for AI clients without shell access (e.g. Claude Desktop). It ships with the CLI install.
airstrings mcp install
airstrings mcp install --claude-desktopmcp install targets Claude Code by default; pass --claude-desktop for Claude Desktop. Restart Claude and the tools are available.
The tools mirror the workspace commands (init, set/rm, ls, push, pull, publish) and your AI picks them automatically. They honor the same environment variables and stored login as the CLI. airstrings_login, and airstrings_init without a key, return status: "pending" with the approval URL; call again after the user approves. airstrings_sdk_config returns SDK setup values (IDs, public keys, per-platform snippets) for any environment, and airstrings_promote_preview includes the apply_url a human opens to apply a promotion. airstrings_status returns the same stored_keys as status --json. A separate set of variant tools — airstrings_variant_set, airstrings_variant_status, airstrings_variant_start, airstrings_variant_stop, and airstrings_variant_promote — exposes the variants workflow (set variant text, inspect status, start/stop, promote a winner) to agents without shell access. Prompt in product terms:
Translate the welcome module into all our locales.
Add a string checkout.cta with en="Place order", translated for every locale, and publish it.
Prefer the CLI when you have a shell
The MCP server exposes a subset of the CLI. If your agent has shell access, drive airstrings directly. It is more composable and supports paging, --json, and the exit codes above.