Documentation Index
Fetch the complete documentation index at: https://docs.orinadus.com/llms.txt
Use this file to discover all available pages before exploring further.
The journal
The journal is a newline-delimited JSON file at:Event struct with skip_serializing_if applied:
Noneoptional fields are omitted entirely — nonullkeystags: []is omitted- All present fields are serialised as-is
Write safety
TheJournal struct holds a std::sync::Mutex<()> write lock. All appends acquire this lock, open the file with OpenOptions::append, write the line, and close. This serialises concurrent writes within a single process.
urchin-mcp and urchin-collectors share the journal file via the filesystem, not via IPC. Multiple processes writing simultaneously will interleave correctly because each write is a single write(2) syscall on a line that fits in a typical page — POSIX guarantees atomicity for writes smaller than PIPE_BUF on a regular file opened with O_APPEND.
Process topology
Intake pipeline
EveryPOST /ingest passes through four sequential gates:
- Auth check — if
intake_tokenis configured, theAuthorization: Bearer <token>header must match exactly. Returns401on mismatch. - Ephemeral check — if the ephemeral flag file is present, the event is accepted but permanently discarded. Returns
202. - Validation —
contentandsourcemust be non-blank after trim. Returns400if either is empty. - Journal write — mutex-guarded append. Returns
200 {"id": "...", "status": "ok"}on success.
Collectors
Each collector is a read-only pull operation against a specific source:| Collector | Source path | Checkpoint mechanism |
|---|---|---|
shell | ~/.bash_history | byte-offset checkpoint |
git | per-repo .git/ | per-repo SHA checkpoint; silent on first run |
claude | ~/.claude/projects/ JSONL transcripts | file + line offset |
copilot | ~/.copilot/command-history-state.json | content-addressed hash |
gemini | ~/.gemini/tmp/*/chats/*.jsonl | partial-offset checkpoint |
codex | ~/.codex/state_5.sqlite | row ID watermark |
opencode | ~/.local/share/opencode/opencode.db | row ID watermark |
local-model | ~/.local/share/urchin/local-model.jsonl | byte-offset checkpoint |
~/.local/share/urchin/ alongside the journal. A collector is a no-op if its source path does not exist.
Ephemeral mode
Ephemeral (burn) mode suppresses all writes across both MCP and HTTP intake simultaneously. State is managed via a flag file:- Activate:
urchin_ephemeral(action: "start")or the MCP tool creates~/.local/share/urchin/ephemeral.lock - Deactivate:
urchin_ephemeral(action: "end")removes the flag file
urchin-mcp and urchin-intake on every ingest request, ephemeral mode is cross-process. Activating it from a Copilot session suppresses writes from a simultaneously running Claude session too.
MCP server
urchin mcp launches a JSON-RPC 2.0 server over stdin/stdout. IDEs and agents connect to it as a subprocess via the MCP protocol. The server exposes 10 tools — see MCP Overview.
The MCP server reads the journal by loading all events into memory on each query. There is no SQLite index or daemon required. This keeps the architecture simple at the cost of linear read time — acceptable for typical journal sizes (tens of thousands of events).
Vault projection
urchin vault project writes a summarised block of the day’s events into:
<!-- URCHIN:start --> / <!-- URCHIN:end --> marker blocks. Content outside those markers is never touched. Running the projection twice on the same day is safe.
Identity
Identity::resolve() produces the Actor envelope attached to events created by CLI and MCP tools:
account—$URCHIN_ACCOUNT→$USER→"unknown"device—$URCHIN_DEVICE→hostname→"unknown"
