Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
},
"metadata": {
"description": "PlugBrain — local project and code memory for AI agents",
"version": "0.3.0"
"version": "0.3.1"
},
"plugins": [
{
"name": "plugbrain",
"source": "./",
"description": "Ask the brain first: AST code intelligence, Obsidian-style notes and agent coordination for this repository, served locally over MCP.",
"version": "0.3.0",
"version": "0.3.1",
"license": "MIT",
"category": "productivity",
"keywords": [
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "plugbrain",
"version": "0.3.0",
"version": "0.3.1",
"description": "Local project and code memory for AI agents: AST code intelligence, Obsidian-style notes and multi-agent coordination, asked through MCP.",
"author": {
"name": "litbitrim"
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ jobs:
- name: Install UI dependencies
run: npm ci --prefix ui

# GP-2 drives the real UI in Chromium. CI is the one place where the
# browser is downloaded (release.yml does the same). Without it GP-2 fails,
# and before v0.3.1 that failure also left the whole test run hanging.
- name: Install Chromium for the UI end-to-end test
run: node node_modules/playwright-core/cli.js install chromium

# Advisory, not blocking: the core runs on --experimental-strip-types
# and carries pre-existing strict-tsc findings in src/ that REL-01 is
# not allowed to touch. The gate makes the debt visible; the load-check
Expand All @@ -47,5 +53,11 @@ jobs:
- name: Run tests
run: npm test

# Timing budgets need the machine to themselves: measured beside other
# test files they measure contention, not the product. `npm test` reports
# them as skipped; this serial step is the only place they run, on every OS.
- name: Run budget tests
run: npm run test:budget

- name: Secret scan
run: npm run secret:scan
59 changes: 58 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,64 @@ All notable changes to PlugBrain are documented here.
The format follows [Keep a Changelog](https://keepachangelog.com/) and the
project adheres to [Semantic Versioning](https://semver.org/).

## [0.3.0] — 2026-09-26
## [0.3.1] — 2026-09-26

The `v0.3.0` tag exists, but no 0.3.0 release was published: its cross-platform
verification failed on macOS and Windows. 0.3.1 is the first published build.

### Fixed

- **Awareness claims reused under load.** An awareness response now reads the live-claim snapshot once and reuses it for conflict evaluation and related-task projection, removing repeated scans without changing claim decisions.
- **Timing budgets measured in isolation.** CI runs the awareness, Board-read and no-hang timing tests in a separate serial `test:budget` step on every matrix OS; the parallel suite reports those tests as skipped with a reason.
- **A vault opened through a linked path could not read its own notes.** When
the vault root was reached through a junction, a symlink or the macOS
`/var` → `/private/var` link, path containment compared each file's real path
with the unresolved root and refused the vault's own files. The root is now
resolved once. Traversal and links that point outside the vault are still
refused.
- **Opening a note during an index run failed silently in the web UI.** While an
index run holds the store's writer lock, the daemon answers store-writing
requests with `503` and `retryAfterMs`. The page gave up on the first `503`
when it attached its agent, so the following read went out without a
registered agent and the note stayed closed. The attach now waits and asks
again for up to 60 seconds.
- **The test suite could hang on a machine without Chromium.** The UI end-to-end
test launched the browser before its cleanup guard. A missing browser left the
test server and the store open, and the run never ended. The test now always
closes what it opened, and CI installs Chromium for it.
- **One folder, one spelling.** Hygiene, the checkout census, workspace
recognition and the daemon compared paths as text. On Windows a folder can
arrive as an 8.3 short name (`C:\Users\RUNNER~1\...`), on macOS as
`/var/...` or `/private/var/...`. Hygiene then missed checkouts and a
registered workspace was not recognised on the next run. Paths are now made
canonical before they are compared; what you typed is still what is shown.
- Two tests only passed in the author's checkout: one read a schema from
private git history, two probes needed PowerShell on Linux. Both are
portable now.

### Changed

- The release workflow can be dry-run on any branch (`workflow_dispatch`).
Publishing still happens only for `v*` tags. When the first UI check of
`verify:standalone` times out, it prints what the daemon and the page saw.
- The README now describes what PlugBrain is for: coordinating many agents on
one project, on top of a shared code and notes index. The screenshots are gone
from it, and it states what is not there yet.
- `docs/cli.md` documents every `swarm` subcommand with its real arguments. The
previous section had wrong signatures (for example `send`, `register`,
`release`) and left out `enqueue`, `ack`, `approve`, `deliver` and `quota`.
- New `docs/agent-protocol.md`: the per-turn rules as a block to paste into a
project's `AGENTS.md` or `CLAUDE.md`.

### Known issues

- **macOS:** when the brain store (`PLUGBRAIN_HOME`) lives inside a watched
vault, the file watcher reports a write to the store as a change of the vault
folder and the daemon starts a re-index that finds nothing to change. The
default store location, `~/.plugbrain`, is outside any vault and is not
affected. The test for this case is skipped on macOS until it is fixed.

## [0.3.0] — 2026-09-26 (tagged, not released)

First public release (MIT), first release prepared for Windows, macOS and
Linux.
Expand Down
177 changes: 108 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,122 +2,161 @@

[![CI](https://github.com/litbitrim/plugbrain/actions/workflows/ci.yml/badge.svg)](https://github.com/litbitrim/plugbrain/actions/workflows/ci.yml)

**PlugBrain is a local project and code memory for AI agents** — real AST-based
code intelligence over your repositories plus an Obsidian-style note vault,
exposed to Claude Code (and any MCP client) as one set of tools. Everything
runs on your machine. No cloud, no telemetry.
**One local brain for all the coding agents working on your project.**

> The web interface is currently in German. An English interface is planned.
> The CLI, the MCP tools, their answers and all documentation are in English.
Claude Code, Codex, Gemini, GLM, a local model, several of each: any agent that
can run a shell command can join the same PlugBrain. Agents take tasks from a
shared queue, claim the files they are about to change, check in at the start
and end of every turn, message each other and wait for a commit approval.
Underneath sits one index of the project's code and notes, so every agent starts
from the same knowledge instead of re-reading the repository.

![Briefing — project summary, entry points and hotspots](docs/images/briefing.png)
![Ask — query the knowledge graph and code symbols](docs/images/ask.png)
![Graph — interactive knowledge graph and dependencies](docs/images/graph.png)
![Notes — Obsidian-style markdown vault with backlinks](docs/images/notes.png)
![Cleanup — git hygiene and uncommitted work protection](docs/images/cleanup.png)
The aim is simple: more agents should mean more work done, not overwritten
files, duplicated tasks or an agent silently stuck for an hour.

## Why PlugBrain?
Everything runs on your machine: one SQLite file, a daemon on `127.0.0.1`, no
cloud, no telemetry. MIT licensed.

Code assistants forget. Every session starts from zero: the agent re-reads
files it has already read, misses the note where you wrote down *why* a
decision was made, and steps on other agents editing the same files.
Existing code-graph tools help with the code half of that problem:
## Status

- **GitNexus** and **CodeGraph** are good local code-graph tools. Both index
a codebase and answer symbol, caller and impact questions, both run as a
CLI and both can serve those answers to an agent over MCP.
- 0.3.1 is the first published release. It is developed on Windows; macOS and
Linux run the same tests and packaging checks in CI.
- PlugBrain's own development runs on it. On 26 September 2026 one board
coordinated Claude Code, three Codex CLI workers and four Freebuff workers on
this repository.
- The web UI and the output of `plugbrain swarm` are in German for now. The
other commands, the MCP tools and all documentation are in English.
- Not there yet: the store keeps only each agent's latest turn, so there is no
turn history to replay, and worktrees of merged branches are not removed
automatically. Both are being built.

What PlugBrain adds is the other half: the project's written knowledge and
the agents working on it, in the same local brain as the code.
## How agents work together

| | GitNexus | CodeGraph | PlugBrain |
| --- | --- | --- | --- |
| Code intelligence (symbols, callers, impact) | ✓ | ✓ | ✓ |
| Local CLI and MCP server | ✓ | ✓ | ✓ |
| Obsidian-style notes vault with code bindings | – | – | ✓ |
| Multi-agent claims, fencing and awareness | – | – | ✓ |
| Plain-language `ask` with cited sources | – | – | ✓ |
| Git hygiene: unsaved work across all checkouts | – | – | ✓ |
```bash
# Once per agent: who it is and which account it spends
plugbrain swarm register codex-1 --surface other --account openai --model gpt-6-luna
plugbrain swarm register claude-1 --surface claude-code --account anthropic

# Whoever plans, a person or an agent, queues work, optionally for one agent
plugbrain swarm enqueue "Fix the flaky login test" --body "Repro in issue #12" --to codex-1

# Every agent, at the start of every turn: read messages, take the offered task
plugbrain swarm turn codex-1 start --claim

# Before writing: claim the paths. A path another agent holds is refused.
plugbrain swarm claim codex-1 src/auth/login.ts --task <task-id>

# Before tests, builds or new worktrees: is there room? Exit 5 means no.
plugbrain swarm admit test

# At the end of every turn: exactly one state and a short summary
plugbrain swarm turn codex-1 end --state awaiting-commit --summary "Fixed the race, login tests pass"
plugbrain swarm release codex-1 --task <task-id>

# The integrator looks, approves, and sends the next hint
plugbrain swarm board --git
plugbrain swarm approve codex-1 --note "Reviewed. Commit it."
plugbrain swarm send codex-1 --subject "Next" --body "Rebase on main after your commit"
```

A turn ends in one of four states: `needs-task` (done, give me work),
`awaiting-commit` (a tested change is ready), `blocked` (a real blocker, named in
the summary) or `paused`. `plugbrain swarm board` lists every agent once with its
account, turn state, unread messages, task, claims and worktree; with `--git` it
adds branch, head and uncommitted files, and it flags two agents writing in the
same worktree.

Agents that speak MCP find the board, turns, claims and messages as tools
(`swarm_board`, `swarm_turn`, `claim`, `release`, `message_send`, `inbox_read`,
`heartbeat`, `awareness`). Queueing, approving and admission are CLI-only today.

The "–" marks reflect the tools' documented commands as of September 2026.
If one of them has since gained a feature, please open an issue and we will
correct the table.
The per-turn rules for agents are written down so you can paste them into your
project's `AGENTS.md` or `CLAUDE.md`: [docs/agent-protocol.md](docs/agent-protocol.md).
All `swarm` commands: [docs/cli.md](docs/cli.md#swarm).

### How it measures up
## The index underneath

We compared PlugBrain with CodeGraph and GitNexus on 120 questions (definitions, callers, impact, config keys, docs) across four of the author's own projects. PlugBrain itself is not one of them. We wrote the questions ourselves. 40 of them were frozen before any tuning and serve as the honest holdout. Every tool was driven through its documented command-line interface, and every raw answer is stored next to the results.
The index answers the questions agents ask all day: where is this defined, who
calls it, what breaks if I change it, and what did we decide about it. The goal
is to match or beat GitNexus and CodeGraph on code questions and Obsidian on
project notes, in one index every agent shares.

**Code.** Symbols, callers and callees, impact of a change, changed files since a
revision, graph queries in Cypher, and `ask` for plain-language questions with
cited sources.

We compared PlugBrain with CodeGraph and GitNexus on 120 questions (definitions,
callers, impact, config keys, docs) across four of the author's own projects;
PlugBrain itself is not one of them. We wrote the questions ourselves. 40 were
frozen before any tuning and serve as the holdout. Every tool was driven through
its documented command-line interface, and every raw answer is stored with the
results.

| Tool | Holdout (40) | All questions (120) | Latency p50 | Latency p95 |
| :--- | :---: | :---: | :---: | :---: |
| PlugBrain | 38 / 40 | 106 / 120 | 265 ms (33 ms with the daemon running) | 478 ms |
| CodeGraph | 38 / 40 | 103 / 120 | 280 ms | 311 ms |
| GitNexus | 36 / 40 | 90 / 120 | 1,134 ms | 3,465 ms |

In short, PlugBrain answers three more of the 120 questions than CodeGraph and ties it on the holdout. Its real edge is speed once the daemon is warm, and that it also searches your notes. CodeGraph's call edges are still more complete on deeply polymorphic class hierarchies. Full method, raw answers, hand-checked misses and how to reproduce the run: [bench/v2/RESULTS.md](bench/v2/RESULTS.md).
PlugBrain ties CodeGraph on the holdout and answers three more of all 120
questions. CodeGraph's call edges are still more complete on deeply polymorphic
class hierarchies. Method, raw answers, hand-checked misses and how to rerun it:
[bench/v2/RESULTS.md](bench/v2/RESULTS.md).

**Notes.** A Markdown vault with wiki-links, backlinks, tags, properties and
full-text search, in the same index as the code. A note can point at a file
(`code:`), a revision (`revision:`) and an agent run (`agentenlauf:`). Compared
with Obsidian there is no canvas, no mobile app and no plugin ecosystem.

## Quickstart

**Windows:** download `PlugBrain-<version>-win-x64.exe` from
[Releases](https://github.com/litbitrim/plugbrain/releases) and run it. The
installer bundles a portable Node.js runtime — nothing else to install.
installer brings its own Node.js runtime.

**macOS / Linux:** grab `plugbrain-<version>-<os>-<arch>.tar.gz` from the same
releases page, unpack it and put `bin/plugbrain` on your `PATH`.
**macOS / Linux:** download `plugbrain-<version>-<os>-<arch>.tar.gz` from the same
page, unpack it and put `bin/plugbrain` on your `PATH`.

Then, inside your project folder:

```bash
# One-time: create the brain store and register this folder as a workspace
plugbrain init

# Start the local brain (UI + API + MCP transport)
plugbrain serve
plugbrain init # register this folder, index it, add PlugBrain to your MCP clients
plugbrain serve # the local daemon: web UI and API on http://127.0.0.1:4310
```

Open `http://localhost:4310` for the cockpit. The data directory defaults to
`~/.plugbrain`; set `PLUGBRAIN_HOME` to choose another location.

### Use it from Claude Code
`plugbrain setup --all` (or `claude`, `codex`, `cursor`, `windsurf`, `hermes`,
`agy`, `opencode`) adds PlugBrain to an MCP client later. It backs up the
client's config first; `--undo` restores it. The data directory defaults to
`~/.plugbrain`; set `PLUGBRAIN_HOME` to choose another one.

PlugBrain ships as a Claude Code plugin with its own marketplace entry:
### Claude Code plugin

```
/plugin marketplace add litbitrim/plugbrain
/plugin install plugbrain@plugbrain
```

The plugin starts the brain when needed (session hook), and gives Claude the
`skills/brain` skill: *ask the brain first* — context packs before edits,
impact analysis before renames, notes before re-deriving decisions.

## MCP tools

`plugbrain mcp` speaks the Model Context Protocol over stdio, giving agents instant access to code intelligence and knowledge:

- `ask` — Ask in plain language; routes to the right tool and returns one clear sentence with source citations.
- `context_pack` — Build goal-oriented context packs with relevant files, symbols, and dependencies.
- `query` — Concept search across indexed AST symbols, file paths, and notes.
- `context` — 360-degree symbol context: callers, callees, and execution flow memberships.
- `impact` — Blast-radius analysis showing upstream and downstream dependency changes before editing.

For the full reference of all tools (including search, notes, git hygiene, and multi-agent coordination), see [MCP Tools Reference](docs/mcp-tools.md).
The plugin starts the brain when a session needs it and gives Claude a skill that
asks the brain first: context before edits, impact before renames, notes before
re-deriving a decision.

## Privacy

- Everything stays on your machine: the store is a single SQLite database
under `PLUGBRAIN_HOME`, indexing runs locally, the UI is served locally.
- No telemetry, no analytics, no phone-home. The only network traffic is the
- The store is one SQLite database under `PLUGBRAIN_HOME`. Indexing runs locally
and the UI is served locally.
- No telemetry, no analytics, no phone-home. The only network listener is the
local HTTP server on `127.0.0.1`.
- The HTTP API requires a bearer token that is generated on first start and
kept in `<PLUGBRAIN_HOME>/auth.token`.
- The HTTP API requires a bearer token that is generated on first start and kept
in `<PLUGBRAIN_HOME>/auth.token`. The `swarm` commands work on the local store
directly and need no token.

## Development

```bash
git clone https://github.com/litbitrim/plugbrain
cd plugbrain
npm install
npm test # unit + integration tests (node:test)
npm test # unit and integration tests (node:test)
npm run serve # start the brain against the current folder
```

Expand Down
2 changes: 1 addition & 1 deletion desktop/PlugBrain.nsi
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Unicode true

!define PRODUCT_NAME "PlugBrain"
!define PRODUCT_VERSION "0.3.0"
!define PRODUCT_VERSION "0.3.1"
!define PRODUCT_PUBLISHER "PLUG"

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
Expand Down
9 changes: 7 additions & 2 deletions desktop/brain-url.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ test('desktop launcher fails closed rather than adopting an unrelated Core', ()
assert.doesNotMatch(launcher, /PlugPT-Shell|electron\\dist/i);
});

test('the launcher quoting form keeps a spaced Core bundle as one Node argument', () => {
// The desktop launcher is a Windows PowerShell script; these two probes run
// that PowerShell. Linux runners have no `powershell`, so they only mean
// something on Windows.
const WINDOWS_LAUNCHER_ONLY = process.platform === 'win32' ? false : 'the PowerShell launcher only runs on Windows';

test('the launcher quoting form keeps a spaced Core bundle as one Node argument', { skip: WINDOWS_LAUNCHER_ONLY }, () => {
const expression = [
"$bundle = 'C:\\Program Files\\PlugBrain\\dist\\plugbrain.mjs'",
"$bundleArgument = [string][char]34 + $bundle + [char]34",
Expand All @@ -72,7 +77,7 @@ test('the launcher quoting form keeps a spaced Core bundle as one Node argument'
assert.equal(probe.stdout.trim(), '"C:\\Program Files\\PlugBrain\\dist\\plugbrain.mjs"');
});

test('PowerShell Start-Process delivers the quoted spaced bundle as one actual Node argv entry', () => {
test('PowerShell Start-Process delivers the quoted spaced bundle as one actual Node argv entry', { skip: WINDOWS_LAUNCHER_ONLY }, () => {
const dir = mkdtempSync(join(tmpdir(), 'plugbrain-launcher-'));
const probeScript = join(dir, 'argv-probe.cjs');
const probeOutput = join(dir, 'argv.json');
Expand Down
Loading
Loading