Skip to main content

/deploy

Best used: when a project is ready to go live and you want it shipped the way that project already ships — or, if it has never been deployed, when you want deployment tooling chosen and wired up properly instead of a one-off shell script. See Skills overview.

/deploy detects before it builds. If the repo has a deploy path — a CI workflow, a platform CLI config, Deployer/Capistrano/Kamal, or just a production git remote — it runs that. Only when nothing is detected does it ask where the project should live and set the tooling up.

Why use it

Without /deployWith /deploy
Every project's deploy lives in someone's shell historyThe repo's own mechanism is detected and run
Agents improvise rsync -a . server:/var/wwwDeployer-class releases: atomic symlink swap, keep N, rollback
"It deployed" = exit code 0Deploy is verified (URL/status/release SHA) or reported failed
Deploy scripts appear next to the ones that already existDetect-first; never scaffolds over working tooling
Secrets get pasted into configSecrets referenced by name only; never printed, never committed

Usage

InvocationBehavior
/deployDetect → plan → confirm → deploy the default environment
/deploy <env>staging, production, preview, …
/deploy --dry-runExact commands + target; no outward action
/deploy --statusConfigured tooling, remotes/targets, last deploy — read-only
/deploy --setupInterview + install tooling; never deploys in the same run
/deploy --target <name>Setup hint: GitHub Pages, Vercel, DigitalOcean, GoDaddy, Fly, S3, SSH, …
/deploy --rollbackPrevious release via the tool's native rollback
/deploy --yesSkip the confirm (target line still printed)
/deploy --allow-dirtyShip an uncommitted tree (risk line printed)
/deploy --no-prepSkip the /commit-prep suggestion

Pipeline

resolve project → tree + branch gate → unreleased-work gap check → detect tooling
→ (none detected: interview → setup → stop)
→ resolve target/env → plan commands
→ confirm (or --dry-run / --yes)
→ deploy → verify → footer

Before detecting tooling, /deploy looks for finished work the deploy would exclude, at both stages of the pipeline: an integration branch (dev, else develop) with commits not yet promoted to the branch this deploy publishes from, and features finished but never reviewed — plans still in .plans/review-needed/ or feature/* branches with commits the deploy branch doesn't have. If it finds any, it lists them and asks whether to run /review first, deploy the current branch as-is, or cancel — under --yes it defaults to deploying as-is. /deploy never merges or promotes branches itself; landing work stays /review's job.

Detection bands

First match wins, top down:

BandMarkersDeploy with
A — project entrypointmake deploy, just deploy, npm run deploy, scripts/deploy*That command (it usually wraps the rest)
B — CI/CD.github/workflows/*deploy*, .gitlab-ci.yml deploy stage, Jenkins/CircleCIgit push is the deploy (or gh workflow run), then watch the run
C — platform CLIvercel.json, netlify.toml, fly.toml, .do/app.yaml, wrangler.toml, serverless.yml, Procfilevercel / netlify / flyctl / doctl / wrangler / serverless / git push heroku
D — release frameworkdeploy.php (Deployer), Capfile, config/deploy.yml + .kamal/, fabfile.py, ansible/, .goreleaser.yml, helm/, k8s/dep deploy / cap deploy / kamal deploy / fab / ansible-playbook / …
E — package publishpyproject.toml, library package.json, Cargo.tomltwine / npm publish / cargo publish — always confirmed (irreversible)
F — plain remoteremote named production / deploy / dokkugit push <remote> <branch>

Terraform is treated as infra, not app deploy: only on an explicit ask, plan before apply, never destroy.

When nothing is detected

/deploy asks three questions — where (GitHub Pages · Vercel · Netlify · Cloudflare · DigitalOcean · Fly · AWS · GoDaddy/shared hosting · VPS over SSH · a package registry), who runs it (CI or a human), and which environments — then picks by stack:

StackFramework of choice
PHPDeployer (deploy.php)
RubyCapistrano, or Kamal if containerized
Node (server)Kamal, or Shipit / PM2 deploy
Node/static front-endVercel · Netlify · Cloudflare Pages · GitHub Pages Action
Python (app)Fabric or Ansible; Kamal if containerized
Python (package)twine / poetry publish in a release workflow
Go / Rust binarygoreleaser, or Kamal / rsync+systemd for services
Any containerized appKamal

Deployer's model is the bar for every SSH-style target, in any language: timestamped releases/ directories, shared storage/uploads/.env symlinked across releases, an atomic current symlink flip, keep N old releases, and a one-command rollback. Where no such framework exists for the stack, /deploy reproduces that shape rather than rsyncing over a live directory.

Setup writes config, a CI workflow when CI deploys, a deploy task-runner entry, docs for the required secret names, and then runs the tool's dry-run and stops. Deploying takes a second, deliberate /deploy.

Safety

  • Dirty tree refused by default — deploy committed, reproducible state
  • Target (host / URL / env / branch / SHA) printed and confirmed before the first remote command; production prints a risk line even under --yes
  • Never commits, merges, promotes branches, or force-pushes — landing work is /review
  • No terraform destroy, no dropping databases, no deleting remote resources, no --force deploy flags
  • Secrets referenced by name; never printed, never committed
  • Verified after the fact — a failed health check is a failed deploy, with rollback offered

Scaffolded?

Yes — dual-use Claude command + Grok skill (scripts/anchor.py platform lists).

Full contract: source .claude/commands/deploy.md / .grok/skills/deploy/SKILL.md.