# rabbitbrain.ai auth.md

This file tells agents how to connect `rb` to a rabbitbrain.ai account, so that `rb sync` can keep a private copy of a record's page there.

rb signs a machine in with a device code that the human approves in their own browser. There is no API key for you to create, store or pass around, and no anonymous account. The record itself needs no account: `rb status`, `rb show`, `rb page` and `rb export` need no account and no network.

## Status

rabbitbrain.ai is open: anyone can make an account at https://rabbitbrain.ai/signin, with an email address and a handle. `rb login` and `rb sync` call it as described below, and a hub named with `--hub` or `RB_HUB_URL` the same way.

## Before connecting

Ask the human first. A sync uploads the record's page to their account, and rb has no command that only checks whether this machine is signed in: `rb sync` is the check and the upload at once.

With their consent, run this in the project, the folder that holds `.rb/`:

```sh
rb sync --json
```

Read the envelope:

- `ok: true`: this machine is signed in, and the page was synced privately. `data.url` is its address, `data.handle` the account. You are done.
- `E_USAGE`, "No credential for rabbitbrain.ai on this machine.": nothing was sent. Sign in with `rb login` (below), then run `rb sync` again.
- `E_HUB_REFUSED`, "The hub answered 401: This token is missing, expired or no longer valid.": the credential was revoked or has expired. Run `rb login` again.
- `E_HUB_UNREACHABLE`: the address did not answer, or did not answer as the hub does. The message names the address.

For any other error, read `errors[0].fix`.

## Sign in

```sh
rb login
```

`rb login` is a device-code flow:

1. rb asks the hub for a short code and prints it on standard error, with the address the hub gives for approving it: on rabbitbrain.ai, its `/link` page with the code filled in (`https://rabbitbrain.ai/link?code=<the code>`). Both go to standard error with `--json` too.
2. Pass the address and the code to the human exactly as printed. They open it on any device, sign in to the hub if needed, check that the code is the one in the terminal, and approve it. The page asks them to approve only if they just ran `rb login`.
3. rb waits, printing a dot each time it asks, until the code is approved, declined or expired. When a check's connection drops or times out, rb asks again, three in a row at most; after that it says the hub could not be reached and stores nothing. Nothing is created until the human approves. Ctrl-C stops it.
4. Once approved, rb stores the credential itself and prints `Signed in as <handle> on <hub>.`

The human approves on the site, whoever started `rb login`, so the credential is theirs. Never ask them to paste a code, a token or an account name into the chat: approving in the browser is the whole step.

`rb login` holds the terminal until the code is approved, declined or expired. If your shell shows output only when a command ends, run it in the background and read its standard error for the code, or ask the human to run `rb login` in their own terminal.

## The credential

rb writes the credential to `credentials.json` in its settings folder: `$RB_CONFIG_DIR`, or else `rabbit-brain/` under `$XDG_CONFIG_HOME`, or else `~/.config/rabbit-brain/` (on Windows, under `%APPDATA%`). The file is readable by its owner alone (mode 0600 where the system has modes), outside the repository and outside the environment, with one entry per hub.

You never need the token: rb reads it. Do not open the credentials file, and never print, log, paste or commit the token, or copy it into `.env`, the repository, a chat, an issue or a tool's output. rb itself never prints it. `RB_HUB_TOKEN` overrides the file for CI; do not set or unset it.

## Sync and share

```sh
rb sync                  # the record's page, privately
rb sync --with-record    # the record too
rb sync --watch          # sync again each time the record changes, at most once a minute; Ctrl-C ends it
```

`rb sync` puts a private copy of the record's page in the account: only the account, signed in, can open it. It says `Synced, privately: <url>`, which `--json` gives as `data.url`. The copy is the record as computed at that sync, so sync again after new runs; the repository stays the store.

`--with-record` sends the record as well. Its files and log keep who made each write, the agent sessions and the user's words, and anyone who can open the copy can read all of it. Use it only when the human asks for it.

Sharing is the human's step, on the site. The record's page has a Share button that makes a link they can revoke; anyone with the link sees the page. If the record was synced with `--with-record` and the human lets the link's readers rerun it, they can get the record too. rb never makes anything public. Each later sync updates what the link shows.

Tell the human the address `rb sync` printed, that it is private until they share it, and where the Share button is.

## Another hub

`--hub <address>` names the hub for `rb login`, `rb sync` and `rb logout`, and `RB_HUB_URL` names it from the environment. Without either, rb uses https://rabbitbrain.ai. A credential is kept per hub, so sign in once on each machine for each hub:

```sh
rb login --hub https://hub.example.org
rb sync --hub https://hub.example.org
```

## Sign out

```sh
rb logout
```

`rb logout` revokes the credential on the hub and removes it from the credentials file. If the hub cannot be reached, rb still removes it here, and says to revoke it at the hub's `/account` page, where the human manages every linked terminal.
