online-claude-code
v0.0.1
Published
Remote Claude Code agent - run Claude Code from anywhere
Maintainers
Readme
online-claude-code (OCC)
A Node.js CLI tool that transforms your local machine into a remote-controllable Claude Code agent. Run Claude Code tasks from anywhere via a persistent daemon.
Installation
npm install -g online-claude-codePrerequisites
- Node.js 18 or higher
- Claude Code CLI installed and authenticated
Quick Start
# Start the daemon
occ start --api-key YOUR_API_KEY
# Check status
occ status
# Stop the daemon
occ stopUsage
Start the daemon
# Start in background (default)
occ start --api-key YOUR_API_KEY
# Start in foreground for debugging
occ start --api-key YOUR_API_KEY --foreground
# Specify max concurrent executions
occ start --api-key YOUR_API_KEY --workers 3
# Use custom remote server
occ start --api-key YOUR_API_KEY --remote-url https://your-server.com
# Bind to specific port (0 = random ephemeral port)
occ start --api-key YOUR_API_KEY --port 8080
# Specify public URL (for NAT/firewall scenarios)
occ start --api-key YOUR_API_KEY --public-url https://myagent.example.com
# Bind to specific address (default: 0.0.0.0)
occ start --api-key YOUR_API_KEY --bind-address 127.0.0.1Environment Variables
You can also configure via environment variables:
export OCC_API_KEY=your_api_key
export OCC_REMOTE_URL=https://api.occ.example.com
export OCC_WORKERS=5
export OCC_HTTP_PORT=0
export OCC_PUBLIC_URL=https://myagent.example.com
export OCC_BIND_ADDRESS=0.0.0.0
occ startCheck daemon status
occ statusShows whether the daemon is running, its PID, and log directory location.
Stop the daemon
occ stopGracefully stops the daemon with SIGTERM, waiting up to 10 seconds for shutdown before force-killing.
How It Works
- Registration: On startup, the daemon registers with the remote coordination server using your API key
- HTTP Server: Starts a local HTTP server to receive commands from the remote server
- Heartbeat: Sends periodic heartbeat (every 30s) to maintain liveness and report status
- Workspace Management: Receives project files via zip upload and extracts into isolated workspaces
- Execution: Spawns Claude Code CLI processes to execute prompts against workspaces
- Streaming: Streams execution results back via HTTP in real-time
Architecture
┌─────────────────┐ HTTP POST ┌──────────────────┐
│ User Machine │ ─────────────────▶ │ Remote Server │
│ │ │ │
│ ┌───────────┐ │ HTTP callbacks │ │
│ │ OCC Daemon │ │◀──────────────────▶│ │
│ │ (HTTP │ │ │ │
│ │ server) │ │ └──────────────────┘
│ └─────┬─────┘ │ │
│ │ │ │ triggers
│ │ spawn │ ▼
│ ▼ │ ┌──────────────────┐
│ ┌───────────┐ │ │ Web UI/Slack │
│ │ Claude CLI│ │ └──────────────────┘
│ └───────────┘ │
└─────────────────┘HTTP API
The daemon exposes an HTTP server with the following endpoints:
Authentication
All endpoints require Bearer token authentication using the token received during registration.
Authorization: Bearer <token>Endpoints
POST /workspace/init
Initialize a new workspace from a zip file upload.
Content-Type: multipart/form-data
Fields:
workspaceId(required): Unique workspace identifiername(required): Workspace namedescription(optional): Workspace descriptionprocessPolicy(required):overwriteorreusezip(required): Zip file containing project files
Response:
{
"status": "success",
"workspaceId": "ws-123",
"path": "/home/user/.occ/workspaces/ws-123"
}POST /execute
Execute a Claude Code prompt in a workspace with streaming response.
Request:
{
"executionId": "exec-456",
"workspaceId": "ws-123",
"prompt": "Explain this codebase"
}Response: Server-Sent Events stream with the following event types:
output: Execution output chunk{"chunk": "Output text...", "timestamp": 1704067200000}complete: Execution finished successfully{"exitCode": 0, "timestamp": 1704067201000}error: Execution failed{"code": "EXECUTION_TIMEOUT", "message": "Execution timeout"}
GET /health
Health check endpoint returning daemon status.
Response:
{
"status": "healthy",
"version": "1.0.0",
"uptime": 3600,
"heartbeat": {
"lastSuccessfulAt": "2026-03-07T12:00:00.000Z",
"consecutiveFailures": 0,
"seqNum": 120
}
}Configuration
The daemon stores its configuration and state in ~/.occ/:
state.json- Registration token and agent IDdaemon.pid- Process ID fileworkspaces/- Downloaded project workspaceslogs/- Log fileslock/- Singleton lock files
Security
- File permissions are set to 0o700 on directories and 0o600 on sensitive files
- Zip extraction includes path traversal protection and zip bomb detection (100MB limit)
- Claude CLI runs with restricted tool access for automation
- No shell execution (direct spawn with array arguments)
- Dangerous environment variables are sanitized (LD_PRELOAD, LD_LIBRARY_PATH, etc.)
- Workspace path validation prevents escaping the allowed directory
- Bearer token authentication on all HTTP endpoints
Development
# Install dependencies
npm install
# Build
npm run build
# Run in development mode
npm run dev
# Run type checks
npm run lint
# Run tests
npm testProject Structure
src/
├── cli.ts # Main CLI entry point
├── commands/ # CLI commands
│ ├── start.ts # Start daemon command
│ ├── stop.ts # Stop daemon command
│ └── status.ts # Status command
├── daemon/ # Daemon implementation
│ ├── index.ts # Main daemon entry
│ ├── registration.ts # Server registration
│ ├── heartbeat.ts # Periodic heartbeat
│ └── shutdown.ts # Graceful shutdown
├── server/ # HTTP server
│ ├── http-server.ts # HTTP server implementation
│ ├── middleware/ # Auth middleware
│ └── routes/ # API routes
├── execution/ # Execution handling
│ ├── runner.ts # Claude CLI runner
│ └── concurrency.ts # Concurrency limiting
├── workspace/ # Workspace management
│ ├── manager.ts # Workspace lifecycle
│ └── zip.ts # Zip handling
├── utils/ # Utilities
│ ├── config.ts # Configuration
│ ├── logger.ts # Logging
│ ├── pidfile.ts # PID file management
│ ├── singleton.ts # Single instance lock
│ └── system.ts # System info
└── protocol/ # Protocol types
└── protocol.ts # Type definitionsLicense
MIT
