# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Spiceflow is an AI Session Orchestration PWA for monitoring and interacting with Claude Code and OpenCode CLI sessions from mobile devices or web browsers. It's a monorepo with three main components: a Clojure backend server, a SvelteKit frontend, and Playwright E2E tests. ## Commands ### Backend (Clojure) ```bash cd server clj -M:run # Start server (port 3000) clj -M:test # Run tests with Kaocha clj -M:repl # Start REPL with nREPL for interactive development ``` ### Frontend (SvelteKit) ```bash cd client npm install # Install dependencies npm run dev # Start dev server (port 5173, proxies /api to 3000) npm run build # Production build npm run check # Type checking with svelte-check npm run check:watch # Watch mode for type checking ``` ### E2E Tests (Playwright) ```bash cd e2e npm test # Run all tests (starts both servers automatically) npm run test:headed # Run tests with visible browser npm run test:ui # Interactive Playwright UI mode ``` E2E tests use a separate database (`server/test-e2e.db`). ### Development Scripts ```bash ./script/dev # Start backend + frontend concurrently ./script/test # Start servers and run E2E tests ``` The `dev` script starts both servers and waits for each to be ready before proceeding. The `test` script uses a separate test database and cleans up after tests complete. ## Architecture ``` Claude Code/OpenCode CLI ↔ Spiceflow Server (Clojure) ↔ PWA Client (SvelteKit) ↓ SQLite DB ``` ### Backend (`/server`) - **Entry point**: `src/spiceflow/core.clj` - Ring/Jetty server with mount lifecycle - **Routing**: `src/spiceflow/api/routes.clj` - Reitit-based REST API - **Database**: Protocol-based abstraction (`db/protocol.clj`) with SQLite (`db/sqlite.clj`) and in-memory (`db/memory.clj`) implementations - **Adapters**: Pluggable CLI integrations (`adapters/protocol.clj`) - Claude Code (`adapters/claude.clj`) and OpenCode (`adapters/opencode.clj`) - **WebSocket**: `api/websocket.clj` - Real-time message streaming - **Session management**: `session/manager.clj` - Session lifecycle ### Frontend (`/client`) - **Routes**: SvelteKit file-based routing in `src/routes/` - **State**: Svelte stores in `src/lib/stores/` (sessions, runtime selection) - **API client**: `src/lib/api.ts` - HTTP and WebSocket clients - **Components**: `src/lib/components/` - UI components - `MessageList.svelte` - Displays messages with collapsible long content - `PermissionRequest.svelte` - Permission prompts with accept/deny/steer actions - `FileDiff.svelte` - Expandable file diffs for Write/Edit operations - `SessionSettings.svelte` - Session settings dropdown (auto-accept edits) - `InputBar.svelte` - Message input with steer mode support - **PWA**: vite-plugin-pwa with Workbox service worker - **Responsive**: Landscape mobile mode collapses header to hamburger menu ### Key Protocols **DataStore** (`db/protocol.clj`): - `get-sessions`, `get-session`, `save-session`, `update-session`, `delete-session` - `get-messages`, `save-message` **AgentAdapter** (`adapters/protocol.clj`): - `discover` - Find existing CLI sessions - `spawn` - Start CLI process with session - `send` - Pipe message to stdin - `read-stream` - Parse JSONL output - Adding new runtimes requires implementing this protocol ## Configuration Server configuration via `server/resources/config.edn` or environment variables: | Variable | Default | Description | |----------|---------|-------------| | `SPICEFLOW_PORT` | 3000 | Server port | | `SPICEFLOW_HOST` | 0.0.0.0 | Server host | | `SPICEFLOW_DB` | spiceflow.db | SQLite database path | | `CLAUDE_SESSIONS_DIR` | ~/.claude/projects | Claude sessions directory | | `OPENCODE_CMD` | opencode | OpenCode command | ## Features ### Permission Handling When Claude Code requests permission for file operations (Write/Edit) or shell commands (Bash), Spiceflow intercepts these and presents them to the user: - **Accept**: Grant permission and continue - **Deny**: Reject the request - **Steer ("No, and...")**: Redirect Claude with alternative instructions File operations show expandable diffs displaying the exact changes being made. ### Auto-Accept Edits Claude sessions can enable "Auto-accept edits" in session settings to automatically grant Write/Edit permissions, reducing interruptions during coding sessions. ### Session Management - **Rename**: Click session title to rename - **Delete**: Remove sessions from the session list - **Condense**: Collapse long messages for easier scrolling ### Mobile Optimization - Landscape mode collapses the header to a hamburger menu - Compact file diffs with minimal padding - Touch-friendly permission buttons ## Session Flow 1. User opens PWA → sees list of tracked sessions 2. User selects session → loads message history 3. User types message → POST to `/api/sessions/:id/send` 4. Server spawns CLI process with `--resume` flag 5. Server pipes user message to stdin 6. CLI streams response via stdout (JSONL format) 7. Server broadcasts to client via WebSocket 8. **If permission required** → WebSocket sends permission request → User accepts/denies/steers 9. Process completes → response saved to database ## API Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/api/health` | GET | Health check | | `/api/sessions` | GET | List all sessions | | `/api/sessions` | POST | Create new session | | `/api/sessions/:id` | GET | Get session with messages | | `/api/sessions/:id` | PATCH | Update session (title, auto-accept-edits) | | `/api/sessions/:id` | DELETE | Delete session | | `/api/sessions/:id/send` | POST | Send message to session | | `/api/sessions/:id/permission` | POST | Respond to permission request | | `/ws` | WebSocket | Real-time message streaming | ## Tech Stack - **Backend**: Clojure 1.11, Ring/Jetty, Reitit, next.jdbc, SQLite, mount, Kaocha - **Frontend**: SvelteKit 2.5, Svelte 4, TypeScript, Tailwind CSS, Vite, vite-plugin-pwa - **E2E**: Playwright