Remote control server for Claude CLI
Project description
Conn Server
A self-hosted server that lets you interact with Claude Code from any device over your network. Run Claude on a home server, connect from your phone or any WebSocket client.
Features
- WebSocket streaming — real-time text deltas, tool use events, and image sharing
- Multiple concurrent conversations — each with its own Claude process and working directory
- Session resume — conversations persist across reconnects
- Project context — point each conversation at a different project directory
- MCP integration — configure Model Context Protocol servers for extended tool access
- Web preview — auto-detect and serve dev servers for web projects
- Built-in TLS — auto-generated EC P-256 self-signed certificate with cert pinning (no CA needed)
- Self-hosted updates — optionally serve app releases from the server
Requirements
- Python 3.10+
- Claude Code (the Claude CLI) —
npm install -g @anthropic-ai/claude-code
Quick Start
Install from PyPI
pipx install conn-server
conn-server start
On first run, conn-server start will:
- Check that the Claude CLI is installed (guides you through installation if not)
- Walk you through configuration (port, projects directory)
- Generate TLS certificates and an auth token
- Ask if you want to install as a background service (launchd on macOS, systemd on Linux)
- Display a QR code for the mobile app
Prerequisites (if you don't have them):
- Python 3.10+ — download from python.org or
brew install python - pipx —
python3 -m pip install --user pipx && python3 -m pipx ensurepath(restart terminal after) - Node.js — download from nodejs.org (needed for Claude CLI)
- Claude CLI —
npm install -g @anthropic-ai/claude-code && claude(to authenticate)
CLI Commands
conn-server start # Start the server (interactive setup on first run)
conn-server stop # Stop the background service
conn-server restart # Restart the background service
conn-server status # Show server status and health
conn-server setup # Reconfigure (port, projects directory, auth token)
conn-server upgrade # Upgrade to latest version and restart
conn-server qr # Show the connection QR code
conn-server config # Show current configuration
conn-server logs # Show recent server logs
conn-server logs -f # Follow logs in real time
conn-server version # Show version
Developer Setup (from source)
If you're contributing or want to run from the repo:
./setup.sh
This creates a virtual environment, installs dependencies via pip install -e ., walks through configuration, and optionally installs the system service. The setup.sh script also handles Homebrew Python detection on macOS for OpenSSL compatibility.
Configuration
The server reads from ~/.conn/config.json:
{
"auth_token": "your-secret-token",
"host": "0.0.0.0",
"port": 8443,
"working_dir": "~/Projects"
}
Environment variables override the config file:
CONN_HOST— bind addressCONN_PORT— listen portCONN_WORKING_DIR— root directory for project listing
API
All endpoints require Authorization: Bearer {token} unless noted.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check (no auth) |
GET |
/conversations |
List all conversations |
GET |
/conversations/active |
List running conversation IDs |
DELETE |
/conversations/{id} |
Delete conversation |
GET |
/conversations/{id}/history |
Get message history |
POST |
/upload?conversation_id={id} |
Upload image |
GET |
/projects |
List available project directories |
POST |
/restart |
Gracefully restart server |
See docs/api.md for the full REST and WebSocket protocol reference.
Building a Custom Client
The WebSocket protocol is straightforward. Connect to wss://{host}:{port}/ws/chat (or ws:// if TLS is not configured) and:
- Authenticate — send
{"type": "auth", "token": "..."}as the first message. Server responds with{"type": "auth_ok"}. - Create a conversation — send
{"type": "new_conversation", "conversation_id": "uuid", "name": "My Chat", "working_dir": "/path/to/project"} - Send messages — send
{"type": "message", "text": "hello", "conversation_id": "uuid"} - Receive streaming responses — the server sends
text_delta,tool_start,tool_done, andmessage_completeevents with theconversation_id - Cancel — send
{"type": "cancel", "conversation_id": "uuid"}to stop a running response
The server sends {"type": "ping"} every 15 seconds; respond with {"type": "pong"} to keep the connection alive.
See docs/api.md for all message types and payloads.
Data Directory
All server data lives in ~/.conn/:
~/.conn/
├── config.json # Server configuration
├── sessions.json # Active conversation metadata
├── tls/ # TLS certificates (auto-generated on first run)
│ ├── server.crt # EC P-256 certificate (PEM)
│ └── server.key # Private key (PEM, 0600 permissions)
├── history/ # Conversation history (JSONL per conversation)
├── uploads/ # Uploaded images
├── logs/ # Server logs
├── releases/ # Optional: self-hosted app releases
├── worktrees/ # Git worktrees for conversations
└── mcp_servers.json # MCP server configuration
TLS
The server generates a self-signed EC P-256 certificate on first run and serves all traffic over HTTPS (port 8443). The certificate's DER bytes are included in the startup QR code so the mobile app can pin the exact certificate — no CA or reverse proxy needed.
To regenerate certificates:
rm -rf ~/.conn/tls/
# Restart the server — new certs are generated automatically
# Re-scan the QR code on all connected devices
macOS note: System Python links against LibreSSL, which has TLS handshake issues with Android's BoringSSL. Use Homebrew Python (brew install python) instead. The setup script handles this automatically.
Project Structure
The server is packaged as conn-server on PyPI. Source code lives in the conn_server/ package:
conn_server/
├── __init__.py # Package version
├── cli.py # CLI entry point (conn-server command)
├── server.py # FastAPI app, WebSocket + REST endpoints
├── config.py # Config management (~/.conn/config.json)
├── tls.py # EC P-256 cert generation, fingerprint, DER export
├── auth.py # Bearer token verification
├── session_manager.py # Conversation tracking, JSONL history
├── agent_manager.py # Claude subprocess management
├── mcp_config.py # MCP server configuration
├── mcp_catalog.py # MCP tool catalog
├── preview_manager.py # Background dev server management
├── project_config.py # Per-project settings
└── git_utils.py # Git utilities
Testing
pytest -v # All tests
pytest tests/test_session_manager.py # Single file
pytest -k "test_create" # Pattern match
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file conn_server-0.1.0.tar.gz.
File metadata
- Download URL: conn_server-0.1.0.tar.gz
- Upload date:
- Size: 73.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c63c97aeb27aa2f7ea84a7a404222dd4c751b74e57e6dba7878715b98399c124
|
|
| MD5 |
07431266214b6a7dfad8b5b3d7e44dd8
|
|
| BLAKE2b-256 |
b5932ab6658e2a96e0472d351c14853b8482b1812c2ccb5457dcd6e14db04502
|
File details
Details for the file conn_server-0.1.0-py3-none-any.whl.
File metadata
- Download URL: conn_server-0.1.0-py3-none-any.whl
- Upload date:
- Size: 46.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0eaeb07ccd2923b85a8a86e5fcdf512a4fe884639df8b9346b07a6ffca0dc396
|
|
| MD5 |
417367fa68ed7aebb6559ffbed2a7b2f
|
|
| BLAKE2b-256 |
4959c398f8e21c439badd8fa518e4807a7182d954a4b868a112282198e45da00
|