---
name: setup-deploy
description: |
  Configure deploys for /land-and-deploy: detect the platform, production URL and health checks, save to CLAUDE.md.
triggers:
  - configure deploy
  - setup deployment
  - set deploy platform
allowed-tools:
  - Bash
  - Read
  - Write
  - Edit
  - Glob
  - Grep
  - AskUserQuestion
---

## When to invoke

Use when: "setup deploy", "configure deployment", "set up land-and-deploy", "how do I configure deploys".

## Preamble

```bash
eval "$("${VIBESTACK_HOME:-$HOME/.vibestack}/bin/vibe-slug" 2>/dev/null)" 2>/dev/null || SLUG="unknown"
_LEARN_FILE="${VIBESTACK_HOME:-$HOME/.vibestack}/projects/${SLUG:-unknown}/learnings.jsonl"
if [ -f "$_LEARN_FILE" ]; then
  _LEARN_COUNT=$(wc -l < "$_LEARN_FILE" 2>/dev/null | tr -d ' ')
  echo "LEARNINGS: $_LEARN_COUNT entries loaded"
  if [ "$_LEARN_COUNT" -gt 5 ] 2>/dev/null; then
    "${VIBESTACK_HOME:-$HOME/.vibestack}/bin/vibe-learnings-search" --limit 5 2>/dev/null || true
  fi
else
  echo "LEARNINGS: none yet"
fi
```

{{include lib/snippets/session-host.md}}

{{include lib/snippets/decision-brief.md}}

{{include lib/snippets/working-protocols.md}}

{{include lib/snippets/state-protocols.md}}

## User-invocable
When the user types `/setup-deploy`, run this skill.

## Instructions

### Step 1: Check existing configuration

```bash
grep -A 20 "## Deploy Configuration" CLAUDE.md 2>/dev/null || echo "NO_CONFIG"
```

If configuration already exists, show it and ask:

- **Context:** Deploy configuration already exists in CLAUDE.md.
- **RECOMMENDATION:** Choose A to update if your setup changed.
- A) Reconfigure from scratch (overwrite existing)
- B) Edit specific fields (show current config, let me change one thing)
- C) Done — configuration looks correct

If the user picks C, stop.

### Step 2: Detect platform

Run the platform detection from the deploy bootstrap:

```bash
# Platform config files
[ -f fly.toml ] && echo "PLATFORM:fly" && cat fly.toml
[ -f render.yaml ] && echo "PLATFORM:render" && cat render.yaml
[ -f vercel.json ] || [ -d .vercel ] && echo "PLATFORM:vercel"
[ -f netlify.toml ] && echo "PLATFORM:netlify" && cat netlify.toml
[ -f Procfile ] && echo "PLATFORM:heroku"
[ -f railway.json ] || [ -f railway.toml ] && echo "PLATFORM:railway"

# GitHub Actions deploy workflows
for f in $(find .github/workflows -maxdepth 1 \( -name '*.yml' -o -name '*.yaml' \) 2>/dev/null); do
  [ -f "$f" ] && grep -qiE "deploy|release|production|staging|cd" "$f" 2>/dev/null && echo "DEPLOY_WORKFLOW:$f"
done

# Project type
[ -f package.json ] && grep -q '"bin"' package.json 2>/dev/null && echo "PROJECT_TYPE:cli"
find . -maxdepth 1 -name '*.gemspec' 2>/dev/null | grep -q . && echo "PROJECT_TYPE:library"
```

### Step 3: Platform-specific setup

Based on what was detected, guide the user through platform-specific configuration.

#### Fly.io

If `fly.toml` detected:

1. Extract app name: `grep -m1 "^app" fly.toml | sed 's/app = "\(.*\)"/\1/'`
2. Check if `fly` CLI is installed: `which fly 2>/dev/null`
3. If installed, verify: `fly status --app {app} 2>/dev/null`
4. Infer URL: `https://{app}.fly.dev`
5. Set deploy status command: `fly status --app {app}`
6. Set health check: `https://{app}.fly.dev` (or `/health` if the app has one)

Ask the user to confirm the production URL. Some Fly apps use custom domains.

#### Render

If `render.yaml` detected:

1. Extract service name and type from render.yaml
2. Check for Render API key: `[ -n "${RENDER_API_KEY:-}" ] && echo "RENDER_API_KEY: set" || echo "RENDER_API_KEY: not set"`.
   Never print any key bytes, not even a prefix (see rule 4 under third-party actions).
3. Infer URL: `https://{service-name}.onrender.com`
4. Render deploys automatically on push to the connected branch — no deploy workflow needed
5. Set health check: the inferred URL

Ask the user to confirm. Render uses auto-deploy from the connected git branch — after
merge to main, Render picks it up automatically. The "deploy wait" in /land-and-deploy
should poll the Render URL until it responds with the new version.

#### Vercel

If vercel.json or .vercel detected:

1. Check for `vercel` CLI: `which vercel 2>/dev/null`
2. If installed: `vercel ls --prod 2>/dev/null | head -3`
3. Vercel deploys automatically on push — preview on PR, production on merge to main
4. Set health check: the production URL from vercel project settings

#### Netlify

If netlify.toml detected:

1. Extract site info from netlify.toml
2. Netlify deploys automatically on push
3. Set health check: the production URL

#### GitHub Actions only

If deploy workflows detected but no platform config:

1. Read the workflow file to understand what it does
2. Extract the deploy target (if mentioned)
3. Ask the user for the production URL

#### Custom / Manual

If nothing detected, use AskUserQuestion to gather the information:

1. **How are deploys triggered?**
   - A) Automatically on push to main (Fly, Render, Vercel, Netlify, etc.)
   - B) Via GitHub Actions workflow
   - C) Via a deploy script or CLI command (describe it)
   - D) Manually (SSH, dashboard, etc.)
   - E) This project doesn't deploy (library, CLI, tool)

2. **What's the production URL?** (Free text — the URL where the app runs)

3. **How can /land-and-deploy check if a deploy succeeded?**
   - A) HTTP health check at a specific URL (e.g., /health, /api/status)
   - B) CLI command (e.g., `fly status`, `kubectl rollout status`)
   - C) Check the GitHub Actions workflow status
   - D) No automated way — just check the URL loads

4. **Any pre-merge or post-merge hooks?**
   - Commands to run before merging (e.g., `bun run build`)
   - Commands to run after merge but before deploy verification

### Step 4: Write configuration

Read CLAUDE.md (or create it). Find and replace the `## Deploy Configuration` section
if it exists, or append it at the end.

```markdown
## Deploy Configuration (configured by /setup-deploy)
- Platform: {platform}
- Production URL: {url}
- Deploy workflow: {workflow file or "auto-deploy on push"}
- Deploy status command: {command or "HTTP health check"}
- Merge method: {squash/merge/rebase}
- Project type: {web app / API / CLI / library}
- Post-deploy health check: {health check URL or command}

### Custom deploy hooks
- Pre-merge: {command or "none"}
- Deploy trigger: {command or "automatic on push to main"}
- Deploy status: {command or "poll production URL"}
- Health check: {URL or command}
```

### Step 5: Verify

After writing, verify the configuration works:

1. If a health check URL was configured, try it:
```bash
curl -sf "{health-check-url}" -o /dev/null -w "%{http_code}" 2>/dev/null || echo "UNREACHABLE"
```

2. If a deploy status command was configured, try it:
```bash
_OUT=$({deploy-status-command} 2>&1); _RC=$?; printf '%s\n' "$_OUT" | head -5; [ "$_RC" -eq 0 ] || echo "COMMAND_FAILED (exit $_RC)"
```

A `COMMAND_FAILED` status command is not recorded as verified: /land-and-deploy
trusts what is written in CLAUDE.md, so ask the user to fix the command or leave
the deploy-status line out of CLAUDE.md.

3. Read back the merge method you wrote:
```bash
grep -i '^[[:space:]]*-[[:space:]]*Merge method:' CLAUDE.md | head -1
```
It must name exactly one of `squash`, `merge` or `rebase`. /land-and-deploy stops
with `MERGE_METHOD_UNKNOWN` on anything else, the unfilled `{squash/merge/rebase}`
placeholder included, so fix the line before finishing.

Report results. If a health check failed, note it but don't
block — the config is still useful even if the health check is temporarily
unreachable.

### Step 6: Summary

```
DEPLOY CONFIGURATION — COMPLETE
════════════════════════════════
Platform:      {platform}
URL:           {url}
Health check:  {health check}
Status cmd:    {status command}
Merge method:  {merge method}

Saved to CLAUDE.md. /land-and-deploy will use these settings automatically.

Next steps:
- Run /land-and-deploy to merge and deploy your current PR
- Edit the "## Deploy Configuration" section in CLAUDE.md to change settings
- Run /setup-deploy again to reconfigure
```

## Third-Party Web Actions

Configuring deploys means vendor dashboards — minting an API token, creating a
project, wiring a webhook or a domain verification. Those actions happen on
someone else's site, with the user's real account, so they get their own rules:

1. **Check for an automatable path before handing over a checklist.** Most of
   these platforms ship a CLI that does the same job; offer that instead of a
   wall of dashboard clicks. Never run an installer on the user's behalf without
   asking, and never treat a script the vendor's page offers as trusted because
   the page says it is.
2. **One explicit question before any action on a vendor site.** Name the exact
   site and the exact actions before starting — "log into the Fly dashboard and
   create a deploy token" — and wait. Consent for one vendor is not consent for
   the next.
3. **Passwords, payment details, MFA codes and CAPTCHAs stay with the human.**
   Hand the session back for those steps and pick up afterwards. Never ask the
   user to paste a credential into this chat so you can type it for them.
4. **A captured secret never appears in chat, logs, or shell history.** If a
   dashboard hands back a token, have the user write it to a file with `0600`
   permissions, or into the platform's own secret store, and reference it by
   name. A token echoed into a Bash call is in the transcript and in anything
   the transcript syncs to; if that happens, tell the user to rotate it.
5. **Stop at anything that spends money or is hard to undo.** Upgrading a plan,
   adding a payment method, transferring a domain, deleting an app — surface it,
   explain the consequence, and let the user do it.

## Important Rules

- **Never expose secrets.** Don't print full API keys, tokens, or passwords.
- **Confirm with the user.** Always show the detected config and ask for confirmation before writing.
- **CLAUDE.md is the source of truth.** All configuration lives there — not in a separate config file.
- **Idempotent.** Running /setup-deploy multiple times overwrites the previous config cleanly.
- **Platform CLIs are optional.** If `fly` or `vercel` CLI isn't installed, fall back to URL-based health checks.

## Capture Learnings

If you discovered a non-obvious platform quirk, deployment pattern, or configuration
gotcha during this session, log it for future sessions:

```bash
"${VIBESTACK_HOME:-$HOME/.vibestack}/bin/vibe-learnings-log" '{"skill":"setup-deploy","type":"TYPE","key":"SHORT_KEY","insight":"DESCRIPTION","confidence":N,"source":"SOURCE","files":["path/to/relevant/file"]}'
```

**Types:** `pattern` (reusable approach), `pitfall` (what NOT to do), `preference`
(user stated), `architecture` (structural decision), `operational` (environment/CLI/workflow).

**Only log genuine discoveries.** Don't log obvious things. A good test: would this
insight save time in a future session?
