factlog
README.md
# factlog
A shared, append-only fact log that lets AI agents (and their humans)
coordinate on one workspace — a repository, or any bounded domain of agent
activity: decisions, invariants, claims on file or uri scopes, questions,
findings, and handoffs — persisted in SQLite, served over MCP (stdio and
streamable HTTP), a CLI, a REST ingest endpoint, and a live web view.
- Protocol semantics: [factlog-rfc-v0.1.md](factlog-rfc-v0.1.md)
- Implementation spec: [factlog-build-spec.md](factlog-build-spec.md)
- Context-discipline addendum (hooks, runner): [factlog-context-discipline.md](factlog-context-discipline.md)
## Install
Node ≥ 20.
```sh
npm install && npm run build && npm link # puts `factlog` and `factlog-mcp` on PATH
npm test # full suite, incl. the 10-process concurrency gate
```
## Initialize a workspace
```sh
cd your-repo
factlog init # creates .factlog/factlog.db, adds it to .gitignore
```
## Connect an agent (MCP)
Add to the repo's `.mcp.json`:
```json
{ "mcpServers": { "factlog": { "command": "npx", "args": ["factlog-mcp"] } } }
```
The server exposes `factlog_brief`, `factlog_post`, `factlog_query`,
`factlog_changes`, `factlog_claim`, `factlog_supersede`, `factlog_release`,
and `factlog_resolve`. Set `FACTLOG_SESSION` / `FACTLOG_AGENT` so writes are
attributed to the right session.
The same 8 tools are served over **MCP streamable-HTTP** at
`http://127.0.0.1:4711/mcp` by `factlog serve` (and on the workspace unix
socket `.factlog/factlog.sock`, mountable into containers). Identity comes
from `x-factlog-agent`/`-session` headers — or, hardened, from an actor token
(`factlog token mint`) presented as `Authorization: Bearer`, which stamps the
actor server-side, marks writes `x-actor-verified`, and can carry write-scope
ACLs plus an `external` taint (decision/invariant posts then land `pending`
until approved in the web UI). Set `require_stamped_actors` in
`.factlog/policy.json` to reject unstamped writes.
## CLI
```sh
factlog brief # deterministic, budgeted context pack
factlog post decision --body "..." --scope 'src/auth/**'
factlog post note --body "..." --scope 'topic://finances/**' # uri scopes (RFC §3.4)
factlog claim --scope 'job://daily-digest' --task "..." # doubles as a run-lock; exit 2 on conflict
factlog release <id> --commit <sha>
factlog watch # tail -f the log
factlog serve # web view :4820 + daemon :4711 (/mcp, /ingest, hooks) + unix socket
factlog token mint --agent whatsapp --origin external --write-scope 'channel://**'
factlog bridge # fenced brief block in CLAUDE.md
factlog export # full log as NDJSON (no lock-in)
```
`factlog help` lists the rest, including the hook-facing commands
(`check-claim`, `session-status`, `next-task`).
## Operational events (RFC Appendix C)
CI, incident, and deploy tooling POSTs distilled judgments to
`http://127.0.0.1:4711/ingest`: incidents and red test suites become findings
auto-resolved by their closing transition; deploy freezes become blocking
invariants with `meta["x-gate"]="block"`, which the PreToolUse hook enforces
mechanically — agents cannot edit a frozen scope — and `meta["x-expires"]`
expires them on schedule.
## Hooks (enforced discipline for Claude Code)
`demo/hooks/` ships a ready-made `settings.json` plus scripts: brief injected
on session start, edits blocked unless the session holds a covering claim,
stop gated on releasing claims and posting a handoff. Install per
[demo/hooks/README.md](demo/hooks/README.md).
## Demo
The two-agents-one-repo walkthrough — parallel claims, a conflict flashing
red on the live timeline, a blocking question resolved across sessions, a
superseded decision — is scripted in [demo/demo.md](demo/demo.md). Seed a
non-trivial log first with `npm run seed`.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing