Files

89 lines
4.4 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Commands
```bash
# Development (client + server with hot reload)
npm run dev
# Server only
npm run dev:server
# Client only
npm run dev:client
# Production build (frontend → dist/)
npm run build
# Run server against built dist/
npm start
```
No test runner is configured. Tests in `test/mvp/` and `tests/` are standalone Node.js scripts run directly:
```bash
node test/mvp/test-e2e.js
node test/mvp/test-hooks.js
```
## Environment
Required: `CLAWTAP_PASSWORD=<password>`
Optional: `PORT` (default 3456), `OPENAI_API_KEY` (enables voice transcription)
State stored in `~/.clawtap/` — SQLite DB, VAPID keys, push subscriptions, PID file.
In production, the server runs as a systemd user service (`~/.config/systemd/user/clawtap.service`) with env vars loaded from `~/.clawtap/env`; use `./update-service.sh` (not `npm install -g .`) to build and redeploy.
## Architecture
ClawTap bridges mobile browsers to AI CLI tools running in tmux on the dev machine.
```
Mobile PWA (React) ◄─ WebSocket ─► Express Server ◄─ tmux sendKeys ─► claude/codex/gemini CLI
```
### Server (`server/`)
- **`index.ts`** — Express app, HTTP/HTTPS server, REST routes, WS transport setup, graceful shutdown
- **`session-manager.ts`** — Bridges adapter events to WebSocket clients. Transport-agnostic. Routes all adapter events (streaming-text, tool-start/done, permission-request, etc.) to connected clients. Manages push notifications when no client is watching.
- **`adapters/`** — Plugin system for CLI backends
- **`interface.ts`** (`IAdapter`) — Abstract base class all adapters extend. Emits standardized events; see JSDoc for full event list.
- **`registry.ts`** — Registers adapters; `DEFAULT_ADAPTER` is `'claude'`
- **`shared/tmux-manager.ts`** — Core tmux primitive: create windows, send keys, paste buffers (>500 chars or multiline use paste buffer instead of sendKeys)
- **`claude/`**, **`codex/`**, **`gemini/`** — Per-adapter implementations
- **`transport/websocket-transport.ts`** — WS server; wraps raw `ws` into `ClientConnection` abstractions
- **`db.ts`** — SQLite via `better-sqlite3`; tables: `push_subscriptions`, `login_attempts`, `session_reviews`, `session_stats`, `user_preferences`
- **`push.ts`** — Web Push (VAPID) notifications
- **`auth.ts`** — Password-based auth with bcrypt + JWT; rate-limits login attempts by IP
- **`config.ts`** — Reads env vars; auto-detects HTTPS certs at `~/.clawtap/cert.pem` + `key.pem`
- **`stores/task-aggregator.ts`** — Aggregates task-tool events (TodoRead/TodoWrite/Task) into round-based groups for the mobile task panel
### Frontend (`src/`)
- **`App.tsx`** — Top-level view router (sessions / newchat / chat / settings). View persisted to `sessionStorage`; URL updated via `history.pushState`.
- **`lib/ws.ts`** — WebSocket singleton; reconnect logic
- **`lib/api.ts`** — Fetch wrapper with JWT auth header
- **`hooks/useChat.ts`** — Main chat hook: sends queries, handles all WS message types, manages message list and tool state
- **`hooks/useTaskState.ts`** — Consumes `TASK_STATE` WS events; surfaces round-based task groups to the FAB
- **`components/ChatView.tsx`** — Full chat screen with message list, tool cards, interactive prompt overlay, review panel
- **`components/FloatingReviewPanel.tsx`** — Multi-tab cross-AI review panel
- **`components/adapters/`** — Adapter-specific UI (models, permission modes, branding)
### WebSocket Protocol
All message types defined in `server/ws-types.ts` (`WS` const) and `server/types/messages.ts`. Key flows:
- Client sends `query` → server routes to adapter → adapter emits `streaming-text` / `tool-start` / `tool-done` / `session-idle` → server broadcasts to clients
- Adapter emits `permission-request` → server sends `interactive-prompt` to client → client sends `prompt-response` → server calls `respondInteractivePrompt`
- Cross-AI review: client calls `POST /api/reviews/register` → server broadcasts `review-started` to parent session clients
### Adding a New Adapter
1. Create `server/adapters/<name>/index.ts` extending `IAdapter`
2. Set static `id`, `displayName`, `command`
3. Implement `setup(app)`, `startSession`, `resumeSession`, `sendMessage`, `interrupt`, `getSessions`, `getMessages`
4. Register in `server/adapters/init.ts`
5. Add frontend branding in `src/lib/adapter-brands.ts`