# Installing the CLI

> Applies to: ChengOS v0.1.0+ ｜ Last verified: 2026-08-12 ｜ Source: `crates/cheng-cli/src/config.rs`, `crates/cheng-cli/src/main.rs`, `deploy/chengos.sh`

The `cheng` CLI is a terminal client for ChengOS. It does not need to live on the server — it
runs on your laptop and drives a ChengOS installation anywhere, which is the point: the machine
you work on and the machine that runs workflows do not have to be the same one.

## Install

If you already installed ChengOS with `--with ...,cli`, you have it. Otherwise run the wizard
from `deploy/`:

```bash
./chengos.sh cli
```

It asks which kind of install this is:

1. **Local machine** — auto-connects to `http://127.0.0.1:19225`.
2. **Remote machine** — prompts for the server URL, e.g. `https://your-server.example.com`.

To get `cheng` on your `PATH` from any directory, choose **Install Command Shortcuts** from the
interactive menu, which symlinks it into `/usr/local/bin`.

## Configuration precedence

Settings resolve highest-first. Knowing this order saves a lot of confusion about why a flag
"did not work":

1. Command-line flags
2. Environment variables — `CHENG_SERVER_URL`, `CHENG_TOKEN`
3. The config file
4. Built-in defaults

The config file lives at `$CHENG_CONFIG`, or `~/.config/cheng/config.json` by default.

## The config file

```json
{
  "server_url": "https://your-server.example.com",
  "token_file": "~/.config/cheng/token",
  "default_workspace": "Default Workspace",
  "default_workflow": "main_chat",
  "workspace_mode": "server_local",
  "auth_storage": "auto",
  "request_timeout_secs": 30
}
```

Defaults: `server_url` is `http://localhost:19225`, `default_workspace` is `Default Workspace`,
`default_workflow` is `main_chat`, and `request_timeout_secs` is `30`.

## Tokens

The CLI is careful with bearer tokens: they are **never echoed, never written to REPL history,
and never written to project files.** Persisting one is an explicit choice, and it goes in the
user-scoped config file — either inline as `token`, or better, as a `token_file` pointer to a
file containing just the token.

Prefer the `CHENG_TOKEN` environment variable over storing it at all.

`--auth-storage` picks the storage policy: `auto`, `keyring` (the OS keychain), `host-bound`,
`encrypted-file`, `file`, or `none`. `auto` chooses the strongest option available on your
system, which on a desktop usually means the keyring.

## Server-side prerequisite for sandboxes

One requirement is easy to miss and produces a confusing failure: **`CHENG_CLI_ALLOWED_ROOTS`
must be set on the server.** It is a colon-separated list of absolute directories usable as CLI
sandboxes, and **CLI sessions are disabled entirely if it is unset.**

The CLI and the API must also see those paths *in the same filesystem namespace*. A path that
means one thing on your laptop and another inside a Docker container will not work — which is
the usual cause when a sandbox appears empty or missing.

## Workspace modes

Where file and shell tools actually execute:

| Mode | Tools run | Use when |
|---|---|---|
| `server_local` (default) | On the API host | The files live on the server |
| `client_local` | In the CLI, against your local directory | You want an agent working on the code in front of you |

Set it per-session with `--workspace-mode`, or persistently with `workspace_mode` in the config
file.

`client_local` has its own safety settings under a `workspace_tools` config section — shell
execution can be enabled or disabled, raw `sh -c` strings are **off by default** as high risk,
and there are timeout limits, an environment variable allowlist, and deny patterns. Git and test
execution are toggled separately.

## Verify

```bash
cheng --version
cheng sessions      # lists your CLI sessions on the server
```

If `sessions` returns an authentication error, the token is wrong or absent. If it reports that
CLI sessions are unavailable, `CHENG_CLI_ALLOWED_ROOTS` is not configured on the server.

## Next steps

- [Using the CLI](/docs/cli-usage) — sessions, commands, and background agents.
- [Installation problems](/docs/fix-install-issues) — when the above does not work.
