Metadata-Version: 2.5
Name: omind
Version: 10.4.0
Summary: Reproduce the OMI/Obsidian memory integration for AI agents, plus a local web app to view, edit, and add memory entries.
Project-URL: Homepage, https://github.com/CryptoJones/omind
Project-URL: Repository, https://github.com/CryptoJones/omind
Project-URL: Issues, https://github.com/CryptoJones/omind/issues
Project-URL: Made in Nebraska (xkcd 2347), https://xkcd.com/2347/
Author-email: "Aaron K. Clark" <akclark@thenetwerk.net>
License: Apache-2.0
License-File: LICENSE
Keywords: claude-code,cli,fastapi,markdown,mcp,memory,nebraska,obsidian,xkcd-2347
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: certifi<2027,>=2026.10.19
Requires-Dist: cryptography<51.0,>=50.0.0
Requires-Dist: fastapi<1.0,>=0.110
Requires-Dist: mcp<3.0,>=2.2.0
Requires-Dist: opentelemetry-api<2.0,>=1.45.1
Requires-Dist: pydantic-settings<3.0,>=2.14.2
Requires-Dist: pyyaml<7.0,>=6.0
Requires-Dist: starlette<2.0,>=1.3.1
Requires-Dist: tomlkit<1.0,>=0.12
Requires-Dist: uvicorn[standard]<1.0,>=0.29
Provides-Extra: dev
Requires-Dist: httpx2<3.0,>=2.12.0; extra == 'dev'
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: msgpack<2.0,>=1.2.3; extra == 'dev'
Requires-Dist: mypy>=1.9; extra == 'dev'
Requires-Dist: numpy<2.5,>=1.24; extra == 'dev'
Requires-Dist: pip-audit>=2.10.0; extra == 'dev'
Requires-Dist: pip>=26.2; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Provides-Extra: e2e
Requires-Dist: runpod>=1.7; extra == 'e2e'
Provides-Extra: embed
Requires-Dist: filelock<5.0,>=4.2.1; extra == 'embed'
Requires-Dist: model2vec<1.0,>=0.3; extra == 'embed'
Requires-Dist: numpy<3.0,>=1.24; extra == 'embed'
Description-Content-Type: text/markdown

<p align="center"><em>Proudly Made in Nebraska. Go Big Red! 🌽 <a href="https://xkcd.com/2347/">https://xkcd.com/2347/</a></em></p>

# omind
OMI/Obsidian memory tooling for AI agents: reproduce the integration on any machine, plus a local web app to view, edit, and add memory entries.
Every PR is cross-reviewed across models by [Flatline Roundtable](https://github.com/CryptoJones/FlatlineRoundtable), and [conveyor](https://github.com/samarmstrong/conveyor) runs omind's backlog factory ([how](https://github.com/CryptoJones/omind/blob/main/docs/conveyor-factory.md)).

[![Tests](https://github.com/CryptoJones/omind/actions/workflows/test.yml/badge.svg)](https://github.com/CryptoJones/omind/actions/workflows/test.yml)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg?logo=apache)](LICENSE)
[![GitHub](https://img.shields.io/badge/GitHub-CryptoJones%2Fomind-181717?logo=github&logoColor=white)](https://github.com/CryptoJones/omind)
[![PyPI](https://img.shields.io/pypi/v/omind?logo=pypi&logoColor=white)](https://pypi.org/project/omind/)
[![Python](https://img.shields.io/badge/Python-3.11%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/)
[![Open Knowledge Format](https://img.shields.io/badge/format-OKF%20v0.1-4285F4?logo=googlecloud&logoColor=white)](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf)
[![Version](https://img.shields.io/github/v/tag/CryptoJones/omind?label=version&color=orange)](https://github.com/CryptoJones/omind/tags)

---

![omind's knowledge graph over a vault's [[wikilinks]]](docs/graph.png)

*`omind graph` over an OMI vault — every note a node **coloured by its OKF `type`** (and sized by link degree), every `[[wikilink]]` an edge. Rendered from `omind graph export` (see [docs/graph-demo](docs/graph-demo/)).*

`omind graph frontier` ranks that same graph by what to work on next: notes that
reach out to many others, that few reach back to, and that were touched recently
— memory is accumulating there and nothing has pulled it together yet. An
*orphan* is disconnected; a *frontier* note is connected but unabsorbed.

## What it does

**OMI** ("Open Mind Interface") is a folder of Markdown notes that an AI agent
reads and writes as long-term memory. `omind` does two things with it:

- **`omind setup`** — idempotently registers **omind's own node MCP server**
  (`omind node`) with your agent — **Claude Code** by default, or **Hermes,
  OpenClaw, OpenCode, Codex CLI, Gemini CLI, Poolside, goose, Claude Desktop,
  Kiro, VS Code, and Amazon Q** via `--agent` (see *Other agents* below) —
  pointed at an OMI folder inside an Obsidian vault, and initializes the folder
  as a **mesh node** (see below). After this, the agent persists memory across
  sessions through the MCP tools — and across machines through the mesh. Setup
  also installs a
  PreToolUse(Bash) **fresh-base git guard** (`git-fresh-base.sh`) that blocks
  branching off a local `main`/`master`/`develop` that is behind its
  `origin/*` counterpart (it fetches first, fails open otherwise).
- **`omind mesh`** — peer-to-peer replication: every machine runs a full local
  node and nodes sync over git+ssh, with per-note Lamport versioning and a
  field-level merge driver. No central server, full offline operation.
  Deleting archives (restorable) instead of removing. See
  [docs/mesh.md](docs/mesh.md) (design) and [docs/mesh-ops.md](docs/mesh-ops.md)
  (operation).
- **`omind serve`** — a small local web app (FastAPI + Tailwind) to **view, edit,
  and add** memory entries in that same folder, without opening Obsidian. Ships
  with five themes and a switchable UI in six languages (English, Spanish,
  French, Arabic, Russian, Chinese), including right-to-left layout for Arabic.
  Its API is unauthenticated by design — the localhost bind is the security
  boundary. Read [docs/serve.md](docs/serve.md) before exposing the port.
- **`omind recover`** — roll back a multi-note write that was interrupted
  mid-apply (a killed `consolidate --apply`, a power loss). Multi-file updates
  can't be truly atomic, so omind journals every target's prior bytes before the
  first write and can put them back. A note edited *after* the interruption is
  reported as a conflict and left alone — that edit is newer than anything the
  journal could restore.
- **`omind doctor`** — diagnose the wiring in one shot: Claude CLI + git on
  `PATH`, the `omi` MCP server registered at user scope with the right command,
  the OMI folder readable, mesh health (node identity, merge driver, per-peer
  ahead/behind, last-sync age, unresolved conflicts), backup health
  (unconfigured / last-success age / failing), and whether the auto-memory
  hooks have recorded any recent failures.
- **`omind backup`** — encrypted, unattended off-machine backup of the OMI
  folder, wrapping [restic](https://restic.net/) (see
  [Encrypted backup](#encrypted-backup) below).
- **`omind guard`** — the **OMI-compliance guard**: a layered set of agent hooks
  that make the agent *consult memory before it acts* and *hard-block* dangerous
  commands, enforcing identically across Claude Code, Hermes, OpenCode, and Codex
  (see [The OMI-compliance guard](#the-omi-compliance-guard) below).
- **`omind checkpoint`** — a scheduled job that records what the agent has been
  doing every N minutes into a daily worklog note, by mining the trails the hooks
  already capture (see [Activity checkpoints](#activity-checkpoints) below).
- **`omind ai`** — account for tokens attributable to OMI and select a manual
  economy/balanced/full expense profile that bounds priming and optional model calls.

The web UI works **fully offline** (fonts, styles, and the Markdown renderer are
vendored — no CDN). It shows **backlinks** for the open note, refreshes the list
live as other tools write the folder, guards against clobbering external edits,
and has keyboard shortcuts (`/` search, `n` new, `j`/`k` to move, `Ctrl`/`Cmd`+`S`
to save, `Esc` to cancel).

Everything runs locally. No accounts, no cloud, no cost.

## Install

**One-step bootstrap** (checks/installs dependencies, installs omind, verifies):

```bash
# clone, then:
scripts/bootstrap.sh                       # or: --remote codeberg, --vault PATH
```

It refuses what it cannot safely do — an unsupported system, no `git`, an existing
install that is still running on Windows, a release that does not install *and
start* in a throwaway environment — before it installs or replaces omind. It
auto-installs `uv` (user-local, no root — and it bootstraps Python ≥3.11 for
you), checks for `claude` with install guidance if it is missing,
then runs `omind setup` + `omind doctor`. Note: omind itself has **no Docker and
no Node.js dependency** — it needs only `git` and an agent CLI (Claude Code on
the default path; Hermes, OpenClaw, OpenCode, and Codex are each wired with
`omind setup --agent <name>` once their own CLI is installed — see *Other
agents* below).

**Manual** — an isolated CLI install from [PyPI](https://pypi.org/project/omind/):

```bash
# via uv (recommended — also provides a compatible Python if the system one is <3.11)
uv tool install omind

# or via pipx
pipx install omind
```

**From source / latest `main`** — the same isolated install straight from the git remote:

```bash
uv tool install git+https://github.com/CryptoJones/omind.git
# or
pipx install git+https://github.com/CryptoJones/omind.git
```

Any of these puts the `omind` command on your `PATH` in its own virtualenv. Codeberg
works too — swap in `git+https://codeberg.org/CryptoJones/omind.git`.

For development, install editable from a clone (see [CONTRIBUTING.md](CONTRIBUTING.md)):

```bash
git clone https://github.com/CryptoJones/omind.git
cd omind
pip install -e ".[dev]"
```

## Quick start

Provision the MCP wiring for your agent — Claude Code by default; add
`--agent hermes|openclaw|opencode|codex|gemini|poolside|goose|claude-desktop|kiro|vscode|q`
for the others (see *Other agents* below). Idempotent; safe to re-run:

```bash
omind setup --vault "$HOME/Documents/Obsidian Vault"
```

Prefer to wire things in yourself? Print the same steps as copy-paste shell
commands and JSON, personalized to your paths — nothing is changed for you:

```bash
omind quickstart --vault "$HOME/Documents/Obsidian Vault"
```

It covers all five pieces (memory folder scaffold, mesh initialization,
user-scope MCP registration, auto-memory hooks, fresh-base git guard hook),
each independently
applicable. The annotated walkthrough lives in
[docs/manual-setup.md](docs/manual-setup.md).

Run the web UI over the same memory folder:

```bash
omind serve --vault "$HOME/Documents/Obsidian Vault"
# open http://127.0.0.1:8765
```

Preview what setup *would* do without changing anything:

```bash
omind setup --vault "$HOME/Documents/Obsidian Vault" --dry-run
```

Check that everything is wired up correctly:

```bash
omind doctor --vault "$HOME/Documents/Obsidian Vault"
```

Add or update a single memory note safely — it creates the note, or updates it
in place if the title already exists, through the same locked, atomic write path
every other tool uses (body comes from stdin):

```bash
echo "the body of the note" | omind note --title "An Insight" --tags thesis,attention
```

Back up or migrate the whole memory dataset:

```bash
# export — json (default; portable & diffable) or targz (full-fidelity snapshot)
omind export --vault "$HOME/Documents/Obsidian Vault" --out omi-export.json
omind export --vault "$HOME/Documents/Obsidian Vault" --format targz --out omi.tar.gz

# import — format auto-detected by extension
omind import omi-export.json --vault "$HOME/Documents/Obsidian Vault"
```

Import adds new notes and leaves identical ones untouched; a note whose content
differs is kept as-is on disk and reported, unless you pass `--force`. Imports
never delete.

## Encrypted backup

The vault is long-term memory on one disk; `omind backup` keeps an encrypted
copy off-machine, wrapping [restic](https://restic.net/):

```bash
# one-time: generate the password file (0600) and create the encrypted repo
omind backup init --repo sftp:host:/path     # or a local path, s3:, b2:, …

# snapshot now, with 7-daily / 4-weekly / 6-monthly retention
omind backup run

# restic check + restore the latest snapshot's index.md and diff it live
omind backup verify

# unattended: a daily systemd user timer running `backup run`
omind backup install-timer
```

Every external command runs with a timeout, so a restic hung on a dead link
fails loudly instead of wedging the timer; three consecutive failures write a
`BACKUP FAILING` note into the vault so the problem surfaces in session
priming, and `omind doctor` reports backup health either way. If restic is
absent, `run` degrades to unencrypted rsync `--link-dest` snapshots and doctor
warns about the degradation.

**Copy `~/.config/omind/backup.pass` somewhere safe off-machine.** It encrypts
every snapshot; losing it with the disk makes the backups unreadable.

## How memory is stored

OMI is just a folder of plain Markdown notes — one note per memory, fully
human-editable (open the folder as an Obsidian vault). It is also a conformant
**[Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf)
bundle** (see below). Each note has a stable shape so tools and the merge driver
can read and write individual fields without stepping on each other:

- a **YAML frontmatter block** — the note's OKF metadata: the required `type`
  plus `title`, `description`, `tags`, and `timestamp`;
- a `# Title` and a `## Metadata` block (created date, `#tags`, the mesh
  `Rev:` Lamport stamp, and optional provenance — `Supersedes:` /
  `Superseded by:`, `Confidence:` (`high`/`medium`/`low`), and `Conflicts with:`
  for two memories that *disagree* rather than one replacing the other), kept
  alongside the frontmatter so existing tooling and un-upgraded mesh peers keep
  reading it unchanged;
- `## Summary` / `## Details` free text;
- `## Connections` — `[[wikilinks]]` to related notes (the graph the web UI and
  `omind lint` traverse);
- `## Action Items` (a checkbox list) and `## References`.

**Open Knowledge Format (OKF).** omind speaks
[OKF](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf) —
Google Cloud's vendor-neutral, Apache-2.0
[specification](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)
for representing knowledge as a directory of Markdown files with YAML
frontmatter, readable by any agent or tool with no SDK, runtime, or lock-in.
Every note omind writes leads with a frontmatter block carrying the one field
OKF requires (`type`) plus the recommended `title` / `description` / `tags` /
`timestamp`, and `index.md` is the OKF directory listing — so an omind vault
drops straight into any OKF-aware consumer. Migrate a pre-OKF vault in place with
**`omind convert`** (idempotent; `--check` validates the three conformance rules,
`--dry-run` previews). More: the
[OKF spec](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)
and [okf.md](https://okf.md/).

**One writer, always.** Every write — `omind note`, the `omind node` MCP server an
agent calls, the web UI, the mesh merge — goes through a single locked, atomic
path: an advisory `flock`, an atomic `os.replace`, and a `note_version`
compare-and-swap that rejects a write made against a stale read. That is what lets
several agents and tools touch the same folder at once without corrupting it.
"Deleting" a note **archives** it (hidden, restorable) rather than removing it.

A maintained `index.md` lists the most recent notes. Session priming compiles a
bounded capsule from its standing directives/recent titles, the Playbook,
workflow/persona summaries, and only a project-matched session handoff. Full note
bodies and auto-journals stay out of always-on context. Run
`omind lint` to catch drift (broken wikilinks, orphaned or near-duplicate notes,
missing titles). The cross-machine replication story — git-backed mesh, per-note
Lamport versioning, the field-level merge driver — is its own section:
[The memory mesh](#the-memory-mesh-20).

## The OMI-compliance guard

Memory only helps if the agent actually reads it *before* acting — and an agent
left to its own devices consults memory inconsistently and will happily run a
destructive command. The guard closes both gaps with a small stack of hooks
around every tool call. `omind setup` installs it for Claude Code; the other
harnesses wire it through [the per-agent adapters](#other-agents-hermes-agent-openclaw-opencode-and-codex-cli).
It enforces the same rules everywhere and **fails open** at every layer — a
broken hook can never wedge the agent.

- **Compact priming.** On session start the agent receives a hard-bounded capsule
  of identity, workflow, operator rules, recent-memory titles, and a cwd-matched
  handoff (Claude Code `SessionStart`, Hermes `pre_llm_call`, …).
- **Turn recall: a hint, not a shove.** Claude's `UserPromptSubmit` and Hermes'
  `pre_llm_call` deterministically select the memory most likely to matter and
  **name** it — one line, ~330 characters, "call `recall-note` if this turn needs
  it." The agent pulls the body when it is actually useful instead of paying for
  it on every turn. This satisfies the ordinary consult gate without asking a
  smaller model to interpret a `PreToolUse` error. When the vault was searched
  and genuinely has
  nothing relevant to the task, the gate auto-clears for that turn instead of
  forcing a manual `search-vault`/`recall-note` round trip on a note that, by
  construction, wouldn't be relevant — the auto-clear is always logged
  (`omind guard log`), never silent. An empty/uncaptured task can't be judged as
  a miss, so it still leaves the gate armed. Set `OMI_GATE_MISS_STRICT=1` to
  restore the old force-a-consult-on-every-miss behavior. Hard rule-specific
  prerequisites remain independent.

  The push-the-whole-note behavior is still there as `OMIND_PREFLIGHT=inject`
  (`off` silences the preflight entirely), and notes that compile an
  `omind-rule` block are **always** injected in full with firm framing — those
  are enforcement, not recall. Three guards keep automatic recall from
  accumulating: a note that announces its own supersession or correction is
  named but never injected, unchecked `- [ ]` action items are stripped from any
  injection (they are somebody else's TODO, not this turn's assignment), and a
  session that has already been pushed 60,000 characters of unrequested omind
  context stops receiving more. The agent's own `recall-note`/`search-vault`
  reads are pull, not push, and do not count against it (#387;
  `OMIND_SPLIT_BUDGET=0` restores the old combined budget). A name that shows up only
  in a tool's output, such as a volume label in `diskutil list`, gets one titles-only
  line naming its notes. Each name is hinted at most once per session, and these lines
  count as push (#388; `OMIND_TOOL_NAME_HINTS=0` turns them off). `create-note` and `edit-note` answer with the other notes that
  mention the same names, so a write that contradicts the vault shows it (#389, pull;
  `OMIND_WRITE_CONTEXT=0` turns it off). A name whose facts changed (a volume label that
  moved between drives) gets its dated history instead of a plain hint, oldest first,
  with superseded and corrected notes marked rather than hidden (#390;
  `OMIND_NAME_TIMELINES=0` turns it off). Why the default flipped in 9.2.0: on the author's own ledger
  the old push path had shipped ~3.4M tokens of unrequested recall across 5,816
  turns at ~25% precision, framed as binding instruction — a cost that never
  surfaced as an omind error, only as "the model has gotten worse in long
  sessions" (#321). Measure it on your own vault with
  `omind bench --precision`, and watch it over time with `omind ai usage`,
  which reports median/p90/p99 per-turn injection and the sessions carrying the
  most omind context.
- **Consult continuity across a long session.** A continuation prompt
  (`retry`, `go ahead`, a task notification — fewer than three meaningful
  terms) carries no signal of its own, so it is retrieved against the **prior
  turn's task plus the agent's recent activity**; the gate auto-clears only when
  the vault has nothing for the work in progress. An identical `retry` re-sent
  within two minutes is the harness's own API auto-retry and carries the
  turn's gate state instead of resetting it. Inside a turn, every allowed
  action counts against a budget (`OMIND_GATE_ACTION_BUDGET`, default 25);
  at the budget the core retrieves against the turn's task and its action
  trail, and if a relevant memory this session has not seen exists it is
  surfaced — injected after the tool call where the harness can do that
  (Claude Code `PostToolUse`), otherwise as a re-arm that demands exactly that
  note before the next action (one `recall-note` clears it). No candidate →
  the budget resets and the auto-clear is logged. At most
  `OMIND_GATE_MAX_REARM` (default 4) mid-turn re-arms per turn, so a turn can
  never be re-gated indefinitely. This lives in the harness-agnostic core, so
  every adapter (Claude, Hermes, OpenCode, Codex, Gemini, DSH) inherits it.
  `omind doctor` reports the 7-day auto-clear rate (`gate_continuity`).
- **The verifier.** Clearing the gate by reading *any* note isn't enough, so a
  `PostToolUse` verifier judges whether the consult was actually **relevant** to
  the turn's task — a deterministic keyword-overlap prefilter decides the clear
  cases. Only the `full` expense profile lets the ambiguous middle shell out to
  headless `claude -p` (fail-open). Default is **WARN** (it logs the off-topic consult and nudges
  toward better notes); opt-in **REQUIRE** (`OMI_VERIFY_REQUIRE=1`) re-closes the
  gate until a relevant consult happens. The thresholds
  (`OMI_VERIFY_HIGH`/`OMI_VERIFY_LOW`) and an always-relevant allowlist
  (`OMI_VERIFY_ALWAYS_RELEVANT`) are tunable, and the check primes on the agent's
  own recent off-topic consults.
- **Hard blocks.** A policy of high-risk command patterns (deleting a repo, a
  destructive git push, rewriting auth config, …) is blocked **unconditionally**,
  regardless of the gate, with the reason and the on-point notes to read.
- **The compliance log + learning loop.** Every guard-relevant action is appended
  to `compliance.jsonl`; a `PostToolUse` detector records soft-rule matches as
  evidence, and recidivism escalates a rule (soft → hard → verifier) over time
  (`omind guard learn` / `escalate`). The log rotates once past 8 MiB
  (`compliance.jsonl.1`); readers span both generations, so escalation counts
  survive a rotation.

**Cross-harness by construction.** Each harness is described as data — a
`HarnessSpec` (can it hard-block? which block-output format?) — and its hook pipes
its event to `omind guard adapter --harness <name>`, so a rule learned under one
agent blocks under all of them. `omind guard selftest` replays canned deny events
through every harness's renderer to verify the wiring without a live agent.

Inspect and operate it with `omind guard log` (recent denies/violations),
`omind guard policy` (active rules), `omind guard status` (which harnesses are
guarded), `omind guard explain "<cmd>"` (dry-run a command), and
`omind guard verify --explain` (why a consult scored relevant or off-topic).
`omind guard repair` (and `omind doctor`) re-heal a wedged or drifted hook-set.

When the guard is impeding critical work, temporarily pause the consult gate and
verifier instead of editing hook config by hand:

```bash
omind guard pause --for 15m   # also accepts 90s, 2h, or bare minutes like 15
omind guard status            # shows the remaining pause window
omind guard resume            # re-arm immediately
```

Running `omind guard pause` without `--for` uses a 30-minute window. The pause is
machine-global, auto-expires, and is written to the compliance log. Hard
destructive blocks remain active while paused; this only skips the per-turn OMI
consult gate and relevance verifier.

## The Playbook

The **Playbook** is the small set of always-on operator rules — the cross-cutting
procedures (sudo, secrets, forges, "pull before you work", "do it yourself") that a
fresh agent instance otherwise keeps re-learning the hard way. It lives as a priming
file, `Playbook.md`, in the OMI vault, and omind surfaces it two ways:

- **Always in context.** A compact digest of `Playbook.md` is compiled into
  *every* session's capsule, so the rules are present whether or
  not the agent thinks to search for them — they do not depend on the per-turn
  gate's relevance matching to surface.
- **Enforced at the action.** The guard backs the most-violated rules with hard
  blocks keyed on the *command*, not the task. Raw `sudo` is blocked and redirected
  to the installed **`fleet-sudo`** wrapper, which reads the fleet sudo password
  from `pass` itself — so no instance ever guesses a per-host `pass` entry or hands
  the user a command to paste. A deliberate raw `sudo` opts in with `OMI_SUDO_OK=1`,
  exactly like the Codeberg-mirror `OMI_PUSH_GITHUB=1` escape hatch.

Edit the rules by editing `Playbook.md` in the vault; add enforcement with a seed
rule in `omind.policy`. The Playbook is the guard's priming made explicit: *don't
ask a fresh instance to remember — put the rule in front of it, and block the wrong
action.*

Operators can also declare **deterministic rules inside ordinary vault notes**
with fenced ```` ```omind-rule ```` blocks (YAML: `id`, `tool`, `match` glob,
optional `when: {repo_visibility, branch}` and `except_repos`, `action:
deny|warn`, `message`). They compile into PreToolUse checks evaluated before
everything else — every rule a hook can decide never depends on model
attention. Repo visibility comes from `gh` (cached a day) and **fails open**
when unknown; invalid blocks are skipped with a breadcrumb. Inspect the
compiled table with `omind rules list`. A note rule with a seed rule's `id`
replaces the seed, so per-repo exceptions stay operator-editable in the vault.

`omind rules export` emits the same set as Markdown for `CLAUDE.md`/`AGENTS.md`.
A behavioral invariant that only binds when retrieval happens to surface it is
not a rule, it is a coin flip — the surest sign is the same correction filed
three times because it never fired. Invariants belong in the file the harness
loads unconditionally; the vault keeps the rest.

## Activity checkpoints

You can't reliably *force* a running agent to do something on a wall clock —
agents are turn-driven and idle between messages. So to "record recent work every
N minutes," omind doesn't ask the agent: `omind checkpoint` is a scheduled job
that mines the two trails the hooks already capture — the per-action **journal**
(`Journal/Session Journal <date>.md`) and the cross-harness **compliance log** —
and upserts a per-day **`Worklog <date>`** note with a timestamped section per
run (one note per day, so it stays a single recent-memory slot instead of
flooding the index).

```bash
# summarize the last 15 minutes into today's worklog note, now
omind checkpoint --since 15m

# or run it unattended every 15 minutes via a systemd user timer
omind checkpoint install-timer --every 15m
omind checkpoint uninstall-timer            # stop + remove it
```

The summary is deterministic (action counts by tool + guard denies/violations);
`--llm` adds a one-paragraph `claude -p` narrative, fail-open to the deterministic
text. Because it's a scheduled job — the same systemd-user-timer mechanism as
`omind backup` and `omind mesh` — it doesn't depend on the agent's cooperation,
which is what makes it a reliable *record* rather than a hopeful instruction.

## Live help and token-efficient recall

`omind setup` installs a managed `omind` skill for Claude Code and Codex. When a
user asks `/omind help` (or `$omind` in Codex), the skill calls the OMI MCP
`help` tool, whose output is generated from the installed argparse tree. The
fallback CLI uses the same source:

```bash
omind help                  # top-level commands
omind help ai usage         # exact nested syntax and flags
omind help guard pause
```

For ordinary memory access, use the bounded `search-vault` result page and then
`recall-note`. `recall-note` returns a single compact representation with an
optional Markdown section and 500–8,000-character bound. `read-note` is the
editing path: it returns *one* representation (`fields` by default, `raw` on
request) plus a version token.

Every list-shaped MCP tool is paged (`limit`, `offset`, `has_more`), so no tool
can return the whole vault in a single result.

## Search

`search-vault` and `omind search` are relevance-ranked, not substring matches:
a derived SQLite index fuses BM25 keyword search, semantic vector similarity,
and a light recency signal, and returns the matched excerpt with each hit. On a
744-note vault a query drops from ~270 ms to ~20 ms, and natural-language
questions that previously matched nothing now return ranked answers.

```bash
omind search "why did release signing fail" --explain
omind reindex --index-only     # refresh the derived index (search does this too)
omind bench                    # latency, MCP schema size, and token cost
omind bench --quality          # labelled recall@1 / recall@5 / MRR
omind bench --precision        # what the per-turn preflight would inject unbidden
omind audit                    # every context-spending surface vs. a declared threshold; exit 1 on a fail
omind bench --needle --transcript SESSION.jsonl   # A/B: does the preflight cost the model recall?
```

`omind audit` is the instrument that can indict omind itself: one row per surface
(preflight, SessionStart priming, MCP responses, the consult gate, learned rules,
the verifier, the MCP tool schema), each with a measured number, a version-controlled
threshold and a verdict that names the remedy — including "turn this off". It reads
only what omind already records, writes nothing, and reports what it cannot judge as
`unmeasured` rather than green. See [docs/audit.md](docs/audit.md).

`omind bench --needle` is the A/B the other instruments cannot give you: it replays a
real long transcript twice — as it was, and with what the preflight would have pushed
after every prompt — plants a fact and an instruction at 20/50/80% depth, and asks a
model to retrieve one and obey the other. See [docs/needle.md](docs/needle.md).

The index lives in the state directory, never in the vault — it is disposable
and rebuildable. Semantic ranking needs the optional `[embed]` extra; without it
search still works on keywords alone. See [docs/retrieval.md](docs/retrieval.md).

## AI token usage and expense profiles

omind keeps a machine-local, per-vault ledger for session priming, proactive
recall, OMI MCP responses, and verifier/checkpoint calls. Claude's Stop hook also
snapshots numeric provider usage from the session transcript, including cache
read/write tokens, so the report can show OMI's share of total session traffic.
Injected/MCP content uses the provider-neutral estimate `ceil(characters / 4)`;
subprocess and session usage use provider-reported counts. The ledger stores only
counts and operational metadata—never prompts, responses, note contents, or
credentials.

```bash
omind ai profile                         # show saved/effective profile
omind ai profile economy                 # 4k priming, deterministic checks
omind ai profile balanced                # default: 8k priming, deterministic checks
omind ai profile full                    # 24k priming, optional model checks enabled
omind ai usage --since 7d                # 24h, 7d, 30d, or all
omind ai usage --since all --json        # machine-readable report
```

Profiles describe OMI overhead; they do not select the parent agent's model.
`balanced` is the default: 8,000 characters of session priming, 2,500 of
proactive recall, deterministic checks only. `economy` caps priming at 4,000
characters, recall at 1,500, and disables optional model subprocesses. `full`
uses 24,000/4,000 and enables verifier/checkpoint model calls. Whatever the
profile, a priming note is injected **whole or not at all** — an oversized note
becomes a one-line stub naming the exact `recall-note` call instead of a
misleading partial body (`index.md`, a catalog, may still truncate mid-list).
An optional operator-maintained `Rules.md` in the OMI folder is first-priority
priming: keep it under ~3,500 characters of imperative one-liners and it is
guaranteed to arrive whole on every profile. Legacy `high`/`medium`/`low` values map
to `economy`/`balanced`/`full`. Set `OMI_AI_EXPENSE` for a temporary override.
The CLI and web app show cache-inclusive OMI share, average priming, exact versus
estimated usage, per-operation totals, and estimated avoided tokens.

## Other agents: Hermes, OpenClaw, OpenCode, Codex, Gemini, Poolside, goose, Claude Desktop, Kiro, VS Code, Amazon Q

[Claude Code](https://github.com/anthropics/claude-code) is the default, but the
same OMI folder can back any agent. `omind setup --agent ...` provisions several
more out of the box —
[Hermes Agent](https://github.com/NousResearch/hermes-agent),
[OpenClaw](https://github.com/openclaw/openclaw),
[OpenCode](https://github.com/sst/opencode), and
[OpenAI Codex CLI](https://github.com/openai/codex):

```bash
omind setup --agent hermes   --vault "$HOME/Documents/Obsidian Vault"   # Hermes Agent
omind setup --agent openclaw --vault "$HOME/Documents/Obsidian Vault"   # OpenClaw
omind setup --agent opencode --vault "$HOME/Documents/Obsidian Vault"   # OpenCode
omind setup --agent codex    --vault "$HOME/Documents/Obsidian Vault"   # OpenAI Codex CLI
```

The **OMI-compliance guard** (hard-blocks + the per-turn consult gate) enforces
across harnesses, not just Claude Code: Hermes via its `pre_tool_call` hook,
OpenCode via a `tool.execute.before` plugin, and **Codex CLI** (>= 0.117) via its
Claude-schema `PreToolUse`/`PermissionRequest` command hooks in
`~/.codex/hooks.json` — so a rule learned under one agent blocks under all of
them. `omind setup --agent codex` also persists Codex `[hooks.state]` trust for
the omind-owned hook definitions it just wrote, so a fresh Codex session can run
the guard and OMI priming hooks without a manual `/hooks` approval pass. The hash
is computed from the exact hook definition on that machine, including the local
`omind` executable path; if you later edit the hook by hand, re-run setup or use
Codex's `/hooks` UI to review the changed definition. `omind guard selftest`
replays a canned deny through every harness's renderer to confirm the wiring
without a live agent.

Codex also gets the `omi` MCP server registered — under `[mcp_servers.omi]` in
`~/.codex/config.toml`, the same table `codex mcp add` writes. Unlike every
other agent config omind touches, `config.toml` is **TOML**, so this merge is
done with `tomlkit` (round-trip parsing) instead of the JSON idiom the rest
share; only the `mcp_servers.omi` table is ever touched, and a `config.toml`
that doesn't parse is never overwritten. A managed `~/.codex/skills/omind`
skill routes `$omind`/help requests to the live MCP `help` tool and ordinary
memory reads to compact recall.

For Codex, one command installs the whole integration:

```bash
omind setup --agent codex --vault "$HOME/Documents/Obsidian Vault"
```

That command idempotently:

1. Registers the `omi` MCP server in `~/.codex/config.toml`.
2. Installs the OMI guard on `PreToolUse` and `PermissionRequest` in
   `~/.codex/hooks.json`.
3. Installs `SessionStart` OMI priming, using the same recent-memory context
   Claude Code receives.
4. Installs `PostToolUse` accounting for OMI MCP response sizes.
5. Installs the managed `omind` help/recall skill.
6. Writes a managed global `~/.codex/AGENTS.md` bootstrap pointer that tells
   fresh Codex sessions to read OMI first.
7. Persists Codex hook trust for those omind-owned hook groups under
   `[hooks.state]` in `~/.codex/config.toml`.

Then restart Codex and verify:

```bash
omind doctor --agent codex --vault "$HOME/Documents/Obsidian Vault"
```

`omind setup --agent <name>` adapts to where each agent keeps its config. The
three **memory-backing** agents — Hermes, OpenClaw, and OpenCode — get the full
treatment:

1. The shared steps — OMI folder scaffold + mesh initialization — identical to
   the Claude Code path, so every agent talks to **one** memory folder through
   the same `omind node` server.
2. Registers the `omi` MCP server where the agent looks for it: `mcp_servers` in
   `~/.hermes/config.yaml` (Hermes), `mcp.servers` in `~/.openclaw/openclaw.json`
   (OpenClaw — legacy `~/.clawdbot` / `~/.moltbot` installs detected too), or the
   `mcp` block in `~/.config/opencode/opencode.json` (OpenCode). Only omind's own
   entry is ever touched; a config file that doesn't parse is never overwritten.
3. Installs an `omind-omi-memory` skill that teaches the agent to **read** memory
   through the MCP tools and **write** it through `omind note` — the single-writer
   path that keeps concurrently running agents from corrupting the folder (see
   [docs/mesh.md](docs/mesh.md) → "Node types & the single-writer rule").
4. **Wires session-start priming** so the agent reads OMI *first* — Hermes via a
   `pre_llm_call` hook (pre-approved in its `shell-hooks-allowlist.json` so it
   loads without a prompt), OpenClaw via a managed `MEMORY.md` bootstrap. It is
   the same `omind hook` payload (recent-memory index + latest session state)
   Claude Code injects through its `SessionStart` hook.

The **Gemini CLI** is wired **guard-only** — just the hard-block hook described
above (the `BeforeTool` hook under `hooks` in `~/.gemini/settings.json`); its
MCP-memory registration, skill, and priming are a separate follow-up. **Codex
CLI** gets guard, MCP-memory registration, compact SessionStart priming,
PostToolUse accounting, the `omind` help/recall skill, and the global AGENTS
bootstrap pointer (see above). **OpenCode** priming is likewise not wired yet (its MCP
server and skill are). The cross-harness **guard** reaches Claude Code, Hermes,
OpenCode, Codex, Gemini, and Poolside as hard-block. **OpenClaw** gets no
guard: it has no shell-command hooks (tool gating is the in-process plugin hook
`before_tool_call`), and the `hooks.agent` entry older omind wrote is rejected by
OpenClaw's strict config schema, which stops its Gateway from starting. `omind
setup --agent openclaw` removes that entry, and `omind doctor --agent openclaw`
fails while it is still there (#425).

**Poolside** (the `pool` CLI for the Laguna agent, >= 1.0.16) gets the full
Claude Code treatment from one `omind setup --agent poolside`: the `omi` MCP
server under `mcp_servers` in `~/.config/poolside/settings.yaml`, plus five
entries under the same file's `hooks` key — `PreToolUse` (the hard-block guard,
`omind guard adapter --harness poolside`), `UserPromptSubmit` (the per-turn
memory preflight + consult gate), and `PostToolUse` / `Stop` / `SessionStart`
(journal, verifier, accounting, loop guard, priming). `pool`'s hooks speak a
snake_case twin of Claude's protocol and name MCP tools `<server>__<tool>`; the
`--harness poolside` flag makes omind translate both ways, so a rule learned
under Claude Code blocks under Laguna too. Re-runs replace only the entries
omind owns (named `omind-omi-*`), so hooks you wrote and pool's own
`stop_hook_max_continuations` are preserved.

**Grok Build** (the `grok` CLI) gets memory, the guard, the skill, and a home
rule from one `omind setup --agent grok`. The `omi` MCP server is registered
under `[mcp_servers.omi]` in `~/.grok/config.toml`. Hooks go in
`~/.grok/hooks/omind.json` (other files in that directory are left alone):
`PreToolUse` hard-blocks via `omind guard adapter --harness grok`,
`UserPromptSubmit` runs the per-turn preflight, and `PostToolUse` / `Stop` /
`SessionStart` do accounting, the loop guard, and session bookkeeping. Grok
does not inject `SessionStart` stdout, so priming is a managed
`~/.grok/rules/omind.md` plus the packaged skill in `~/.grok/skills/omind/`.
Grok also runs Claude Code's hooks. The bash fast path and the Python
adapter accept camelCase (`toolName`, `toolInput`, `sessionId`) and
snake_case, unwrap `use_tool` so an `omi__…` recall counts as a consult,
and answer a deny as `{"decision":"deny","reason":…}`. `$GROK_HOME` overrides
`~/.grok`. `omind quickstart --agent grok` prints the same wiring to apply
by hand.

**goose** (Block's on-machine agent) gets OMI **memory + priming** from one
`omind setup --agent goose` — it has no blocking pre-tool or session-start shell
hooks, so the guard is not wired here. The `omi` MCP server is registered as a
stdio **extension** (goose's term for an MCP server) under the `extensions` map
in `~/.config/goose/config.yaml` — the same `{type: stdio, cmd, args, enabled,
timeout}` shape `goose configure` writes, so only omind's own `omi` entry is
touched and a config that doesn't parse is never overwritten. Priming rides
goose's global hints file: omind writes a fenced, managed OMI block into
`~/.config/goose/.goosehints` (which goose injects into every session's system
prompt), preserving any hints you wrote around it. Start a new goose session to
pick both up.

### MCP-only targets: Claude Desktop, Kiro, VS Code, Amazon Q

Four more agents are wired by **MCP registration alone** — omind drops the `omi`
server into the tool's own config file and nothing else (no guard, no skill); the
agent reaches memory through the MCP tools the server exposes:

```bash
omind setup --agent claude-desktop --vault "$HOME/Documents/Obsidian Vault"  # Claude Desktop app
omind setup --agent kiro           --vault "$HOME/Documents/Obsidian Vault"  # Kiro IDE
omind setup --agent vscode         --vault "$HOME/Documents/Obsidian Vault"  # VS Code (native MCP)
omind setup --agent q              --vault "$HOME/Documents/Obsidian Vault"  # Amazon Q
```

Each writes only the `omi` entry it owns and refuses to overwrite a config file it
can't parse. Config locations: Claude Desktop's `claude_desktop_config.json` (under
`~/Library/Application Support/Claude` on macOS, `~/.config/Claude` on Linux,
`%APPDATA%\Claude` on Windows; `mcpServers` block); Kiro's `~/.kiro/settings/mcp.json`
(`mcpServers`); VS Code's user-level `mcp.json` (under the same per-OS app-support dir
as Claude Desktop but `Code/User`; a `servers` block with `type: stdio`); and Amazon
Q's `~/.aws/amazonq/mcp.json` (`mcpServers`). Restart the tool afterward to load the
server.

`omind doctor --agent hermes|openclaw|opencode|codex|gemini|poolside|goose|grok|claude-desktop|kiro|vscode|q`
diagnoses that agent's wiring, and `omind quickstart --agent <name>` prints the manual
steps (YAML/JSON snippets personalized to your paths) if you'd rather merge them in
yourself.

The auto-memory **journal** hooks (the per-action trail) remain Claude Code-only;
the other agents' actions reach OMI through the MCP skill instead.

See [CHANGELOG.md](CHANGELOG.md) for release notes.

## The memory mesh (2.0)

2.0.0 turned omind from a single-machine tool into a **git-backed mesh** —
every machine runs a full local memory node, and the nodes replicate to one
another **peer-to-peer over git**, so memory is shared across the house with
**no central server** and full offline operation. Concurrent writes build on
the per-node write safety (advisory `flock` + atomic `os.replace` +
`note_version` compare-and-swap) and add cross-node **Lamport versioning**
with a field-level merge; "deleting" a note **archives** it (hidden,
restorable) rather than tombstoning it. Design:
**[docs/mesh.md](docs/mesh.md)**; operation:
**[docs/mesh-ops.md](docs/mesh-ops.md)**.

## License

Apache 2.0. See [LICENSE](LICENSE).

Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/
