add resizing
This commit is contained in:
@@ -1,167 +1,137 @@
|
||||
# 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
|
||||
./script/dev # Start backend + frontend
|
||||
./script/test # Run E2E tests
|
||||
```
|
||||
|
||||
### Backend
|
||||
|
||||
```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
|
||||
clj -M:dev # Start REPL with dev tools
|
||||
clj -M:run # Start server (production mode)
|
||||
clj -M:test # Run unit tests
|
||||
```
|
||||
|
||||
### Frontend (SvelteKit)
|
||||
**REPL commands:**
|
||||
```clojure
|
||||
(go) ; Start server + file watcher
|
||||
(reset) ; Reload code
|
||||
(stop) ; Stop server
|
||||
```
|
||||
|
||||
### Frontend
|
||||
|
||||
```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
|
||||
npm install
|
||||
npm run dev # Dev server
|
||||
npm run build # Production build
|
||||
npm run check # TypeScript check
|
||||
```
|
||||
|
||||
### E2E Tests (Playwright)
|
||||
### E2E Tests
|
||||
|
||||
```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
|
||||
npm test
|
||||
npm run test:headed # Visible browser
|
||||
npm run test:ui # Interactive explorer
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
### Backend
|
||||
|
||||
```
|
||||
Claude Code/OpenCode CLI ↔ Spiceflow Server (Clojure) ↔ PWA Client (SvelteKit)
|
||||
↓
|
||||
SQLite DB
|
||||
server/src/spiceflow/
|
||||
├── core.clj # Entry point
|
||||
├── config.clj # Settings from config.edn
|
||||
├── db/
|
||||
│ ├── protocol.clj # DataStore interface
|
||||
│ ├── sqlite.clj # SQLite implementation
|
||||
│ └── memory.clj # In-memory (tests)
|
||||
├── adapters/
|
||||
│ ├── protocol.clj # AgentAdapter interface
|
||||
│ ├── claude.clj # Claude Code CLI
|
||||
│ ├── opencode.clj # OpenCode CLI
|
||||
│ └── tmux.clj # Terminal multiplexer
|
||||
├── api/
|
||||
│ ├── routes.clj # HTTP endpoints
|
||||
│ └── websocket.clj # Real-time streaming
|
||||
└── session/
|
||||
└── manager.clj # Session lifecycle
|
||||
```
|
||||
|
||||
### Backend (`/server`)
|
||||
### Frontend
|
||||
|
||||
- **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
|
||||
```
|
||||
client/src/
|
||||
├── routes/ # SvelteKit file-based routing
|
||||
│ ├── +layout.svelte
|
||||
│ ├── +page.svelte # Home (session list)
|
||||
│ └── session/[id]/+page.svelte
|
||||
├── lib/
|
||||
│ ├── api.ts # HTTP + WebSocket client
|
||||
│ ├── stores/sessions.ts
|
||||
│ └── components/
|
||||
└── app.css # Tailwind
|
||||
```
|
||||
|
||||
### Frontend (`/client`)
|
||||
### Protocols
|
||||
|
||||
- **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
|
||||
Database and CLI adapters use protocols for swappability:
|
||||
|
||||
### Key Protocols
|
||||
```clojure
|
||||
(defprotocol DataStore
|
||||
(get-sessions [this])
|
||||
(save-message [this msg]))
|
||||
|
||||
**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 (gear icon) to automatically grant file operation permissions. When enabled:
|
||||
|
||||
- **Applies to**: `Write` and `Edit` tools only (file create/modify operations)
|
||||
- **Does NOT apply to**: `Bash`, `WebFetch`, `WebSearch`, `NotebookEdit`, or other tools
|
||||
- **Behavior**: Permission is still recorded in message history (green "accepted" status) but no user interaction required
|
||||
- **Use case**: Reduces interruptions during coding sessions when you trust Claude to make file changes
|
||||
|
||||
Other permission types (shell commands, web access, etc.) will still prompt for manual approval.
|
||||
|
||||
### 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
|
||||
(defprotocol AgentAdapter
|
||||
(spawn-session [this session])
|
||||
(send-message [this session msg]))
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/health` | GET | Health check |
|
||||
| `/api/sessions` | GET | List all sessions |
|
||||
| `/api/sessions` | POST | Create new session |
|
||||
| `/api/sessions` | GET | List sessions |
|
||||
| `/api/sessions` | POST | Create session |
|
||||
| `/api/sessions/:id` | GET | Get session with messages |
|
||||
| `/api/sessions/:id` | PATCH | Update session (title, auto-accept-edits) |
|
||||
| `/api/sessions/:id` | PATCH | Update session |
|
||||
| `/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 |
|
||||
| `/api/sessions/:id/send` | POST | Send message |
|
||||
| `/api/sessions/:id/permission` | POST | Handle permission |
|
||||
| `/api/sessions/:id/terminal` | GET | Get tmux content |
|
||||
| `/api/sessions/:id/terminal/input` | POST | Send tmux input |
|
||||
| `/api/ws` | WebSocket | Event streaming |
|
||||
|
||||
## Tech Stack
|
||||
## Configuration
|
||||
|
||||
- **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
|
||||
Environment variables or `server/resources/config.edn`:
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `SPICEFLOW_PORT` | 3000 | Server port |
|
||||
| `SPICEFLOW_HOST` | 0.0.0.0 | Server host |
|
||||
| `SPICEFLOW_DB` | spiceflow.db | SQLite path |
|
||||
| `CLAUDE_SESSIONS_DIR` | ~/.claude/projects | Claude sessions |
|
||||
| `OPENCODE_CMD` | opencode | OpenCode binary |
|
||||
|
||||
## Subdirectory CLAUDE.md Files
|
||||
|
||||
Each directory has specific details:
|
||||
- `server/` - REPL workflow, Mount lifecycle
|
||||
- `server/src/spiceflow/db/` - Schema, queries
|
||||
- `server/src/spiceflow/adapters/` - Adding adapters
|
||||
- `server/src/spiceflow/api/` - HTTP handlers, WebSocket
|
||||
- `server/src/spiceflow/session/` - Session state
|
||||
- `client/` - SvelteKit, PWA
|
||||
- `client/src/lib/` - API client, stores
|
||||
- `client/src/routes/` - Pages, routing
|
||||
- `e2e/` - E2E tests
|
||||
|
||||
Reference in New Issue
Block a user