Skip to content

essential-contributions/spec-forest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

539 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spec Forest

A specification-building tool that models specs as directed acyclic graphs (DAGs) of questions and answers. Uses entropy-based prioritization to surface the most impactful unanswered questions first.

How To Run Locally

1. Start the server

cargo run --release

2. Start the web UI (in a separate terminal)

cd web
npm install
npm run build
npm run preview

The server runs at http://localhost:8080 and the web UI at http://localhost:4173.

Prerequisites

  • Rust toolchain (1.80+)
  • Node.js (v18+) for the web UI

Build

cargo build --release

The binary is at target/release/spec-forest.

Run

# Default: SQLite at ~/spec-forest/spec-forest.db, HTTP on 127.0.0.1:8080
cargo run --release

# Custom database path and port
cargo run --release -- --db-path /path/to/spec-forest.db --port 3000 --host 0.0.0.0

The server exposes two interfaces on a single HTTP port:

  • MCP at /mcp — Streamable HTTP transport for Claude Code and other MCP clients
  • REST API at /api/ — read-only endpoints for the web UI

Add to Claude Code

claude mcp add --transport http spec-forest --scope project http://127.0.0.1:8080/mcp

Or add globally with --scope global to use across all projects.

MCP Tools

Tool Description
create_spec Create a new specification
seed_spec Initialize a spec with a root document
list_specs List all specifications
get_spec_summary Get spec metadata and node counts
get_next_question Get the highest-entropy unanswered question
answer_question Answer a question
add_children Create child questions under a node
update_answer Update an existing answer
trigger_review Mark descendants for review
get_review_candidate Get next node needing review
delete_node Soft-delete a node and its descendants
get_ancestors Get ancestor chain to root
get_descendants Get subtree from a node
search_nodes Semantic search across nodes

Web UI

From the repo root, run:

cd web
npm install
npm run build
npm run preview

Opens at http://localhost:4173. Requires the backend running on port 8080.

Sync Server

The sync server (spec-forest-sync) enables real-time collaborative editing of specs across multiple clients via WebSocket.

Running the Sync Server

# Start with a persistent JWT secret (recommended)
cargo run --release -p spec-forest-sync -- --jwt-secret "your-secret-here"

# Or via environment variable
JWT_SECRET="your-secret-here" cargo run --release -p spec-forest-sync

# Custom port and host
cargo run --release -p spec-forest-sync -- --jwt-secret "secret" --port 9090 --host 0.0.0.0

# Custom token lifetime (default: 86400 seconds / 24 hours)
cargo run --release -p spec-forest-sync -- --jwt-secret "secret" --token-lifetime 3600

If no secret is provided, a random one is generated at startup (tokens won't survive restarts).

The sync server listens on 127.0.0.1:9090 by default and stores its database at ~/.spec-forest/sync.db.

Authentication

All sync server interactions use JWT-based authentication over WebSocket.

1. Connect and register/login

Connect to ws://<host>:<port>/ws without a token. Send a Register or Login message:

{"type": "register", "username": "alice", "password": "secret123"}
{"type": "login", "username": "alice", "password": "secret123"}

The server responds with an AuthToken:

{"type": "auth_token", "token": "eyJ..."}

2. Reconnect with token

On subsequent connections, pass the JWT as a query parameter to skip the login step:

ws://localhost:9090/ws?token=eyJ...

Invalid tokens are rejected with a 401 before the WebSocket handshake completes.

3. Token refresh

The server sends a TokenExpiring warning when the token has less than 20% of its lifetime remaining. The client should re-authenticate via Login to get a fresh token.

Access Control

  • Specs use binary access control: full read-write or no access
  • The user who creates a spec is its owner and the only one who can manage the access list
  • Owners grant/revoke access via WebSocket messages:
{"type": "grant_access", "spec_name": "my-spec", "username": "bob"}
{"type": "revoke_access", "spec_name": "my-spec", "username": "bob"}
  • ListSpecs only returns specs the authenticated user has access to
  • Revoking access immediately disconnects affected users

Connecting the Main Server

Start the main spec-forest server with --sync-url to configure a sync server:

cargo run --release -- --sync-url ws://localhost:9090/ws

The sync connection is deferred until credentials are unlocked. The main server stores credentials in an encrypted SQLite database at ~/.spec-forest/cred.db (protected by a master password using SQLCipher/AES-256).

Unlock credentials via the REST API:

# Unlock the credential store (also connects to the sync server)
curl -X POST http://localhost:8080/api/credentials/unlock \
  -H 'Content-Type: application/json' \
  -d '{"master_password": "my-master-pass"}'

# Store sync server credentials
curl -X POST http://localhost:8080/api/credentials/store \
  -H 'Content-Type: application/json' \
  -d '{"server_url": "ws://localhost:9090/ws", "username": "alice", "password": "secret123"}'

# Check connection status
curl http://localhost:8080/api/status

Rate Limiting

Failed login attempts trigger per-username exponential backoff (2^n seconds, capped at 15 minutes). Successful login resets the counter.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors