You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
berth runs on your laptop. It talks to the laptop agent,
starting it if needed, and through it to every box. berth help prints this
list; berth kit help the kit commands, berth team help the team setup ones,
berth review help the review ones.
Addressing. A box is devl; a location on it devl/shop; a worktree
devl/shop/checkout; a session devl/SESSION.
Set a box up over SSH (once), quietly: installs berthd, tmux and git if missing (Shipyard's own tmux needs no sudo), the agent CLIs (--agents, Claude Code by default) and their hooks, and pairs, with no plan and no Enter. Only a step that needs sudo's password (git missing, or lingering the box allows only as root) runs in a terminal, where sudo asks; lingering alone is asked about first and can be skipped. --guided shows the whole plan, waits for Enter, and runs every step in one terminal. --yes (or no terminal) asks nothing and stops with the command to run where sudo would need a password; --from retries from a step. See add a box.
A join link for another computer of yours: a fresh single-use code from each box (every paired box, or --boxes), valid ten minutes. Offline boxes are left out and listed. Asks first unless --yes; --for names the computer in the boxes' events. See more than one computer.
berth join '<link>'|- [--check] [--yes] [--json]
Pair this computer with every box in a join link (- reads it from stdin; pasting the whole message is fine). Each box reports paired, already, needs-network (sign in to its tailnet, then join again) or failed; --check only says what the link holds
berth network login NAME
Join another tailnet (a personal one, say) to reach its boxes
berth network proxy NAME HOST PORT
Connect stdin and stdout to HOST:PORT through that network, for SSH's ProxyCommand
berth networks [--json]
Joined networks
berth discover [--network NET] [--json]
Machines on the tailnet that could be boxes
berth boxes [--json]
Paired boxes, whether they are online, and the route each is reached by
berth ping BOX [-c N]
Check a box answers and still trusts you: how long connecting took, then N−1 round trips on the open connection (its latency)
berth upgrade BOX [--check] [--json]
Upgrade the box's daemon over Shipyard's own connection (no SSH); --check only reports whether it is older
Open a worktree, or a file at a line, in your editor (default: the first installed)
berth ssh-config [--write] [--json]
Show (then write) the SSH hosts editors use: berth-<box>
berth forget BOX
Remove a box from this laptop
berth discover --json prints { user, machines, tailscale, tailnet }:
user is the SSH user to suggest (yours on this computer), tailscale is
this computer's Tailscale (running, stopped, logged-out or missing;
anything but running lists no machines rather than failing), and
tailnet its tailnet's name. Each machine has name, dns_name, ip,
os, online, ssh (it runs Tailscale SSH), host_keys (the SHA256
fingerprints of the SSH host keys the tailnet reports for it) and box
(the box it is paired as, if any). With --network, the machines are that
network's, and tailscale and tailnet are left out.
Kits
Command
What it does
berth kit list [--json]
Kits on this laptop, and where each is installed
berth kit add LINK [--yes]
Fetch a kit (git repo, …/tree/REF/DIR, gist, kit.json URL or folder), show what it does, and keep it
What <org>/.berth does: the org, the pinned commit, each box step (and which ask for your password), each repo and whether you can read it, the keys, and an update if there is one
Run it on BOX: the steps in a terminal on the box (berth attach BOX/team-<id> to type your password), then the repos; asks for keys it needs, and follows the progress. --no-1passwordskips 1Password: the shared keys are asked for once instead (Enter leaves one missing) and op is never signed in on the box; refused when the team's team.json says "onepassword": "required"
berth team status [--json]
Each team setup you accepted, its box, commit, state and progress
berth team retry ORG [--from STEP|PROJECT] [--box BOX]
Start a failed setup again from a step or a repo
ORG is a GitHub org, whose <org>/.berth holds the team setup, or a link
to one anywhere: github.com/OWNER/REPO[@REF] or
github.com/OWNER/REPO/tree/REF/FOLDER. GitHub goes through gh: this laptop's reads the team setup, and the box
signs in with its own. See team setup.
The review sheet: the PR, its author and the exact head commit, the box, what will run there and which keys it gets, and what in the PR changes setup. Then asks, and makes the worktree at that commit (--yes doesn't ask; --json prints the sheet and makes nothing). --as and --pathopen it logged in as one of the project's dev users, at a page, and print that address. Also takes a berth://review link
berth review link OWNER/NAME#N [--as EMAIL] [--path /x]
Print the PR's review link, to paste in its description or a chat
berth reviews BOX [--idle-days N] [--json]
The reviews on BOX; --idle-days sets how long one may sit unused before it is cleaned up (0: never)
Who may be reviewed is read from GitHub with this laptop's gh, as you. See
review a PR.
Reaching services
Command
What it does
berth url BOX PORT|SERVICE
Print the private URL for a port, or a service by name
berth open BOX PORT|SERVICE
Open that URL in your browser
berth forward BOX PORTS [--json]
Forward local ports: 3000, 8080:3000, 3000-3005
berth forwards [--json]
List forwards
berth unforward ID
Stop and forget a forward
berth route add '*.x.localhost' BOX PORT
Send every matching host to a box port, Host unchanged
berth routes [--json]
List routes (berth route rm PATTERN removes one)
berth units BOX [--json]
Managed units on a box
berth unit add BOX/NAME -- COMMAND...
Install and start a unit
berth unit get BOX/NAME [--json]
A unit's state and where its log is
berth unit log BOX/NAME
What a unit has written, for one that will not stay up
berth worktree new BOX/LOC/NAME [--branch B] [--base REF] [--pr N [--ref REF]] [--parent NAME] [--no-setup]
Create a git worktree and run its setup; --pr checks out that pull request (pass its head branch as --branch; a fork's head comes from --ref, by default pull/N/head); --parent nests it under another worktree of the location; --no-setup skips setup and autostart services, and the worktree shows setup_pending in locations --json
berth worktree setup BOX/LOC/NAME [--wait]
Run the location's setup script and autostart services in a worktree, for one made with --no-setup. --wait blocks until setup finishes and exits non-zero if it fails
berth worktree rm BOX/LOC/NAME [--force]
Remove a worktree
berth worktree rename BOX/LOC/NAME [TITLE]
Give a worktree a display name; its branch and folder keep their names, and no TITLE clears it