# Prompt — Deploy a project from a cheap agent

Use this when a low-cost agent (DeepSeek, Qwen, quota-limited Claude
sessions) is asked to ship code that's already merged. Pattern: planner
agent decides what to ship → deployer agent runs the deploy script.

---

## 1 · Ask the user (only if not given)

### Q1 — What target?

```
1. cloudflare-pages   (static site / wrangler pages)
2. cloudflare-workers (wrangler deploy)
3. fly.io             (flyctl deploy)
4. npm-publish        (package release)
5. docker-image       (build + push)
6. other              — user describes
```

If the user already named it ("deploy the webapp", "ship the api"), pick
automatically: webapp → cloudflare-pages, api → fly.io, sdk → npm-publish.
Only ask if ambiguous.

### Q2 — From which branch / commit?

```
1. current branch HEAD (default — what's checked out now)
2. specific commit / tag (user provides)
3. main / master (force a fresh checkout)
```

Default: 1.

---

## 2 · Pre-flight (always)

Refuse to proceed if any of these fails. Publish `agent.task_failed`
with the reason and stop. **Do not attempt to fix issues outside the
deploy scope.**

- Working tree clean (`git status` returns no changes).
- Tests pass (look in `package.json` scripts, `Makefile`, `Cargo.toml`,
  `.github/workflows/`; run the canonical `test` command).
- Required secrets are present in `.meshkore/credentials/` and exported
  as env vars before running the deploy command.
- Deploy runbook for this target exists in `.meshkore/docs/deploy/`
  (read it before improvising commands).

---

## 3 · Execute

| Target | Command |
|---|---|
| cloudflare-pages | `npx wrangler pages deploy <build-dir> --project-name <name>` |
| cloudflare-workers | `cd <worker-dir> && npx wrangler deploy` |
| fly.io | `cd <app-dir> && flyctl deploy --remote-only` |
| npm-publish | `cd <pkg-dir> && npm publish --access public` |
| docker-image | `docker build -t <tag> . && docker push <tag>` |

Capture stdout + stderr + exit code. **Do not retry on failure** — let
the planner decide what to do.

---

## 4 · Post-deploy

If exit code 0:

1. Capture the deployed URL from stdout (regex `https?://[^\s]+`).
2. `git tag deploy/<target>/<YYYY-MM-DD-HH-MM>` and `git push --tags`.
3. Smoke test: `curl -fsS <deployed-url>/health` (or `/` if no health
   endpoint). If non-200, publish `deploy.smoke_failed`.
4. Publish `agent.task_completed` with URL + tag + smoke result.

If exit code non-zero:

1. Publish `agent.task_failed` with last 50 lines of stderr.
2. Stop. Do not roll back automatically — that's the planner's call.

---

## 5 · Things you must NEVER do

- Edit code as part of a deploy. If the deploy needs a code change,
  fail and let the planner re-route.
- Bump versions automatically. Versioning is a planner responsibility.
- Push to a different branch than `cluster.yaml.git.branch`.
- Skip tests because "we already tested locally".
- Run `git push --force` for any reason.

---

## See also

- [`/reference/prompts/project-audit.md`](https://meshkore.com/reference/prompts/project-audit.md) — pre-flight diagnostic
- [`/reference/stacks/`](https://meshkore.com/reference/stacks/) — per-target deploy patterns (when populated)
