Docs · install

The binary, the brain
and the hour after.

Four steps. Everybody skips one of them: checking the hooks really work. If the brain depends on the agent remembering to read it, one day it won't. The hook is what makes sure it does.

1 · Get the binary #

$ curl -fsSL https://brain.fightclub.pro/install.sh | sh
$ ns-brain --version

The installer reads latest-version.txt, works out your OS and chip, downloads the right binary, fetches SHA256SUMS and checks the binary against it. Only then does it move it to /usr/local/bin/ns-brain. If it can't write there it asks for sudo.

Two options change where it goes:

$ curl -fsSL https://brain.fightclub.pro/install.sh | sh -s -- --user         # ~/.local/bin, no sudo
$ curl -fsSL https://brain.fightclub.pro/install.sh | sh -s -- --dir ~/tools/bin  # anywhere you name

An agent doing the install should use --user. An agent can't answer a sudo prompt. With no terminal to ask on, the installer stops and tells it to use --user instead of hanging. Make sure ~/.local/bin is on the PATH your agent's hooks run with.

If the check can't be done, the install stops. SHA256SUMS has to be signed by our release key, which the installer has built in. The signature includes the version number, so nobody can pass off an old release as a new one. Something other than the new binary checks the signature: OpenSSL 3, or Python's cryptography package if OpenSSL 3 is missing. If you have neither (stock macOS ships LibreSSL), the only thing left to check it is the downloaded binary itself. A tampered binary would just say yes, so the installer refuses unless you set INSTALL_ALLOW_SELF_VERIFY=1. Better to install OpenSSL 3 (brew install openssl@3). If you do set it, compare the fingerprint it prints with the one in the repository.

The installer won't replace a newer ns-brain with an older one. To go back on purpose, name the version: curl -fsSL https://brain.fightclub.pro/install.sh | sh -s -- --to <version> --allow-downgrade. --allow-downgrade is refused without --to.

Rather not pipe a URL into a shell? Read install.sh first, or download the build for your machine and chmod +x it: linux amd64, linux arm64, macOS arm64, macOS amd64, Windows amd64, with SHA256SUMS to check it against. It is one self-contained file: no runtime to install, no cgo. Windows has one gap.

2 · Create the brain #

$ cd ~/projects/yours
$ ns-brain init
To autowire your agent you need to tell us what agent you want to use:
   1) Claude Code  (found on this machine)
   2) Codex CLI
   ...
  12) I will do it myself
Choose 1-12:

At a terminal, init asks which agent to connect. The list shows every agent it can set up and marks the ones it found on this machine. I will do it myself sets up nothing and prints each agent's config for you to add by hand. Pass --agent claude (or codex, cursor and so on) to skip the question. With no terminal, as when an agent runs it, init doesn't ask: it sets up the agent you named, or the ones it finds.

It tells you everything it creates:

WhatWhy it is there
brain/brain.jsonThe project's name, its scopes and the project notes added to every brief.
brain/brain.dbThe memories themselves. A versioned SQLite database in WAL mode, readable only by you (mode 600).
.gitignoreLines for the database, its dumps and snapshots. Memories don't belong in the repository.
brain/HOWTO.md
brain/BEST-PRACTICES.md
Copied out of the binary, so your agent already knows how to use the brain and what is worth saving. They go in brain/, not the repository root.
brain/autoexec.shA small script that finds this brain from where the script itself lives, so a hook works whatever directory the agent runs it from. It is for agents that don't tell their hooks which project they are in.
agent hooksIn the config of the agent you picked or it found. The table below lists them.
.claude/commands/Claude Code only: seven slash commands for messaging other sessions (/who, /msg, /inbox and the rest).

init does not edit CLAUDE.md or any other instructions file. It gitignores the database and every copy of it. brain.json, the two docs and autoexec.sh hold no memories, so they are safe to commit. Commit them and everyone on the project gets the same scopes and docs. Leave them out if not everyone uses ns-brain. init rewrites the two docs every time it runs, so don't edit them.

Useful flags: --dir marketing/brain puts the brain somewhere other than brain/. --project "Acme Sales" names it when the folder name is wrong. --agent claude,codex sets up those agents instead of looking for them. --no-hook, --no-auto-recall and --no-gitignore each skip one piece.

You can run init again at any time. On an older install it upgrades the database in place and replaces the hooks instead of adding new ones next to them, so you end up with exactly one per event. It never overwrites brain.db, which is the only copy of that project's memory.

3 · Check the hooks really work #

This is the step people skip. It is also the one that decides whether any of this works.

$ ns-brain wakeup

That prints exactly what a session gets when it opens. If you see the brief, the current git state and this project's own checks, the brain works. Then open a new session and look for the brief before you type anything. wakeup shows the command works. A new session shows the hooks do.

If init could not set up any hook, it says so. It prints the exact file and the exact JSON to add, installs the brain anyway and exits with an error. It does not fall back to writing instructions into some file instead, because that would look like it worked when it didn't.

If init reports another memory store

You will see ANOTHER MEMORY STORE IS ALREADY LOADED FOR THIS PROJECT, naming a MEMORY.md, a memory/ directory or Claude Code's own auto-memory for this project.

Two memory stores that both load on their own will contradict each other without telling you. Every session reads both. Nothing says which is newer, so the session believes whichever it read, even a fact the other one corrected months ago. Nothing warns you. You find out from a wrong answer on some ordinary day and nobody traces it back to this.

Do not delete the old store. Copy what is still true into the brain with ns-brain remember, then let the user delete it. It is theirs and only they know which parts are still true.

4 · Fill it, if the project has history #

Install a brain into a six-month-old project and it starts empty, while the history sits on disk as session transcripts.

$ ns-brain bootstrap

This writes nothing to the brain. It finds this project's Claude Code session transcripts, lists them oldest first and prints the rules for pulling facts out of them. Your agent does the reading and decides what to keep.

There is no automatic extractor and there won't be. Pattern-matching over transcripts fills a new brain with confident noise, which is worse than an empty one. We saw a competitor's auto-learner do exactly that: two thirds of what it saved was function renames and generic advice, all filed project-wide.

Finish with ns-brain bootstrap --done. It records that the job is finished so no later session does it again.

Your first memories #

$ ns-brain remember --type infra \
    --title "TLS terminates at nginx on 8443, not at the app" \
    --body "the app listens on 127.0.0.1:8080 and never sees a cert" \
    --source "nginx/sites-enabled/app.conf"
remembered #1 [global/infra] TLS terminates at nginx on 8443, not at the app
  review on <30 days from today> (default for infra, 30d — --review <date> to move it, --no-review if it is permanent)

$ ns-brain prefer "commit messages stay lowercase" --why "corrected me twice"
$ ns-brain log "deployed v2.3.1 to staging"
$ ns-brain recall "TLS nginx"

Your next session opens knowing that, plus the time of day, the branch, how many commits you are behind and any rule you have saved. Read the memory model before you save much: the type you pick when you save matters more than anything else you choose.

Which agents get set up #

When it doesn't ask, init looks for .claude/, .codex/, .cursor/, .gemini/, .opencode/, .kilo/, .copilot/, .qwen/, .hermes/, .continue/ and .devin/ in the project and under $HOME (OpenCode, Kilo and Devin CLI also under ~/.config/). Each agent keeps its config in its own file and handles hook output its own way, so init has to find each one rather than write one shared config. For Claude Code it writes these into .claude/settings.json. Other agents get whichever of these their hooks support, listed on the Agents page.

EventCommandWhat it does
SessionStartns-brain wakeupThe brief, the current git state and this project's checks, before you type.
UserPromptSubmitns-brain hook-recallSaves what you typed, then searches the brain for it and adds what it finds. What it stores.
PostToolUsens-brain hook-toolDelivers a message sent to this session on its next tool call.
Stopns-brain hook-stopWhat this session did and whether it stored any of it.
SessionEndns-brain hook-endMarks the session gone, so nobody sends it a message.

What the prompt hook stores

The hook that runs on every message keeps a word-for-word copy of each prompt you type, before your agent answers it. That way a memory can later point back at the message it came from.

init tells you this in one line when it sets up the hook.

Your coding agent has the files for each agent and what each one can't do. An agent that can't run shell commands has no hooks. That is what MCP over stdio is for. That page explains how it differs.

Windows

The Windows build runs every command, MCP over stdio included. Setting up hooks on Windows is not covered yet. The hooks init writes expect a Unix shell: Claude Code's set BRAIN_HOME in shell syntax and the other agents' call brain/autoexec.sh, a shell script. We haven't tested either on Windows, so expect to set them up by hand.

Upgrading #

$ ns-brain upgrade --check    # just compare versions
$ ns-brain upgrade            # the plan, written out, nothing done
$ ns-brain upgrade --apply    # backs up first

Every project's brief checks its version against the latest one and tells you when it is behind. Nothing upgrades itself. Back up first. Afterwards, check on the project's own data: doctor finds nothing, the counts haven't changed and a recall whose answer you already know still gives it. An upgrade that says it worked may not have.

Database upgrades only add, never remove. Each one runs as a single step and is undone completely on any error, because a half-finished upgrade would fail on every later command and lock you out.

Uninstalling #

$ ns-brain uninstall                  # dry run: every file and line it would touch
$ ns-brain uninstall --apply          # hooks and files go, brain.db STAYS
$ ns-brain uninstall --purge --apply  # also deletes the memory

Without --purge your memories stay, so one ns-brain init puts everything else back. The one exception is brain/brain.json, which is deleted: copy it first if you set scopes or project notes in it. Removal is a command because an agent that did it by hand once deleted a project's whole .claude/settings.json.

If you are the agent doing this #

Four rules. They change what you do, not what you read.

This page for machines: llms.txt for the short form, install.md for the full procedure.