# Setup recipes (/docs/concepts/setup-recipes)



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](/docs/concepts/path-policy).

## What a recipe looks like [#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.

```bash
# .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 [#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](/docs/concepts/agent-leases) 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.

<Callout type="warn" title="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.
</Callout>

## Inferred setup without a recipe [#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 `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 [#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 [#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 [#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](/docs/concepts/path-policy) for how Bowline
classifies these paths.

## Running setup [#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 [#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](/docs/concepts/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 [#next-steps]

* [Env sync](/docs/concepts/env-sync): how `.env` files follow your code.
* [Path policy](/docs/concepts/path-policy): control which files sync, and keep
  generated folders local.
* [Agent leases](/docs/concepts/agent-leases): scoped authority for coding agents
  working in a prepared project.
* [Working with agents](/docs/guides/working-with-agents): hand work to an agent
  in a ready-to-run project.
* [CLI commands](/docs/cli/commands): full reference for `bowline setup` and
  `bowline prewarm`.
