A shared notebook for your agents.

JBrain keeps what your agents learn as plain Markdown in a Git repo, and lets every agent read and write it over MCP, HTTP or the CLI. No embeddings. No model server. No API key.

./setup.sh

Detects Docker, falls back to a native build, writes your .env and prints the line that connects Claude Code.

What it does for your agents.

p. 002

One service holds the knowledge. Agents read and write it; you can read, diff and take it with you, because it is just files in Git.

Plain files
Each note is a Markdown file with YAML frontmatter in the Open Knowledge Format. IDs are paths like projects/jbrain. Unknown frontmatter is preserved.
Many agents, no collisions
Writes carry the revision the agent read. A stale write is refused with a clear conflict, never silently merged. Retrying with the same request ID is safe.
Search
BM25 over title, description, tags, aliases and body, with question filler ignored. No embeddings and no API key.
Links
Markdown links between notes become a graph: outgoing links, backlinks and bounded neighbours.
History in Git
Every write is a commit carrying the request ID and the actor. On by default, with a durable write journal behind it.
GitHub sync
Optionally push every commit to your own repo in the background. A failed push never blocks a write; it retries and reports in /health.
Any client
MCP over HTTP (12 tools), a plain HTTP API and a CLI. A stdio proxy covers clients that need it.
Crash safe
Atomic file writes, a journal replayed at startup, and tests that kill the process at each step.
Optional answers
brain_ask plans, reads and verifies an answer with a remote model. Everything else works without one.
Easy to run
One installer, a non-root Docker image with a health check, and about 20 MiB of memory.

Not here yet

  • Per-agent permissions: one shared token today (#1).
  • Pulling changes back from GitHub: sync is push-only (#7).
  • Paraphrase search: no embeddings, so questions that share no words with a note can miss (#3).
  • A web UI, prebuilt binaries and a published Docker image (#17, #10).

Set it up in four steps.

p. 003

You need git and either Docker or Rust 1.89+. The installer checks both and chooses for you.

  1. Get the code

    git clone https://github.com/Jayesh1512/jbrain
    cd jbrain
  2. Run the installer

    ./setup.sh

    It uses Docker when a daemon and docker compose are available, and a native build otherwise. It asks for:

    • a port (default 7331);
    • optionally, a GitHub repo to sync to (see below);

    Then it generates an access token into a private .env, builds, starts, waits until the service is healthy, and prints your connect command. Run it again any time: it offers to keep your .env and to change the sync settings.

  3. Connect an agent

    claude mcp add --transport http jbrain \
      http://127.0.0.1:7331/mcp \
      --header "Authorization: Bearer <JBRAIN_TOKEN>"

    The installer prints this with your token filled in. Any client that speaks Streamable HTTP MCP uses the same URL and header.

  4. Check it works

    curl -H "Authorization: Bearer $JBRAIN_TOKEN" http://127.0.0.1:7331/health
    # {"history":"git","status":"ready", ...}

    Then ask your agent to search or write a note. The first write creates the knowledge repo and its first commit.

Sync every update to GitHub (optional)

  1. Make a repo

    Create an empty GitHub repository, private if the notes are not public.

    A repo whose main already has other history rejects the push; JBrain never force-pushes.

  2. Make a token

    A fine-grained token limited to that repo, with Contents set to read and write.

    Docker cannot see the credentials saved on your machine, so it needs this.

  3. Tell setup

    Run ./setup.sh and paste owner/repo at the sync prompt, then the token (hidden).

    It checks it can reach the repo and offers to create it with gh.

  4. Confirm

    Say yes to the welcome note. The installer writes it and waits until it appears on GitHub.

    Afterwards /health shows sync.pushedCommit and any error.

Only the Markdown knowledge is pushed, not the search index or the journal. Pushes are one way: GitHub edits do not come back yet.

Without the installer

# Docker
cp .env.example .env          # set JBRAIN_TOKEN to a long random string
docker compose up -d --build

# Native (Rust 1.89+)
cargo build --release --locked
JBRAIN_TOKEN=change-me ./target/release/jbrain serve

Settings

VariableDefaultWhat it does
JBRAIN_TOKENunsetBearer token for HTTP and MCP. Required whenever the service listens beyond localhost, which Docker always does.
JBRAIN_PORT7331HTTP port.
JBRAIN_DATA_DIR.jbrainWhere the notes, search index and journal live (/data in Docker).
JBRAIN_HISTORYgitSet off to skip the Git history.
JBRAIN_GIT_REMOTEunsetPush every commit to this repo.
JBRAIN_GIT_TOKENunsetToken for an https remote. Sent only as a header when pushing; never written into the Git repo or logs.
JBRAIN_MODEL
OPENAI_API_KEY
unsetOnly for the optional brain_ask.

Every write is checked, filed and witnessed.

p. 004

Agents never open the database or touch the files. They ask one service, and every write takes the same six steps.

  1. Agent sends the write

    brain_write with actor, request ID, action, concept ID, expected revision and the full Markdown.

    Retrying with the same ID and payload is safe and returns the original result.

  2. Revision check

    The service compares the revision you read with the file on disk.

    A stale writer gets 409 REVISION_CONFLICT, then reads, merges and retries with a new ID.

  3. File replaced

    The concept file is written atomically and synced to disk.

    Readers see the old version or the new one, never half of each.

  4. Git commit

    One commit per write in knowledge/.git, carrying the request ID and actor.

    History, diffs and restore for every note. On by default.

  5. Index published

    Search rows, links and metadata update in one SQLite transaction.

    A successful write is searchable immediately.

  6. Optional push

    A background thread pushes main to a GitHub repo you choose.

    Never blocks a write. Retries with backoff, status in /health.

A crash between any two steps is repaired at startup from the journal. The test suite kills the process at each boundary and checks that nothing is lost.

Then every agent works the same way.

p. 005

Agents talk to the service; they never touch the files. Tell them to send two to five distinctive keywords, search once per fact, and read a note before updating it.

Clients that only speak stdio can run jbrain mcp as a proxy.

Real output from a test brain holding six sample notes, searching with a plain question:

brain_search "How does GitHub sync work?"
1  runbooks/github-sync    Runbook: GitHub sync
2  projects/jbrain         JBrain
Tools
ToolUse
brain_searchBM25 search. Send 2 to 5 distinctive keywords, one fact per search.
brain_readOne concept and its revision. Read before you update.
brain_writeCreate, update or delete, with a revision precondition.
brain_linksOutgoing links and backlinks.
brain_list
brain_browse
Browse metadata by prefix, type or period.
brain_operationLook up a write after a dropped connection.
brain_query
brain_evidence
Model-free evidence with revisions and quotes.
brain_askOptional. Plans, reads and verifies an answer with a remote model. The only tool that needs an API key.

What search gets right, and what it does not.

p. 006

Search is lexical BM25 with no embeddings. The numbers below are measured, and so are the ones that do not flatter it.

Search before and after dropping question filler and falling back to any-word matches
TestBeforeAfterConditions
All answerable queries43.5%86.1%Recall@5, 54 queries, 226 notes
Full-sentence questions0%100%12 queries
Paraphrases10%70%10 queries, no shared words in some
Typos0%83%6 queries
Premier League corpus, raw questions21.2%75.8%Complete evidence in top 5, 13,989 notes, 66 questions
Median latency, same corpus1.8 ms15.3 msThe price of the fallback. Tracked as an open issue.

Not proven

  • The automatic query endpoint returned every requested fact for 9 of 36 harder Premier League questions. Qualifiers such as home versus away get lost.
  • The optional ask workflow with a real model answered 11 of 16 answerable questions (68.75%) at about $0.28 each. The 97% target is not met.
  • Every question set was written by the authors, who knew the system. None is a blind holdout.

Method and raw results: retrieval evaluation, hard questions, real-model baseline.

Small enough to leave running.

p. 007
Process
One native Rust service per brain. Agents connect over HTTP, MCP or the CLI and never open the files themselves.
Memory
About 20 MiB resident while serving a 14,000-note brain.
Storage
Markdown files in a Git repo, a rebuildable SQLite search index, and a write journal. Back up by copying the data directory.
Docker
Non-root image with a health check and a named volume. About 284 MB. Built locally, no registry image yet.
Runtime needs
Nothing besides the binary and git. No Python, Node or database server. Rust 1.89+ only for a native build.
Platforms
macOS and Linux.
Access
Bearer token over HTTP. One shared token today; per-agent roles are an open issue.

Open entries.

p. 008

The work still to do, filed as GitHub issues. Pick one.

All 17 issues on GitHub

Signed.

p. 009

JBrain is built by Jayesh Shete. Issues, ideas and pull requests are welcome.

Project repo
github.com/Jayesh1512/jbrain
GitHub
github.com/Jayesh1512
LinkedIn
linkedin.com/in/jayeshnshete15
X
x.com/noob_jys