> ## Documentation Index
> Fetch the complete documentation index at: https://docs.synti.co/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Reference

> Full command and flag reference for synti-cli, the terminal client for a Synti server.

`synti-cli` is the terminal client for Synti. It connects over WebSocket (`ws://` or `wss://`)
to a running [headless server](/server/headless) and lets you list workspaces, drive
sessions, and stream agent responses from scripts and CI.

<Note>
  For a gentler, task-oriented walkthrough of connecting the client, see
  [CLI Client](/server/cli). This page is the exhaustive flag reference.
</Note>

## Prerequisites

* [Bun](https://bun.sh/) runtime installed.
* For `run` and `--validate-server`: an API key via `--api-key`, `$LLM_API_KEY`, or a
  provider-specific variable (e.g. `$ANTHROPIC_API_KEY`).
* For every other command: a running Synti headless server with a URL and token.

## Installation

```bash theme={null}
# Option A: run directly from the workspace
bun run apps/cli/src/index.ts <command>

# Option B: link globally (adds synti-cli to your PATH)
cd apps/cli && bun link
synti-cli <command>
```

### Quick start

The fastest way to try it — no server setup needed. The `run` command spawns its own server:

```bash theme={null}
ANTHROPIC_API_KEY=sk-... synti-cli run "Hello, world!"
```

## Connection options

| Flag                  | Env var              | Default     | Description                            |
| --------------------- | -------------------- | ----------- | -------------------------------------- |
| `--url <ws[s]://...>` | `SYNTI_SERVER_URL`   | —           | Server WebSocket URL                   |
| `--token <secret>`    | `SYNTI_SERVER_TOKEN` | —           | Authentication token                   |
| `--workspace <id>`    | —                    | auto-detect | Workspace ID                           |
| `--timeout <ms>`      | —                    | `10000`     | Request timeout                        |
| `--tls-ca <path>`     | `SYNTI_TLS_CA`       | —           | Custom CA cert for self-signed TLS     |
| `--json`              | —                    | `false`     | Raw JSON output for scripting          |
| `--send-timeout <ms>` | —                    | `300000`    | Timeout for the `send` command (5 min) |

Flags take precedence over environment variables. If `--workspace` is omitted, the CLI
auto-detects the first available workspace.

## Commands

### Info & health

```bash theme={null}
synti-cli ping              # Verify connectivity (clientId + latency)
synti-cli health            # Check credential store health
synti-cli versions          # Show server runtime versions
```

### Resource listing

```bash theme={null}
synti-cli workspaces        # List all workspaces
synti-cli sessions          # List sessions in the workspace
synti-cli connections       # List LLM connections
synti-cli sources           # List configured sources
```

### Session operations

```bash theme={null}
synti-cli session create [--name <n>] [--mode <m>]   # Create a session
synti-cli session messages <id>                       # Print message history
synti-cli session delete <id>                         # Delete a session
synti-cli cancel <id>                                 # Cancel processing
```

### Send a message (streaming)

```bash theme={null}
# Send a message and stream the agent response in real time
synti-cli send <session-id> <message>

# Pipe text from stdin
echo "Summarize this file" | synti-cli send <session-id>

# Read from stdin explicitly
cat document.txt | synti-cli send <session-id> --stdin
```

The `send` command subscribes to session events and streams them to stdout:

* `text_delta` — text streamed inline
* `tool_start` — `[tool: name]` marker
* `tool_result` — tool output (truncated to 200 chars)
* `error` — printed to stderr, exit code 1
* `complete` — exit code 0
* `interrupted` — exit code 130

### Power user

```bash theme={null}
# Raw RPC call — send any channel with JSON args
synti-cli invoke <channel> [json-args...]

# Subscribe to push events (Ctrl+C to stop)
synti-cli listen <channel>
```

Examples:

```bash theme={null}
synti-cli invoke system:homeDir
synti-cli invoke sessions:get '"workspace-123"'
synti-cli listen session:event
```

### Run (self-contained)

```bash theme={null}
synti-cli run <prompt>
synti-cli run --workspace-dir ./project --source github "List open PRs"
```

The `run` command is fully self-contained — it spawns a headless server, creates a session,
sends the prompt, streams the response, and exits. No separate server setup needed. An API key
is resolved from `--api-key`, `$LLM_API_KEY`, or a provider-specific variable (e.g.
`$ANTHROPIC_API_KEY`, `$OPENAI_API_KEY`).

| Flag                     | Default     | Description                                   |
| ------------------------ | ----------- | --------------------------------------------- |
| `--workspace-dir <path>` | —           | Register a workspace directory before running |
| `--source <slug>`        | —           | Enable a source (repeatable)                  |
| `--output-format <fmt>`  | `text`      | Output format: `text` or `stream-json`        |
| `--mode <mode>`          | `allow-all` | Permission mode for the session               |
| `--no-cleanup`           | `false`     | Skip session deletion on exit                 |
| `--server-entry <path>`  | —           | Custom server entry point                     |

**LLM configuration:**

| Flag                | Env fallback   | Default            | Description                                                                             |
| ------------------- | -------------- | ------------------ | --------------------------------------------------------------------------------------- |
| `--provider <name>` | `LLM_PROVIDER` | `anthropic`        | Provider: `anthropic`, `openai`, `google`, `openrouter`, `groq`, `mistral`, `xai`, etc. |
| `--model <id>`      | `LLM_MODEL`    | (provider default) | Model ID (e.g. `claude-sonnet-4-5-20250929`, `gpt-4o`, `gemini-2.0-flash`)              |
| `--api-key <key>`   | `LLM_API_KEY`  | (provider env)     | API key — also checks provider-specific vars like `$OPENAI_API_KEY`                     |
| `--base-url <url>`  | `LLM_BASE_URL` | —                  | Custom endpoint for proxies, OpenRouter, or self-hosted models                          |

```bash theme={null}
# Multi-provider examples
synti-cli run --provider openai --model gpt-4o "Summarize this repo"
GOOGLE_API_KEY=... synti-cli run --provider google --model gemini-2.0-flash "Hello"
synti-cli run --provider anthropic --base-url https://openrouter.ai/api/v1 --api-key $OR_KEY "Hello"
```

The prompt can also be piped via stdin:

```bash theme={null}
echo "Summarize this file" | synti-cli run
cat error.log | synti-cli run "What's causing these errors?"
```

### Validate server

```bash theme={null}
# Against a running server
synti-cli --validate-server --url ws://127.0.0.1:9100 --token <token>

# Self-contained (auto-spawns a server)
synti-cli --validate-server
```

When no `--url` is provided, `--validate-server` automatically spawns a local headless server
(the same way `run` does), runs the validation, and shuts it down. It exercises a full
server-lifecycle integration test — connect/handshake, credential health check, workspace and
session listing, message streaming, tool use, and temporary source and skill creation — cleaning
up every resource it creates on completion. Use `--json` for machine-readable output.

<Warning>
  `--validate-server` mutates workspace state while it runs: it creates and deletes a temporary
  session, source, and skill. All of them are removed when the run finishes.
</Warning>

## Scripting patterns

```bash theme={null}
# Get workspace IDs
WORKSPACES=$(synti-cli --json workspaces | jq -r '.[].id')

# Count sessions per workspace
for ws in $WORKSPACES; do
  COUNT=$(synti-cli --json --workspace "$ws" sessions | jq length)
  echo "$ws: $COUNT sessions"
done

# Create a session and capture its ID
SESSION_ID=$(synti-cli --json session create --name "CI Run" | jq -r '.id')

# Send a message and wait for completion
synti-cli send "$SESSION_ID" "Run the test suite and report results"

# Clean up
synti-cli session delete "$SESSION_ID"
```

## TLS / wss\://

For remote servers with TLS:

```bash theme={null}
# Trusted certificate (Let's Encrypt, etc.)
synti-cli --url wss://server.example.com:9100 ping

# Self-signed certificate
synti-cli --url wss://server.example.com:9100 --tls-ca /path/to/ca.pem ping
```

The `--tls-ca` flag sets `NODE_EXTRA_CA_CERTS` before connecting. You can also set `SYNTI_TLS_CA`
in your environment.

## Troubleshooting

| Symptom                        | Cause                             | Fix                                           |
| ------------------------------ | --------------------------------- | --------------------------------------------- |
| `Connection timeout`           | Server not running or unreachable | Check the server is started; verify the URL   |
| `AUTH_FAILED`                  | Wrong token                       | Check `SYNTI_SERVER_TOKEN` matches the server |
| `PROTOCOL_VERSION_UNSUPPORTED` | Version mismatch                  | Update the CLI and server to the same version |
| `WebSocket connection error`   | Network issue or TLS problem      | For self-signed certs, use `--tls-ca`         |
| `No workspace available`       | Workspace not yet created         | Create one via the desktop app or API         |
