# kenari CLI

`@kenarihq/cli` is the official kenari wrapper for using native models and kenari models in one Claude Code, Codex or Grok Build session. Plain `claude`, `codex` and `grok` commands keep using their native provider. kenari routing applies only when you start the tool through the wrapper.

To send every session to one kenari model instead, configure the tool directly: Claude Code uses environment variables and Codex uses its configuration file. See [Claude Code](/en/docs/claude-code) or [Codex](/en/docs/codex).

## Prerequisites

The CLI needs Node.js 18 or newer, and the tool you want to run must already be installed. The CLI starts that tool and does not install it. Check Node.js:

```bash
node --version
```

If Node.js is missing, install it from [nodejs.org](https://nodejs.org) or with your package manager, for example `brew install node` or `nvm install --lts`.

## Install

```bash
npm install -g @kenarihq/cli
```

`kenari update` upgrades the global install. `kenari update --check` reports the current and latest versions without installing. It refuses to run on a git checkout.

## Sign in

```bash
kenari login
```

This opens the kenari approval page in your browser. Click **Approve access**, and the CLI receives a new API key through a local callback on `127.0.0.1` and stores it in `~/.kenari/credentials.json`. The key is never printed in full. The callback needs a browser on the same machine as the CLI, and the sign-in times out after 5 minutes.

The new key appears under **API Keys** in the dashboard. You can revoke it at any time like any other key, and requests made with it follow the same billing as your other keys. This key can also create a separate key for each tool. See [Per-tool keys](/en/docs/account-keys).

### On a server or over SSH

On a server, container or SSH session there is no local browser. Create a key on the [API Keys](https://kenari.id/keys) page, then run:

```bash
kenari login --api-key
```

The prompt hides what you paste and shows one `*` per character, so you can see the paste landed. When stdin is not a terminal, the same flag reads the key from stdin, which suits an entrypoint or a CI step:

```bash
echo "$KENARI_KEY" | kenari login --api-key
```

Never pass the key as an argument. `kenari login --api-key kn-...` is rejected, because a key on the command line is saved in your shell history and is visible in `ps` to every user on the machine.

The old `--no-browser`, `--paste` and `--stdin` flags were removed. Use `--api-key` instead.

If your home directory is read-only, as in many containers, point `KENARI_HOME` at a writable path before you log in:

```bash
export KENARI_HOME=/tmp/kenari
echo "$KENARI_KEY" | kenari login --api-key
```

### Check the sign-in

```bash
kenari status --check
```

The `credential` line reads `stored` when a key is saved and `missing` when it is not. With `--check`, the command also reaches out over the network and prints one `check` line per target: `router`, `native_anthropic`, `native_openai`, `native_xai`, `kenari` and `catalog`. Each reads `ok` or `failed` with a reason. The `kenari` and `catalog` checks load the model catalog with your key. They do not prove that your balance covers a paid model. The command exits with a non-zero code when any check fails. Add `--json` for machine-readable output.

## Configure roles

```bash
kenari configure
```

The command asks which tool and which roles should use kenari. If more than one tool is installed, it asks which one to configure and defaults to all of them. If only one is installed, kenari selects it. In scripts, name the tool: `claude`, `codex` or `grok`.

Each role either stays `native` or uses a fixed model with the value `kenari/<model-id>`:

| Tool | Roles |
| --- | --- |
| Claude Code | `main`, `opus`, `sonnet`, `haiku`, `fable`, `subagents` |
| Codex | `main`, `review`, `subagents` |
| Grok Build | `main` |

`native` is the default. A `native` role keeps using the tool's own provider and sign-in, so sign in to Claude Code, Codex or Grok as you normally do. In Codex, `main` also accepts `picker`, which leaves the model choice to Codex, and `review` and `subagents` accept `inherit`, which uses the same model as the session.

Grok subagents use the same model as the session, so kenari copies `main` onto that slot and does not ask for it. Requests that Grok sends to kenari include kenari web search, and requests that stay native keep Grok's own search. If every Grok role is kenari, `kenari login` is enough. A native Grok role still needs `grok login` or `XAI_API_KEY`.

Non-interactive runs need `--yes` and every role of the tool. Grok only needs `--main`:

```bash
kenari configure claude \
  --main native \
  --opus native \
  --sonnet kenari/step-3-7-flash:free \
  --haiku native \
  --fable native \
  --subagents native \
  --yes

kenari configure codex \
  --main picker \
  --review inherit \
  --subagents kenari/step-3-7-flash:free \
  --yes

kenari configure grok \
  --main kenari/step-3-7-flash:free \
  --yes
```

A model id with the `kenari/` prefix always goes to kenari, and the wrapper never falls back to another provider. In Codex and Grok, an id without the prefix always stays native. In Claude Code, an id without the prefix on a main turn stays native, while the aliases `opus`, `sonnet`, `haiku`, `fable`, `best` and `opusplan`, and side requests such as compaction or subagents, follow the matching kenari slot. Choose ids from [Models and pricing](/en/docs/models), or run `kenari models`.

### Reasoning effort per role

A role that uses a kenari model can pin a reasoning level, and every request sent to that role uses it. Add `--<role>-effort`, for example:

```bash
kenari configure claude \
  --main native \
  --opus native \
  --sonnet kenari/glm-5-2 --sonnet-effort max \
  --haiku native \
  --fable native \
  --subagents native \
  --yes
```

The interactive `kenari configure` offers the same choice after you pick a model. The pin overrides the level the session asks for. kenari does not validate the level. If the model does not support it, the gateway uses the nearest supported level, and `kenari status` shows both values:

```text
effort      kenari/glm-5-2 requested=max (pinned) gated=xhigh 200 4m ago
```

`requested` is the level that reached the gateway and `gated` is the level it applied. `unset` means no level was sent, and `unreported` means the gateway did not say.

See the active routes per role:

```bash
kenari status
```

## Run the wrapper

```bash
kenari claude [args...]
kenari codex [args...]
kenari grok [args...]
```

Each launch starts a private router on a random `127.0.0.1` port, starts the original tool with settings that apply only to that process, forwards your terminal input and signals, and stops the router when the tool exits. The wrapper does not write provider settings or credentials into Claude Code, Codex or Grok configuration.

If `~/.claude/settings.json` still contains `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_API_KEY` or `apiKeyHelper`, `kenari claude` warns and ignores those values for the session. It does not edit the file.

To verify, send a first message inside the wrapped tool. A `401` means the credential is missing or revoked, so run `kenari login` again.

## Other commands

```bash
kenari status               # show the routing configuration, offline
kenari status --check       # also check the network, exits non-zero on failure
kenari models               # list models with prices
kenari reset [claude|codex|grok] # remove routes, keep the login
kenari logout               # remove the kenari credential from this machine
kenari update --check       # compare the installed and latest version
```

`kenari reset` does not change the tool's native configuration or your login. `kenari logout` removes only the kenari credential, so native roles keep working.

`kenari configure` downloads the model catalog and keeps it for 24 hours. A configuration with only native roles works without a login or catalog. A role that uses a kenari model fails to start when there is no valid catalog or credential, or when the model no longer exists.

## Files

The CLI keeps its own files in `~/.kenari`: `config.json`, `credentials.json`, `model-cache.json` and `state.json`. On macOS and Linux the directory is readable only by you (mode `0700`) and so are the files (mode `0600`). The key lives only in `credentials.json`, never in Claude Code, Codex or Grok configuration, command arguments or logs.

`KENARI_HOME` moves this directory. `KENARI_BASE_URL` overrides the kenari gateway, and plain HTTP is rejected unless `KENARI_ALLOW_HTTP=1` is set for local development. `CLAUDE_CONFIG_DIR`, `CODEX_HOME` and `GROK_HOME` point the CLI at non-default configuration directories of those tools.

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| `command not found: kenari` | The CLI is not installed, or `PATH` does not include the npm global prefix. | Reinstall with `npm install -g @kenarihq/cli`. Run `npm config get prefix` and add `<prefix>/bin` to `PATH`. |
| `credential  missing` in `kenari status` | No key is stored. | Run `kenari login`, or `kenari login --api-key` on a server. |
| `kenari login` never finishes | There is no browser on this machine, or the sign-in timed out after 5 minutes. | Use `kenari login --api-key` with a key from the [API Keys](https://kenari.id/keys) page. |
| `--paste was removed` or the same message for `--stdin` or `--no-browser` | You used a flag from an older CLI. | Use `kenari login --api-key`. |
| `--api-key takes no value` | You passed the key as an argument. | Run `kenari login --api-key` and paste at the prompt, or pipe the key on stdin. |
| `Kenari login required` | A role uses a kenari model and no key is stored. | Run `kenari login`. |
| `model "kenari/<id>" is not in the Kenari catalog` | The id is misspelled or the model was removed. | Run `kenari models`, then `kenari configure` with a listed id. |
| `check kenari failed: ...` in `kenari status --check` | The CLI cannot reach kenari, or the key was rejected. | Check your network, proxy and firewall, then log in again if the key was revoked. |
| `401` in a wrapped session | The key was revoked in the dashboard. | Run `kenari logout`, then `kenari login`. |
| `402` in a wrapped session | A configured model is paid and your balance is Rp 0. | Switch the role to `kenari/step-3-7-flash:free`, or top up. See [How billing works](/en/docs/billing). |

## See also

- [Claude Code](/en/docs/claude-code)
- [Codex](/en/docs/codex)
- [Models and pricing](/en/docs/models)
- [Authentication and API keys](/en/docs/authentication)
