Jordan Newell3 downloads(changes coming) Local-first audit trail for AI agent activity. Every agent inference gets an append-only markdown receipt in your vault.
Local-first audit trail for AI agent activity in your Obsidian vault. Every agent inference gets an append-only markdown receipt — a journal you keep on your own agents, not a forensic system, and honest about the difference (see SPEC.md).
Speaks OM-1 (Obsidian Messenger): agents, other plugins, or a shell one-liner can all file receipts — see INTEGRATION.md. The messenger plugin is not required — the audit inbox is just a file.
audit.v1 block per agent action: who, what, when,
model, duration, tokens, status, plus a rendered human summary.Audit/ledger/YYYY-MM-DD.md.
Envelope = the receipt as canonical JSON; body = the summary. Readable in
Obsidian, parseable by anything.Messenger/audit/inbox.md) with
proper cursor semantics; junk is rejected, redeliveries are deduped.Install agent audit hooks writes vault-scoped configs
(Claude Code, OpenCode) so local agents file their own receipts through the
bundled writer (bin/curtis-audit-file.mjs); Codex and Gemini get manual
recipes. Metadata only — tool input content is never recorded. Source
installs only: the writer ships with the repo, not with plugin releases
(Paths A and B work everywhere).window.curtisAudit.record({ agent, model, tokens, ... }).window.curtisAudit.query({ agent, status, since, ... }) for status bars, dashboards, and other plugins.Audit/digest.md: counts, statuses, tokens,
durations, a per-day breakdown, errors.From a release: download main.js, manifest.json, and
styles.css into <vault>/.obsidian/plugins/curtis-ai-audit/, then enable
the plugin in Obsidian (Settings → Community plugins). Once accepted into the
community directory it installs from there directly.
From source: clone this repo into
<vault>/.obsidian/plugins/curtis-ai-audit/, run
npm install && npm run build, and enable it in Obsidian.
Ribbon icon or commands:
| command | what it does |
|---|---|
| Check audit inbox now | poll + ingest, with a summary notice |
| Verify ledger | integrity scan; details to console |
| Write digest | (re)write Audit/digest.md and open it |
| Prune ledger now | manual retention pass (needs retention > 0) |
| Open today's ledger | open/create today's shard |
| Install agent audit hooks | write vault-scoped hook configs (Path C) |
| Uninstall agent audit hooks | remove exactly what install added |
Other plugins (same window):
const receipt = await window.curtisAudit.record({
agent: "curtis-ai-chat",
action: "inference", // optional, default "other"
model: "gpt-4o",
provider: "openai",
durationMs: 1234,
tokens: { input: 812, output: 341 },
subject: "Notes/question.md",
summary: "Answered a question about the spec",
});
// also: .poll(), .verify(), .digest(days?), .query(filter)
// workspace event: "curtis-audit:receipt"
The read side, for dashboards and status bars:
const errors = await window.curtisAudit.query({
agent: "curtis-ai-chat",
status: "error",
since: "2026-10-01", // bounds apply to `recorded` (local write time)
order: "desc", // newest first (the default)
limit: 20,
});
Anything that can append to a file (other device, script, agent):
<!-- messenger: {"id":"msg_x","from":"research-agent","to":"audit","ts":"2026-10-10T12:00:00.000Z","replyTo":null} -->
{"action":"inference","model":"gemini-2.5-pro","summary":"Summarized a paper"}
<!-- /messenger -->
See INTEGRATION.md for wiring up curtis-ai-chat.
npm test # 107 unit tests, in-memory vault, no Obsidian needed
npm run build # typecheck + bundle to main.js
v0.2.2 — the local-first tier, deliberately. Tamper-evidence, retention enforcement, and reporting are the next tier up and are not pretended here. Requires Obsidian 1.13.0+ (declarative settings).
MIT © Jordan Newell