brain

package module
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

README

Logos

When one coding agent stops, the next one continues the work.

Setup Benchmark Agent guide Contributing Site

About

Logos is a local-first memory and continuity layer for coding agents. Claude Code, Cursor, Codex and your own agents share one vault over MCP: an agent checkpoints what it did, and the next one — a different model, in a different tool, on a different day — resumes exactly where that one stopped.

Claude Code  ──▶  checkpoint  ──▶  Logos  ──▶  resume  ──▶  Cursor
                                (your vault)

It runs on your machine, against a directory of markdown files you own, and uploads nothing. .brain/index.db is a cache you can delete and rebuild from the markdown. If this project dies, you keep a vault.

Nothing is observed. Logos does not watch your screen, your browser history, your files or your calendar. The only things in your vault are things an agent explicitly wrote there — a checkpoint, a note, a memory it asked to remember and you approved. The one network call Logos ever makes on its own is brain update checking for a new release, and only when you type it; nothing else leaves the machine, ever.

Logos is built for continuity:

  • resume / context — where the last agent stopped, what it verified, what it ruled out
  • before_you_try — whether an approach was already attempted and abandoned, here or elsewhere
  • why — what was being decided when a given file was last worked on
  • checkpoint / handoff — the durable record, with verified and failed kept deliberately separate
  • Receipts on every write, so you can see the memory layer working instead of taking it on faith
  • A SessionStart hook that puts the last handoff in front of the model before it does anything

Logos is local and durable:

  • Markdown is the truth; the SQLite index is a disposable cache
  • Runs with no model runtime at all — semantic search degrades to lexical, nothing breaks
  • Hybrid retrieval: FTS5 plus local embeddings through Ollama, when one is available
  • Vault files are written 0600, and brain doctor reports what the rest of the machine can read
  • Survives SIGKILL mid-write, a full disk, and two processes racing on one vault (chaos/)
  • Project- and worktree-scoped, so one repository's facts do not surface in another

Logos works where you already work:

  • MCP server for Claude Code, Claude Desktop, Cursor, Codex and anything else that speaks the protocol
  • Read-only tools annotated as such, so they stay available in read-only chat modes
  • A CLI equivalent for every tool, for agents that only have a shell
  • A Go package to embed the engine directly — import "github.com/Coder8124/brain"
  • A Wails v2 desktop app: menubar orb, panel, graph canvas

Does it work?

On a handoff suite built for this — 32 scenarios, nine memory systems, one machine — Logos passes 84.4%; the next best system passes 46.9%.

Every real system retrieves about equally well. What separates them is whether the agent that resumes gets the current answer, or gets it sitting next to the stale one it replaced. Method, per-scenario scores and the cases Logos loses are in the benchmark.

Getting started

In Claude Code, which also installs the SessionStart hook that puts the last handoff in front of the model before it does anything:

/plugin marketplace add Coder8124/logos
/plugin install logos@logos

Anywhere else — no Go toolchain, no clone, no build:

npx -y @noeton/logos setup

setup picks a vault, finds your local model runtime, runs the first index, and then shows you which agents it would wire and asks before touching any of them. --dry-run shows the whole plan and writes nothing.

From source, if you have Go:

git clone https://github.com/Coder8124/logos && cd logos
go build -o bin/brain ./cmd/brain && ./bin/brain setup

One-click buttons for Cursor and VS Code, release binaries, and wiring a host by hand are in SETUP.md.

Contributing

Contributions are welcome. CONTRIBUTING.md covers the build, the test tiers, and the two conventions that are load-bearing here: the vault is the truth, and every feature announces itself.

If you are an agent working in this repository, the context-connect and continuity skills that ship with the Logos plugin (plugin/skills/) cover how to connect to brain here and how to use it — this repository dogfoods its own plugin, so both are already available in a Claude Code session.

On the two names

Logos is the product — the repository, the npm packages, the MCP server hosts see. brain is the development name and stays one internally: the Go module github.com/Coder8124/brain, the brain command, BRAIN_VAULT, and .brain/. The npm wrapper installs logos and brain as the same command, so either spelling works wherever you meet it.

Contact

License

Apache 2.0. See LICENSE.

Contributors: git history satisfies §4(b). You do not need to add change notices to files you modify, and there is no NOTICE file and no CLA. See CONTRIBUTING.md.

Documentation

Overview

Package brain is a local-first memory and continuity layer for AI agents.

It is the same engine behind the `brain` CLI, the desktop app and the MCP server, exposed for embedding directly in your own agent. Memory lives in an Obsidian-compatible vault on disk that the user owns; nothing is uploaded.

b, err := brain.Open("/path/to/vault")
if err != nil {
	log.Fatal(err)
}
defer b.Close()

// What did the last agent — possibly a different product — leave behind?
c, _ := b.Resume("kestrel-one")
fmt.Println(c.Render())   // ready to drop into a system prompt

// Before proposing something, check nobody has already ruled it out.
if ruled, _ := b.Tried("switch to a plastic frame", "kestrel-one"); len(ruled) > 0 {
	fmt.Println(brain.Explain("switch to a plastic frame", ruled))
}

// Record progress as you go, then commit where you stopped.
b.Note("kestrel-one", "re-quoted the waveguide; no movement under 10k units")
b.Checkpoint(brain.Checkpoint{
	Project: "kestrel-one",
	Failed:  []string{"re-quoting the waveguide — no movement under 10k units"},
	Next:    "quote the display driver alternatives",
})

What this package is, and is not

This is a deliberately small facade over a much larger engine. The implementation lives under internal/ and stays there: keeping it private is what lets the retrieval, budgeting and consolidation internals change without breaking anyone. What is exported here is the surface an agent actually needs, which is roughly the same surface the MCP server exposes — that server having been the forcing function for working out what an external consumer genuinely uses.

The domain types (Memory, Checkpoint, Note, Hit, Ruling, Context) are aliases for their internal definitions rather than copies. That makes them part of this package's contract: they are stable, and changing them is a breaking change. The alternative — parallel structs and a translation layer — buys freedom nobody asked for at the cost of conversions in every call.

Models

Open discovers a local model runtime (Ollama, LM Studio, Jan, Msty) and uses it for embeddings. If none is running, everything still works: retrieval falls back to lexical and graph traversal, which needs no model at all. Pass WithoutEmbedding to skip discovery entirely — useful in tests and CI. The exported surface is split across files by the question a caller is asking: context.go (what do I need to start), continuity.go (record where I stopped), deadend.go (has this been ruled out), memory.go (what's known about the user), vault.go (search the notes), serve.go (put a host in front of it). This file holds the package doc, the domain types, and opening and closing a vault.

Index

Constants

View Source
const (
	Preference = memory.Preference
	Person     = memory.Person
	Fact       = memory.Fact
	Standing   = memory.Context
	Procedure  = memory.Procedure
)

Memory kinds, re-exported so callers need not reach into internal packages.

Variables

This section is empty.

Functions

func Explain

func Explain(approach string, rulings []Ruling) string

Explain renders the result of Tried as prose to put in front of a model, taking the same approach string so the output can quote what was proposed. A recorded failure is evidence, not a veto, and the wording says so. An empty slice renders as an explicit "no record", which is worth showing: silence and approval are different answers.

Types

type Brain

type Brain struct {
	// contains filtered or unexported fields
}

Brain is an open vault. It is safe to keep for the life of a process and must be closed when done. Not safe for concurrent use across goroutines: the underlying SQLite handle is single-writer by design.

func Open

func Open(vaultPath string, opts ...Option) (*Brain, error)

Open loads the vault at path, creating its cache if absent.

The vault directory itself must exist; brain will not invent one, because pointing this at a typo and silently creating an empty knowledge base is a worse failure than an error.

func (*Brain) Ask

func (b *Brain) Ask(question string, k int) (string, []Hit, error)

Ask retrieves and then answers in prose, citing what it used. Requires a chat model; without one it returns an error rather than a guess.

func (*Brain) Checkpoint

func (b *Brain) Checkpoint(c Checkpoint) (string, error)

Checkpoint commits where you stopped to a markdown note in the vault and returns its slug.

Call it before finishing a session, not after. Anything omitted is lost, and the field that matters most is Failed: approaches that did not work are the expensive knowledge, and without them the next agent repeats them.

func (*Brain) Close

func (b *Brain) Close() error

Close releases the vault.

func (*Brain) Context

func (b *Brain) Context(req Request) (*Context, error)

Context assembles everything bearing on a task: where the last agent stopped, what it ruled out, uncommitted progress since, the project dossier, the prose of relevant notes, notes reached one hop through the user's own links, memories with their provenance, and open commitments — spent against a token budget and cited by source.

This is the call to make at the start of a task, in preference to Recall. Recall answers "what do you know about X"; this answers "give me what I need to do X", which is not a longer version of the same question.

func (*Brain) Embedded

func (b *Brain) Embedded() bool

Embedded reports whether a model runtime was found. When false, retrieval is lexical and graph-only — still useful, measurably weaker.

func (*Brain) Forget

func (b *Brain) Forget(id int64) error

Forget deletes a memory by id.

func (*Brain) History

func (b *Brain) History(project string, n int) ([]Checkpoint, error)

History returns a project's checkpoints, newest first.

func (*Brain) Index

func (b *Brain) Index() (SyncReport, error)

Index reconciles the vault into the cache: notes, embeddings and memories. Call it after writing files into the vault by other means, or on a watcher.

func (*Brain) Memories

func (b *Brain) Memories() ([]Memory, error)

Memories returns everything currently held.

func (*Brain) Note

func (b *Brain) Note(project, text string) error

Note records one line of progress. Cheap and meant to be called often — after a decision, a dead end, a surprising discovery. Notes stay uncommitted until Checkpoint folds them into a durable record, so use them freely rather than saving everything for the end.

func (*Brain) Notes

func (b *Brain) Notes(project string) ([]Note, error)

Notes returns a project's uncommitted progress — work that happened but was never written down properly, including anything left by an agent that died mid-task.

func (*Brain) Projects

func (b *Brain) Projects() ([]string, error)

Projects lists the projects that have at least one checkpoint.

func (*Brain) Recall

func (b *Brain) Recall(query string, k int) ([]Memory, error)

Recall retrieves what is known about the user relevant to a query.

func (*Brain) Remember

func (b *Brain) Remember(text string, kind Kind) (Receipt, error)

Remember stores something durable about the user and reports what happened: whether it created a fact or corroborated one already held. Near-identical statements reinforce rather than duplicate.

func (*Brain) Resume

func (b *Brain) Resume(project string) (*Context, error)

Resume picks up a project where the last agent left off. Equivalent to Context with a continuation task, and named separately because that is how people think about it.

func (*Brain) Search

func (b *Brain) Search(query string, k int) ([]Hit, error)

Search retrieves vault notes, fusing lexical and vector rankings.

func (*Brain) ServeMCP

func (b *Brain) ServeMCP(in io.Reader, out io.Writer) error

ServeMCP speaks the Model Context Protocol over the given streams, exposing this vault's tools to any MCP host. Use it to put your own product in front of brain's memory rather than reimplementing the tool surface.

A missing model runtime is not an error, matching Open: retrieval degrades to lexical and every continuity tool works untouched. Refusing to serve would have contradicted the rest of this API, which is built to keep working on a machine with no models on it.

It blocks until the input stream closes.

func (*Brain) Tried

func (b *Brain) Tried(approach, project string) ([]Ruling, error)

Tried reports whether an approach has already been ruled out, searching every dead end recorded across the whole vault — other projects included, and findings left in working notes by agents that no longer exist.

Call this before proposing a solution, especially when it seems obvious: obvious approaches are the ones already attempted. Pass the project being worked on so rulings from elsewhere can be flagged as possibly not transferring. An empty result means no record, which is not the same as approval.

func (*Brain) Vault

func (b *Brain) Vault() string

Vault is the path this Brain was opened on.

func (*Brain) Why

func (b *Brain) Why(file string, limit int) ([]Mention, error)

Why reports what was being decided when a file was worked on: the decisions taken and the approaches ruled out while it was being touched, newest first.

The complement to `git blame`, which answers who and when and cannot answer why. Matching on the path is deliberately loose — an agent records whatever path it had in hand and a caller asks with whatever they have — so a bare filename or a partial path both resolve.

It reads markdown from the vault, so it needs no model and no index. limit of 0 means every match.

type Checkpoint

type Checkpoint = session.Checkpoint

Checkpoint is where an agent stopped, written well enough that a different agent can start. Failed is the field that earns its keep.

type Context

type Context = contextpack.Pack

Context is everything bearing on a task, budgeted. Call Render for the markdown to put in a model's context window.

type Hit

type Hit = index.Hit

Hit is a retrieved vault note, with its provenance.

type Kind

type Kind = memory.Kind

Kind classifies a memory: Preference, Person, Fact or Context.

type Memory

type Memory = memory.Memory

Memory is one durable thing the store knows about the user.

type Mention

type Mention = session.Mention

Mention is a checkpoint that touched a file, and what was being worked out at the time. Returned by Why.

type Note

type Note = session.Note

Note is one line of uncommitted progress.

type Option

type Option func(*config)

An Option configures Open.

func WithAgent

func WithAgent(name string) Option

WithAgent sets the name recorded against notes and checkpoints — "claude", "cursor", your own product's name. A handoff is meaningless without knowing who is handing off, so this is worth setting.

func WithEmbeddingModel

func WithEmbeddingModel(name string) Option

WithEmbeddingModel names the embedding model instead of taking the detected default.

func WithoutEmbedding

func WithoutEmbedding() Option

WithoutEmbedding skips model discovery. Retrieval then uses lexical search and graph traversal only — no model process required, which is what you want in tests and CI.

type Receipt

type Receipt = memory.Receipt

Receipt reports what a write actually did — created a fact, or corroborated one already held.

type Request

type Request struct {
	// Task is what you are about to do, in a sentence. Required.
	Task string
	// Project narrows to one piece of work. Optional — when empty, the task
	// text is matched against known projects.
	Project string
	// Budget is the approximate token ceiling. Zero means 4000.
	Budget int
}

A Request describes what you are about to do. Task is the important field: "continue the MCP implementation" retrieves differently from a project name alone, because it says which corner of the project matters right now.

type Ruling

type Ruling = deadend.Ruling

Ruling is something already tried that did not work.

type SyncReport

type SyncReport = index.SyncReport

SyncReport counts what an Index call changed.

Directories

Path Synopsis
Package main is the Wails desktop app.
Package main is the Wails desktop app.
cmd
brain command
Command brain is the CLI front end.
Command brain is the CLI front end.
examples
handoff command
Command handoff is the smallest useful embedding of brain: two agents, one vault, no shared process.
Command handoff is the smallest useful embedding of brain: two agents, one vault, no shared process.
internal
activity
Package activity is the append-only record of what an agent actually did.
Package activity is the append-only record of what an agent actually did.
agent
Package agent is the conversational assistant.
Package agent is the conversational assistant.
agentprompt
Package agentprompt carries the instructions an agent should read before it uses Logos.
Package agentprompt carries the instructions an agent should read before it uses Logos.
announce
Package announce decides how loudly Logos says what it just did.
Package announce decides how loudly Logos says what it just did.
bootstrap
Package bootstrap seeds a cold vault from the git history already on disk.
Package bootstrap seeds a cold vault from the git history already on disk.
buildinfo
Package buildinfo holds the one version string this product reports.
Package buildinfo holds the one version string this product reports.
consent
Package consent tracks whether the app is allowed to call agent.Learn after a chat exchange without asking first.
Package consent tracks whether the app is allowed to call agent.Learn after a chat exchange without asking first.
contextpack
Package contextpack assembles everything needed to work on something into one bundle.
Package contextpack assembles everything needed to work on something into one bundle.
deadend
Package deadend answers one question: has this been tried before?
Package deadend answers one question: has this been tried before?
dream
Package dream is the nightly consolidation pass — brain sleeping on the day.
Package dream is the nightly consolidation pass — brain sleeping on the day.
eval
Package eval is a benchmark for agentic memory and handoff.
Package eval is a benchmark for agentic memory and handoff.
eval/adapters
Package adapters holds one implementation of eval.Adapter per memory system under test.
Package adapters holds one implementation of eval.Adapter per memory system under test.
flavor
Package flavor holds the assistant's identity and how present it makes itself.
Package flavor holds the assistant's identity and how present it makes itself.
gitstate
Package gitstate reads what the repository was, so a checkpoint does not have to rely on being told.
Package gitstate reads what the repository was, so a checkpoint does not have to rely on being told.
graph
Package graph builds the memory graph the widget renders.
Package graph builds the memory graph the widget renders.
health
Package health answers "is this actually working", and is careful about the difference between a thing that is fine and a thing nobody looked at.
Package health answers "is this actually working", and is careful about the difference between a thing that is fine and a thing nobody looked at.
index
Package index is the rebuildable cache.
Package index is the rebuildable cache.
mcpserver
Package mcpserver exposes brain's memory layer as an MCP server.
Package mcpserver exposes brain's memory layer as an MCP server.
memory
Package memory is the assistant's persistent memory.
Package memory is the assistant's persistent memory.
procedure
Package procedure answers the question before_you_try's dead-end half leaves unanswered: not just what was ruled out, but what is known to work, including the trap in doing it the obvious way.
Package procedure answers the question before_you_try's dead-end half leaves unanswered: not just what was ruled out, but what is known to work, including the trap in doing it the obvious way.
project
Package project auto-detects the pieces of work a life is organised around and assembles a dossier for each — its notes, the people involved, the files it touches, its goals, and recent progress — without the user filing anything.
Package project auto-detects the pieces of work a life is organised around and assembles a dossier for each — its notes, the people involved, the files it touches, its goals, and recent progress — without the user filing anything.
provider
Package provider is one client for every model runtime.
Package provider is one client for every model runtime.
reflection
Package reflection is descriptive statistics over long-term memory.
Package reflection is descriptive statistics over long-term memory.
rename
Package rename moves every trace of a project from one name to another, so that renaming a project is an ordinary edit rather than an event that costs you your history.
Package rename moves every trace of a project from one name to another, so that renaming a project is an ordinary edit rather than an event that costs you your history.
replay
Package replay is "catch me up since I've been away."
Package replay is "catch me up since I've been away."
router
Package router decides which model does which job.
Package router decides which model does which job.
scope
Package scope answers one question — what is the work in this directory called — the same way for every caller, so that a hook, the CLI and the MCP server cannot disagree about it.
Package scope answers one question — what is the work in this directory called — the same way for every caller, so that a hook, the CLI and the MCP server cannot disagree about it.
secretary
Package secretary tracks the open loops an agent or a person has left open — "I'll send the deck", "waiting on the vendor" — so they can be surfaced again without depending on anyone remembering to check.
Package secretary tracks the open loops an agent or a person has left open — "I'll send the deck", "waiting on the vendor" — so they can be surfaced again without depending on anyone remembering to check.
selfupdate
Package selfupdate implements `brain update`: check GitHub for a newer release, verify it actually runs on this machine, then replace the running binary.
Package selfupdate implements `brain update`: check GitHub for a newer release, verify it actually runs on this machine, then replace the running binary.
session
Package session records what an agent was doing, so a different agent can pick it up.
Package session records what an agent was doing, so a different agent can pick it up.
setup
Package setup connects brain to the agents that will use it.
Package setup connects brain to the agents that will use it.
textmatch
Package textmatch is the small lexical toolkit two subsystems needed at once.
Package textmatch is the small lexical toolkit two subsystems needed at once.
untrusted
Package untrusted renders vault content that was written by someone else's agent, not by brain itself.
Package untrusted renders vault content that was written by someone else's agent, not by brain itself.
vault
Package vault reads and writes notes in the Obsidian vault.
Package vault reads and writes notes in the Obsidian vault.
when
Package when resolves the time expressions people put in questions.
Package when resolves the time expressions people put in questions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL