pentimento-fs
A filesystem MCP server that journals every file operation (write, delete, move, mkdir) and outbound commands (exec, http) into an append-only ledger, enabling undo and compensation of actions.
README
Pentimento
An open, local, single-file ledger for AI agent actions — with undo.
Ogni azione dichiara la propria inversa. Every action declares its inverse.
In painting, a pentimento is the visible trace of an earlier choice beneath the surface — proof that the artist changed their mind, preserved in the work itself. Pentimento is that, for AI agents: a flight recorder for everything an agent does on your machine, written as one plain, append-only .pnt file per session. Every action carries its timestamp, its target, and its declared inverse.
Not a service. Not a SaaS. Not a framework. A file format, a tiny CLI, and an MCP server. The SQLite move, not the platform move.
The 30-second demo
$ # an agent (via the pentimento-fs MCP server) deletes a folder…
$ pentimento log
4 09:14:02 fs.delete reversible done src/old
$ pentimento undo --last
undone action #4 (fs.delete src/old)
$ ls src/old # the folder is back, byte for byte
a.txt sub/
That is the entire pitch.
Want to see it end to end? examples/refactor_rescue/ plays an agent doing a refactor through the real MCP server, then rescues what it broke — undo restoring a deleted tree, undo refusing to trample your edits, and a risky deploy parked as a draft. Run it: python examples/refactor_rescue/demo.py.
How it works
- One session = one file.
.pentimento/sessions/<date>_<id>.pnt, JSON Lines, append-only. An undo never rewrites history — it is a new event referencing the old one. The correction stays visible beneath the surface, like in the painting. - Record before effect. The action event is durable on disk before the action touches the world. A flight recorder that loses exactly the crashes is not a flight recorder.
- Snapshots are content-addressed. Prior state goes into
.pentimento/objects/keyed by SHA-256, git-style; identical content is stored once. Directories are snapshotted as tree manifests. - Undo never tramples. Reverting requires proof that the world still matches the state the action left behind; otherwise the undo is refused — and the refusal is recorded too.
- Reversibility is declared, never assumed. Every action carries its class —
reversible,compensable,irreversible— fixed by the spec, so that policy becomes possible.
Read the full format in PENTIMENTO_SPEC.md.
Install
$ pip install .
Zero runtime dependencies — Python ≥ 3.10 standard library only.
The CLI
$ pentimento log # timeline of the current session, with derived states
$ pentimento diff 7 # before/after (or evidence) of one action
$ pentimento undo 7 # revert one reversible action (post-state verified first)
$ pentimento undo --last # revert the most recent revertible action
$ pentimento compensate 9 # present the declared compensation, run it on confirmation
$ pentimento approve 11 # present a drafted action, execute it on confirmation
$ pentimento discard 11 # kill a draft, visibly and terminally
$ pentimento status # sessions, ledger size, snapshot store size
$ pentimento verify # check the optional per-line hash chain, if present
$ pentimento gc [--dry-run] # remove blobs no session on disk references
Undo executes, compensation proposes. Exact inverses run mechanically; a compensation — closing the ticket an agent created, deleting the resource it provisioned — is shown to you, command included, and runs only when you confirm. Either way, it lands in the ledger.
And a draft proposes before the act. An agent can journal a shell command or an HTTP request as a draft: fully on the record, not executed. pentimento approve runs it after you've seen it; pentimento discard kills it — and the discarded stroke stays visible in the ledger, a pentimento in the original sense.
The pentimento-fs MCP server
Point any MCP client — Claude Code, Claude Desktop, Cursor — at pentimento-fs and every file operation it performs is journaled, snapshotted, and undoable, with zero changes to the agent.
{
"mcpServers": {
"pentimento-fs": {
"command": "pentimento-fs",
"args": ["--root", "/path/to/your/project"]
}
}
}
Then tell the agent to prefer the journaled tools — one line in your CLAUDE.md (or equivalent):
For file writes, deletions and moves in this project, use the
pentimento-fstools instead of native file access.
The server exposes eight tools. Four journaled filesystem tools — write, delete, move, mkdir — where each response names the action id, so the human always knows the undo handle: journaled as action #7 (reversible: pentimento undo 7). Two executable outbound tools — exec and http — that run a command or a request through the journal, storing exit codes, output and response bodies as content-addressed evidence; both accept draft: true to journal without executing. And two for everything else: record journals an external action before it happens (compensable ones declare their compensation up front; irreversible ones are flagged for human approval first), and report appends the outcome afterwards.
A note on secrets in evidence
exec and http store commands, headers, bodies, and outputs verbatim. That evidence is local — it never leaves your machine — but it is not redacted by default, so it can capture tokens, Authorization headers, or passwords that appear in arguments or output. Opt in to redaction and those values are stripped before they are hashed and stored, so the secret never reaches the ledger or the blob store (spec §14):
$ pentimento-fs --redact # strip Authorization, Cookie, … headers
$ pentimento-fs --redact-pattern 'sk-[A-Za-z0-9]+' # and any matching pattern
Redaction is visible (pentimento diff marks it), it applies to immediately-executed actions and to all evidence, and — because a draft must stay runnable until you approve it — a draft's own command and headers are stored verbatim.
Running the tests
$ PYTHONPATH=src python3 -m unittest discover -s tests
Durability, safety, integrity
The reference implementation aims to match the spec's strongest promise under abrupt failure:
- Crash durability. Snapshot blobs, the files an action writes or restores, and every ledger append are
fsynced and atomically renamed, and their directory entry isfsynced too — so astartedevent and its snapshot reach stable storage before the effect runs (spec §4). - Symlinks are refused before they are followed — at every path component, not just the final target — so no link ever redirects where an action lands (spec §17).
- Serialized appends. A session may have more than one writer (an agent, plus you running
pentimento undo); appends take a brief advisory lock and the event id is assigned under it, so ids never collide and lines never interleave (spec §4). - Optional integrity chain. Opt in with
pentimento-fs --hash-chainand each line hashes the previous one;pentimento verifyreports the first break. It catches corruption and naive edits — not a determined actor with write access (spec §15). - No SSRF footgun by default. Because
httpperforms the request, it refuses targets with no legitimate HTTP use — link-local (169.254.169.254cloud metadata), multicast, reserved — while leaving loopback and private hosts reachable for local dev.pentimento-fs --block-privatehardens further by also refusing loopback/private ranges (spec §11). It's a best-effort send-time check, not DNS-rebinding-proof. - Tunable timeouts.
execandhttpdefault to 600s and 60s; override withpentimento-fs --exec-timeout/--http-timeoutso a hung command can't pin a session forever.
Status
Spec v0.3 (draft). The registry covers reversible filesystem actions and the executable outbound pair (shell.exec, http.request — irreversible unless a compensation is declared); everything else is journaled through x. extension kinds as compensable or irreversible — never anything rosier. Scope discipline is a feature.
Draft v0.3 — written to be argued with. Issues and pull requests welcome.
License
MIT — spec and reference implementation. A Red Rio Lab open spec.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。