CLI & Scriptability API

Updated April 25, 2026

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:

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.

crystl status
crystl status --json

gems

List all open gems with their shards and agent status.

crystl gems
crystl gems --json

open

Open a project directory as a new gem.

crystl open ~/Projects/myapp
crystl open .

close

Close a gem by name or UUID.

crystl close myapp

shards

List shards in a gem.

crystl shards
crystl shards --gem myapp

send

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

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.

crystl screen
crystl screen --gem myapp
crystl screen --gem myapp --shard opal

pending

List pending permission requests.

crystl pending

approve / deny

Approve or deny a pending permission request by ID.

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.

crystl token

Scripting Examples

Monitor an agent

# 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

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

Launch parallel agents

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

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:

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

EndpointMethodPurpose
/api/v1/gemsGETList open gems
/api/v1/gemsPOSTOpen a gem
/api/v1/gems/:idGETGet gem details
/api/v1/gems/:idDELETEClose a gem
/api/v1/gems/:id/shards/:sid/sendPOSTSend text to terminal
/api/v1/gems/:id/shards/:sid/screenGETGet screen content
/api/v1/pendingGETList pending permissions
/api/v1/pending/:id/decidePOSTApprove or deny
/api/v1/historyGETRecent decisions
/api/v1/notificationsGETRecent notifications
/api/v1/eventsGETSSE 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