skills/vercel-verify/SKILL.md
--- name: vercel-verify description: After pushing to a Vercel-connected repo, verify the deploy actually succeeded — don't trust a green local gate. Resolves the project, polls the Vercel API for the deployment matching the pushed commit until READY / ERROR / CANCELED, and on failure pulls the build error log and surfaces the failing lines. Exists because a local pre-push gate can pass on a Turbo cache hit while the real Vercel build breaks (e.g. a server-only module reaching the client bundle)
npx skillsauth add RonanCodes/ronan-skills skills/vercel-verifyInstall 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.
The local pre-push gate is necessary but not sufficient on Vercel. Turbo (and other build caches) can return a cache hit so pnpm build passes locally, while the actual Vercel build fails on something the cache masked — the classic being a server-only import leaking into the client bundle, or an env var present locally but missing in Vercel. A green push is not a green deploy. This skill closes that gap: after you push, confirm the deployment for that commit reached READY, and if it didn't, show you why.
This is the backstop. The real fix for a recurring class of failure is to make it un-pushable (see "Prevention" below). Use both.
/ro:ship / /ro:cf-ship-style push when the repo deploys to Vercel.Do NOT use for Cloudflare/Fly deploys — those have their own verify paths.
cat .vercel/project.json 2>/dev/null # → { "projectId": "...", "orgId": "..." }
projectId and orgId (orgId is the teamId for API calls).vercel.json / ask for the project name, or fall back to the Vercel CLI path (step 4).--project <name> overrides.Per the env convention, check the shared env first — do not ask the user to paste a token before looking:
grep -i 'VERCEL_TOKEN' ~/.claude/.env
If absent, offer two paths: (a) add VERCEL_TOKEN=... to ~/.claude/.env, or (b) use the Vercel CLI which carries its own auth (step 4).
Target the deployment whose commit matches HEAD (or --sha), so you never read a stale older deploy:
SHA=$(git rev-parse HEAD)
TEAM="&teamId=$ORG_ID" # omit if personal scope
curl -s "https://api.vercel.com/v6/deployments?projectId=$PROJECT_ID&limit=5$TEAM" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
| jq -r '.deployments[] | "\(.uid) \(.readyState) \(.meta.githubCommitSha // "")"'
Pick the row whose commit sha matches (prefix-match is fine). Poll its readyState every --wait seconds (default 15) until it's terminal:
QUEUED / INITIALIZING / BUILDING → keep waiting.READY → success. Print the deployment URL and stop.ERROR / CANCELED → go to step 5.Give up after --timeout (default 300s) and report "still building after Ns" rather than hanging.
.vercel)vercel ls --yes | head # latest deployments + states
vercel inspect <deployment-url> --logs # build logs for a specific one
vercel inspect ... --logs is also the quickest way to read a failed build's output by hand.
curl -s "https://api.vercel.com/v2/deployments/$UID/events?builds=1&limit=1000$TEAM" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
| jq -r '.[] | select(.type=="stderr" or .type=="stdout") | .payload.text' \
| tail -60
Surface the failing lines (the error, not the whole log). Common signatures to call out:
server-only / client-only boundary violation → a server module reached the client bundle.Module not found → dependency not installed or path wrong in the real (uncached) build.Environment Variable "X" references Secret / is not defined → set it in Vercel (vercel env add).Then propose the fix and, if it's a code bug, offer to open it as an issue or fix it directly.
VERCEL-VERIFY — <project>
commit: <sha7> (matched deployment <uid7>)
state: READY ✓ | ERROR ✗ | TIMEOUT
url: https://<deployment>.vercel.app
cause: <on failure: the one-line root cause from the log>
next: <on failure: the fix / issue filed>
The verify loop catches the failure after the fact. To stop the class of failure from reaching main:
turbo run build --force) so a cache hit can't hide a break.server-only modules (e.g. eslint-plugin-boundaries, or Next's own boundary checks). That turns the most common Vercel-only break into a pre-commit lint error. This is repo-specific config; apply it in the app repo, not here.[[ship]] / [[cf-ship]] — the push side; this is the post-push verify.[[diagnose]] — when the deploy is READY but the app misbehaves at runtime.testing
--- name: linear-pipeline description: The Fable orchestrator for a single dispatched Linear ticket. Holds almost no context itself; it receives `--issue <ID> --detached`, decides the stage sequence, and fans out a sub-agent per stage, passing forward only each stage's artifact (never re-derived, never inlined into its own context). Step zero, before any planning or stage routing, is a boundary triage against `canon/security-boundary.md` (#199): a match tags Ronan Connolly and stops the run, no
development
--- name: in-your-face description: Capture a chat-only answer into a durable artifact (markdown + HTML, PDF when cheap) and launch it automatically so the user cannot miss it. Use when user says "in your face", "don't let me lose this", "save that answer", "make that durable", or right after answering a substantive side question (a recipe, comparison, how-to, or generated prompt) that would otherwise die with the context. category: workflow argument-hint: [--no-open] [--vault <short>] [hint of
tools
One-shot headless OpenAI Codex CLI calls for background/admin AI tasks — summaries, classification, extraction, admin glue. The default engine for anything that runs AI constantly in the background (daemon-driven, per-event), because it bills the flat ChatGPT subscription instead of Claude usage or per-token API spend, and it keeps working while Claude is rate-limited. NEVER for coding — coding stays Claude. Use when a skill or daemon needs a cheap always-on AI call, when the user says "use codex", "ask codex", "codex as backup", or when building a background summarizer/classifier into a listener or loop. Reads auth from ~/.codex/auth.json (ChatGPT account, no API key).
research
Turn a warranty rejection, repair quote, or RMA email into a cited decision brief — legal read (NL/EU consumer law), is the part user-serviceable, live part and new-unit prices, repair-vs-DIY-vs-new economics, before-you-send-it checklist, deadlines. Use when the user pastes or screenshots a repair quote, warranty rejection, "not covered" email, onderzoekskosten fee, or asks "should I repair or replace this".