Docs · Hive setup

The same binary,
pointed at a server.

The edition is a setting in your project, not a different download. Joining a server is a config change and your hooks keep working. We left out a separate hive recall command on purpose, so nothing you are used to typing stops working the day you start paying.

Sign in #

There are two ways in. A person uses the device flow: it prints a code and somebody with admin on that server approves it. --token stores a credential you already have, such as the one signup shows you once. There is no command yet for an admin to issue a separate token for CI. Sign the CI machine in once with the device flow, as the person it acts for.

$ ns-brain hive login --server https://hive.example.com
$ ns-brain hive login --server https://hive.example.com --token hive_...

# from an account that can approve
$ ns-brain hive approve WXYZ-1234 --email them@example.com --node 4 --role contributor

Run login inside a project and, once the credential is saved, it offers to attach that project. First it tells you what will happen: how many memories, open tasks and log entries a local brain would copy up (it writes a dump first and keeps the local copy) and which files in .claude/ get the hooks. Then it asks Attach now? [y/N]. Anything but yes attaches nothing, sends nothing and prints the command to run later. If nobody is there to answer (an agent, CI or a pipe), it does not attach. --attach says yes up front. A project already on another server is never switched over, because that would leave its memories behind. Login prints the leave/join pair that moves it instead. Without --server, login and logout use the project's own server, then fall back to https://hive.fightclub.pro. They tell you which one they picked.

There is no identity provider behind the device flow yet. A named admin approves each sign-in. That works and leaves an audit trail. Google or GitHub sign-in would slot in behind the same flow without a redesign. We would rather say so here than have you find out.

The first approval on a new server comes from somebody with shell access. Everyone after that is approved by a human admin through the API. It works this way because the owner --init-org creates once held a credential that could not let anyone else in, so there was no way to get from one person to two.

Where the credential lives

Outside every project, in your OS config directory as ns-brain/credentials.json, mode 600. That location matters: a token inside a project is one git add away from being published. If the file is readable by group or world, the client refuses to read it at all and tells you to chmod it. NS_BRAIN_CREDENTIALS moves it.

One machine can hold credentials for several brains and they never mix. Each one is keyed by server and organisation, because one server can host two companies you belong to. A project names its organisation in brain.json (hive join writes it). If a project names a server where you have several brains but names no organisation, it is refused with the list. The client never guesses. ns-brain hive status shows every brain this machine holds and hive logout --org <name> --revoke signs out of one of them for good.

$ ns-brain hive status     # is the server there, who am I, what is queued
$ ns-brain hive nodes      # the part of the tree this credential can reach

Get a machine onto the brain #

A machine joins with one command and its private key never leaves it. The key is made on the machine that will use it. Only a certificate request goes to the server.

$ ns-brain axon enrol --email you@example.com --relay relay.example.com:7800

It asks for your password and never takes it on the command line. If the server has not seen the email before, it registers a new brain and gives it a generated id that reveals nothing. If it knows the email, it adds this machine to the brain you already have.

A machine enrolled this way is temporary. A password works from a machine you will never see again, so what you get is a device that expires by itself thirty days later, whatever its certificate says. For a machine you keep, approve it from one you already have:

$ ns-brain axon enrol --relay relay.example.com:7800   # on the new machine; prints a code
$ ns-brain hive approve-machine WXYZ-1234              # on a machine already on the brain

The code lets nobody in by itself. It points at a waiting request and the real authority is the credential of whoever approves it. That is why it can be short enough to read out over the phone.

The password only ever enrols. It is never accepted for reading or writing a memory. Somebody who phishes it can add a machine and nothing else. That machine shows up in ns-brain hive machines and you can revoke it.

$ ns-brain hive machines                              # what is enrolled
$ ns-brain hive pending                               # what is waiting to be approved
$ ns-brain hive password                              # set the password that enrols a new machine
$ ns-brain axon status                                # this machine's name, relay and expiry
$ ns-brain axon renew                                 # a fresh certificate before this one expires
$ ns-brain hive logout --server <url> --machine ci-box # revoke there, forget here

Revoking a machine other than the one you are sitting at leaves yours signed in. That is the point: you log out a lost laptop from a machine you still have. The relay refuses the revoked machine within a minute and drops any session it holds straight away. Its name is then retired for good. Machines are let in by name and the certificate it holds stays valid until it expires, so if the name came back the certificate would come back with it.

Certificates last ninety days on a machine allowed to renew. Renewal is not automatic until you put axon renew on a timer, on every machine.

Renew the relay first. Every machine checks the relay by name before it will talk to it. The day the relay's certificate expires, nothing reaches the brain from anywhere. ns-brain axon status shows the expiry.

Machines that are not on the same network #

This has its own page: how much latency it adds, what the relay can and cannot see and what happens the day a machine is stolen. The two-machine walkthrough puts every step below in order.

A brain at home and a laptop in a cafe cannot reach each other. Neither has a public address and neither should. Axon gets you across. Every machine dials out to a relay you run. The relay joins two outgoing connections together without ever opening the TLS inside them. No inbound port anywhere, no VPN, no TUN device. Whoever runs the relay sees only encrypted bytes.

$ ns-brain axon init --dir ~/axon-ca --org $(openssl rand -hex 8)  # your own authority
$ ns-brain axon issue --dir ~/axon-ca --machine relay              # the relay's identity
# on the box that will be the relay
$ ns-brain axon install --from ./relay --relay 127.0.0.1:7800
$ ns-brain axon relay --addr 0.0.0.0:7800 --dir /etc/axon \
    --admit /etc/axon/admit --hive <the machine holding the brain> --enrol

Machines are named <machine>.<org>.axon.internal and a client checks the name it asked for, not just that the certificate chain is valid. Every machine in one org has a certificate from the same authority, so the chain always checks out. A client that stopped there could be connected to a different machine in your own org by a hostile relay. The names are never looked up in DNS, so there is nothing to publish and no list of your machines to leak.

The relay lets machines in from a list copied from the brain's own register. The brain pushes it on every change and again every minute. With two separate registers, somebody would revoke a machine in one and forget the other. Nothing would warn you and the machine would still get in.

Move a project onto it #

$ cd ~/projects/yours
$ ns-brain hive join                     # dry run
$ ns-brain hive join --apply
$ ns-brain hive leave --apply            # back to a local brain

It is a dry run by default, one project at a time, the same way share works. It writes the server and the node into the project's brain.json under "hive". From then on the ordinary commands go to the server: recall, remember, brief and the session hooks you already wired.

An attached project never falls back to the local file. If a read cannot reach the server, you get an error naming the server. You do not get a confident answer from an empty database nobody has written to in a month.

The URL comes from brain.json, which is committed to git. So the client refuses to send a bearer token anywhere that is not https or loopback.

Add another project on a machine already signed in #

The credential belongs to the machine, so a second project needs no second login and no approval. In the new project's root:

$ ns-brain init --hive https://hive.example.com   # no brain yet
$ ns-brain hive join --apply                      # a local brain: copied up first

Both commands find the right node themselves. If the organisation already has a project by that name, they use it. Otherwise they use the organisation's node and the server files the project under it on its first write. So starting a new project needs the contributor role on the organisation. Somebody granted access to a single project is refused with that reason and nothing is left behind. An admin fixes it by approving a fresh login from them at the organisation. Every hive server serves the full reference at /docs: here is the reference on hive.fightclub.pro.

What happens when the server is down #

$ ns-brain hive queue     # what is waiting, and what the server refused
$ ns-brain hive flush     # send it now

Writes wait in a local queue, in order, per device. They go in on the next command that reaches the server. Reads do not queue, because there is nothing to queue: a read either gets an answer or it does not.

Refused writes stay in the queue instead of being dropped. A write the server rejected tells you something about your data. Throwing it away to keep the queue tidy would lose the only copy you have.

There is no offline copy. We decided against keeping a local copy of a hosted brain. If the network is down your agent cannot reach its model either, so a brain that still answered would be answering nobody. What we promise is that nothing you wrote gets lost.

The HTTP API #

The server speaks HTTP and JSON under /v1: recall, remember, brief, nodes, whoami, export, doctor and the admin routes for retention, legal hold and settings. Send the bearer token in the Authorization header. It is the same one hive login saved.

/v1/health needs no token. It reports what the server actually has, including whether an embedding model is loaded, instead of a bare yes or no that nobody can interpret.

Every route the server serves is documented, with the credential each one needs. A Hive server has no MCP endpoint yet. MCP is served by ns-brain on your own machine, over stdio or your own HTTP listener. The MCP page covers it. An OAuth endpoint on the hosted server, so a client can attach with nothing installed locally, is planned but not built.

Minimum client versions #

The client sends its version and the server refuses anything older than its minimum. The refusal includes the install command. A server supports clients back to that minimum, not forever.

$ ns-brain version
$ curl -s https://hive.example.com/v1/health

Nothing upgrades itself. Back up first and check on your own data afterwards: the counts are unchanged, doctor is clean and a recall whose answer you already know still returns it. An upgrade that says it succeeded has not necessarily worked.

Running your own #

The server is one binary on top of Postgres, which you install and run. Each organisation's data key is encrypted with a master key. That master key lives in a file on the server or in a key service you run. It is your whole safety net: lose it and nobody can read the memories, you included. Copy it off the machine before the server holds anything real. Test that your backups actually restore instead of only scheduling them.

If you want it inside your own network with your own key custody, packaged as an image with a signed licence, that is Enterprise. If you want us to host it, that is Hive. The code is the same either way.

Server flags

ns-brain hive serve --help lists them all. These are the ones that decide what the server is:

--dsn
--master-key
Postgres and the file holding the key that wraps every organisation's data key. Both required.
--addrWhat to listen on. Loopback by default.
--tls-cert
--tls-key
Serve HTTPS directly. Without them, keep --addr on loopback and put a TLS terminator in front of it on the same host. Nothing should reach this server unencrypted, on any network.
--signupLet anyone create an organisation. Off by default. When on, the store rate limits it.
--licenceAn appliance licence file. It is checked before the shell subcommands run, not after, so the seat limit applies to them too.
--axon
--axon-dir
Serve over axon as well as HTTP, using this machine's identity and the admission list in that directory. The user the service runs as must be able to read that directory.
--embed-url
--embed-model
--embed-dims
--embed-every
Turn on semantic search (matching by meaning): where the embedder is, which model, how wide its vectors are and how often to sweep. Without them search matches words, which is what the free edition does. Semantic search is never worse than that: it adds candidates and reorders them but never removes a word match.

Then the one-shot flags, which do one job and exit instead of serving. --init-org with --init-owner creates the first organisation and its owner. --approve with --approve-email, --approve-node and --approve-role lets the first person in from a shell. That is how a server gets from one person to two. --adopt-axon with --adopt-org installs an authority you generated by hand. It takes only the issuing half, because normally the root key stays offline. --adopt-axon-root is the exception and covers one case. If an organisation's authority was generated before the root key was kept, it cannot sign a successor to its own issuing CA. The day that certificate expires, every machine stops at once. Giving the server the root key lets it rotate. The cost is that root and issuing then sit behind the same master key. --adopt-machine puts a name into the admission register directly. --credit adds credit to an organisation's balance.