GitHub & CI/CD
Auto-deploy on push + PERCHER_TOKEN for GitHub Actions
Three ways to deploy from GitHub: the dashboard (recommended), a server-side webhook for public repos, or PERCHER_TOKEN in GitHub Actions for full CI control.
Option A — Dashboard + GitHub App (public + private repos)
Install the Percher GitHub App from the GitHub section at percher.app/account#github. Choose exactly which repos to grant access to. Then browse your repos and click Deploy — auto-deploy on push is active immediately, no webhook configuration needed.
AI agents (Claude via MCP, Cursor, etc.) can connect repos and set up auto-deploy with one command after the one-time App install: percher github connect https://github.com/owner/repo --app myapp
A committed percher.toml is optional here — if the repo has none, Percher detects the framework at clone time and generates one for the deploy (the card shows what it detected). Commit a percher.toml to pin the config: a committed one always wins, and it's the only way to set what detection can't infer (health path, build command, database mode, password protection).
Every open PR on a connected repo gets its own preview at {app}-pr-{n}.percher.run. Percher posts a sticky comment on the PR with the preview URL — updated on every push, edited to "torn down" when the PR closes — plus a check-run in the Checks tab.
Option B — GitHub webhook auto-deploy (public repos only)
Percher clones the repo server-side and deploys on every push to the tracked branch — no GitHub Actions runners or billing minutes required.
If the app doesn't exist yet, github connect creates it from the repo. Run it from a directory with percher.toml, or pass --app <name> explicitly. The repo argument must be a full HTTPS URL.
bunx percher github connect https://github.com/owner/repo --branch main
The command clones, queues an initial deploy, generates a webhook secret, and prints setup instructions. Then in GitHub: repo Settings → Webhooks → Add webhook:
- Payload URL:
https://api.percher.run/webhooks/github - Content type:
application/json - Secret: (printed by the command — save it now, it won't be shown again)
- Which events: Just the push event
Percher verifies the HMAC-SHA256 signature and ignores pushes to other branches. Only public repos are supported for the webhook path.
If webhook setup fails during github connect, recover without re-cloning: bunx percher github setup-webhook --app <name>
Option C — GitHub Actions with PERCHER_TOKEN (public + private repos)
Get a token at percher.app/account → API token → Create, then add it as a GitHub Actions secret named PERCHER_TOKEN.
# .github/workflows/deploy.yml
name: Deploy to Percher
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bunx percher publish
env:
PERCHER_TOKEN: ${{ secrets.PERCHER_TOKEN }}Preview deploys on pull requests
name: Preview Deploy
on:
pull_request:
branches: [main]
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bunx percher publish --preview
env:
PERCHER_TOKEN: ${{ secrets.PERCHER_TOKEN }}The CLI auto-detects GITHUB_HEAD_REF / GITHUB_REF_NAME and uses the branch name as the deploy note automatically. Also works with GitLab CI (CI_COMMIT_REF_NAME), Vercel (VERCEL_GIT_COMMIT_REF), and Netlify (BRANCH).
Token auth in any shell
# Inline (CI-safe, no browser login): PERCHER_TOKEN=<token> bunx percher publish # Save permanently (dev machine): bunx percher login --token <token>
Scoped tokens — least privilege for CI
A default token has full account access — more than a pipeline needs. Mint a least-privilege one instead:
bunx percher token create ci-deploy --scope deploy --app my-app --ttl-days 90
--scope deploy— the publish loop (publish, redeploy, rollback, logs, diagnostics) but no env, domains, data, sharing, or account routes.env,read, andfullare the other scopes.--app my-app— binds the token to one app; requests against any other app are rejected.--ttl-days 90— built-in expiry. The secret is shown once at create time.
Rotate by creating the replacement first, swapping the CI secret, then percher token revoke <id> (ids via percher token list).