COMPASS docs

Use the SDKs

For an agent that can't run an MCP server (or just wants a direct dependency instead of a subprocess), two thin client libraries call the Core's REST API directly — no MCP in between. They cover the same seven verbs the MCP exposes for the common path: check what holds, ask why, create a Sache, set/supersede a rule, record a lesson, search, and export the rule book.

Both live in sdk/ in this repo, are not published to a registry yet (open license, but no PyPI/npm release so far — install straight from the path or a Git checkout), and share the same auth model as everything else in COMPASS: header X-Compass-Key, one key per call.

Python — compass_client

from compass_client import Compass

c = Compass("http://localhost:18080", "<your-key>")
regel = c.gilt("deploy-freigabe")

Install locally with pip install -e sdk/python. Only runtime dependency: httpx. An async twin, AsyncCompass, mirrors every method as async def.

TypeScript — @athron/compass

import { Compass } from "@athron/compass";

const c = new Compass("http://localhost:18080", "<your-key>");
const regel = await c.gilt("deploy-freigabe");

Built with tsc (npm run build in sdk/typescript) into dist/ (ESM, with .d.ts). No runtime dependencies — uses the global fetch.

The package is not published. npm install @athron/compass fails (the registry answers 404, measured 02.10.2026) — @athron/compass is the name inside the repo, not a source to install from. Until it is published, pull the SDK in locally, the way its Python twin already does: npm install ./sdk/typescript, or a "@athron/compass": "file:../sdk/typescript" entry in your own package.json. The import above stays unchanged.

Method-to-route map

Both SDKs expose the same seven calls, in each language's own naming convention (snake_case in Python, camelCase in TypeScript):

Python TypeScript Route
c.gilt(sache, ...) c.gilt(sache, ...) GET /gilt/{sache}
c.warum(sache, ...) c.warum(sache, ...) GET /warum/{sache}
c.sache_anlegen(slug, titel, frage, bereich=None, ...) c.sacheAnlegen(slug, titel, frage, bereich?, ...) POST /sachen
c.regel_setzen(sache, text, ersetzt=None, ...) c.regelSetzen(sache, text, { ersetzt?, ... }) POST /aussagen (art=regel)
c.lehre_festhalten(art, titel, was, lehre, ...) c.lehreFesthalten(art, titel, was, lehre, ...) POST /lehren
c.suche(q, ...) c.suche(q, ...) GET /suche — returns {treffer, gesamt, abgeschnitten, weiter}, not an array (since 2026-10-05)
c.export(art="claude-md-section0", ...) c.export(art?, ...) GET /export/claude-md-section0 (also agents-md, cursor-rules)

Every non-2xx response raises a structured error — CompassFehler in Python, CompassError in TypeScript — carrying status, detail (the plain-language sentence, "Fehlerform"), feld (the field a 409/422 names, if any), and everything else the response body carried (e.g. the currently-held rule on a 409 from regel_setzen).

When to use the SDK instead of the MCP

The MCP (mcp/server.py, see Connect Claude Code, Cursor, and Codex) is the right fit for an agent that already speaks MCP — Claude Code, Cursor, Codex. The SDKs are for everything else: a CI job, a backend service, a script that just needs gilt() before it acts, without a subprocess or an MCP client library in the loop. Both talk to the same Core, over the same REST contract — neither one is a second source of truth.

Tests

Each SDK ships its own test suite next to the source (sdk/python/tests, sdk/typescript/tests) — request shape (path, method, header, body) and error mapping against a mocked Core, plus a static check that every route the SDK calls actually exists in the running Core (the same cross-check this documentation site runs on its own REST mentions).