# CTXD — Context Dossier # LLM Installation & Deployment Guide # Feed this file to an LLM to assist with setup and deployment. ## What is CTXD? CTXD (Context Dossier) is a single source of truth for multi-harness project context. It serves one canonical AGENTS.md per project to Claude, Hermes, Codex, Cursor, and any OAuth-capable MCP client via Streamable HTTP. It runs as two Docker containers: a PostgreSQL 16 database and a Python ASGI daemon. ## Prerequisites - Docker 24+ and Docker Compose v2+ - A reverse proxy with TLS (Traefik recommended; Caddy or nginx also work) - Linux host with ~1GB free RAM - (Optional) Existing PostgreSQL 14+ instance if not using the bundled one ## Quick Deployment 1. Clone the repository: git clone ssh://git@code.cubecraftcreations.com:2288/CubeCraft-Creations/CTXD.git cd CTXD/app 2. Copy the environment template: cp .env.example .env 3. Generate secrets and fill in .env: python3 -c "import secrets; print(secrets.token_urlsafe(32))" # Use for CTXD_API_KEY python3 -c "import secrets; print(secrets.token_urlsafe(32))" # Use for OAUTH_APPROVAL_KEY 4. Edit .env with your values. Required variables: - DATABASE_URL — PostgreSQL connection string - POSTGRES_PASSWORD — Password for the bundled PG container - CTXD_API_KEY — Shared key for internal MCP and HTTP auth - OAUTH_ENABLED=true - OAUTH_ISSUER=https://your-domain.com - OAUTH_APPROVAL_KEY — Key for approving OAuth authorizations 5. Build and start: docker compose up -d 6. Wait for PostgreSQL to be healthy and the daemon to start: docker compose ps # Both ctxd-postgres and dossier should show "healthy" / "running" 7. Set the admin password: docker exec ctxd dossier user-set-password admin -p "your-admin-password" 8. Verify: curl http://localhost:9091/status # Expected: {"status": "ok", "db": "/data/ctxd.db"} 9. Access the Web UI: http://:9091/ Sign in with admin / your-admin-password ## Environment Variables Reference All config is driven by environment variables in .env. Precedence: env var > ctxd.yaml > defaults. ### Database - DATABASE_URL — PostgreSQL connection string. If empty, falls back to SQLite. - POSTGRES_USER — PostgreSQL user for bundled container (default: ctxd) - POSTGRES_PASSWORD — PostgreSQL password for bundled container - POSTGRES_DB — PostgreSQL database name (default: ctxd) ### Server - CTXD_HOST — Bind address (default: 0.0.0.0) - CTXD_PORT — Listen port (default: 9091) - CTXD_HOME — Data directory inside container (default: /data) - LOG_LEVEL — Uvicorn log level: debug, info, warning, error (default: info) ### Auth - CTXD_AUTH_ENABLED — Enable authentication globally (default: false) - CTXD_API_KEY — Shared API key for Hermes/internal MCP and HTTP auth - CTXD_EXTERNAL_READONLY_KEY — Legacy ?key= on read-only MCP (migration only) ### OAuth - OAUTH_ENABLED — Enable OAuth authorization server (default: false) - OAUTH_ISSUER — Public URL used in OAuth discovery metadata - OAUTH_APPROVAL_KEY — Fallback key for /oauth/authorize approval - OAUTH_APPROVAL_USER_ID — User ID for attributing approvals (default: admin) - OAUTH_ACCESS_TOKEN_TTL — Access token lifetime in seconds (default: 3600) - OAUTH_REFRESH_TOKEN_TTL — Refresh token lifetime in seconds (default: 2592000) ### Web Sessions - WEB_SESSION_TTL — Session cookie lifetime in seconds (default: 604800) ### Snapshots - SNAPSHOT_MIN_KEEP — Minimum snapshots per project (default: 5) - SNAPSHOT_MAX_KEEP — Maximum snapshots before rotation (default: 25) ## MCP Endpoints CTXD exposes three MCP surfaces via Streamable HTTP: 1. /readonly/mcp — Read-only tools (OAuth ctxd.read or API key) Tools: list_projects, get_project_context, search_context, get_project_tags, list_files, get_file, get_client_guide 2. /write/mcp — Write tools (OAuth ctxd.write only) Tools: update_file, set_project_tags, sync_to_project, get_client_guide 3. /mcp — Internal full MCP (shared API key only, not exposed publicly) All read + write tools plus auto_generate_tags and get_user_profile ## Connecting LLM Clients ### Claude Desktop Connector URL: https://your-domain.com/readonly/mcp Claude auto-discovers OAuth metadata and registers via DCR. For write access, use: https://your-domain.com/write/mcp ### Hermes Agent Edit ~/.hermes/config.yaml: mcp_servers: dossier: url: http://:9091/mcp timeout: 30 headers: Authorization: "Bearer your-api-key" Restart Hermes after changing config. ### Other MCP Clients 1. Register an OAuth client: POST /oauth/register with your redirect URI 2. Authorize: GET /oauth/authorize (admin must approve) 3. Exchange code: POST /oauth/token 4. Connect to /readonly/mcp or /write/mcp with Bearer token ## Traefik Configuration Route everything except the internal MCP endpoint: rule: Host(`ctxd.yourdomain.com`) && !Path(`/mcp`) This exposes: landing page, dashboard, REST API, OAuth, read-only MCP, write MCP. Only /mcp (internal, API key) is blocked. ## CLI Commands All commands run inside the container: docker exec ctxd dossier Commands: init Initialize database project-create [--display-name N] Create a project project-list List projects read Print context to stdout edit Open in $EDITOR file-list List context files file-read Read a single file sync [path] Sync AGENTS.md to project root search "query" Full-text search audit [--limit N] Show audit log user-list List users user-create --display-name "Name" [--password "pw"] user-set-password -p "password" oauth-client-create [-n "Name"] [--redirect-uri URI] oauth-client-list List OAuth clients oauth-client-revoke Revoke client and invalidate tokens import-vault Import from Obsidian vault ## Admin UI Sign in as admin, click "admin" in the masthead. Three tabs: 1. oauth clients — Create and revoke OAuth clients 2. users — List, create, edit, activate, inactivate, delete users 3. projects — List and delete projects (typed-name confirmation required) ## Project Files Each project has multiple context files: - CONTEXT.MD — Canonical overview (synced as AGENTS.md, cannot be deleted) - DECISIONS.MD — Architecture decisions and rationale - RUNBOOKS.MD — Deploy, troubleshoot, operate procedures - PROMPTS.MD — Project-specific prompts for different harnesses - GLOSSARY.MD — Project-specific terms and acronyms The compiled view (get_project_context) concatenates all files with metadata header. ## Locked Files - CONTEXT.MD — Cannot be deleted from any project (minimum required file) - CONTEXT.MD and LLM-CLIENT.MD — Fully locked in the ctxd-docs project (cannot update or delete) ## Backups PostgreSQL backup: docker exec ctxd-postgres pg_dump -U ctxd ctxd > backup.sql PostgreSQL restore: cat backup.sql | docker exec -i ctxd-postgres psql -U ctxd ctxd Snapshots are automatic (before each context update, rotated min 5 / max 25 per project). ## Migrating from SQLite to PostgreSQL If you started with SQLite: 1. Start PostgreSQL: docker compose up -d postgres 2. Run migration: docker exec ctxd python3 -m ctxd.migrate_sqlite_to_pg 3. Set DATABASE_URL in .env and restart: docker compose up -d dossier ## Using an External PostgreSQL 1. Create database and user on your external PG instance 2. Set DATABASE_URL in .env to point to it 3. Start only the app: docker compose up -d dossier (or scale postgres to 0: docker compose up -d --scale postgres=0) ## Troubleshooting Login fails: Reset password with "docker exec ctxd dossier user-set-password admin -p newpass" Use double quotes if password contains single quotes. Use single quotes for $ ` ! characters. MCP 404: Traefik is not routing /readonly/mcp. Check router rule includes it. MCP 401: Auth is working. Check OAuth token scope and expiry. PostgreSQL connection fails: Check DATABASE_URL password matches POSTGRES_PASSWORD. If PG data volume was initialized with a different password, reset it: docker exec ctxd-postgres psql -U ctxd -c "ALTER USER ctxd PASSWORD 'newpass'" Then update .env. Container keeps restarting: Check "docker logs ctxd --tail 30". Common causes: wrong PG password, OAUTH_ENABLED=true but OAUTH_ISSUER empty, missing CTXD_API_KEY. ## File Structure CTXD/ ├── .env Production environment (gitignored, contains secrets) ├── .env.example Template with all documented variables ├── .gitignore ├── README.md Full documentation ├── SKILL.md LLM client guide (canonical source for LLM-CLIENT.MD) ├── data/ Runtime data (gitignored) │ ├── ctxd.yaml Fallback config (env vars take precedence) │ ├── oauth_state.json OAuth clients, codes, tokens │ ├── web_sessions.json Web UI sessions │ ├── snapshots/ Point-in-time context backups │ └── pg/ PostgreSQL data volume └── app/ Application source ├── docker-compose.yml ├── Dockerfile ├── pyproject.toml └── src/ctxd/ ├── config.py Env-driven config ├── db.py Database layer (PostgreSQL + SQLite) ├── schema.sql PostgreSQL schema ├── schema_sqlite.sql SQLite schema fallback ├── server.py ASGI: HTTP + MCP + OAuth ├── cli.py CLI commands ├── ui.html Web UI dashboard ├── landing.html Public landing page ├── auth_password.py PBKDF2 password hashing └── migrate_sqlite_to_pg.py Migration script