CLAUDE.md content for agentic deploys
Add this to your project's CLAUDE.md, cursor rules, or paste it when you start a new project. Your AI assistant will know how to build the app so it deploys correctly on Percher.
This app will be deployed on Percher (https://percher.app).
## Percher deployment requirements
- The app MUST expose an HTTP server on a configurable port (default 3000)
- The app MUST have a health check endpoint that returns HTTP 200, usually GET /health
- A percher.toml file must exist in the project root
- Percher uses Nixpacks to auto-detect and build — use standard project structures (package.json, requirements.txt, go.mod, etc.)
## Supported runtimes
Percher config uses runtime = "node", "bun", "python", "static", or "docker".
Use Dockerfile-based projects for Go, Rust, PHP, Ruby, Java, .NET, Elixir, and other runtimes.
## How to deploy
**Standard deploy:** `bunx percher publish` (or the percher_publish MCP tool).
Handles auth, config generation, packaging, and deploy in one call. Returns
structured errors with explanations and suggestions on failure — this is the
recommended path whether the deploy succeeds or fails. Supports `--dry-run`,
`--preview`, `-m "note"`, `--force`, `--no-cache`.
**Agentic happy path (MCP only):** the standard flow is
publish (waitForLive: false) -> wait_for_deploy -> if recovery says so: doctor -> exact action
Call `percher_publish` with `waitForLive: false`. The tool returns
within a few seconds with `status: 'queued'` and a `deployId`,
instead of blocking for the 30-90s build. Then call
`percher_wait_for_deploy` (the args come back pre-filled in
`recovery.args`) to learn whether the deploy went `live` /
`failed` / `replaced`. For ambiguous failures wait_for_deploy
points at `percher_doctor` — call it and keep following its
`recovery.nextAction` until you reach a terminal state.
**Agent recovery contract:** every Percher MCP tool that can fail
returns a `recovery` field with a machine-readable next step. The
full action set:
recovery.nextAction = "none" | "open_login" | "wait_deploy"
| "run_doctor" | "set_env_vars" | "fix_problems"
| "retry" | "fix_config" | "ask_user"
| "inspect_build_log" (advisory, hand-off only)
Rules:
1. Always read `recovery.nextAction`. Don't regex-parse the
suggestion text — that's for surfacing to the user.
2. Call EXACTLY the suggested tool with EXACTLY the suggested args
(`recovery.args`). Don't strip `mode` or `deployId` —
they're load-bearing.
3. If `recovery.nextAction` is `ask_user`, ask
`recovery.prompt` verbatim and wait.
4. `run_doctor` means call `percher_doctor` with the supplied
args; doctor is the recovery hub and will route to the right
low-level tool.
5. Repeat until `recovery.nextAction` is `none` (success) or
`ask_user` (needs the user).
**Build cache:** Percher caches built images keyed on a content hash of
percher.toml + package.json + lockfile + Dockerfile + build-time env vars +
every source file. Identical inputs produce a cache hit and skip
nixpacks/docker rebuild (typically <10s wall-clock). Every successful
publish prints either `Build cache: hit (reused image — re-run with
--no-cache if your changes aren't reflected)` or `Build cache: miss
(fresh build)` so you can tell at a glance which path ran. If your
changes don't seem to be live and the line says "hit", run
`bunx percher publish --no-cache` to force a fresh build — the new
image still gets cached, so future deploys benefit.
**Preview deploys (`--preview`):**
Deploy to a temporary URL like `my-app--p-<slug>.percher.run` without
replacing the live version. On the **free plan** there is one preview
slot per app — running `--preview` again automatically rotates the
existing preview out (no manual `percher preview discard` needed) and
the CLI prints a "replaced previous preview" note. On paid plans you
get up to `activePreviewsPerApp` parallel previews and the previous
ones are kept; once at the limit a new `--preview` returns 403 and
you discard explicitly. Either way, the live URL is untouched.
**Granular control / debugging:** `bunx percher login`, `bunx percher init`,
`bunx percher push` for stepwise execution. Use this only when you need to
isolate a single phase (e.g. validating the bundle without an upload, or
re-running a specific step). `push` errors point at `percher deploys
inspect <id>` for the full build log.
Either path hits the same server-side build pipeline; the choice is purely
about where the error surface lives.
## percher.toml
Generated by percher init. Key fields:
[app]
name = "my-app" # becomes my-app.percher.run
runtime = "node" # auto-detected
[web]
port = 3000 # the port your app listens on
health = "/health" # health check path
## Database
For apps that need a database, add to percher.toml:
[data]
mode = "pocketbase"
A managed PocketBase instance is provisioned automatically.
Use the POCKETBASE_URL env var to connect from your app.
## Environment variables
Set via: bunx percher env set KEY=VALUE
Or MCP tool: percher_env_set
Available at runtime as standard environment variables.
Apps deploy to https://<app-name>.percher.run with automatic SSL.
### [env] contract in percher.toml
[env]
required = ["OPENAI_API_KEY"] # must exist before deploy queues
optional = ["SENTRY_DSN"] # may be referenced; not required
ignore = ["NODE_ENV"] # explicitly ignored by the scanner
Source code that references env keys not in any of these lists
blocks the deploy with `recovery.nextAction = "fix_config"`. Set
required keys via `percher env set` before publishing.With this context, you can just say "build me an app that does X" and the agent will structure it correctly for Percher deployment.