zap

Internal deploy tool

Ship an experiment in one command.

zap lets anyone on the team spin up and deploy experiments — static sites, small backends, databases, later realtime — with a single CLI command. No infra to think about: every project gets its own private GitHub repo, its own hosted container, its own subdomain, and its own environment variables, all provisioned automatically.

1
zap login

One-time GitHub device-flow login. No password to remember.

2
zap start

Pick a template, scaffold it locally, dependencies installed for you.

3
zap deploy

Repo created, pushed, built, and live on its own subdomain.

What you get, automatically

  • A private GitHub repo under the team org — created for you, no manual setup.
  • Your local folder linked to itgit push works immediately, no git remote add needed.
  • A live URL on *.zap.subliminal.global, HTTPS by default, excluded from search indexing.
  • Real ownership — only you (or someone you invite) can touch your project's env vars, protection, or hosting.
  • Real git history — every push builds on top of whatever's already on main, nothing gets squashed away.

Who can use it

Authorization is just GitHub org membership — no separate accounts, no password database. If you're in the org, zap login works and you can deploy. Removed from the org → your cached CLI token stops working on the very next call. See How it works for the details.

Command reference

#

zap start

zap start

Scaffolds a new project locally from a template, interactively.

  1. Pick a template (currently: vite — more get added over time in templates/).
  2. Pick a project name — checked for availability against the control-plane as you type.
  3. Files are copied into the current folder (if empty) or a new subfolder named after your project.
  4. If the template has a package.json, pnpm install runs automatically.

Doesn't touch GitHub or hosting — it's purely local. Run zap git or zap deploy next.

#

zap git requires login

zap git [name]

Creates just the GitHub repo for your project — no hosting, no build — and links your local folder to it. Use this when you want to git init, commit, and push a few times before you're ready to actually go live.

  • Name defaults to the current folder name if omitted.
  • Your local folder is left in a state where git status is already clean against origin/main — no manual git remote add.
  • Every commit you push (with git push, or later via zap deploy) builds on top of the previous one. Nothing gets squashed.
cd my-experiment
zap git
git add -A && git commit -m "wip"
git push
# ...iterate for a while, whenever you're ready:
zap deploy
#

zap deploy requires login

zap deploy [name]

Uploads the current directory, pushes it to the project's GitHub repo, and makes sure it's live. It's safe to run more than once:

  • First time for a name that doesn't exist yet → creates the repo, creates the hosted app, deploys it.
  • Project already exists (started with zap git, or deployed before) and you own it → pushes the latest files and, if it's not live yet, creates the hosted app now. If it's already live, this is effectively a redeploy.
  • Name defaults to the current folder name if omitted.

On success, prints the repo URL, the live URL, how long the deploy took, and a small lightning bolt for fun.

zap deploy               # uses the current folder name
zap deploy my-experiment # explicit name
#

zap env set requires login owner only

zap env set KEY=value

Sets an environment variable on the deployed app. Run from inside the project's folder — the project name is always taken from the current folder, there's no separate name argument.

Takes effect on the next deploy — run zap deploy (or git push, once auto-deploy on push is wired up) after setting it.

cd my-experiment
zap env set API_KEY=sk-live-...
#

zap protect requires login owner only

zap protect [name]

Puts HTTP Basic Auth in front of the project's live URL — good for sharing a work-in-progress with someone outside the team without exposing it publicly. Prompts for a password (or auto-generates one if left blank), triggers a redeploy so the change takes effect, then prints the username/password.

#

zap unprotect requires login owner only

zap unprotect [name]

Removes the Basic Auth gate added by zap protect and triggers a redeploy.

#

zap invite requires login owner only

zap invite <project> <github-username>

Adds someone as a direct GitHub collaborator (push access) on your project's repo. Only the project's owner can invite. GitHub creates a normal pending repository invitation — the invited person just needs to run zap clone to accept it and start coding.

zap invite my-experiment octocat
#

zap clone requires login

zap clone <project>

The easy path onto someone else's project after zap invite. In one command it:

  1. Looks up the project via the control-plane.
  2. Auto-accepts any pending GitHub invitation for that repo, using your own zap login token.
  3. Clones it over HTTPS (the token is passed as a transient header — it's never written to .git/config).
  4. Runs pnpm install if there's a package.json.

No manual "accept invite in the browser, then set up git auth" dance.

#

zap login

zap login

One-time GitHub device-flow login. Opens a code for you to enter at github.com/login/device, then stores your token locally (~/.zap/credentials.json). Required before any command that creates or changes a project.

#

zap doctor

zap doctor

Sanity-checks your local setup: Node version, git config, pnpm, control-plane reachability, and login status. Run this first if anything else misbehaves.

#

zap help

zap help

Lists every command with a one-line description and a link to this site. Also shown automatically when you run zap with no arguments, or an unrecognized command.

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.

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

  1. 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.
  2. 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.
  3. 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.

Installation

Coming soon. The CLI isn't published to npm yet — this tab gets filled in with real install instructions the moment @zaptool/zap (name TBD) is published. For now, ask in the team channel for the local path to run it from source.

What you'll need either way

  • Node.js 18+
  • git, with user.email configured
  • pnpm (used for installing dependencies in JS templates)
  • Membership in the team's GitHub org

Run zap doctor any time to check all of the above at once.

Planned: once published

npm install -g @zaptool/zap
zap login
zap doctor

Roadmap

Rough state of things — see ZAP_PLAN.md in the repo for the full detail behind each of these.

Shipped

  • Core CLI: start, git, deploy, env set, protect/unprotect, login, doctor, help.
  • Control-plane, shared DB service, Coolify integration, GitHub App-based repo automation.
  • Org-membership authorization, enforced server-side on every mutating call.
  • Real per-project ownership, enforced (not just a label).
  • Collaborator flow: zap invite / zap clone, one command to accept + clone + install.
  • Local-folder auto-linking (zap git, zap deploy) — no manual git remote add ever.
  • Real, non-squashed git history across zap git → manual pushes → zap deploy.

Planned

  • zap protect --team-only — gate a subdomain behind GitHub org/team login instead of a shared password.
  • Publish the CLI to npm as a global package.
  • More templates beyond vite (a framework-of-the-week folder under templates/).
  • @zaptool/zap-db client library for the shared DB service, with realtime subscriptions.

Later / optional

  • Dedicated websocket relay service for realtime beyond DB sync (multiplayer cursors, live collaboration) — only if multiple projects actually need the same pattern. Until then, any project can just run its own ws server in its own container.
  • Deploy-webhook driven screenshot capture for dashboard thumbnails.