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 buildCommands 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 (for example with bowline setup or bowline prewarm) or
when an agent lease enters it.
Bowline runs the recipe only then. It does not run setup during cold sync, plain
bowline init, 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.
| Ecosystem | Detected lockfile |
|---|---|
| pnpm | pnpm-lock.yaml |
| npm | package-lock.json |
| Bun | bun.lock and bun.lockb |
| uv | uv.lock |
| Cargo | Cargo.lock |
| Go modules | go.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
preinstallorpostinstall, 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 or
bowline prewarm --approve-setup. 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
Two commands drive setup, and both prepare a project under the accepted workspace root.
| Command | What 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. |
bowline prewarm <project> [--approve-setup] | Hydrates the project and prepares it in one step. --approve-setup approves a pending recipe hash. |
Add --json to either command for machine-readable output. Use bowline status
and bowline explain <path> to inspect setup state. For example,
bowline explain node_modules reports local-regenerate state and the receipt
that 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 hydration, an approved recipe means an agent lease lands in a real project directory with dependencies restored and env in place, ready to run the project's commands with no manual hydrate, secret grant, or config step.
Next steps
- Env sync: how
.envfiles follow your code. - Path policy: control which files sync, and keep generated folders local.
- Agent leases: scoped authority for coding agents working in a prepared project.
- Working with agents: hand work to an agent in a ready-to-run project.
- CLI commands: full reference for
bowline setupandbowline prewarm.