---
title: "CLI"
description: "Install the frazer CLI, sign in, pick an organization and project, choose an output format, and plan, apply and approve changes from your terminal."
url: https://frazer.ai/docs/cli
index: https://frazer.ai/docs/cli/llms.txt
tokens: 4651
---

> For agents: this page is indexed at https://frazer.ai/docs/cli/llms.txt, and every page at https://frazer.ai/llms.txt. Copy commands from this file exactly.

# CLI

`frazer` is the command line for everything in Frazer. It calls the same API as the console, the MCP server and the Terraform provider, so a command does exactly what the matching console action does, with the same permissions, plans and audit records. The command tree is generated from the API contracts, and a check in every Frazer build fails when an API method has no command, so the CLI never lags behind the API.

## Install

```sh
curl -fsSL https://get.frazer.ai | sh
```

The install script verifies the release’s signature before it installs anything. Builds exist for macOS, Linux and Windows, on amd64 and arm64, and every build is signed with cosign and carries SLSA provenance. The CLI is also published in a public Homebrew tap.

Check the install:

```sh
frazer version
```

## Sign in

1.  Sign in from a machine with a browser:
    
    ```sh
    frazer login
    ```
    
    The CLI opens Frazer’s sign-in page in your browser and receives the result on this machine. It creates a signing key for this device and keeps it in the OS keychain (macOS Keychain, Windows CNG or Linux Secret Service; a file readable only by you when there is no keychain).
    
2.  On a machine without a browser, such as a server you reached over SSH, use the device flow:
    
    ```sh
    frazer login --no-browser
    ```
    
    The CLI prints a code and `https://console.frazer.ai/device`. Open that page on another device where you are signed in, check who started the request and from where, type the code and choose **Approve**. Choose **Deny** if you did not start it.
    
3.  Check which configurations are signed in:
    
    ```sh
    frazer auth list
    ```
    

Your sign-in lasts up to 90 days, or 30 days without use. Access tokens live 15 minutes and the CLI refreshes them before each call. Credentials are stored in `~/.config/frazer/credentials.json`, readable only by you, and they are bound to this device’s key: a copy of the file is useless on another machine.

`frazer logout` revokes the sign-in and deletes the device key.

### Step-up for sensitive actions

Approving a change, creating a personal access token and a few other actions need a passkey or second factor from the last 10 minutes:

```sh
frazer login --step-up
```

### Scripts and CI

-   **A token in the environment.** `FRAZER_TOKEN`, or a file passed with `--access-token-file`, takes precedence over the stored sign-in. Use a [personal access token](https://frazer.ai/docs/api#authentication) here.
-   **A token for a script.** `frazer auth print-access-token` prints a 15-minute access token.
-   **CI without stored keys.** Use workload identity federation: a GitHub Actions or GitLab job exchanges its own OIDC token for a 15-minute Frazer token, and a condition on the job’s claims decides which jobs may. See [Identity and access](https://frazer.ai/docs/iam).
-   **Act as a service account** you are allowed to impersonate with `--impersonate-service-account`.
-   **Push and pull images.** `frazer auth configure-docker` installs the credential helper for [Registry](https://frazer.ai/docs/registry).

> **Caution:** The CLI sends a token over plain HTTP only to a loopback address, and it never prints a token unless you run `frazer auth print-access-token`.

## Configurations

A configuration is a named set of defaults, so you can switch between, for example, a staging and a production setup. Each configuration has its own sign-in.

```sh
frazer config configurations create acme-staging
frazer config configurations list
frazer config configurations activate acme-staging
```

Configurations are YAML files in `~/.config/frazer/configurations/` (under `$XDG_CONFIG_HOME` when it is set):

```yaml title="~/.config/frazer/configurations/acme-staging.yaml"
project: acme-staging
location: us-virginia1
format: table
```

| Key | What it sets |
| --- | --- |
| `project` | The project a command acts on when you pass no `--project` |
| `location` | The location when you pass no `--location`, such as `us-virginia1` or `global` |
| `format` | The default output format (see [Output formats](#output-formats)) |
| `api_endpoint` | The API endpoint; leave it unset for `api.frazer.ai` |
| `universe_domain` | The domain of a Frazer Private installation; also `FRAZER_UNIVERSE_DOMAIN` |

A flag beats a `FRAZER_*` environment variable, and an environment variable beats the active configuration.

## Organizations and projects

One sign-in reaches every organization you belong to. Most resources live in a project, and a project belongs to one organization. Two shortcuts reach them directly: `frazer organizations` (alias `orgs`) and `frazer projects` are the same commands as `frazer resourcemanager organizations` and `frazer resourcemanager projects`.

```sh
frazer projects list --organization acme
frazer projects create acme-staging --organization acme --dry-run
frazer projects create acme-staging --organization acme
frazer projects get acme-staging
```

-   **Project IDs** are 6 to 30 characters: lowercase letters, digits and hyphens, starting with a letter. They are unique across Frazer and never reused, even after a project is purged. IDs that start with `frazer`, `goog` or `system` are reserved.
-   **Organization IDs** are 4 to 24 characters. `frazer orgs create` also creates the organization’s infrastructure project, `<organization>-infra`.
-   **Choose the project** per command with `--project`, or set `project` in the active configuration. Choose the location with `--location`; there is no `--region` flag.
-   **Deleting a project** (`frazer projects delete`) stops its billing and suspends its resources at once, and keeps everything for 30 days. `frazer projects undelete` restores it within that window.

## Command grammar

Commands follow one pattern:

```text
frazer <service> <collection> <verb> [ID] [flags]
```

-   **Service**: the product’s one-word service ID, such as `kubernetes`, `databases`, `dns` or `secrets`. Registered aliases: `k8s` (kubernetes), `db` (databases) and `kv` (keyvalue, the in-memory store). The CLI never guesses from a prefix.
-   **Collection**: plural, in kebab case: `clusters`, `managed-zones`, `record-sets`. When a service’s ID is the plural of its main collection, the collection is dropped: `frazer devboxes create`, `frazer secrets create`.
-   **Verb**: `list`, `get`, `create`, `update`, `delete` and `undelete` map to the API’s standard methods; other verbs are the API’s custom methods in kebab case, such as `get-credentials` or `upgrade`.
-   **ID**: the resource’s ID. The CLI completes it into the full resource name from `--project`, `--location` and the active configuration.
-   **Flags**: `--kebab-case`. Request fields become flags; a structured field takes a JSON or YAML file through `--<field>-from-file`.

```sh
frazer kubernetes clusters create acme-production-2 --project acme-production \
  --location us-virginia1 --class production --dry-run
frazer kubernetes clusters get-credentials acme-production-1
```

`frazer --help` lists the services and workflows; `frazer <service> --help` lists a service’s commands.

### Workflows

A few top-level commands are workflows rather than API methods:

| Command | What it does |
| --- | --- |
| `frazer login`, `frazer logout` | Sign in and out ([Sign in](#sign-in)) |
| `frazer auth` | `list`, `print-access-token` and `configure-docker` |
| `frazer config` | Named configurations ([Configurations](#configurations)) |
| `frazer apply -f FILE` | Apply declarative YAML: plan first, then apply; removing resources asks for confirmation |
| `frazer export` | Write existing resources as YAML for `frazer apply`, or as HCL with `--format=hcl` for [Terraform and OpenTofu](https://frazer.ai/docs/terraform) |
| `frazer deploy` | Deploy the repository you are in ([Serverless](https://frazer.ai/docs/serverless)) |
| `frazer servers add` | Add a Linux server: over SSH from your laptop (`frazer servers add root@host`), or on the server itself ([Servers](https://frazer.ai/docs/servers#add-a-server-with-the-cli)) |
| `frazer logs` | Read and follow logs ([Frazer Monitoring](https://frazer.ai/docs/monitoring)) |
| `frazer monitoring metrics` | Read metrics ([Frazer Monitoring](https://frazer.ai/docs/monitoring)) |
| `frazer ssh` | Reach machines over Frazer Access, built into the CLI, with no VPN client to install ([Frazer Access and VPN](https://frazer.ai/docs/access)) |
| `frazer api` | Call any API method by name |
| `frazer mcp install` | Add the Frazer MCP server to your agent ([MCP](https://frazer.ai/docs/mcp)) |
| `frazer review` | Ask Frazer Reviewer for a review of a target; `frazer review verdict` is the second opinion auto-merge reads ([Lanes, verdicts and outcomes](https://frazer.ai/docs/reviewer/lanes)) |
| `frazer status --statusline` | One line of your plan’s and your organization’s usage, for a terminal’s status line |
| `frazer help --json` | Help as data: services, workflows and shortcuts with `--level names`, then `frazer <service> --help --json` ([The CLI for agents](https://frazer.ai/docs/for-agents/cli)) |
| `frazer schema <command>` | The JSON Schema of a command’s output; `--input` for its request |
| `frazer doctor` | Check sign-in, versions, the warm path and agent detection, with `next` for each failure |
| `frazer help search "<words>"` | The best commands for a sentence, from a local index of the cards, with no model and no network |
| `frazer version --json` | The version, the output contract and the optional behaviors this binary implements (`capabilities`) |
| `frazer config get --show-source` | Each default and where it came from: a flag, a `FRAZER_*` variable or a configuration; `--no-config` ignores configurations |
| `frazer version`, `frazer update` | Show the version; update the CLI ([Update](#update)) |
| `frazer completion` | Print a shell completion script |

## Output formats

Results go to stdout; plans, warnings and errors go to stderr, so a pipe gets only the result. When stdout is not a terminal, lists come as TSV with a header and errors as one JSON envelope on stderr; when an agent is detected, the output also keeps to a budget and says the count and the next page ([The CLI for agents](https://frazer.ai/docs/for-agents/cli)).

| `--format` | Output |
| --- | --- |
| `table` | Columns for people. The default |
| `table(field,…)` | A table with the columns you name |
| `json`, `yaml` | The full resource, in the same schema `frazer apply` reads |
| `tsv` | Rows with a header line, the default when piped |
| `ndjson` | One object a line, with `@meta` first and `@end` last |
| `value(field,…)` | Bare values, one line per item, for scripts |

```sh
frazer projects list --organization acme --format=json
frazer projects list --organization acme --format='value(name)'
```

Lists read every page for you. `--page-size` sets how many items each request asks for, and `--limit` caps the total.

## Common flags

| Flag | What it does |
| --- | --- |
| `--project`, `--location` | The project and location to act in; they override the configuration |
| `--format` | The output format |
| `--dry-run` | Plan the change and write nothing |
| `--async` | Return the long-running operation instead of waiting for it |
| `--wait` | When the change needs a person’s approval, wait for it and print what the change returned |
| `--etag` | Change the resource only if it still has this etag |
| `--page-size`, `--limit` | Page size and total for lists |
| `--access-token-file` | Use the token in this file |
| `--budget <usd>` | On a command that starts metered work: refuse above this cost (`BUDGET_EXCEEDED`, exit `5`); a run that spends it part way stops at a turn boundary and exits `14` |
| `--no-config` | Read only flags and `FRAZER_*` variables, so the result is the same on every machine |
| `--impersonate-service-account` | Act as a service account you may impersonate |
| `--help`, `--version` | Help for any command; the CLI’s version |

## Plans, apply and approvals

### Plan first

Every command that changes something takes `--dry-run`. `--plan` is a hidden alias of the same flag. Frazer runs every check of the real call, changes nothing and records nothing, and the CLI prints the plan:

-   **Changes**: each resource the call creates, changes or deletes.
-   **Quota impact**: each quota counter before and after, with a warning when one would be at 80 % or more of its limit. A change that would pass a limit fails here with `QUOTA_EXCEEDED` and a link to request more.
-   **Policy violations**: organization policy the change would break.
-   **Estimated cost**: the monthly cost of the change.
-   **Warnings**.

The would-be resource goes to stdout and the plan to stderr. For a plan a program can read, add `--async --format=json`.

### Apply

Run the same command without `--dry-run`. Calls that take a while return a long-running operation; the CLI follows it and prints the result. With `--async` it prints the operation and returns, and the service’s `operations` commands (`list`, `get`) follow it later.

Each invocation carries one request ID, reused for its own retries, so a retried create never creates twice. The CLI retries only calls that are safe to repeat.

To keep a set of resources in files, write them out with `frazer export` and apply them with `frazer apply -f`; an export applied unchanged plans no changes:

```sh
frazer apply -f vint-hill-default.yaml --dry-run
frazer apply -f vint-hill-default.yaml
```

### When a change needs approval

Some changes wait for a person. Every write an agent makes through MCP waits, IAM changes through MCP wait for someone who can set IAM policy, and an organization can hold people’s destructive or IAM changes in a project. In a production project a second person must approve.

A command that needs a person’s approval changes nothing. It prints the approval’s link and exits with code 13, needs a person (reason `APPROVAL_REQUIRED`). Add `--wait` to follow the approval instead: the CLI prints what the change returned once Frazer applies it, or exits with code 12 if the approval ends without applying it (rejected, expired, invalidated, canceled or failed).

#### Approver

```sh
frazer login --step-up
frazer approvals list --can-decide
frazer approvals approve apr_01JA3KQ7
```

#### Requester

```sh
frazer approvals wait apr_01JA3KQ7
```

`frazer approvals get`, `reject` and `cancel` complete the set. Only people approve: agents, service accounts, MCP tokens and personal access tokens can ask but never vote. A vote binds to the exact plan and the target’s current version, so if the resource changes first, the approval is void. A pending approval expires after 24 hours by default; once approved, Frazer applies the change at once, exactly once, as the person or agent who asked. See [Identity and access](https://frazer.ai/docs/iam) for the rules.

## Exit codes

Exit codes are stable, the same for `frazer` and `fir`: changing one is a breaking change.

| Code | Meaning |
| --- | --- |
| `0` | Success |
| `1` | An error no other code names |
| `2` | Usage: an unknown command, flag or argument, input refused before the call, the server’s `INVALID_ARGUMENT`, or `CONFIRMATION_REQUIRED` |
| `3` | Not found (`NOT_FOUND`) |
| `4` | Not signed in or not allowed (`UNAUTHENTICATED`, `PERMISSION_DENIED`) |
| `5` | A precondition failed (`FAILED_PRECONDITION`, `ABORTED` on a stale etag or version, `ALREADY_EXISTS`, `SESSION_REQUIRED`) |
| `6` | A quota or rate limit that time fixes (`RESOURCE_EXHAUSTED`, with when to retry) |
| `7` | Frazer was unavailable or too slow after retries (`UNAVAILABLE`, `DEADLINE_EXCEEDED`), or `--timeout` was reached |
| `10` | A long-running operation finished with an error |
| `11` | A check found a problem, for example `frazer approvals verify`, `frazer billing usage verify` or a review verdict of fail |
| `12` | An approval followed with `--wait` or `frazer approvals wait` ended without applying the change |
| `13` | Needs a person: an approval (`APPROVAL_REQUIRED`), no funds (`FUNDS_EXHAUSTED`), a person task or an answer only a person can give; `next` names what to follow |
| `14` | Stopped at a limit you set (`--max-turns`, a step limit or `--budget` reached part way); the result so far is kept and printed, and `next` continues with a larger limit |
| `130` | Interrupted (Ctrl-C) |
| `143` | Terminated (SIGTERM) |

## Errors

Errors go to stderr. In a terminal they print as text with the message from the API, then `next:` lines with the calls that fix them; when stdout is not a terminal, every error is one JSON envelope (`code`, `reason`, `message`, `next`, `retry`, `effects`, `exit`, `requestId`, `docs`), described on [The CLI for agents](https://frazer.ai/docs/for-agents/cli#errors). A permission denial adds a `decision:` line with its decision ID and a `troubleshoot:` line with the command that explains the denial; run it as printed. A quota error prints the limit, the usage and when it resets; a no-funds error prints the balance, the amount needed and the top-up step. See [Errors](https://frazer.ai/docs/errors) for the error model and every reason.

## Update

```sh
frazer update
```

`frazer update` installs the latest release from a signed manifest and refuses a manifest that fails verification. The CLI warns when it is more than one minor version behind the API, and when you use a deprecated command or field.

## Shell completion

`frazer completion` prints a completion script for your shell; `frazer completion --help` lists the shells and how to load the script.

## Commands

Every product’s commands, with what each does, are on [CLI commands](https://frazer.ai/docs/cli/commands), grouped by product page; `frazer <command> --help` shows every flag, and `--help --json` its card.

## Related

-   [API](https://frazer.ai/docs/api): the methods behind every command
-   [MCP](https://frazer.ai/docs/mcp): the same API for AI agents
-   [Errors](https://frazer.ai/docs/errors): reasons, decision IDs and fixes
-   [Terraform and OpenTofu](https://frazer.ai/docs/terraform): the same resources as code
-   [Identity and access](https://frazer.ai/docs/iam): roles, tokens, approvals and workload identity

## Pages in Reference

- [CLI](https://frazer.ai/docs/cli.md) (this page)
- [CLI commands](https://frazer.ai/docs/cli/commands.md)
- [Fir CLI](https://frazer.ai/docs/source/reference/cli.md)
- [API](https://frazer.ai/docs/api.md)
- [MCP](https://frazer.ai/docs/mcp.md)
- [Errors](https://frazer.ai/docs/errors.md)
- [Example values](https://frazer.ai/docs/example-values.md)
