# Command line (CLI)

`tandem` runs every Tandem operation from your terminal: the same ones the app, the REST API and the MCP server use, with the same checks and the same change history.

## Install and sign in

```bash
npm install -g tandemcrm
tandem login
```

`tandem login` shows a code and opens https://app.tandemcrm.app/device in your browser. Approve it there and the CLI is signed in **as you**, so it can do everything you can in the app, including approving suggestions and managing webhooks. Changes it makes are signed with your name. `tandem logout` signs it out.

For scripts and CI, use an API key instead: `tandem login --key crm_sk_…`, or set `TANDEM_API_KEY`. The CLI then acts as that key, like an agent, with the key's scopes. Self-hosting? Set `TANDEM_URL` or pass `--url` to `tandem login`.

## Commands

| Command | What it does |
| --- | --- |
| `tandem whoami` | Who you're signed in as, and the open workspace |
| `tandem workspaces` | Your workspaces |
| `tandem use <workspace>` | Switch workspace, by name, slug or id |
| `tandem ops` | Every operation you can run |
| `tandem help <operation>` | An operation's parameters |
| `tandem <operation> --param value …` | Run one |
| `tandem api <METHOD> <path>` | Any other endpoint, e.g. `tandem api GET /v1/webhooks` |
| `tandem export [file.zip]` | Download the whole workspace |

## Running operations

```bash
tandem search --query acme
tandem upsert_company --name Acme --domain acme.com
tandem update_deal --id 3f1c… --stage won --amount 24000
tandem create_task --title "Send the proposal" --due 2026-11-12 --record.type deal --record.id 3f1c…
tandem set_custom_fields --type deal --id 3f1c… --fields '{"budget": 50000}'
echo '{"name": "Globex", "domain": "globex.com"}' | tandem upsert_company -
```

Parameters are the operation's input fields as flags. Numbers, true/false and comma-separated lists are converted using the operation's schema; objects and lists of objects take JSON; dots set nested fields. `--input '{…}'` or `-` (JSON on stdin) gives the whole input, and flags override it. `--idempotency-key` makes a retried write run once.

Output is the operation's JSON result; `--compact` prints it on one line for `jq`. Errors go to stderr with a hint, and the exit code is 1.
