Skip to content

Latest commit

 

History

History
136 lines (103 loc) · 7.01 KB

CLAUDE.md

File metadata and controls

136 lines (103 loc) · 7.01 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Focus Compass Server is a real-time collaborative WebSocket server built on Hocuspocus with SQLite persistence. It implements CRDT (Conflict-free Replicated Data Type) synchronization using Yjs for conflict-free document collaboration.

Development Commands

npm run dev      # Start server with file watching (node --watch)
npm start        # Run production server
npm run lint     # Check code with ESLint
npm run lint:fix # Auto-fix ESLint violations

Requires Node.js >= 24.0.0. Uses ES modules ("type": "module").

Architecture

Entry Point: src/server.js - Hocuspocus server with SQLite extension

Key Components:

  • Hocuspocus Server (30s timeout, 2-10s debounce) handles WebSocket connections
  • SQLite extension persists Yjs documents to DB_PATH
  • BackupService (src/services/backup.js) handles database backups on document updates

REST API Endpoints (all require Bearer token auth):

  • POST /api/upload - Image upload with idempotency (skips existing files)
  • GET /api/images - List all images
  • GET /api/images/{id} - Retrieve image with MIME type
  • GET /api/mcp/status - { enabled }: true when at least one MCP token is active (no auth required)
  • GET /api/mcp/tokens - List active MCP tokens: id, name, prefix, createdAt, lastUsedAt (master token required)
  • POST /api/mcp/tokens - Issue an MCP token; body { name? }, empty name becomes "Token N"; returns the full token once (master token required)
  • DELETE /api/mcp/tokens/{id} - Revoke an MCP token (master token required)
  • /api/admin/documents/{doc}/projects[/{id}[/validate|/history[/{hid}[/restore]]]] - Admin project editor (master token required): list/get projects, PUT {baseVersion, project}, PATCH {baseVersion, patch}, dry-run validation, history and restore. Strict schema in src/yjs/projectSchema.js (must match the app's Project type); writes are one Yjs transaction via a Hocuspocus direct connection; stale baseVersion → 409; previous versions in PROJECT_HISTORY_DB_PATH (last PROJECT_HISTORY_LIMIT, default 20)

Static Routes:

  • / or /index.html - Admin UI (see src/index.html)
  • /focus-compass-skill.md - Claude Code skill template
  • /install.sh?token=TOKEN&host=ORIGIN - One-liner setup script (bash)

Healthcheck:

  • GET /health (health-check) - Returns { ok: true }

Key Patterns

  • Event-driven hooks: onAuthenticate, onStoreDocument, onRequest
  • Image metadata: Stored as separate .meta.json files alongside image files
  • Path sanitization: Image IDs validated with regex [a-zA-Z0-9_-] to prevent traversal
  • Idempotent uploads: Existing files return existed: true without overwriting

Locked Setup-mode Product Decision

When no environment or persisted master token exists, the public first visitor may initialize the server and create the master token. This is the intentional consumer onboarding model and must not be reported as a vulnerability or replaced with a bootstrap secret, pairing code, SSH confirmation, IP allowlist, or localhost-only setup unless the project owner explicitly changes the product decision. Preserve atomic one-time initialization and the security of all post-initialization operations.

Environment Configuration

PORT=8080                           # Server port
ACCESS_TOKEN=your-secret-token      # Bearer token for auth
DB_PATH=./data/db.sqlite            # SQLite database path
IMAGES_DIR=./data/images            # Image storage directory
BACKUP_DIR=./data/backups           # Backup directory
MAX_UPLOAD_BYTES=10485760           # Upload limit (bytes)
MAX_WEBSOCKET_MESSAGE_BYTES=16777216 # Max complete WS/Yjs message (16 MiB)
MAX_UNAUTHENTICATED_QUEUE_BYTES=262144 # Per-connection pre-auth buffer (256 KiB)
MAX_UNAUTHENTICATED_QUEUE_MESSAGES=32 # Per-connection pre-auth message count
MAX_PENDING_DOCUMENTS=8             # Pending document auths per connection
HOCUSPOCUS_TIMEOUT_MS=30000         # Pre-auth deadline + authenticated idle timeout
CORS_ALLOW_ORIGINS=*                # CORS allowlist (comma-separated) or '*'
YJS_GC=true                         # Default: true (smaller docs, no full Yjs history)

Backup interval and retention are not environment variables — they are configured at runtime from the admin UI and persisted to backup-settings.json next to the database.

Docker

docker compose up -d    # Start with Docker Compose

Volume hocuspocus-data persists /app/data (database and images).

MCP Server (Model Context Protocol)

The server exposes a read-only MCP endpoint at POST /mcp (Streamable HTTP, stateless mode) so that Claude Code and other MCP clients can read project/workspace data directly from the database.

Notes:

  • POST /mcp only (no long-lived GET SSE streams).
  • The Streamable HTTP transport expects Accept: application/json, text/event-stream and Content-Type: application/json.
  • The server replies with JSON (no SSE streaming), but clients still send the Accept header above.
  • Request body is limited to 1 MiB.
  • MCP uses its own tokens, separate from the master token. Any number can be issued and revoked individually from the admin UI (/) or via /api/mcp/tokens (master token required). MCP is disabled while no token is active.
  • Only SHA-256 hashes of MCP tokens are stored, in MCP_TOKENS_DB_PATH (default mcp-tokens.sqlite next to the DB, kept out of document backups so a restore cannot revive a revoked token). The full token is shown once at issue time. MCP_TOKEN / mcp-auth.json are no longer supported.
  • MCP setup guide is integrated into the admin UI (/).

MCP Tools (read-only):

  • list_documents - List all documents/workspaces with summary info
  • get_workspace - Get workspace overview with configurable sections (project info, current focus, tasks, notes)
  • list_projects - List projects in a document (IDs/titles; optional project info)
  • get_project - Get a single project by ID

Architecture: src/mcp/server.js (factory), src/mcp/tools.js (tool definitions), src/routes/mcp.js (HTTP handler). Each request creates a fresh McpServer + transport pair (stateless pattern).

Connect from Claude Code:

claude mcp add --transport http focus-compass http://localhost:8080/mcp \
  --header "Authorization: Bearer YOUR_MCP_TOKEN"

Verification

Do NOT start the dev server or take screenshots to verify UI changes. Run npm run lint for code quality checks (and node --check <file> for a quick syntax check) — that is sufficient. There is no typecheck or unit-test suite; the tests/ directory holds Docker/e2e guide smoke tests that need Docker or a running server, so they are not part of routine verification.

Client Connection Example

import { HocuspocusProvider } from '@hocuspocus/provider';
import * as Y from 'yjs';

const ydoc = new Y.Doc();
const provider = new HocuspocusProvider({
  url: 'ws://localhost:8080',
  name: 'document-name',
  document: ydoc,
  token: 'your-auth-token',
});