itechmeat/open-second-brain

382 stars ยท Last commit 2026-08-28

Local-first ๐Ÿง  memory for Hermes Agent that lives in your Obsidian vault and remembers project context. Nightly ๐Ÿ˜ด dream passes turn repeat corrections into confirmed preferences with measurable confidence. Adapters ship for Claude Code, Codex, and OpenClaw, with an MCP server for anything else.

README preview

# Open Second Brain

![Open Second Brain - your knowledge, amplified by AI](docs/images/readme-poster.jpg)

> An [Obsidian](https://obsidian.md)-native memory layer for your AI agent. Plain Markdown you own, in the same vault you already use.

Open Second Brain plugs into [Hermes Agent](https://github.com/NousResearch/hermes-agent) and turns your Obsidian vault into a memory layer the agent reads and writes through deterministic CLI / MCP tools. Preferences, signals, evidence, and audit trails are real `.md` files under `Brain/` in the vault you already open in Obsidian every day. You can grep them, version them with git, search them in Obsidian, edit them by hand. No daemon, no vector black box, no hidden state outside the vault.

## What is new

Open Second Brain 1.54.0 turns `visibility:` from a label into a boundary. The field, the predicate that reads it and the filter that applies it have all shipped for several releases, and until now the filter was wired into one call site and the scope it filtered against came from the caller - so a remote caller that asked for the private scope was handed it. One reserved token is now denied by default at remote reach, enforced at the three roots every read surface reaches page content through: the ranked search pipeline, the page walker, and the by-path and by-chunk-id read primitives. An architecture sweep proves mechanically that there is no fourth root, and it found two direct filesystem reads on its first run.

The reach that decides is a transport fact, not a request field. stdio and the command line mint `local`, because the caller already started the process and holds whatever filesystem access it runs with; every non-loopback HTTP bind mints `remote`. A caller that puts a reach-shaped argument in a tool call is refused by name rather than quietly ignored, and what the local bypass actually proves is written down where it is defined rather than overclaimed. A withheld page is reported exactly as an absent one - byte for byte on the key-addressed reads, where the key spaces are enumerable and a distinguishable refusal would be an existence oracle over the population being hidden. Twenty-four of the seventy-six enumerated note-returning surfaces now consult the field, up from three of seventy-one, and `o2b search check` reports the honest remainder alongside the count of pages the boundary withholds. Schema 12 records what the index measured of each page's frontmatter and backfills it from data the index already holds, so a vault that never wrote the token sees no change at all and no operator has to reindex to get there.

Previous releases, 1.53.1 and 1.53.0, closed a dedup pass that proposed the same merge forever and could write a merge cycle, and taught Hermes recall to carry the turn's query without leaving the curated lane that makes injection safe. The [CHANGELOG](CHANGELOG.md) has the detail on both.

Previous release, 1.52.0, was the honesty wave: nothing writes silently, nothing degrades silently. Nine tracker cards were read against the live source before anything was designed, and the reading did most of the work - one card described a feature that had already shipped end to end, one asked for privacy by riding a predicate that is inert in every default install, and four more had premises the source contradicted. What survived is one rule applied eight ways.

A note update now refuses to destroy what it could not read - an unreadable note raises `target_unreadable` instead of parsing as empty, and a blank body over a non-empty note needs an explicit `allow_empty`. `o2b search check` measures instead of inferring: a real pending-vector count replaces a recommendation that told fully embedded vaults to compute their first vectors, an embedder record audit reports when the recorded dimension contradicts the stored data, and `o2b search restamp` repairs the one drift that needs no provider. Every structured Brain record carries a server-derived `origin_channel` no caller can supply; Brain status derives `log_events_since_dream` from the shards it already reads and names an unreadable shard a lower bound; imports read back what they claim and report every missing key by name, and the sessions lane resumes an interrupted transcript at the turn boundary; the three note-producing envelope lanes hand the generating agent a bounded, ownership-filtered wikilink candidate manifest; a failed multi-artifact write leaves a durable dead letter; and a standing census documented - truthfully, at the time - that `visibility: private` was a view filter rather than a privacy boundary, with `o2b search check` saying so on vaults that use the field. That census is the coverage map 1.54.0 built the enforcement against.

View full repository on GitHub โ†’