anolilab/lunora/lunora-deploy
Claude Code and agent skill by anolilab/lunora
- community
Checking that the SKILL.md file is still in the repository.
Deploys a Lunora app to Cloudflare Workers + Durable Objects and gets wrangler.jsonc, remote resources and secrets to line up. Covers `lunora deploy` (and `--env`, `--dry-run`, `--migrate`), isolated per-PR previews (`lunora preview deploy | list | delete`), the `lunora doctor` / `lunora verify` / `lunora prepare` preflights, Durable Object bindings (SHARD, SHARD_REGISTRY, SCHEDULER), the `DB` D1 binding and its placeholder id, R2 buckets, production secrets (`lunora env push`, `wrangler secret put`) versus `.dev.vars`, the schema-drift gate, the architecture diff, and rollback with `lunora cloudflare deployments`. Use when the user asks to "deploy", "ship to production", "set up a staging environment", wire CI deploys, or when a deploy fails on a binding, a placeholder `database_id`, an unexported Durable Object class, a missing secret, or "schema drift gate blocked deploy".
Install
npx vskill@latest install anolilab/lunora/lunora-deploySKILL.md
Lunora Deploy
Deploying a Lunora app means making wrangler.jsonc, the remote Cloudflare resources (D1, R2, secrets) and the worker's exports agree. lunora deploy automates most of that and refuses to ship when they don't.
Local development is lunora dev (see lunora-quickstart). If the deploy is blocked by a breaking schema change, stage it with lunora-migration-helper first.
What lunora deploy does
In order, stopping at the first failure:
- Codegen — regenerates
lunora/_generated/. ERROR-level codegen
advisories fail the deploy in CI (--strict-advisories forces this locally, --no-strict-advisories turns it off). Nothing here runs tsc and wrangler strips types, so a project with a type error deploys — gate CI on lunora verify, which does type-check.
- Schema-drift gate — compares the schema with the committed baseline
lunora/.lunora-schema.json (details below).
- Architecture diff — prints modules and edges (calls, table reads/writes,
enqueues) added or removed since the last successful deploy. Informational only; the manifest is recorded in .lunora/architecture[.<env>].json after wrangler succeeds.
- Binding reconcile — writes the bindings the code implies into
wrangler.jsonc: Durable Object bindings plus their new_sqlite_classes migration, the DB D1 binding for .global() tables, crons, and the compatibility date. R2 buckets are not auto-written (the bucket name is yours to choose); you get a warning instead.
- Read-only checks — blocks on a D1
database_idstill set to
<replace-with-d1-create-id>, on a loopback URL (localhost, 127.x, ::1) in vars, on a missing container Dockerfile, or on no Docker engine when a container builds locally.
- Validate `wrangler.jsonc` — the
SHARDbinding toShardDO(or
LunoraDO for apps that merge their DOs), a minimum compatibility_date, DO classes registered in migrations, and the shape of every binding. compatibility_flags are not checked; templates ship nodejs_compat for dependencies that import node: builtins.
- Secrets gate — lists the secrets the app's packages need and checks
which are set on the worker. Interactive runs offer to mint and push the generatable ones (BETTER_AUTH_SECRET, LUNORA_ADMIN_TOKEN, …). In CI a missing required secret aborts the deploy. Skipped for --dry-run, for lunora preview (it uploads its own secrets), and when the worker doesn't exist yet.
- Services, then `wrangler deploy` — services declared in
lunora.config deploy first (--skip-services to skip), then the app.
- After a successful deploy — records the URL as the project link
(lunora link), optionally runs --migrate and --health-check, and only then re-blesses the schema baseline.
lunora prepare runs steps 1–6 without deploying (useful in CI), but it takes no --env, so it validates the top-level config only. lunora verify runs validation, a codegen dry run and tsc --noEmit without writing files, and does take --env.
Flags worth knowing:
| Flag | Effect | |
|---|---|---|
--env <name> | Deploy a wrangler environment; checks read that env's (non-inherited) bindings. | |
--dry-run | Run every gate and bundle without publishing; wrangler.jsonc edits roll back. | |
--health-check | Probe /_lunora/health/ready on the new version; fail if it never answers. | |
--prebuilt | Skip codegen and the drift gate when lunora prepare already ran in this job. | |
--migrate | Run every declared data migration (up is idempotent) against the live worker. | |
--allow-schema-drift | Deploy despite blocked drift; checks nothing, the baseline is not advanced. |
--migrate is checked before wrangler runs, so a missing requirement aborts the whole deploy:
--migrate-yes— confirms running production data migrations.--migrate-url <https://…>— required unless this checkout is linked for the
same --env (a previous successful deploy links it automatically).
- An admin token —
--migrate-tokenorLUNORA_ADMIN_TOKEN.
Per-PR previews
lunora deploy --preview is refused: a Worker version shares production's Durable Objects, D1 and R2, and gets no preview URL. Use lunora preview:
- Records are keyed by
lunora.appIdinpackage.json(the first local
lunora preview deploy writes it; commit it, CI cannot mint one), so a Worker rename does not lose a preview. Old Worker-name keys are re-keyed on the next deploy/delete.
--env <name>plans from that Wrangler environment (top level plusenv.<name>)
for an app whose bindings live only there; recorded, so delete needs no flag for the resources. If that environment names a different account_id, pass the same --env to list/delete (or set CLOUDFLARE_ACCOUNT_ID); they refuse rather than guess. Without it, env-only bindings are refused. CI leaves it unset.
- Resources are named
<worker>-preview-<name>-<binding>and recorded in the
account's lunora-preview-registry KV namespace; delete only removes what a record lists, and refuses anything production's config names.
- Mintable secrets are minted per deploy, or derived from
LUNORA_PREVIEW_SECRET_SEED when set (stable across deploys); a provider key reaches the preview only via --secret KEY (value from the environment).
- Production
varsare copied; override one with--var KEY=VALUE(e.g. an
auth base URL pointing at the preview's workers.dev URL).
- Refused (with the list) when the app binds Hyperdrive, services, queues,
workflows, Vectorize or another binding a preview cannot isolate yet.
- Token needs Workers Scripts, D1, Workers KV Storage and Workers R2 Storage:
Edit. Cloudflare only; celld and Node refuse.
lunora init --ci github|gitlabscaffolds the deploy-on-PR and
delete-on-close jobs.
Preflight
lunora doctor fails on a missing or invalid wrangler.jsonc, a missing SHARD binding, a placeholder D1 id (d1-placeholder-id), and a binding whose class the worker doesn't export (wrangler-class-unexported), and an Artifacts namespace in the wrong jurisdiction. It warns on unfilled .dev.vars secrets, placeholder send_email destinations, an account near its Durable Object class cap, and a cloudflare.config.ts (cf-config-present).
wrangler.jsonc
Templates ship this shape. The d1_databases and r2_buckets entries are only needed when the app uses .global() tables or auth (D1) and storage (R2):
Reconcile adds SCHEDULER → SchedulerDO when the app schedules work, and bindings for generated containers, workflows and agents. Every class_name must be exported by the worker entry or wrangler rejects the deploy.
Lunora writes the bindings but cannot create the remote resources:
When using --env, remember that vars, d1_databases, durable_objects and containers do not inherit in wrangler. Each environment needs its own entries, including its own D1 database.
Secrets
.dev.vars is for development only: it is git-ignored and wrangler deploy never uploads it. Production secrets live in Cloudflare:
lunora env push uploads the values from .dev.vars. If production needs different values than dev (it usually does for provider keys), set those with wrangler secret put instead.
Schema-drift gate
The gate blocks when the schema changed in a breaking way since lunora/.lunora-schema.json and no new defineMigration on the affected table covers it. The block message lists each change and a paste-ready lunora migrate create … --table … command. Commit the baseline file so CI and every machine gate against the same shape. It is advanced only after a successful deploy, so a failed deploy never moves it past a change that didn't ship.
When the stored rows already fit a tightening, lunora deploy notices on its own: it reads the affected tables from the deployed worker (--migrate-url or the project link, plus LUNORA_ADMIN_TOKEN) and lets the change through, naming any row that does not fit otherwise. A new unique index is checked the same way, for repeated values. --allow-schema-drift skips the gate for one run without checking. Otherwise stage the change with lunora-migration-helper.
.global() table DDL
The runtime provisions .global() tables itself on first use (CREATE TABLE IF NOT EXISTS plus additive ADD COLUMN / indexes), so additive changes need no step. lunora migrate generate writes a reviewable SQL file for D1-backed global tables, but no command applies it, lunora deploy included. Destructive or hand-written statements in it (drops, a backfilling UPDATE, a rename) must be applied by hand:
See lunora-migration-helper for the full flow.
Rollback
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingpackages/cli/skills/lunora-deploy/SKILL.md
Popularity
- 7-day trend score
- 5
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/anolilab/lunora/lunora-deploy)