Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ The Makefile's `dev-backend` target and `run.sh` both conditionally set `NODE_EX
| GET/POST | `/api/sessions` | `routes/sessions.ts` | List sessions, create session |
| POST | `/api/sessions/:id/stop` | `routes/sessions.ts` | Stop active session |
| GET/POST | `/api/settings` | `routes/settings.ts` | Persistent key-value settings (SQLite-backed) |
| GET | `/api/system` | `routes/system.ts` | Read-only runtime info (SQLite DB path) |
| GET | `/health` | `server.ts` | Health check |
| WS | `/ws/session/:id` | `ws/session.ts` | Chat PTY I/O over WebSocket |
| WS | `/ws/terminal/:id` | `ws/terminal.ts` | Terminal PTY I/O over WebSocket |
Expand All @@ -88,7 +89,7 @@ Two modes are supported per session, stored in the `sessions.mode` column:

### Frontend data flow

- `useDashboard.ts` fetches account + usage + sessions in parallel with a 60s auto-refresh
- `useHomeData.ts` fetches account + usage + sessions in parallel with a 60s auto-refresh
- `SessionContext.tsx` holds the active session state (including `mode`); `useWebSocket.ts` manages the chat WS connection; `useTerminalSession.ts` manages the terminal WS connection
- `TerminalSession.tsx` and `TerminalDrawer.tsx` are **never unmounted** — both are CSS-toggled (`display: none`) to preserve xterm scroll buffer across navigation

Expand All @@ -103,13 +104,13 @@ Two modes are supported per session, stored in the `sessions.mode` column:
## Docker

```bash
docker build -t claude-code-dashboard .
docker build -t claude-code-webui .
docker-compose up
# Dashboard at http://localhost:8080
# Web UI at http://localhost:8080
```

`docker-compose.yml` mounts `~/.claude` (read-write — required for session deletion) and `~/projects` (read-write) from the host.

## Systemd service (Linux)

`scripts/install-service.sh` generates a systemd user unit from `scripts/claude-code-dashboard.service.template`, writes an env file to `~/.config/systemd/user/`, builds the project, and enables the service. Run with `--skip-build` to reuse existing `dist/` directories.
`scripts/install-service.sh` generates a systemd user unit from `scripts/claude-code-webui.service.template`, writes an env file to `~/.config/systemd/user/`, builds the project, and enables the service. Run with `--skip-build` to reuse existing `dist/` directories.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ make service-install ARGS=--skip-build

```bash
make service-uninstall
systemctl --user status claude-code-dashboard
journalctl --user -u claude-code-dashboard -f
systemctl --user status claude-code-webui
journalctl --user -u claude-code-webui -f
```

## Commands reference
Expand Down
5 changes: 3 additions & 2 deletions backend/src/db/schema.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Database from 'better-sqlite3'
import path from 'path'
import fs from 'fs'
import os from 'os'

const DB_DIR = process.env.DATA_DIR ?? path.join(process.env.HOME ?? '/root', '.claude', 'dashboard')
const DB_PATH = path.join(DB_DIR, 'dashboard.db')
const DB_DIR = process.env.DATA_DIR ?? path.join(os.homedir(), '.claude', 'webui')
export const DB_PATH = path.join(DB_DIR, 'webui.db')

function initDb(): Database.Database {
fs.mkdirSync(DB_DIR, { recursive: true })
Expand Down
8 changes: 8 additions & 0 deletions backend/src/routes/system.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { FastifyInstance } from 'fastify'
import { DB_PATH } from '../db/schema'

export async function systemRoutes(fastify: FastifyInstance) {
fastify.get('/api/system', async (_req, reply) => {
return reply.send({ db_path: DB_PATH })
})
}
4 changes: 3 additions & 1 deletion backend/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import { sessionRoutes } from './routes/sessions'
import { sessionWsRoutes } from './ws/session'
import { terminalWsRoutes } from './ws/terminal'
import { settingsRoutes } from './routes/settings'
import { systemRoutes } from './routes/system'
import { initAccountCache } from './services/accountCache'
import { statuslineRoutes } from './routes/statusline'
import { setupStatusline } from './lib/setup-statusline'

// TODO: add bearer token auth — add @fastify/bearer-auth plugin here
// and set token via DASHBOARD_TOKEN env var
// and set token via WEBUI_TOKEN env var
// fastify.addHook('onRequest', async (request, reply) => { ... })

const fastify = Fastify({ logger: true })
Expand All @@ -42,6 +43,7 @@ async function start() {
await fastify.register(sessionWsRoutes)
await fastify.register(terminalWsRoutes)
await fastify.register(settingsRoutes)
await fastify.register(systemRoutes)
await fastify.register(statuslineRoutes)

fastify.get('/health', async () => ({ status: 'ok' }))
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
services:
dashboard:
webui:
image: ghcr.io/adeotek/claude-code-webui:latest
build:
context: .
Expand Down
Loading
Loading