clarc/README.md

116 lines
2.3 KiB
Markdown

# clarc
Self-hosted remote control for Claude Code. Wraps CLI in PTY, streams output to server, approve prompts from phone.
## quick start
```bash
# 1. start the server
just dev
# 2. create a device (one-time setup)
just seed dev "My Phone"
# 3. build the binary + symlink to ~/bin
bun build --compile src/cli.ts --outfile clarc
ln -sf $(pwd)/clarc ~/bin/clarc
# 4. set your secret
export CLAUDE_REMOTE_SECRET=dev # add to .bashrc/.zshrc
# 5. use it like claude
clarc
clarc -r
clarc --dangerously-skip-permissions
# 6. open browser/phone
open http://localhost:7200
```
## usage
### server
```bash
just dev # development with hot reload
just start # production
just check # lint + typecheck + test
```
Server runs on port 7200 (configure via PORT env var).
### create device
```bash
just seed <secret> <name>
```
Creates a device with the given secret and name. The secret is used to authenticate the CLI wrapper.
Default if you just run `just seed`:
- secret: "dev"
- name: "dev device"
### run claude
With the binary installed and `CLAUDE_REMOTE_SECRET` set, just use `clarc` like `claude`:
```bash
clarc # interactive
clarc -r # resume
clarc --help # shows help
clarc -p "explain this" # print mode
```
All arguments pass through to claude.
### configuration
Environment variables (add to .bashrc/.zshrc):
```bash
export CLAUDE_REMOTE_SECRET=dev # required
export CLAUDE_REMOTE_SERVER=ws://localhost:7200/ws # optional, this is the default
```
Or use flags to override:
```bash
clarc --secret other-device --server ws://remote:7200/ws
```
### shell aliases
```bash
alias cr='clarc'
alias crr='clarc -r'
alias crd='clarc --dangerously-skip-permissions'
alias crdr='crd -r'
```
### view output
Open http://localhost:7200 in browser or phone to:
- see live terminal output
- approve/reject permission prompts
- answer questions
## docker
```bash
just build # build image
just up # compose up
just down # compose down
just logs # compose logs
```
## architecture
Pure Bun stack:
- bun-pty for PTY wrapper
- bun:sqlite for persistence
- Bun.serve() for HTTP + WebSocket + SSE
- @xterm/headless for terminal emulation and state tracking
- plain text output (mobile-friendly)
Target: ~1000-1500 lines total.