wraith-cli
v0.6.0
Published
TUI and CLI for managing headless Claude Code runners, powered by Linear
Readme
Wraith
A TUI and CLI for managing headless Claude Code runners, powered by Linear.
Pick an issue from your Linear triage, fire off an autonomous Claude Code session in an isolated git worktree, and monitor everything from a keyboard-driven terminal dashboard — or remotely from your phone.
Prerequisites
- Bun v1.1+
- Git (wraith creates worktrees for each run)
- A Linear account and API key
- Claude Code CLI installed globally
Install
bun install -g wraithQuick Start
# 1. Navigate to your project
cd my-project
# 2. Initialize config
wraith init
# 3. Open the TUI
wraithwraith init will prompt you for your Linear API key and optional settings, then write a wraith.json in the current directory.
Configuration
Wraith looks for config in two places (in order of precedence):
wraith.json (per-project)
{
"linear_token": "lin_api_...",
"base_branch": "main",
"workspace": "my-workspace",
"anthropic_api_key": "sk-ant-...",
"prompt": {
"provider": "anthropic",
"api_key": "sk-ant-..."
},
"notifiers": [
{ "type": "slack", "webhook_url": "https://hooks.slack.com/..." },
{ "type": "telegram", "bot_token": "...", "chat_id": "..." }
],
"pair": {
"port": 7280,
"tunnel": true
}
}.env file
LINEAR_API_KEY=lin_api_...
ANTHROPIC_API_KEY=sk-ant-...Bun auto-loads .env files — no extra setup needed.
| Variable | Required | Description |
|---|---|---|
| LINEAR_API_KEY / linear_token | Yes | Linear API key from linear.app/settings/api |
| ANTHROPIC_API_KEY / anthropic_api_key | No | Enables AI-powered prompt generation. Without it, a basic template is used. |
Note: If
ANTHROPIC_API_KEYis set in your environment, Claude Code will use API token billing instead of your subscription. Wraith warns you about this on startup.
Usage
TUI (Interactive)
wraithOpens a full terminal dashboard with five screens:
- Home — Navigation hub with keyboard shortcuts
- Issues — Browse Linear triage, search, view details, move issues between states, fire off runs
- Projects — View Linear projects and their issues, start runs
- Runs — Monitor active sessions, view status, retry failed runs, archive completed ones
- Pair — Remote control via QR-based WebSocket pairing
Keyboard shortcuts
| Key | Action |
|---|---|
| 1-5 | Jump to screen |
| j / k or arrows | Navigate lists |
| Enter | Select / expand |
| / | Search issues |
| f | Fire off run (Issues screen) |
| m | Move issue state (Issues screen) |
| C | Start custom run (Runs screen) |
| R | Retry failed run (Runs screen) |
| x | Archive run (Runs screen) |
| r | Refresh |
| Esc | Back |
| q | Quit |
CLI
wraith init # Create wraith.json config
wraith issue <id> --run # Start a run for a Linear issue
wraith custom "<prompt>" # Start a custom run with a raw prompt
wraith runs # List all active runs
wraith runs <prefix> # Show run detail
wraith retry <prefix> # Retry a failed/crashed run
wraith archive <prefix> # Archive a completed/failed run
wraith logs <prefix> # Tail logs for a run
wraith watch # Watch run state transitions live
wraith pair # Start pair server (WebSocket + QR)
wraith telegram pair # Link Telegram DM to wraith
wraith telegram watch # Start Telegram bot (long-running)
wraith telegram supervisor # Install systemd service
wraith telegram supervisor uninstall # Remove systemd service
wraith telegram supervisor status # Check service statusRun prefixes are the first 8 characters of the run ID — just enough to be unique.
How Runs Work
When you fire a run (from TUI or CLI):
- Wraith fetches the full issue from Linear (description, attachments, comments)
- A git worktree is created at
.wraith/worktrees/<issue-id>/for branch isolation - An AI-powered prompt is generated from the issue context (or a basic template if no API key)
- A detached
claudeprocess is spawned in the worktree - Run metadata is stored in a local SQLite database (
.wraith/wraith.db) - Logs stream to
.wraith/runs/<run-id>/stdout.log
Run states: pending → spawning → running → completed / failed / crashed
You can also start a custom run without a Linear issue — just provide a raw prompt. Custom runs skip prompt generation and Linear integration, but still create an isolated worktree and ask Claude to open a PR. Use C in the Runs screen, wraith custom "<prompt>" from the CLI, or /prompt <text> via Telegram.
Telegram Bot
Wraith includes a Telegram bot for monitoring and controlling runs from your phone.
Setup
- Message @BotFather on Telegram and create a new bot
- Copy the bot token and add it to your
wraith.json:{ "telegram_bot": { "bot_token": "123456:ABC-DEF..." } } - Pair your chat:
wraith telegram pair— then send/startto your bot - Start the bot:
wraith telegram watch
Bot Commands
| Command | Description |
|---|---|
| /status | List all runs |
| /issue REG-123 | View issue details |
| /run REG-123 [note] | Start a run for an issue |
| /prompt <text> | Start a custom run |
| /retry REG-123 | Retry a failed run |
| /help | Show available commands |
Pair Mode (Remote Control)
Pair mode starts a WebSocket server and displays a QR code for connecting a remote client (e.g., an Android app):
wraith pairSupports optional Cloudflare Tunnel for NAT traversal — install cloudflared and set "pair": { "tunnel": true } in your config.
Notifications
Configure Slack or Telegram notifications for run state changes in wraith.json:
{
"notifiers": [
{ "type": "slack", "webhook_url": "https://hooks.slack.com/services/..." },
{ "type": "telegram", "bot_token": "123:ABC", "chat_id": "-100123" }
]
}Prompt Providers
Wraith can use different LLM providers to generate Claude Code prompts from issue context:
| Provider | Model | Config |
|---|---|---|
| anthropic (default) | Claude Sonnet | "prompt": { "provider": "anthropic", "api_key": "..." } |
| openai | GPT-4o | "prompt": { "provider": "openai", "api_key": "..." } |
| together | Llama 3.1 8B | "prompt": { "provider": "together", "api_key": "..." } |
If no provider is configured, a basic template is used instead.
Data Storage
All runtime data lives in .wraith/ in your project root:
.wraith/
├── wraith.db # SQLite database (run metadata)
├── runs/
│ └── <run-id>/
│ ├── config.json # Run config (issue, prompt, branch)
│ └── stdout.log # Claude Code output
└── worktrees/
└── <issue-id>/ # Isolated git worktreesAdd .wraith/ to your .gitignore.
VPS Setup (Headless Server)
Wraith is designed to run headless on a remote server so Claude Code can work autonomously while you monitor from anywhere. Here's how to set up a dedicated VPS.
1. Provision a Droplet
We recommend DigitalOcean. Create a Droplet with:
- Image: Ubuntu 24.04 LTS
- RAM: 8 GB minimum (Claude Code sessions are memory-hungry)
- CPU: 2+ vCPUs recommended
- Storage: 50 GB+ SSD (worktrees and logs add up)
2. Harden the Server
SSH in as root and lock things down:
# Enable firewall — block everything except SSH
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw enable
# Install and enable fail2ban
apt update && apt install -y fail2ban
systemctl enable --now fail2ban3. Create the claude User
# Create user with home directory
adduser claude
# Grant passwordless sudo
echo "claude ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/claude
chmod 0440 /etc/sudoers.d/claude4. Set Up the Workspace
Switch to the claude user and prepare your repos:
su - claude
# Install Bun
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
# Install Git if not present
sudo apt install -y git
# Clone your project(s)
git clone [email protected]:your-org/your-project.git
cd your-project
# Install dependencies and set up env
bun install
cp .env.example .env # Edit with your actual valuesRun any build steps your project needs and verify the repo is in a clean state.
5. Install Claude Code
Install Claude Code using the native installer:
curl -fsSL https://cli.anthropic.com/install.sh | shThen log in with your Max subscription:
claude loginFollow the prompts to authenticate. Your subscription covers all Claude Code usage — no API key billing.
6. Install and Run Wraith
bunx wraith-cli
# Navigate to your project
cd ~/your-project
# Initialize config
wraith-cli init
# Launch Wraith
wraith7. Set Up Telegram Bot
Set up the Telegram bot so you can monitor and control runs from your phone (see Telegram Bot for full details):
# Add bot token to wraith.json, then pair
wraith telegram pair
# Install as a systemd service (auto-restarts)
wraith telegram supervisor8. Pair with Wraith
From the TUI or CLI, start pair mode to connect a remote client:
wraith pairScan the QR code from your phone to monitor and control runs remotely.
License
MIT
