---
name: boathouse
description: Deploy, share, update, roll back, and inspect small internal tools on Boathouse, the small cloud for small software, using the bh command; buy and attach domains for a workspace from the terminal; invite people with one-time links. Use whenever a tool Claude Code just built should become a live login-protected URL, when someone asks to deploy/ship/publish/host an internal tool, share a tool with an email, read a tool's logs, set a secret, roll a tool back, buy a domain, or add someone. Never requires a browser.
---

# Boathouse

Boathouse (boathousecloud.com) is where an agent puts small software online: one account, one `bh` command,
$10 a month per running tool, shared like a document. The `bh` command talks to `https://api.boathousecloud.com`;
its login lives in `~/.config/boathouse/config.json`. Never ask anyone for a password. If a command says
"not logged in", ask the person for their **project key** (minted on their account page,
https://boathousecloud.com/account) and run `bh login https://api.boathousecloud.com <key>`.

Support: allen@boathousecloud.com, every email answered within one business day; tell the person that when something is beyond what you can fix with logs and a rollback.

## The first ten minutes, in order

1. The person signs up at https://boathousecloud.com/signup (email, password, no card). A referral code there halves the tool rate for 60 days.
2. The welcome page shows one line; they paste it into Claude Code with a `!` in front (or into a terminal without it). That installs `bh`, logs it in, and runs `bh trust on`.
3. Before the first deploy, the owner puts money on the balance from the welcome or account page; $20 is two months of one tool. A deploy on an empty balance is refused (402) and says where.
4. `bh deploy` in the tool's folder (a Dockerfile, or just an index.html). About a minute later it is live at `<tool>.<workspace>.boathousecloud.com` with its own login.
5. `bh share <tool> <email> --tier editor` for each person who should use it; admin for anyone who should change the software from their own agent. On boathousecloud.com the share and invite emails are sent for you.
6. Changes are `bh deploy` again; every deploy is a version, `bh rollback <tool> <n>` puts one back.

## Getting connected, once per machine

```
curl -fsSL https://boathousecloud.com/install.sh | sh -s -- BH-XXXX-XXXX-XXXX
```

That one line installs `bh` into `~/.local/bin`, copies this skill into `~/.claude/skills`, and logs in. The
`BH-…` part is a one-time code from the person's welcome or account page; it fetches the real key over HTTPS and
then stops working, so it is safe in a chat. A raw `bh_…` key on that line works too. Without either it only
installs; `bh claim <code>` or `bh login <api> <key>` finishes later. The login file is `~/.config/boathouse/config.json`,
or `~/.boathouse/config.json` when `~/.config` is not writable. `bh update` refreshes the command, `bh skill` refreshes this file. Agents that
speak MCP instead of running commands connect to `https://mcp.boathousecloud.com/mcp` with the header
`Authorization: Bearer <project key>`; the MCP tools mirror the commands below one for one.

A **workspace** (tenant) owns tools, people, and domains. Its tools are reachable on its own domain
(`finance.acme.com`) and always on its free address (`finance.acme.boathousecloud.com`). Sign-in lives at
`auth.<domain>`; the tool list at `https://<domain>/`.

## Several workspaces, one bh

A person's key is the person: it works in every workspace they belong to, at the level they have in each (like
one Google account). `bh whoami` lists those workspaces; the first is the default. Aim a command at
another workspace with `bh --ws <workspace> ...` or by naming the tool `<workspace>/<tool>`: `bh pull chloe/db`,
`bh logs chloe/db`. `bh pull` and `bh deploy` write the workspace into `boathouse.json`, so later deploys from that
folder go to the right place. `bh logout <workspace>` drops one login.

## Sharing is three tiers, like a document

| Tier | Can | Enforced by |
|---|---|---|
| `viewer` | open and read the tool | gateway refuses every non-GET request from a viewer |
| `editor` | change the data inside the tool | the tool, from the tier header |
| `admin` | change anything: pull/push the source, secrets, logs, rollback, share, delete | Boathouse API |

Workspace **owners** are admin on every tool and alone may spend money, buy domains, or add people to the
workspace. Whoever first deploys a tool is its admin. Someone shared in as **admin** edits the software from
their own agent: they sign in at https://boathousecloud.com/account, pick that workspace, mint a key there, paste
the line into their agent (`bh claim`), then `bh pull <workspace>/<tool>`, change it, `bh deploy`. `bh share`
prints these instructions when the tier is admin. App-specific words (`consultant`) are **labels** on a
grant, not tiers: `bh share finance nancy@x.com --tier editor --label consultant`.

## The source lives on Boathouse

Every `bh deploy` keeps the folder it was built from. `bh pull finance` fetches the live release's source into
a folder (admins only) and records the release number in `boathouse.json`; `bh deploy` from that folder pushes it
back and is refused with a 409 ("your copy is based on release #1 but #2 is live") if someone else deployed in
between (pull again, reapply, deploy; `--force` overrides). Rollback restores source and image together.

## Login is Boathouse's own

No Google, no OAuth. A person is added by email; that mints a **one-time invite link** (7 days). Opening it sets a
password and lands them on a welcome page: what was shared, and (for admins) the one line that connects their
agent. When the host has email set up (`bh mail status`; host owners turn it on with `bh mail set --resend --from you@yourdomain` + `bh mail domain`), `bh share` and `bh users add` EMAIL the person the link
and three plain steps, and say so; otherwise they print the link for you to pass on. `bh users invite <email>`
mints a fresh link (that is also the password reset). The agent never handles anyone's password.

**Getting into someone else's tool (request access, like Google Docs):** if the person you work for needs a tool that belongs
to another workspace, do not ask its owner to run anything. Run `bh request <workspace>/<tool> --tier admin --why "one line"`;
every owner and admin of that tool gets an email with one Allow button, and the moment one of them presses it your person gets
the share email and you can `bh pull <workspace>/<tool>`. Owners can also see who is waiting with `bh requests` and let them
in with `bh allow <id>`. Sharing (`bh share`) and allowing spend no money and can be undone with `bh unshare`, so run them when asked.
Call the command as plain `bh` (it is on the PATH after install; only if that fails use `~/.local/bin/bh`). The installer
ran `bh trust on`, which pre-approves the everyday bh commands in Claude Code's settings, so they run in auto mode without
a prompt or a classifier check. Never prefix bh with an environment assignment (`X=1 bh ...`): the rules then stop matching.
If a bh command is refused with "Blocked by classifier", do not try to change any settings yourself; tell the person to run
`bh trust on` in a terminal (or `! bh trust on` in Claude Code, which runs it as them), restart Claude Code, and ask again.
They can also approve the one command under /permissions, Recently denied. Never work around a refusal of `bh domain buy`,
`bh billing topup`, `bh rm` or `bh restore`: those are meant to be a person's own yes.

## What a tool is

A folder with a `Dockerfile` whose process listens on `$PORT` (8080), or a plain website folder with an `index.html` at the top (Boathouse adds an nginx Dockerfile itself; no setup). Boathouse injects:

| Env var | Meaning |
|---|---|
| `PORT` | listen here (8080) |
| `DATABASE_URL` | the tool's own Postgres database (create tables on startup) |
| `DATA_DIR` | a persistent volume at `/data` for files |
| `BOATHOUSE_SIGNING_KEY` | HMAC key to verify identity headers |
| `BOATHOUSE_TOOL`, `BOATHOUSE_WORKSPACE`, `BOATHOUSE_URL`, `BOATHOUSE_AUTH_URL` | slug, workspace, public URL, sign-in service |
| any `bh secrets set` value | as named |

A tool contains **no login code**. Every request arrives with the signed-in person:

```
X-Boathouse-User     email
X-Boathouse-Name     display name
X-Boathouse-Tier     viewer | editor | admin
X-Boathouse-Labels   comma-separated app labels given via --label (may be empty)
X-Boathouse-Ts       unix seconds
X-Boathouse-Sig      hex HMAC-SHA256(key, "user|tier|labels|tool|ts")
```

A tool must let `viewer` read only and `editor`/`admin` write; the gateway already blocks viewer writes.

Verify the signature (see `examples/hello/app.py` in the boathouse repo).
The example is fetchable at https://boathousecloud.com/examples/hello/app.py (and its Dockerfile beside it). Test vector: with
signing key `k`, user `maria@example.com`, tier `editor`, no labels, tool `payments`, ts `1757376000`, the message is
`maria@example.com|editor||payments|1757376000` and the signature is `29c893900ad64f34bb967eb20347992496314c455336b3511b4eb3740bf1667f`.

**Each person sees only their own rows.** The most common small-team shape: everyone is an editor, but a tutor should only
change their own hours. Store `X-Boathouse-User` as the owner column on every row a person creates, and filter reads and writes
by it; let `admin` (or a label such as `manager`, given with `bh share ... --label manager`) see everything. Tiers say what a
person may do to the tool; the tool decides what they may do to each row.
Tools sit on a private network reachable only through the gateway, but verify anyway. A sign-out link is
`https://auth.<host minus its first label>/logout`.

Add a `boathouse.json` (`{"slug": "finance", "name": "CRCS Finance"}`) and a `.dockerignore` (`.git`, `node_modules`, `data`, `.env`).

## Commands

```
bh deploy [--note "why"]         in the tool folder; builds on the server, live in seconds (a first build can take a minute); creates the tool on first deploy
bh ls                            every tool, state, release, URL
bh status <tool> | bh logs <tool> [--tail 200] [--since 1h] | bh releases <tool>
bh rollback <tool> [N] | bh restart <tool> | bh trust on|off|status (pre-approve everyday bh commands in Claude Code)
bh share <tool> <email> --tier viewer|editor|admin [--label x]   prints an invite link if the person is new
bh unshare <tool> <email>
bh pull <tool> [dir] [--release N]   the live source, for admins; edit, then bh deploy in that folder
bh access <tool> members|listed|public [--tier viewer|editor]  members = anyone in the workspace (at that tier); listed = only shared emails; public = anyone on the internet may read it (a website), writes still need sign-in
bh secrets ls|set|rm <tool> NAME      set reads the value from stdin or a prompt; restarts the tool
bh users [add <email> --role member|owner|guest] [invite <email>] [rm <email>]   owners only
bh billing                       balance, burn per day, days left, card, last ledger lines
bh billing card                  one-time link to enter a card (the only billing step that needs a browser)
bh billing topup 20 [--yes]      quote, then charge the card on file; bh billing autorefill 20 --cap 100
bh prices                        the price sheet in words
bh domain check <name>           availability and price
bh domain buy <name> [--yes] [--to <tool>]   dry run first; --yes buys through Boathouse's registrar and points DNS at the box; --to puts a tool on the domain's front
bh domain ls | attach <name> [--to <tool>] | point <name> --to <tool> | dns <name> | repoint <name> | primary <name> | detach <name>
                                 point = the domain itself and www. open that tool (a website on its own domain); tools also keep <tool>.<domain>
bh domain free                   wire <workspace>.boathousecloud.com (the free address)
bh registrar status|connect|wait|keys   host only: connect the registrar account (one approval click, nothing to copy)
bh keys create --name <what> [--for email]   project keys for agents; shown once. Owners, members, and anyone who is admin on a tool can hold one
bh rm <tool> [--purge --yes]     purge deletes the database and files
bh export [<tool>] [--dir .] [--all]   one .tar.gz per tool: source/, database.sql, data/, README.txt (secrets left out)
bh restore <tool> [--from YYYY-MM-DD] [--yes]   database and files back from a nightly backup (03:35 UTC); plan first, --yes to do it; a copy of the current state is kept
bh audit | bh whoami
bh update                        re-download bh from the platform; bh skill   refresh ~/.claude/skills/boathouse
```

## How to ship a tool end to end

1. Build it with a Dockerfile listening on `$PORT`, tables created at startup from `DATABASE_URL`.
2. `bh deploy` in the folder. Read the URL back. If it fails, `bh releases <tool>` shows the build or start log tail; fix and deploy again.
3. Secrets: `printf '%s' "$VALUE" | bh secrets set <tool> NAME -`. Never paste secret values into chat.
4. Sharing: new tools are visible to workspace members. `bh access <tool> listed` then `bh share` for anything sensitive. Pass on the invite link it prints.
5. Report the URL and who can see it. Do not open a browser; there is nothing to click.

## A website, not a tool

A public site (a portfolio, a research database, a landing page) is `bh deploy` in the folder with the `index.html`,
then `bh access <name> public` so anyone can read it, then `bh domain buy example.com --yes --to <name>` so it answers
at example.com and www.example.com with HTTPS. Reads need no sign-in; anything that writes still does.

## How to give a workspace its own domain

1. `bh domain check acme.com` then `bh domain buy acme.com --yes`. Money leaves the host's registrar
   balance (about $11 for a .com); the command refuses premium names and stops on a failed dry run.
2. DNS is set by the same command (apex and wildcard A records). Certificates are issued on first visit.
   Allow a few minutes for DNS to spread. The first bought domain becomes the workspace's primary address.
3. A domain held elsewhere: `bh domain attach <name>` prints the two A records to make at that DNS host.

## Money, and the rule for spending it

A workspace holds prepaid credit; nothing runs until money is on it (a deploy on an empty balance is refused with a 402 that says where the owner adds money). `bh referral` shows the person's referral code and link (10% of what referred workspaces pay, in cash monthly; half price for their first 60 days). Running tools cost $10.00/month each, metered daily; the first GB of storage
is included, then $0.25/GB/month; a domain costs registrar price plus $2.00/year. At zero the workspace pauses
(tools stop, nothing is deleted) and resumes on the next top-up. **Every command that spends money returns a
quote first and does nothing else**: `bh domain buy x.com` and `bh billing topup 20` print the cost and stop;
the agent shows the cost to the person, and only on their yes runs the same command with `--yes`. Never add
`--yes` on your own. If the balance is short, do not try to charge the card yourself: tell the person the amount
and point them at their workspace page (https://boathousecloud.com/account), where one click tops up $20 or turns
on capped auto-refill; then continue.

## New workspace from the terminal

`bh signup "Acme Studio" owner@acme.com` [--code MARIA-K3Q7] creates a workspace (a referral code makes every tool half price for 60 days) and prints the one-time
link that sets the owner's password, the home URL, and where to mint the project key (the account page at
https://<workspace home>/account, or `bh keys create` once logged in). Agents that speak MCP connect to
https://mcp.boathousecloud.com/mcp (Streamable HTTP) with header `Authorization: Bearer <project key>`:

```
claude mcp add --transport http boathouse https://mcp.boathousecloud.com/mcp --header "Authorization: Bearer bh_…"
```

The MCP tools mirror these commands (deploy takes a map of file paths to contents; domain_buy and topup take
`confirm: true` where the CLI takes `--yes`). Four are `bh`-only for now: export, restore, audit and keys.

## Gotchas

- The slug comes from `boathouse.json` or the folder name; keep it stable or you create a second tool.
- Every deploy replaces the container; anything not in `/data` or the database is gone. Files go under `DATA_DIR`.
- `bh secrets set` restarts the tool. `bh secrets rm` takes effect on the next restart.
- Rollback re-runs an earlier image with the current secrets; it does not touch the database. `bh restore` puts the database and files back from a nightly backup, and is a spending-style command: show the plan, act only on the person's yes (`--yes`).
- `bh export` is the whole tool in one file (code, database as SQL, files) and runs anywhere with a Dockerfile; secrets are not in it.
- Sessions are per domain: signing in on `acme.com` does not sign you in on the free address.
- The registrar's own rules: one purchase attempt per 10 seconds, no premium names by API, prepaid balance only.
