.bohr/deploy.json
.bohr/deploy.json tells bohr how to build and deploy your production site. The agent writes it when it prepares the repository and keeps it working; you can edit it too. bohr generates the deploy workflow from it, and the CLI runs its install and build before deploying.
{ "directory": ".", "node": "24", "packageManager": "npm", "install": "npm ci", "build": "npm run build"}Fields
Section titled “Fields”| Field | Default | Description |
|---|---|---|
directory |
"." |
Folder with the project’s package.json and wrangler config, relative to the repository root. "." or a relative path like "apps/web": no .., no folders starting with a dot. |
node |
"24" |
Node.js major version for the build, two digits ("22", "24"). |
packageManager |
"npm" |
npm, pnpm, yarn or bun. pnpm and yarn come from Corepack; bun is set up with oven-sh/setup-bun. |
python |
— | Python version when the build needs it (Python Workers), like "3.12". |
install |
— | Installs dependencies, e.g. "npm ci". Omit to skip. |
build |
— | Builds production, e.g. "npm run build". Omit to skip. |
deploy |
"npx wrangler deploy" |
Deploys the build to your Cloudflare account. Keep the default unless the framework needs its own command (for example "npx opennextjs-cloudflare deploy"): password protection only applies with the default. |
secrets |
[] |
Names of GitHub repository secrets the install and build steps need, e.g. ["SENTRY_AUTH_TOKEN"]. Up to 50. |
Rules for commands
Section titled “Rules for commands”install, build and deploy are single shell lines of up to 500 characters, without line breaks and without GitHub expressions (${{ … }}). Chain commands with &&.
Rules for secrets
Section titled “Rules for secrets”Names use A-Z, 0-9 and _. Names starting with GITHUB_ (reserved by GitHub) or CLOUDFLARE_ (the Cloudflare credentials only go to the deploy step, which bohr writes) are refused.
You rarely need secrets: prefer build variables, which you set in the bohr panel and which reach install and build without touching your repository’s settings. Use secrets for values you already keep as GitHub Actions secrets.
When it is invalid
Section titled “When it is invalid”If the file has a problem, the deploy workflow is not updated and the chat says: “The file .bohr/deploy.json has a problem (…), so the production deploy was not updated. Ask me to fix it.” The CLI stops with .bohr/deploy.json is invalid: … (exit code 2).
Examples
Section titled “Examples”A static site built with Vite:
{ "install": "npm ci", "build": "npm run build" }A pnpm monorepo app:
{ "directory": "apps/web", "packageManager": "pnpm", "install": "pnpm install --frozen-lockfile", "build": "pnpm build"}Next.js with OpenNext:
{ "node": "22", "install": "npm ci", "build": "npx opennextjs-cloudflare build", "deploy": "npx opennextjs-cloudflare deploy"}