# CLI & Scriptability API

> Control Crystl from the command line. Open gems, manage shards, approve permissions, and read terminal output programmatically.

The `crystl` CLI lets you control Crystl from any terminal. List gems, approve permissions, read terminal output, and script multi-agent workflows — all without touching the GUI.

## Setup

After installing Crystl, the CLI binary is inside the app bundle. Create an alias:

```bash
alias crystl='/Users/$(whoami)/Applications/Crystl.app/Contents/MacOS/CrystlCLI'
```

Or add it to your `.zshrc` for permanent access. The CLI automatically reads the auth token from `~/.crystl-bridge-token` — no configuration needed.

**Requires Crystl.app to be running.** The CLI talks to Crystl's local HTTP bridge.

## Commands

### status

Overview of all gems, shards, and running agents. This is the default command.

```bash
crystl status
crystl status --json
```

### gems

List all open gems with their shards and agent status.

```bash
crystl gems
crystl gems --json
```

### open

Open a project directory as a new gem.

```bash
crystl open ~/Projects/myapp
crystl open .
```

### close

Close a gem by name or UUID.

```bash
crystl close myapp
```

### shards

List shards in a gem.

```bash
crystl shards
crystl shards --gem myapp
```

### send

Send text to a terminal shard. Like typing into the terminal.

```bash
crystl send "git status"
crystl send --gem myapp "claude 'fix the tests'"
crystl send --gem myapp --shard opal "ls -la"
```

### screen

Dump the terminal screen content. See what an agent is doing without switching tabs.

```bash
crystl screen
crystl screen --gem myapp
crystl screen --gem myapp --shard opal
```

### pending

List pending permission requests.

```bash
crystl pending
```

### approve / deny

Approve or deny a pending permission request by ID.

```bash
crystl pending          # see request IDs
crystl approve 1        # approve request #1
crystl deny 2           # deny request #2
```

### token

Print the current bearer token for debugging.

```bash
crystl token
```

## Scripting Examples

### Monitor an agent

```bash
# What is the agent doing right now?
crystl screen --gem myapp

# Poll every 5 seconds
watch -n5 crystl screen --gem myapp
```

### Approve from another terminal

```bash
crystl pending        # see what's waiting
crystl approve 1      # approve it
```

### Launch parallel agents

```bash
crystl open ~/Projects/frontend
crystl open ~/Projects/backend
crystl send --gem frontend "claude 'update the API client'"
crystl send --gem backend "claude 'add the new endpoint'"
```

### JSON for scripting

```bash
crystl gems --json | jq '.gems[].name'
crystl pending --json | jq '.pending | length'
```

## HTTP API

The CLI wraps a local HTTP API at `http://127.0.0.1:19280/api/v1/`. You can call it directly with curl:

```bash
TOKEN=$(head -1 ~/.crystl-bridge-token)

# List gems
curl -s -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:19280/api/v1/gems | jq

# Send a command
GEM_ID="..."  # from gems response
SHARD_ID="..."  # from gems response
curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text":"ls\r"}' \
  "http://127.0.0.1:19280/api/v1/gems/$GEM_ID/shards/$SHARD_ID/send"

# Subscribe to real-time events (SSE)
curl -N -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:19280/api/v1/events
```

### Endpoints

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/v1/gems` | GET | List open gems |
| `/api/v1/gems` | POST | Open a gem |
| `/api/v1/gems/:id` | GET | Get gem details |
| `/api/v1/gems/:id` | DELETE | Close a gem |
| `/api/v1/gems/:id/shards/:sid/send` | POST | Send text to terminal |
| `/api/v1/gems/:id/shards/:sid/screen` | GET | Get screen content |
| `/api/v1/pending` | GET | List pending permissions |
| `/api/v1/pending/:id/decide` | POST | Approve or deny |
| `/api/v1/history` | GET | Recent decisions |
| `/api/v1/notifications` | GET | Recent notifications |
| `/api/v1/events` | GET | SSE event stream |

All endpoints require `Authorization: Bearer <token>` header.

## Security

- **Auth:** Every request requires a bearer token read from `~/.crystl-bridge-token` (0600 permissions, regenerated each launch)
- **Remote /send disabled:** The `send` endpoint only works from localhost. Remote connections (Tailscale, relay) cannot send terminal input.
- **Rate limited:** 100 requests per second per client IP

---
Source: https://crystl.dev/docs/cli/
