Package Exports
- relay-ide
- relay-ide/dist/server/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (relay-ide) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
relay-ide
Control Claude Code from your phone or any browser — manage multiple terminal sessions across repos and worktrees with a mobile-friendly web UI.
Prerequisites
| Dependency | Why |
|---|---|
| Node.js 24+ | Runtime for the server |
| Claude Code CLI | Default coding agent — must be in your PATH |
| Codex CLI | Optional — alternative coding agent. Install if you want to use Codex sessions |
GitHub CLI (gh) |
Optional — required for the PRs tab. Run gh auth login after installing. |
Getting Started
1. Install
npm install -g relay-ide2. Start the server
relay-ide --bgThis installs a persistent background service (launchd on macOS, systemd on Linux) that starts on login and restarts on crash. See Background Service for more options.
Or run in the foreground:
relay-ide3. Set your PIN
Open http://localhost:3456 in your browser. On first visit you'll be prompted to create a PIN that protects access to your Claude sessions.
If you started the server in the foreground, you can set the PIN in the terminal instead.
4. Add your project directories
Click Settings in the app to add root directories — these are parent folders that contain your git repos (scanned one level deep).
You can also edit ~/.config/relay-ide/config.json directly:
{
"rootDirs": ["/home/you/projects", "/home/you/work"]
}5. Access from your phone
Relay IDE binds to 0.0.0.0 by default, but you should not expose it to the public internet. Use Tailscale for a private encrypted connection between your devices — see Remote Access below.
Remote Access
The recommended way to access Relay IDE from another device (phone, tablet, laptop) is Tailscale, which creates a private encrypted network using WireGuard.
Install Tailscale on your computer and on your phone/tablet
- macOS:
brew install tailscaleor download from tailscale.com/download - Linux: follow the install guide
- iOS/Android: install the Tailscale app from your app store
- macOS:
Sign in to the same Tailscale account on both devices
Find your computer's Tailscale IP — run
tailscale ipor check the admin console (looks like100.x.y.z)Open the app on your phone at
http://100.x.y.z:3456
Your traffic is encrypted end-to-end, no ports are exposed to the internet, and only devices on your Tailscale network can reach the server.
Alternatives: Cloudflare Tunnel or ngrok also work, but they expose your server to the public internet and rely on the PIN as your only defense.
Platform Support
Tested on macOS and Linux. Windows is not currently tested — file watching and PTY spawning may behave differently.
CLI Usage
Usage: relay-ide [options]
relay-ide <command>
Commands:
update Update to the latest version from npm
install Install as a background service (survives reboot)
uninstall Stop and remove the background service
status Show whether the service is running
worktree Manage git worktrees (wraps git worktree)
add [path] [-b branch] [--yolo] Create worktree and launch Claude
remove <path> Forward to git worktree remove
list Forward to git worktree list
pin Manage authentication PIN
reset Reset the PIN (interactive, requires TTY)
Options:
--bg Shortcut: install and start as background service
--port <port> Override server port (default: 3456)
--host <host> Override bind address (default: 0.0.0.0)
--config <path> Path to config.json (default: ~/.config/relay-ide/config.json)
--yolo With 'worktree add': pass --dangerously-skip-permissions to Claude
--version, -v Show version
--help, -h Show this helpBackground Service
Run as a persistent service that starts on login and restarts on crash:
relay-ide --bgOr with custom options:
relay-ide install --port 4000Manage the service:
relay-ide status # Check if running
relay-ide uninstall # Stop and remove- macOS: Uses launchd (
~/Library/LaunchAgents/) - Linux: Uses systemd user units (
~/.config/systemd/user/) - Logs (macOS):
~/.config/relay-ide/logs/ - Logs (Linux):
journalctl --user -u relay-ide -f
Configuration
Config is stored at ~/.config/relay-ide/config.json (created on first run).
When running from source, it uses ./config.json in the project root instead.
| Field | Default | Description |
|---|---|---|
host |
0.0.0.0 |
Bind address |
port |
3456 |
Server port |
cookieTTL |
24h |
Auth cookie lifetime (e.g. 30m, 12h, 7d) |
rootDirs |
[] |
Directories containing your git repos (scanned one level deep) |
claudeCommand |
claude |
Path to the Claude Code CLI binary |
claudeArgs |
[] |
Extra arguments passed to every session |
defaultAgent |
claude |
Default coding agent CLI (claude or codex) |
Root directories can also be managed from the Settings button in the app.
PIN Management
The PIN hash is stored in config under pinHash.
Reset via CLI (recommended):
relay-ide pin resetThis requires an interactive terminal. You'll be asked to verify your current PIN (if set), then enter a new one.
Reset manually:
- Delete the
pinHashfield from~/.config/relay-ide/config.json - Restart the server (
relay-ide uninstall && relay-ide --bg) - Open the web UI and set a new PIN
Features
Session Management
- Multi-agent support — choose between Claude Code and Codex as the coding agent per session, with a configurable default in Settings
- Repo sessions — click any idle repo to instantly open Claude with
--continue(no dialog), or start fresh from the new-session dialog - Branch-aware worktrees — create worktrees from new or existing branches with a type-to-search branch picker
- Worktree isolation — each worktree session runs in its own git worktree under
.worktrees/ - Resume sessions — click inactive worktrees to reconnect with
--continue - Persistent session names — display names, branch names, and timestamps survive server restarts
- Scrollback buffer — reconnect to a session and see prior output
- Yolo mode — skip permission prompts with
--dangerously-skip-permissions(per-session pill button) - Worktree cleanup — delete inactive worktrees via the trash pill button (removes worktree, prunes refs, deletes branch)
Pull Requests
- Pull requests tab — view your open PRs (authored and review-requested) via
ghCLI, organized in collapsible per-repo groups with count badges, Author/Reviewer filter, and one-click session creation from any PR branch
GitHub Webhooks (real-time PR / CI updates)
By default the app polls GitHub every 30 seconds for PR and CI status. Connect a webhook for instant updates instead:
- Connect GitHub — open Settings → Integrations → GitHub and authorise the OAuth App. This requests the
repoandadmin:repo_hookscopes so the app can manage webhooks on your behalf. - Set up webhooks — open Settings → Integrations → Webhooks. Click Setup Webhook next to any repo. The app creates a GitHub webhook pointing at a smee.io proxy channel and starts a local smee client to relay events.
- Verify — the webhook panel shows a health indicator (last event timestamp). Once connected, polling stops for that repo and updates arrive in real time.
No public server is required. The smee.io proxy forwards GitHub webhook payloads to your local instance over a persistent SSE connection.
UI
- Tabbed sidebar — switch between Repos, Worktrees, and PRs views with shared filters and item counts
- Sidebar filters — filter by root directory, repo, or text search
- Inline actions — pill buttons on session cards for rename, YOLO, worktree creation, and delete (hover on desktop, long-press on mobile)
- Resizable sidebar — drag the sidebar edge to resize; collapse/expand with a button (persisted to localStorage)
- Responsive layout — works on desktop and mobile with slide-out sidebar
- Touch toolbar — mobile-friendly buttons for special keys (hidden on desktop)
- Clipboard image paste — paste screenshots directly into remote terminal sessions (macOS clipboard + xclip on Linux)
Settings
- Full-screen Settings dialog — redesigned as a scrollable full-screen modal with a table-of-contents drawer for quick section navigation
- GitHub integration — connect via OAuth App (Device Flow) for PR data, CI status, and webhook management
- Webhook management — self-service webhook CRUD per repo with smee.io proxy, health state, and auto-provision backfill
- Jira integration — connect Jira and configure project mappings for the org dashboard tickets panel
Operations
- PIN-protected access with rate limiting
- Real-time updates — worktree changes on disk are pushed to the browser instantly via WebSocket
- Smart polling — falls back to 30-second polling for repos without webhooks; switches off automatically once a webhook is active
- Update notifications — toast notification when a new version is available, with one-click update
- CLI self-update —
relay-ide updateto update from npm
Architecture
TypeScript + ESM backend (Express + node-pty + WebSocket) compiled to dist/. Svelte 5 frontend (runes + Vite) compiled to dist/frontend/.
relay-ide/
├── bin/
│ └── relay-ide.ts # CLI entry point
├── server/
│ ├── index.ts # Express server, REST API routes
│ ├── sessions.ts # PTY session manager (node-pty)
│ ├── ws.ts # WebSocket relay (PTY ↔ browser)
│ ├── watcher.ts # File watcher for .worktrees/ changes
│ ├── auth.ts # PIN hashing, verification, rate limiting
│ ├── config.ts # Config loading/saving, worktree metadata
│ ├── clipboard.ts # System clipboard operations (image paste)
│ ├── service.ts # Background service management (launchd/systemd)
│ └── types.ts # Shared TypeScript interfaces
├── frontend/
│ └── src/
│ ├── components/ # Svelte 5 components (Sidebar, Terminal, SessionList, etc.)
│ ├── lib/state/ # Reactive state modules (.svelte.ts)
│ ├── lib/api.ts # REST API client
│ ├── lib/ws.ts # WebSocket connection management
│ ├── lib/types.ts # Frontend TypeScript interfaces
│ ├── lib/utils.ts # Shared utilities (path display, time formatting, device detection)
│ └── lib/actions.ts # Svelte actions (scroll-on-hover, longpress-click)
├── test/ # Unit tests (node:test)
├── dist/ # Compiled output (gitignored)
├── config.example.json
└── package.jsonLicense
MIT