Skip to main content
Glama
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`.

Maintenance

ActivityMaintained
ResponsivenessSyncing