How it works
Everything runs on the team's own VPS through Coolify. There's a single Coolify
Project called zap holding a handful of shared services, plus one app
resource per deployed experiment.
Your laptop
zap CLI
API calls →
Control-plane
holds GitHub App creds
+ Coolify API token
API calls →
GitHub + Coolify
repos, containers,
proxy, TLS
git push (your own GitHub identity) → Coolify webhook → rebuild
Credentials never touch your laptop
The GitHub App private key and the Coolify API token live only on the control-plane
backend, as environment variables. Your laptop only ever holds a personal GitHub
token from the one-time device-flow login (zap login) —
the same kind of token GitHub itself issues for any third-party CLI.
Authorization = GitHub org membership
No separate password system. Being allowed to use zap at all means being
an active member of the team's GitHub org. Every mutating call the CLI makes
is checked server-side with GET /user/memberships/orgs/{org},
using your own token — so it needs no special GitHub App permissions, and it fails
closed if you're not a member. Add someone to the org and the very next
zap command works; remove them and their cached token stops working on
the next call.
Ownership is enforced, not just labeled
Every project has an owner — whoever ran zap deploy or
zap git first. The control-plane resolves your identity from your login
token on every request and checks it against that owner before letting you set env
vars, protect/unprotect, or invite collaborators on a project. Only the invite flow
(zap invite) extends access to someone else,
and it does so through a real GitHub repo invitation — nothing custom-built.
What a deploy actually does
- Your files are uploaded to the control-plane and pushed to your project's GitHub repo as a new commit on top of whatever
main already points to.
- The first time, a Coolify application resource is created: its own container, its own subdomain under
*.zap.subliminal.global, TLS via Let's Encrypt, an X-Robots-Tag: noindex header injected at the proxy layer so nothing leaks into search results.
- A build is triggered and polled until it finishes (or fails).
Shared building blocks
- Shared Postgres — one instance, every project's data lives here scoped by
project_id.
- Shared DB service — a small Firebase-like client API in front of that Postgres, so projects don't need their own database.
- Templates repo — what
zap start scaffolds from; add a new starting point by adding a folder.