berthdocs

Guides

Project config

A repository's .berth/config.json says how every worktree is set up, run and torn down, on every box.

A repository's .berth/config.json, committed with the code, says how every worktree of that repository is set up and torn down, which ports, environment and services it gets, and which agents to offer. It travels with the repo, so every box does the same.

.berth/config.json
{
  "setup": "pnpm install && createdb $BERTH_WORKTREE_SLUG",
  "archive": "dropdb --if-exists $BERTH_WORKTREE_SLUG",
  "ports": 2,
  "env": {
    "DATABASE_URL": "postgres://localhost/$BERTH_WORKTREE_SLUG",
    "NEXT_PUBLIC_WEBAPP_URL": "http://localhost:$BERTH_PORT"
  },
  "services": [
    { "name": "web", "run": "pnpm dev --port $BERTH_PORT", "autostart": true },
    { "name": "worker", "run": "pnpm worker" }
  ],
  "agents": [
    { "id": "claude", "name": "Claude Code (Opus)", "command": "claude --model opus" }
  ],
  "hooks": [
    { "on": "worktree.created", "run": "cp ../cal/.env .env" }
  ],
  "flows": []
}

Every field is optional; the config reference lists them all with their rules.

Setup and teardown

  • setup runs right after a worktree is created, in it, through a login shell (up to 30 minutes, with its output in a log on the box).
  • archive runs before a worktree is removed, after its services stop; if it fails, the worktree stays.
  • Both also get Orca's names (ORCA_ROOT_PATH, ORCA_WORKTREE_PATH, ORCA_WORKSPACE_NAME), so setup scripts written for Orca work unchanged.

Ports and environment

  • Ports. Every worktree has its own block of ports, stable for its life and freed when it is removed: $BERTH_PORT, then $BERTH_PORT_1… up to ports of them (at most 10; at least one). Whatever listens on a port in the block counts as the worktree's, containers included, and the worktree's private URL, http://<worktree>.<location>.<box>.localhost:1377/, reaches the lowest one.
  • Environment. Everything run in a worktree (setup and archive scripts, terminals and agents, exec, hooks, flows, services) gets these, then env with them expanded:
VariableMeaning
BERTH_BOXThe box's name for itself
BERTH_LOCATIONThe location, like cal
BERTH_ROOT_PATHThe repository's main checkout
BERTH_WORKTREE_PATH, BERTH_WORKTREE_NAMEThis worktree
BERTH_WORKTREE_SLUGLike cal_fix_billing, safe for database names
BERTH_BRANCHIts branch
BERTH_PORT, BERTH_PORT_1, …Its ports
BERTH_KIT_DIRWhere the project's kit keeps its files, if it has one

A value in env can use $NAME for those variables or berthd's own environment, and can be a secret reference instead of a value.

Services

Services run in each worktree as managed processes that survive the daemon restarting and come back if they crash, with their output in a log.

  • autostart ones start when the worktree is created, after setup succeeds.
  • All of them stop before the archive script runs.
  • A service also gets PORT (its worktree's $BERTH_PORT) unless env sets it.
  • Start, stop and open them from the app's Run menu, or:
berth service list devl/cal/billing
berth service start devl/cal/billing web
berth service log devl/cal/billing web

Agents

agents adds ways to start agents in this repository, or replaces a built-in one with the same id (claude, codex, opencode, gemini, cursor). A first prompt goes at the end of command, or after prompt_flag if the agent needs one.

Hooks and flows

  • Hooks fire only for this repository's events, inside the worktree the event is about, with its environment. before: gates here can refuse actions in this repository. See hooks.
  • Flows are this repository's automations, on every box that has it. See automations.

This box only

Some of it should not be committed: a database password, one box's paths. Each box keeps its own config for a location, laid over the file (and over the project's kit, if it has one):

  • setup, archive, ports and each env entry replace the file's;
  • services, agents and flows replace the file's by name or id, and add new ones;
  • hooks add up.

Edit it in the app's Project settings, or PUT /v1/locations/{name}/config on the box. berth location config devl/cal shows the repository's, the box's and the effective config side by side.

berth location scripts devl/cal --setup "make bootstrap"   # just the scripts
berth location scripts devl/cal --clear

A box can also give every worktree on it some environment, in ~/.berth/env.json ({"env": {"KEY": "value"}}), under the project's own.

Next

  • Kits carry this same config to a repository you can't commit to, or to several at once.
  • Secrets keep passwords out of env.
  • Task templates fill in the agent, branch and prompt for kinds of task you start often.

On this page