skills/cf-ship/SKILL.md
--- name: cf-ship description: Ship a TanStack Start / Cloudflare Workers app with pre-flight checks (typecheck + lint + test + D1 migrations + build + deploy). Use when user wants to deploy, ship, release, push, or go live with a Cloudflare Workers app. Handles secrets, D1 migrations, and a post-deploy smoke check. category: deployment argument-hint: [--skip-tests] [--skip-migrations] [--env <name>] allowed-tools: Bash(pnpm *) Bash(wrangler *) Bash(curl *) Bash(git *) Read Edit --- # CF Ship
npx skillsauth add RonanCodes/ronan-skills skills/cf-shipInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Deploy a Cloudflare Workers app (TanStack Start on Path C) with a pre-flight gate. Prevents shipping broken code.
/ro:cf-ship # full pipeline
/ro:cf-ship --skip-tests # skip pnpm test (hotfix mode)
/ro:cf-ship --skip-migrations # skip D1 migrations (schema unchanged)
/ro:cf-ship --env staging # deploy to a non-default wrangler env
wrangler authed. Three options in priority order:
~/.claude/.env has CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID from /ro:cloudflare-setup (the default for this user). Source pattern:
set -a && source "$(ro context env)" && set +a
unset GH_TOKEN GITHUB_TOKEN # ~/.claude/.env shadows gh CLI keychain — must unset before any gh call
Always grep this file BEFORE asking the user to paste a token or run wrangler login — for already-onboarded providers, the value is there.wrangler login (browser OAuth) — fine for one-off interactive runs${CLAUDE_PLUGIN_DATA}/.env (legacy, prefer ~/.claude/.env)wrangler.toml in repo root with a valid main or TanStack Start preset configuredRun in parallel:
git status --short
wrangler whoami
git rev-parse HEAD
If uncommitted changes exist, warn the user — offer to proceed anyway or abort. Print the current commit SHA and branch so there's a paper trail of what's shipping.
Run in this order. Stop on first failure — do not try to "fix forward" without asking.
pnpm typecheck # tsc --noEmit, strict mode
pnpm lint # eslint .
pnpm format:check # prettier --check .
pnpm test # vitest run (skip if --skip-tests)
If any fails, surface the output and stop. Suggest /ro:commit after the fix.
Unless --skip-migrations:
pnpm drizzle-kit generate # generate any pending migrations
wrangler d1 migrations list <db-name> --remote # show what's pending remotely
Read the db name from wrangler.toml ([[d1_databases]] database_name). Show the user the list. If migrations are pending, confirm before applying:
wrangler d1 migrations apply <db-name> --remote
Apply local too (keeps dev DB matching):
wrangler d1 migrations apply <db-name> --local
List current secrets and compare against .dev.vars:
wrangler secret list
grep -E '^[A-Z_]+=' .dev.vars 2>/dev/null | cut -d= -f1
If .dev.vars has a key that's NOT in wrangler secret list, warn the user and offer to push it:
wrangler secret put KEY_NAME # prompts for value
Never auto-push secrets without confirmation.
pnpm build
wrangler deploy # add --env <name> if --env passed
Capture the deployed URL from wrangler's output (https://<worker>.<account>.workers.dev or custom domain).
curl -sfI <deployed-url> | head -1 # expect HTTP/2 200 or 301
If it returns non-2xx/3xx, surface it immediately. Offer to tail logs:
wrangler tail
Once the smoke check passes: if docs/infrastructure/ does not exist (this is the first successful deploy), OR this deploy changed bindings/resources, run /ro:infra-docs to generate (or refresh) living architecture documentation — the live resource inventory, C4 + sequence diagrams, security model, and provisioning runbook. Standing up a new app should always leave it documented. The skill is idempotent, so a periodic re-run after notable deploys keeps it honest.
Offer to tag the release (optional):
git tag -a "deploy-$(date +%Y%m%d-%H%M%S)" -m "🚀 deploy: $(git log -1 --pretty=%s)"
Report to user: commit SHA, deployed URL, migrations applied, secrets status, smoke-check result, and whether infra docs were generated/refreshed.
typecheck fails — stop. Fix types, commit via /ro:commit, re-run /ro:cf-ship.test fails — stop. Don't use --skip-tests as a habit; treat red tests as the signal they are.drizzle-kit generate with a clean working DB first.wrangler deploy fails on compatibility_date — bump to today's date in wrangler.toml.wrangler tail immediately; usually a missing secret or bad D1 binding.--skip-tests + --skip-migrations together without explicit user confirmation--env production) without showing current vs new commit firstwrangler delete / wrangler d1 delete are NOT part of this skill — refuse if asked/ro:commit — emoji commits (use before shipping)/ro:new-tanstack-app — scaffold that this skill ships/ro:cloudflare-dns — add a custom domain after first deploydevelopment
--- name: worktree description: Coordinate multiple agents on one repo via a worktree-lock pool, so two agents never clobber each other's working tree. Acquire the first free slot (main, then beta/gamma… worktrees, created on demand), work there on your own branch, release when you've pushed. Use before modifying any repo that might be in use by another agent (factory, dataforce, etc.), or whenever you're told a repo is being worked on. Backed by `ro worktree`. category: development argument-hin
testing
--- name: ship description: Ship a feature branch the local-CI-first way — run the full local gate, push, open a PR, squash-merge, then deploy, without waiting on GitHub Actions. Use when a branch is ready for main and you want it merged and deployed now. Reads CI policy from `ro ci` (default skips remote CI because GitHub Actions billing keeps hitting limits). Sibling to /ro:gh-ship (waits on GitHub checks) and /ro:cf-ship (the deploy half). Triggers on "ship it", "ship this", "merge and deploy
testing
--- name: setup-logging description: Set up (or audit) the observability stack in a TanStack Start + Cloudflare Workers app so it is "diagnosable by default" — structured logging (logtape) with a request context carrying trace_id + userId + tenant/orgId, a trace_id propagated FE→BE→logs→Sentry→PostHog, Cloudflare Workers observability enabled, and Sentry + PostHog wired. Two modes: `setup` (wire it into an app) and `audit` (check an existing app + report gaps). Use when scaffolding a new app, wh
development
Manage credentials INSIDE the active ~/.claude/.env file — read which token/account to use for a given app (Simplicity vs Dataforce vs Ronan-personal), add or update a secret WITHOUT it passing through the chat (an interactive Terminal window prompts for it), and track secrets that were exposed in a transcript so they get rotated. Sibling to /ro:context (which switches WHICH env file is active). Use when the user wants to add an API key/token/secret, asks "which credential do I use for X", needs the env organized/labelled, or a secret was pasted into the chat and should be rotated.