Skip to main content
Percher is still being built and account creation is paused — get notified when it opens.

GitHub & CI/CD

Auto-deploy on push + PERCHER_TOKEN for GitHub Actions

Ask your agent
Make my app update itself every time I push to GitHub.Read the guide at percher.app/docs/github-cicd
Set up automatic deploys from my GitHub repo.Read the guide at percher.app/docs/github-cicd
For agents and developers

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, and full are 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).