Project memory for AI agents that knows when it's wrong — dated facts, verified against git. Local, zero dependencies.
Project description
Facto
Every memory tool remembers. Facto knows when it's wrong.
Project memory for people who build with AI agents: a local engine of dated facts that knows what is true now, checks itself against your git repo, and feeds every agent session automatically — Claude Code, Cursor, Copilot, Codex, Gemini, or whatever you use next.
Quickstart
uv tool install facto-memory # or: pipx install facto-memory / pip install facto-memory
No uv? One line installs everything, even on a machine with no Python at all:
macOS · Linux
curl -LsSf https://raw.githubusercontent.com/giorgiocreazione-web/facto/main/install.sh | sh
Windows (PowerShell)
irm https://raw.githubusercontent.com/giorgiocreazione-web/facto/main/install.ps1 | iex
Then wire your project:
cd your-project
facto connect --all # Claude Code hook + MCP + git + AGENTS.md — and any editor it detects
facto dashboard # Mission Control opens in your browser by itself
Now open your agent (claude, cursor, …) in the same folder. On first run it
receives the guided-setup playbook, explores the project, proposes the areas
to you, and builds the memory once you confirm — no blind auto-detection.
From then on every session opens with your briefing already injected (goal, current state, blockers, last handoff), and the agent reads and writes the memory through MCP on its own. If the engine ever breaks, the session is told it is starting blind — no silent failures.
Requires git. Works offline. facto --help for everything.
(If the facto command isn't found afterwards, python -m facto … always works.)
Why a trust light
Every memory tool can tell you what it stored. None of them can tell you whether to believe it — and stale memory is worse than no memory, because your agent acts on it with confidence.
Facto compares what it remembers against the real state of your git repo at every start, and says so out loud:
================ TRUST LIGHT ================ (2026-07-24 19:28)
[GREEN ] ENGINE · aligned
[YELLOW] UI · memory 2 commits behind git
[RED ] CONTENT · no status recorded, 4 facts possibly outdated by the code
----
GLOBAL: RED (GREEN=trust it · YELLOW=verify · RED=refresh/do not trust)
A memory that can say "don't trust me" is the only kind you can trust.
How it works
flowchart LR
A["Your AI agent<br/>Claude Code · Cursor · Codex · Gemini · …"]
subgraph P["Your project — 100% local, zero network calls"]
direction LR
E["Facto engine<br/>dated facts, bi-temporal"]
DB[(".facto/facto.db<br/>SQLite, WAL")]
G["your git repo"]
T{{"TRUST LIGHT<br/>green · yellow · red"}}
E --> DB
DB --> T
G -->|"compared at every start"| T
end
A -->|"writes facts via MCP<br/>as decisions happen"| E
T -->|"briefing injected<br/>at session start"| A
DB --> M["Mission Control<br/>dashboard in your browser"]
- Facts, not chat. Short, dated, typed entries — "Decision: Tailwind v4, Bootstrap rejected — 2026-06-19". A thousand facts stay searchable in milliseconds.
- Bi-temporal. A new fact closes the old one instead of overwriting it: the current picture stays clean, the history stays queryable. You can always ask what did we believe in May, and why did it change?
- Areas, not one big blob. The memory is split by area (engine, ui, content…), so each agent gets the compass of its corner of the project.
- Local by design. One SQLite file inside your project. Pure Python standard library — zero dependencies, no accounts, no telemetry. The engine makes zero network calls, and the code is right here for you to check.
Your first 10 minutes
A real walkthrough on a fresh project — every output below is the actual command output.
1 · Wire the project (once)
$ cd starforge && facto connect --all
prepared facto.config.json (empty — the agent designs the areas on first run)
connecting (claude-code):
[ OK ] claude-code: hook added in .claude\settings.json
NEXT — open your AI agent in this folder (claude, cursor, …):
it gets the setup playbook, explores the project, proposes the areas,
and builds the memory once you confirm. Prefer by hand? `facto add-area <slug> <path>`
2 · Open your agent — or build the memory by hand. The agent proposes the areas on first run; doing it yourself is two commands:
$ facto add-area engine engine --label "Engine (ECS)"
✓ area 'engine' added -> engine [1 area(s) total]
$ facto add engine decisione "ECS over inheritance - profiled 4x faster with 10k asteroids"
+ [engine/decisione] valid_from=2026-07-24 -> Compass: «DECISIONS / CONSTRAINTS»
3 · Ask the light if the memory can be trusted:
$ facto status
================ TRUST LIGHT ================ (2026-07-24 19:28)
[YELLOW] ENGINE · state not yet anchored to git — run `facto ingest-git`
...
It even tells you how to fix it:
$ facto ingest-git
engine: 2026-07-24 05547a8 [master] (updated)
ingest-git: done.
$ facto status
[GREEN ] ENGINE · aligned
4 · Close the session with a baton for the next one:
$ facto handoff engine
handoff saved [engine] (new, 171 chars)
5 · Tomorrow, the briefing opens the session by itself — this is what your
agent (and facto brief engine) gets before writing a single line:
================ ENGINE ================ (state at 2026-07-24 19:29)
REAL GIT > active branch: master
-------- WHERE WE ARE NOW --------
- Spatial hash landed: 10k entities at 62 fps on the min-spec laptop
-------- LAST HANDOFF — end-of-session baton --------
- Vertical slice on track. Next: navmesh rework (gameplay), then wire mining
tiers to the HUD heat gauge. Watch out: the collision fix still needs its
regression test in CI.
-------- DECISIONS / CONSTRAINTS --------
- ECS over inheritance for entities - profiled 4x faster with 10k asteroids
Zero re-explaining. Every session starts further ahead.
The dashboard
facto dashboard serves Mission Control locally. The reactor answers the
only question that matters — can I trust this memory right now? — then shows
where you are, the next step, and the blockers. It fills itself with the facts
your agent writes, and updates live while you work.
And when you don't feel like opening a terminal, Compose writes facts, handoffs, closures and areas straight from the browser:
Plus the graph of every fact (filter by area or type), full-text search, the compass per area and statistics. English and Italian. Pro-only views appear as honest cards, never as traps.
Works with your stack
One memory, every agent — through the open standards (MCP + AGENTS.md):
| Agent | How | Wired by |
|---|---|---|
| Claude Code | session hook + .mcp.json |
facto connect --all (tested end-to-end) |
| Cursor | .cursor/mcp.json + AGENTS.md |
facto connect cursor |
| VS Code / Copilot | .vscode/mcp.json (servers key) + AGENTS.md |
facto connect vscode |
| OpenAI Codex (CLI/VS Code/app) | .codex/config.toml + AGENTS.md |
facto connect codex |
| Gemini CLI | .gemini/settings.json + AGENTS.md |
facto connect gemini |
| Grok Build | reads Claude Code's MCP config | already covered by .mcp.json |
| Windsurf, Zed, Cline… | standard MCP + AGENTS.md | point them at facto mcp-serve |
| Anthropic-compatible harnesses (GLM…) | run inside Claude Code (ANTHROPIC_BASE_URL) |
nothing extra |
| Any other — even one that doesn't exist yet | the universal block (command: facto, args: [mcp-serve]) |
facto connect any |
connect --all wires the base (Claude Code, MCP, git, AGENTS.md) and adds an
editor only if this project already uses it — having Cursor installed on
your machine doesn't mean you want its folder in this repo. The others are
suggested, never imposed. Configs are merged, never overwritten (a .bak
is written first), and .facto/ is added to your .gitignore so the database
stays out of your repo.
No MCP at all? Every step works from the shell too — facto add-area,
facto add, facto handoff, facto status — which is exactly what the
AGENTS.md block teaches any agent that reads it.
Claude Code is tested end-to-end. For every other config a deterministic check
(mcp_config_check.py, green on Windows/macOS/Linux in CI) proves the file we
write actually launches a working Facto server — including the unknown-tool
case.
What your agent gets (MCP — read and write, in Free)
facto_status · facto_brief · facto_search · facto_add_fact ·
facto_close_fact · facto_handoff · facto_add_area · facto_remove_area
(the CRM trio — entities, tasks, relations — joins in Pro).
The daily loop
- Open a session — the hook injects the briefing. Zero re-explaining.
- Work — the agent records decisions, blockers and bugs through MCP as they happen.
- Close —
facto handoff <area>(three guided questions) leaves the baton for the next session. facto status— the trust light tells you whether the memory kept up.- Tomorrow: start further ahead. A silent snapshot of the database is
taken at session start (
.facto/backups), so months of memory never hinge on anyone's discipline.
Several agents at once
Yes — and it is a normal setup, not a hack. The database takes concurrent readers even while someone writes (SQLite in WAL mode) and a write that finds it busy waits its turn. Verified, not assumed: four processes writing at the same instant, 48 facts, none lost.
Two things worth knowing:
-
Give them different areas. Facts pile up without conflict, but state and handoff are one-per-area: if two agents write the handoff of the same area, the last one wins (the earlier is closed into history, not lost).
-
Need a hard boundary? Launch an agent with
FACTO_AREA=<slug>and it is refused if it tries to write anywhere else — including the project-wide area:error: this agent can only write to [api], not [web]
Where your data lives (no surprises)
Every fact is written to .facto/facto.db the moment it is recorded — no
save button, nothing buffered, nothing lost if a session dies. A silent snapshot
goes to .facto/backups at session start (at most one every 12 hours, last ten
kept). It never leaves your machine: no account, no cloud, no telemetry — and
since the engine makes zero network calls, that is something you can check in
the code rather than take on trust.
Sessions start on their own — opening any agent in the folder injects the briefing. They do not end on their own: ask for the handoff before you close, or the next session knows what is true but not where you were heading.
Always on (optional)
facto tray on # start at login; on Windows, an icon next to the clock
facto tray off # remove it — nothing is left behind
Opt-in, never automatic. On Windows you get a real tray icon: double-click opens the dashboard, right-click gives you Open dashboard and Quit. On macOS and Linux the dashboard simply starts at login, always one click away.
Editions
| Free — this repo | Pro (coming) | Max (coming) | |
|---|---|---|---|
| Engine: dated facts, bi-temporal history, trust light | ✅ | ✅ | ✅ |
| Full CLI + session hook + snapshots | ✅ | ✅ | ✅ |
| Complete MCP — read and write | ✅ | ✅ | ✅ |
| Mission Control incl. Compose, EN/IT | ✅ | ✅ | ✅ |
| Tray / start at login | ✅ | ✅ | ✅ |
| CRM with git auto-import (entities · tasks · relations) | — | ✅ | ✅ |
| Backups with retention, exports, project templates | — | ✅ | ✅ |
| Encryption at rest + dashboard access control | — | ✅ | ✅ |
| Browser onboarding wizard | — | ✅ | ✅ |
| Team sync over git (no server required) | — | — | ✅ |
| Agent fleet orchestrator | — | — | ✅ |
| License | MIT, forever | commercial | commercial |
The Free edition is not a demo: engine, CLI, MCP and dashboard are the full thing, MIT, forever.
Learn more
- docs/CONCEPTS.md — facts, areas, the compass, the light.
- docs/SETUP.md — manual setup, hook details, folder mode.
- examples/game-dev — a worked example configuration.
- CHANGELOG.md — what changed, release by release.
MIT © Giorgio Cristea · Built and owned by WCA — Web Creation Agency
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file facto_memory-0.1.0-py3-none-any.whl.
File metadata
- Download URL: facto_memory-0.1.0-py3-none-any.whl
- Upload date:
- Size: 111.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.14 {"installer":{"name":"uv","version":"0.9.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a56ca5ccef688dcca5ca04ad0a514675031bd752d50bc90d78c50560c989c350
|
|
| MD5 |
81622d741cc69b16ae7eb75f381c8d03
|
|
| BLAKE2b-256 |
06f0cef82bc7bb6b9a26b7d548fc8484498e66d25a634752acd0b7e332dd491c
|