bowline
Concepts

Setup recipes

How the optional .bowlinesetup file prepares a freshly synced project to run when it becomes hot on a new machine or agent.

A Setup Recipe is an optional .bowlinesetup file that records the project-owned commands needed to make a project runnable after it becomes hot on a fresh machine or agent. Syncing the files is not enough on its own: dependencies still need restoring. A Setup Recipe closes the gap between "the code is here" and pnpm dev works.

A Setup Recipe is not sync policy. It never runs merely because files synced, and it does not decide which files travel with your workspace. That job belongs to path policy.

What a recipe looks like

A .bowlinesetup file is line-based and project-owned. Each non-empty line is a command, blank lines and # comments are ignored, and Bowline never writes or edits the file for you.

# .bowlinesetup: prepare this project after it becomes hot.
pnpm install --frozen-lockfile
pnpm db:migrate
pnpm build

Commands run sequentially from the directory that contains the recipe, and setup stops at the first failure. A recipe applies to its own directory subtree, so a monorepo can place recipes where they belong.

When setup runs

Setup is hot-triggered, not sync-triggered. A project becomes hot when you explicitly prepare it with bowline setup <path>.

Bowline runs the recipe only then. It does not run setup during background sync, plain machine setup, or remote manifest import. Seeing the files arrive is never enough to execute commands.

Important

A setup recipe runs commands on your machine or agent host. Bowline confines execution to paths under the accepted workspace root and redacts command output, but the commands themselves are whatever the project author wrote. Approval gates protect you when a recipe arrives or changes through sync.

Inferred setup without a recipe

Most projects do not need a .bowlinesetup. When none exists for a subtree, Bowline can infer a safe, lockfile-backed dependency restore for common ecosystems.

EcosystemDetected lockfile
pnpmpnpm-lock.yaml
npmpackage-lock.json
Bunbun.lock and bun.lockb
uvuv.lock
CargoCargo.lock
Go modulesgo.sum

For each, Bowline runs a conservative, lockfile-pinned restore. Inference is deliberately narrow:

  • It uses no-lifecycle-script install modes where the package manager supports them.
  • A restore that would run package lifecycle hooks, for example preinstall or postinstall, requires your approval before it runs.
  • It never runs unknown project scripts. Anything beyond dependency restore needs an explicit .bowlinesetup.

A recipe beats inference: when a .bowlinesetup exists for a subtree, it is authoritative there and Bowline does not infer.

Approving synced recipes

Because a recipe is just a project file, it can arrive or change through sync. Bowline does not run an unapproved recipe on the receiving machine.

The first time a machine or agent sees a recipe, or whenever its contents change, Bowline records the new recipe hash and raises an approval-required state instead of executing. You approve it once, locally, through the CLI, TUI, or status surface, for example bowline setup --yes. Approval binds the recipe hash, the source and approving devices, the working directory, and the trigger.

Setup receipts

Every setup run records a setup receipt so reruns are idempotent and explainable. A receipt captures enough identity to know whether setup is still valid: the recipe hash, relevant lockfile and toolchain hashes, the package-manager identity, the env profile, the OS and architecture, the trigger, command exit state, a timestamp, and a redacted output summary.

Bowline never stores raw env values or full secrets in a receipt; full logs are kept outside the workspace with owner-only permissions. Because receipts are hash-based, a second bowline setup on an unchanged project is a fast no-op. Changing the recipe, a lockfile, the toolchain, the package manager, the OS, the architecture, or the env profile invalidates the receipt, and setup runs again.

Generated output stays local

Setup creates dependency and build folders, and those stay on the machine that made them. node_modules, .venv, target, .next, and caches are local-regenerate or cache state. Setup can create them, but they never become canonical workspace state, never sync across machines, and deleting one never creates a conflict. See Path policy for how Bowline classifies these paths.

Running setup

One command drives project setup under the accepted workspace root.

CommandWhat it does
bowline setup [path] [--yes]Makes the project hot, runs its recipe or inferred restore, and reports the receipts. --yes approves a first-seen or changed recipe hash.

Add --json for machine-readable output. Use bowline status --root ~/Code --project <path> to inspect setup state — for example, whether node_modules is in its expected local-regenerate state and which receipt created it.

Zero-setup machines and agents

A Setup Recipe makes a project usable on a fresh machine or agent without manual work. Combined with env sync and materialize-by- default file sync, an approved recipe means a coding agent lands in a real project directory with dependencies restored and env in place, ready to run the project's commands with no manual materialization, secret grant, or config step.

Next steps

On this page