11 KiB
CC-Web
A lightweight browser interface for Claude Code and Codex, designed to keep each agent close to its native CLI workflow while sharing the same web shell.
Screenshots
Features
- Lightweight runtime: low backend overhead, browser-based control panel.
- Dual-agent sessions: create Claude or Codex sessions on the same backend core.
- Agent-isolated views: switching Claude / Codex only shows that agent's sessions, recent state, settings, and import entry points.
- Agent-specific settings: Claude keeps template-based model config; Codex has its own path, default model, mode, and search settings.
- Multi-session management: create, switch, rename, and delete sessions; deleting a session also removes the local Claude history record.
- Local history import: import Claude history from
~/.claude/projects/and Codex rollout history from~/.codex/sessions/. - Session resume: context continuity via
--resume; you can also reattach via SSH +tmux attach -t claudewhen needed. - Background task support: Claude processes continue after browser disconnect and notify you on completion.
- Multi-channel notifications: PushPlus / Telegram / ServerChan / Feishu bot / QQ (Qmsg), configurable in Web UI.
- Process persistence: detached subprocess + PID files; running tasks survive service restarts.
- Multi-API switching: configure multiple API profiles and switch between them instantly from the UI.
- Password-based auth: initial password generation, forced first-login reset, and password change in Web UI.
Requirements
- Node.js >= 18
- Claude Code CLI and/or Codex CLI installed and configured
npm install -g @anthropic-ai/claude-code
npm install -g @openai/codex
Quick Start
Linux / macOS
git clone https://github.com/ZgDaniel/cc-web.git
cd cc-web
npm install
cp .env.example .env # optional; if omitted, an initial password is auto-generated
npm start
Windows
git clone https://github.com/ZgDaniel/cc-web.git
cd cc-web
npm install
copy .env.example .env & REM optional
Then run start.bat, or start manually with node server.js.
After startup, open http://localhost:8002 and sign in with your password.
Configuration
Environment Variables (.env)
| Variable | Required | Default | Description |
|---|---|---|---|
CC_WEB_PASSWORD |
No | Auto-generated | Web login password (migrated into config/auth.json on first start) |
PORT |
No | 8002 |
Service port |
CLAUDE_PATH |
No | claude |
Executable path to Claude CLI |
CODEX_PATH |
No | codex |
Executable path to Codex CLI |
PUSHPLUS_TOKEN |
No | - | PushPlus token (migrated into notification config on first start) |
Notification Configuration
Open the Settings (⚙) button in the sidebar to configure notifications in Web UI.
| Channel | Required Fields | How to Get |
|---|---|---|
| PushPlus | Token | Register at pushplus.plus |
| Telegram | Bot Token + Chat ID | Create bot via @BotFather |
| ServerChan | SendKey | Register at sct.ftqq.com |
| Feishu Bot | Webhook URL | Feishu group → Settings → Group Bot |
| QQ (Qmsg) | Qmsg Key | Obtain from qmsg.zendee.cn |
Settings are stored in config/notify.json. Tokens are masked in UI display.
Password Management
Passwords are stored in config/auth.json and support generation + UI updates:
- First startup (no password in
.envand noauth.json): auto-generates a random 12-character password, prints it to console, and requires password reset on first login. - Migration from
.env: ifCC_WEB_PASSWORDis already set, it is migrated toauth.jsonautomatically at startup. - Change password in UI: Settings panel → Change Password (requires current password).
- Password policy: at least 8 characters, with at least 2 of these categories: uppercase, lowercase, number, special character.
- After password change: all existing logged-in sessions are invalidated.
Project Structure
cc-web/
├── server.js # Node.js backend (HTTP + WebSocket + process management + notifications)
├── public/
│ ├── index.html # UI structure
│ ├── app.js # Frontend logic (WebSocket, UI interactions)
│ ├── style.css # Styles
│ └── sw.js # Service Worker (mobile notifications)
├── config/
│ ├── notify.json # Notification channel config (generated at runtime)
│ └── auth.json # Auth config (generated at runtime)
├── sessions/ # Chat history JSON files (generated at runtime)
├── logs/ # Process lifecycle logs (generated at runtime)
├── lib/ # Agent runtime + Codex rollout parsing helpers
├── scripts/ # Regression tooling + mock CLIs
├── .env.example # Environment variable template
├── start.bat # Windows startup script
├── .gitignore
├── package.json
└── README.md
Architecture
Process Model
Browser ←WebSocket→ Node.js (server.js) ←file I/O→ Claude / Codex CLI (detached)
- Each user message spawns either a Claude or Codex subprocess depending on the session agent.
- Subprocesses use
detached: true+proc.unref()and run independently from Node.js lifecycle. - stdin/stdout/stderr are bridged via files in
sessions/{id}-run/. - PID is persisted to disk and recovered after service restart (
recoverProcesses()). FileTailerstreams file updates to frontend in real time.
Background Task Flow
- User sends a message → spawn Claude subprocess.
- User closes browser → subprocess keeps running.
- Process completes → PID monitor detects exit.
- Completion notification is sent.
- User reconnects → completed response is synced.
Process Logs
logs/process.log uses JSONL format with automatic 2MB rotation.
| Event | Description |
|---|---|
process_spawn |
Process created (PID, mode, model) |
process_complete |
Process finished (exit code, duration, cost) |
ws_connect / ws_disconnect |
Client connected/disconnected |
ws_resume_attach |
Client reconnected to running process |
recovery_alive / recovery_dead |
Process recovery during service restart |
heartbeat |
Active process snapshot every 60 seconds |
View logs:
tail -f logs/process.log | jq .
Production Deployment
systemd Service
Create /etc/systemd/system/cc-web.service:
[Unit]
Description=CC-Web - Claude Code Web Chat UI
After=network.target
[Service]
Type=simple
User=your-user
WorkingDirectory=/path/to/cc-web
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=5
# Important: only stop Node.js process, not Claude child processes
KillMode=process
[Install]
WantedBy=multi-user.target
KillMode=process is important. It ensures systemd restart only stops Node.js, while Claude subprocesses continue and are reattached after recovery.
sudo systemctl enable cc-web
sudo systemctl start cc-web
Nginx Reverse Proxy
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8002;
proxy_http_version 1.1;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Long-running tasks may take time
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Windows Deployment
Use this mode when running CC-Web on a personal PC and controlling Claude / Codex from mobile.
Start with start.bat, or run manually:
cd cc-web
npm install
node server.js
LAN access (same Wi-Fi):
- Open
http://<your-lan-ip>:8002
Remote access:
- Recommended: Tailscale for secure private networking.
- Alternative: Cloudflare Tunnel (requires domain setup).
Release Notes
-
v1.2.10
- Implemented
/initbehavior aligned with native Claude Code and Codex CLI
- Implemented
-
v1.2.8
- Dual-agent (Codex): create Claude or Codex sessions on the same backend; agent-isolated sidebar, settings, and import
- Image upload: drag, paste, or attach images in both Claude and Codex sessions; client-side WebP compression, 7-day server cache, up to 4 images per message
- Session loading: loading overlay, hot session cache (4 slots, strong/weak hit), fix for streaming content disappearing on tab switch
- Theme system: full theme engine with CoolVibe Light, washi, and editorial variants; theme picker moved to sub-page
- Mobile UX: swipe-to-open/close sidebar, running-state badge replaces cwd label, button sizing fixes
- Backend refactor: spawn spec + event parsing extracted to
lib/agent-runtime.js; isolated regression scriptnpm run regression
-
v1.2.2
- Aligned context compression with Claude Code native behavior:
/compactis now actually sent to CLI instead of doing a local pseudo-reset. - Added automatic overflow recovery: when
Request too large (max 20MB)occurs, CC-Web runs/compactand replays the failed prompt automatically. - Added retry guard: if context is still too large after compacting, CC-Web stops auto-retry and asks for a narrower prompt range.
- Aligned context compression with Claude Code native behavior:
-
v1.2.1
- Fixed missing
AskUserQuestionoptions in Web UI by preserving structured tool input in backend and rendering question/option cards on frontend. - Added option-to-input shortcut: click an option to append it into the input box for quick confirmation.
- Fixed missing
-
v1.2
- Fixed layout overflow caused by long code blocks in messages. The page no longer stretches horizontally; code blocks scroll within the block.
- Improved mobile input behavior: Enter inserts newline by default, and sending is done via the send button.
-
v1.1
- Added compatibility improvements for Claude Code CLI on Windows.
Notes
- Claude support is still the more mature path, while Codex now supports isolated sessions, resume, import, background execution, and local cleanup.