Team Server

One shared knowledge graph for your whole team — on your own infrastructure. No data leaves your network.

Overview

The Team Server is the Waystone API backed by a multi-writer PostgreSQL + pgvector graph. Each team member's Claude Code session injects the team's context every prompt and writes new decisions back to the same graph, automatically. You run it; nothing leaves your network.

  • Shared memory — a teammate's decision shows up in your next session.
  • Self-hosted — your hardware, your Postgres, your data.
  • Drop-in — the same query / extract / hooks, just pointed at the server.

Quickstart

No clone, no build — pull the published image:

curl -O https://unbidden.ai/team-server/docker-compose.yml
curl -o .env https://unbidden.ai/team-server/env.example
# edit .env (see below), then:
docker compose up -d        # Postgres (pgvector) + the API, ready in ~30s
curl localhost:8000/v1/health

(Prefer to build from source? git clone https://github.com/Unbidden-AI/waystone and use the repo's root docker-compose.yml instead.) docker compose up brings up two services: db (pgvector/pgvector:pg16, data in a named volume) and server (ghcr.io/unbidden-ai/waystone-server). The Postgres schema is created automatically on first use — no migration step.

In .env, set one auth value plus the LLM key:

  • Bought a license? Paste it as WAYSTONE_LICENSE=<token> — that alone enables per-seat mode (issue keys below). Nothing else to flip.
  • Just want one shared key? Set WAYSTONE_API_KEY instead (any strong random string).
  • LLM_API_KEY (+ optional LLM_BASE_URL, LLM_MODEL) — the OpenAI-compatible endpoint the server uses to extract facts (defaults target Gemini 2.5 Flash).

The server refuses to start if you set neither a license nor a shared key — it never comes up unauthenticated.

Connect a client

In each member's ~/.waystone/config.yaml:

backend: remote
api_url: http://<server-host>:8000
api_key: <the WAYSTONE_API_KEY you set>

That's it. Now:

  • The UserPromptSubmit hook injects shared context from the team graph on every prompt (fail-open, capped at ~8s so a slow server never blocks you).
  • Extraction is routed to the server — assistant turns and decisions land in the shared graph automatically.
  • waystone query, extract, show, export, and init all operate against the Team Server.

Use backend: local to force a machine back to its private SQLite graph even if api_url is set.

Per-seat licensing

If you set WAYSTONE_LICENSE in the quickstart, the server is already in per-seat mode — just hand out keys with the team CLI:

docker compose exec server waystone team issue alice@acme.com
docker compose exec server waystone team members      # who has a seat
docker compose exec server waystone team license      # seats used / total
docker compose exec server waystone team revoke bob@acme.com   # free a seat

Licenses are Ed25519-signed tokens verified locally — no phone-home. An airgapped server stays correctly licensed. Seats are enforced offline; a tampered or expired license never grants seats (fail-closed). Without a license you get 3 trial seats to evaluate; a license raises the cap.

Notes & ops

  • Data lives in the waystone-pgdata volume. Back it up with docker compose exec db pg_dump -U waystone waystone > backup.sql.
  • Upgrades: image deploy → docker compose pull && docker compose up -d; source build → git pull && docker compose up -d --build. Schema migrations are additive, so rolling forward is safe.
  • TLS / public exposure: put the server behind a reverse proxy or a private network (e.g. Tailscale) — the bearer key is the only gate.
  • Tenancy: each project is an isolated tenant inside the one Postgres graph.

Full reference (env vars, compose file, examples): docs/team-server.md on GitHub →