void 0.21.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/{auth-cmd-MkBG2u1f.mjs → auth-cmd-g_ymMkUe.mjs} +2 -2
  2. package/dist/{auth-link-Devmv96E.mjs → auth-link-DFvxIyZi.mjs} +2 -2
  3. package/dist/{build-cmd-DsBGwtfs.mjs → build-cmd-wJAv808h.mjs} +1 -1
  4. package/dist/{cache-BMw8eMyF.mjs → cache-Be0Fu5Ka.mjs} +1 -1
  5. package/dist/{cancel-deploy-B3_s9NIN.mjs → cancel-deploy-BgmyOwhe.mjs} +1 -1
  6. package/dist/cli/cf-compat.mjs +13 -3
  7. package/dist/cli/cli.mjs +35 -35
  8. package/dist/{connect-BvC9kolB.mjs → connect-LnvW4HKx.mjs} +2 -2
  9. package/dist/{create-project-C9lQhRzj.mjs → create-project-BZBl_gQ0.mjs} +1 -1
  10. package/dist/{create-project-CI-17RVJ.mjs → create-project-JV9-6ICF.mjs} +1 -1
  11. package/dist/{db-R7IQgOv5.mjs → db-Mzv88E1C.mjs} +3 -3
  12. package/dist/{delete-CghI_NXn.mjs → delete-Ri6JemSU.mjs} +1 -1
  13. package/dist/{deploy-CYPymbtG.mjs → deploy-DAH2-m_-.mjs} +1 -1
  14. package/dist/{deploy-H968Lo4T.mjs → deploy-DEsMVrCY.mjs} +83 -46
  15. package/dist/{domain-CITt8lC-.mjs → domain-BA37Ye7T.mjs} +1 -1
  16. package/dist/{email-_8VmyX7V.mjs → email-C5NsxrQG.mjs} +2 -2
  17. package/dist/{env-DV4r3nHz.mjs → env-U_ohASB0.mjs} +1 -1
  18. package/dist/gen-B87rlalt.mjs +2 -0
  19. package/dist/{gen-CFOEEc-t.mjs → gen-pg-Ojg8Y.mjs} +1 -1
  20. package/dist/{github-cmd-jYjha2LO.mjs → github-cmd-DsrkweIl.mjs} +1 -1
  21. package/dist/help-B403BLBB.mjs +2 -0
  22. package/dist/{help-C46mnlUS.mjs → help-sBhFH6pi.mjs} +1 -1
  23. package/dist/index.mjs +3 -3
  24. package/dist/{init-CSXmvxKu.mjs → init-C--Yyj1b.mjs} +5 -5
  25. package/dist/{link-DxMOALXk.mjs → link-BC-mNG9-.mjs} +2 -2
  26. package/dist/{list-0wQs0oYg.mjs → list-DHU1Wj6c.mjs} +1 -1
  27. package/dist/login-BwiopVdg.mjs +2 -0
  28. package/dist/{login-CKk5NX4d.mjs → login-jKe_0QZL.mjs} +2 -2
  29. package/dist/{logs-hxWBSoej.mjs → logs-BG11f5PR.mjs} +1 -1
  30. package/dist/{migrate-DcW8F2W8.mjs → migrate-BV8qHiCb.mjs} +1 -1
  31. package/dist/migrate-BXY3B3m7.mjs +2 -0
  32. package/dist/{operator-cmd-BEUYhaHB.mjs → operator-cmd-BwAS2XZt.mjs} +3 -3
  33. package/dist/{output-urU86XeT.mjs → output-CCH48AMM.mjs} +4 -4
  34. package/dist/{platform-auth-config-Df6yVw-e.mjs → platform-auth-config-C-hv-_Ok.mjs} +2 -2
  35. package/dist/{platform-auth-protection-Jb0yftay.mjs → platform-auth-protection-DjTE5Hj-.mjs} +2 -2
  36. package/dist/{platform-auth-recovery-DmRyIfW0.mjs → platform-auth-recovery-Cr0r8TEb.mjs} +2 -2
  37. package/dist/{platform-cmd-DRxCOTwy.mjs → platform-cmd-0tEh2ZtA.mjs} +4 -4
  38. package/dist/{platform-cmd-C9Vt7m-d.mjs → platform-cmd-DE6dw45v.mjs} +1 -1
  39. package/dist/{platform-domain-IjiXgrXJ.mjs → platform-domain-B_7x6Iqx.mjs} +2 -2
  40. package/dist/{platform-lifecycle-CuJIZNvA.mjs → platform-lifecycle-Dhx9Pnub.mjs} +1 -1
  41. package/dist/{platform-lifecycle-BquAaU-5.mjs → platform-lifecycle-Di0LbhPM.mjs} +7 -7
  42. package/dist/{platform-management-Cgyed0WY.mjs → platform-management-B9LUtMt9.mjs} +1 -1
  43. package/dist/{platform-management-CCQKGsq4.mjs → platform-management-eaiaU3uM.mjs} +2 -2
  44. package/dist/{platform-recovery-DS8ih1SW.mjs → platform-recovery-BxfA8E5C.mjs} +2 -2
  45. package/dist/{prepare-CaUxODOU.mjs → prepare-_T-Haxrr.mjs} +1 -1
  46. package/dist/{project-cmd-2lN--YAX.mjs → project-cmd-DrnRJdep.mjs} +13 -13
  47. package/dist/{project-team-Dapn9HZn.mjs → project-team-CzRbO_kA.mjs} +1 -1
  48. package/dist/{project-token-C90v9SJK.mjs → project-token-Bwxjf4y6.mjs} +1 -1
  49. package/dist/{requests-CzX46I0i.mjs → requests-DwrqUQZ8.mjs} +1 -1
  50. package/dist/{rollback-BEeyc73H.mjs → rollback-B4tFWmkN.mjs} +1 -1
  51. package/dist/{secret-wnTel5Yw.mjs → secret-UtrRjhEO.mjs} +1 -1
  52. package/dist/{subcommand-prompt-Gj3VzLIh.mjs → subcommand-prompt-BuGYkAkC.mjs} +1 -1
  53. package/package.json +7 -7
  54. package/skills/void/docs/guide/deployment.md +6 -13
  55. package/skills/void/docs/guide/email.md +53 -59
  56. package/skills/void/docs/guide/index.md +15 -41
  57. package/skills/void/docs/guide/quickstart.md +11 -78
  58. package/skills/void/docs/index.md +17 -17
  59. package/skills/void/docs/integrations/cloudflare.md +16 -23
  60. package/skills/void/docs/reference/cli.md +13 -7
  61. package/skills/void/docs/reference/config.md +6 -6
  62. package/dist/gen-BBiIZw6g.mjs +0 -2
  63. package/dist/help-CS_nAsWu.mjs +0 -2
  64. package/dist/login-Ch9cgWRF.mjs +0 -2
  65. package/dist/migrate-CLty4mZR.mjs +0 -2
@@ -4,11 +4,11 @@ outline: deep
4
4
 
5
5
  # Cloudflare
6
6
 
7
- Void runs on Cloudflare Workers. This page covers how bindings work, how the plugin merges Cloudflare configuration, and how to deploy directly to your own Cloudflare account.
7
+ Void runs on Cloudflare Workers. Use this guide to access bindings, configure your Worker, and deploy to your own account.
8
8
 
9
9
  ## Bindings
10
10
 
11
- Void automatically infers and provisions Cloudflare bindings (D1, KV, R2, AI, Queues) by scanning your source files. There are two ways to access them at runtime depending on your setup.
11
+ Void detects supported resource use in your source and provisions the corresponding bindings. How you access them depends on your framework.
12
12
 
13
13
  ### Via Hono context (`c.env`)
14
14
 
@@ -132,43 +132,36 @@ For environment variables, declare the schema in `env.ts` and put local values i
132
132
  API_URL=https://api.example.com
133
133
  ```
134
134
 
135
- Binding arrays such as `d1_databases`, `kv_namespaces`, and `r2_buckets` belong in the `cloudflare` field. Void adds inferred bindings that are missing by name and preserves custom bindings with real resource IDs. See [Cloudflare config merging](#cloudflare-config-merging) for details.
135
+ Binding arrays such as `d1_databases`, `kv_namespaces`, and `r2_buckets` belong in the `cloudflare` field. Void adds inferred bindings that are missing by name and preserves custom bindings with real resource IDs. See [Cloudflare Configuration](#cloudflare-configuration) for details.
136
136
 
137
137
  For non-secret plain-text defaults, you can also set `worker.vars` in `void.config.ts`. Local `.env` values override `worker.vars` during development. Production builds reject any `worker.vars` name that is declared as a server key in `env.ts`; store those values remotely with `void secret put` instead.
138
138
 
139
- ## Cloudflare config merging
139
+ ## Cloudflare Configuration
140
140
 
141
- Void reads `void.config.ts`, combines its `cloudflare` settings with provisioned values in `void.lock.json`, and generates the Cloudflare config needed by the build and deploy tools. Root `wrangler.jsonc` and `wrangler.json` files from existing apps are migrated automatically by `void init` or `void deploy`. Bindings are inferred from source code and use local placeholder IDs for development.
141
+ Set Worker options in `void.config.ts`. Void combines its `cloudflare` settings with resource IDs in `void.lock.json` for development and deployment. `void init` and `void deploy` migrate root `wrangler.jsonc` or `wrangler.json` files from existing apps.
142
142
 
143
- Edit `cloudflare` in `void.config.ts` for custom Worker settings. Commit `void.lock.json` when Void records resource IDs or Durable Object migration history.
143
+ Commit `void.lock.json` when Void records resource IDs or Durable Object migration history.
144
144
 
145
145
  ### Void-only mode and Vite-based frameworks
146
146
 
147
- In Void's default mode and frameworks where Void controls the Cloudflare integration (TanStack Start, React Router), Void manages `@cloudflare/vite-plugin` directly. It merges inferred bindings with the generated Cloudflare config:
147
+ In native Void apps, TanStack Start, and React Router, Void manages the Cloudflare Vite plugin. It merges inferred bindings with your `cloudflare` settings:
148
148
 
149
- 1. The plugin reads the generated config containing your `cloudflare` settings and Void's recorded resource values.
150
- 2. Void checks each inferred binding **by name** (e.g. `"DB"`, `"KV"`, `"STORAGE"`). If a binding with that name already exists in your config, it is left untouched.
151
- 3. Only bindings that are **missing** from your config are added with local placeholder IDs (e.g. `database_id: "local"`).
152
- 4. The merged config is used for both `vite dev` (Miniflare) and `vite build` (output `wrangler.json` in `dist/`).
149
+ - An existing binding with the same name stays unchanged.
150
+ - Missing inferred bindings get local placeholder IDs for development. Deploy replaces them with provisioned IDs.
151
+ - Other `cloudflare` settings, such as routes, services, variables, and compatibility settings, pass through.
153
152
 
154
- All other `cloudflare` fields -- `name`, `routes`, `services`, `vars`, `env`, `compatibility_date`, etc. -- flow through to the build output.
155
-
156
- Fields that Void always sets (`main`, `triggers`, `assets`) don't need to be in your Cloudflare config -- they're added programmatically based on your project structure.
157
-
158
- In this mode, normal inferred bindings are merged in memory. Typed state modules in `durable-objects/` are the exception: Void records their bindings and append-only `new_sqlite_classes` history in `void.lock.json`. Commit the lock.
153
+ Void sets `main`, `triggers`, and `assets` from your project structure. It also records typed Durable Object bindings and migration history from `durable-objects/` in `void.lock.json`.
159
154
 
160
155
  ### Adapter-based frameworks (SvelteKit, Nuxt, Astro)
161
156
 
162
- When using SvelteKit, Nuxt, or Astro, the framework's own Cloudflare adapter owns the worker build and dev server. Void does **not** provide `@cloudflare/vite-plugin` in that setup. It only contributes DB type codegen, migration management, and binding sync.
157
+ SvelteKit, Nuxt, and Astro build Workers through their own adapters. Void provides database types, migrations, and binding sync without replacing those adapters.
163
158
 
164
- Because Void does not control the Cloudflare plugin in this mode, it syncs inferred bindings to the generated Cloudflare config on dev startup:
159
+ At dev startup, Void updates the framework's generated Cloudflare config:
165
160
 
166
- - Only adds bindings that are **missing** by name -- existing bindings are never modified or removed.
167
- - If `worker.compatibility_date` is set in `void.config.ts`, syncs that date into the Cloudflare config so the framework adapter reads the same value.
168
- - Also ensures the `nodejs_als` compatibility flag is present.
169
- - The framework adapter reads the generated config through its configured path.
161
+ - It adds missing bindings by name without changing existing ones.
162
+ - It copies `worker.compatibility_date`, when set, and adds the `nodejs_als` compatibility flag.
170
163
 
171
- The framework adapter reads the generated config. Void adds bindings as you import resources, and `void deploy --platform cloudflare` replaces local placeholder IDs when it provisions production resources.
164
+ `void deploy --platform cloudflare` provisions production resources for inferred bindings.
172
165
 
173
166
  ### Merge precedence
174
167
 
@@ -78,7 +78,9 @@ Use `void --help` for the command list. For a specific command, try `void deploy
78
78
 
79
79
  ### `void migrate`
80
80
 
81
- `void migrate` converts `void.json` and root `wrangler.jsonc` or `wrangler.json` into a typed `void.config.ts`. It also recognizes a single root `wrangler*.json(c)` file explicitly referenced by a supported framework adapter. Void backs up the originals under `.void/config-migration/`, keeps Cloudflare resource state in `void.lock.json`, and updates supported framework adapters to use its generated Cloudflare config. `.void-wrangler.jsonc` is a generated Cloudflare tooling file; migration adds it to `.gitignore`. `void init` and `void deploy` run this migration automatically when they find legacy files. Before Cloudflare deployment, the project's installed `void` package must match the CLI version. Review and commit the new config, lock, and `.gitignore`. If multiple Cloudflare config files exist or existing files disagree, resolve them before retrying.
81
+ `void migrate` converts legacy `void.json` and root `wrangler.jsonc` or `wrangler.json` files into `void.config.ts`. It also accepts one root `wrangler*.json(c)` file referenced by a supported framework adapter. Void saves backups in `.void/config-migration/`, records resource IDs in `void.lock.json`, and updates supported adapters to use its generated Cloudflare config.
82
+
83
+ `.void-wrangler.jsonc` is generated for Cloudflare tooling and belongs in `.gitignore`; migration adds the entry. Review and commit `void.config.ts`, `void.lock.json`, and `.gitignore`. `void init` and `void deploy` migrate legacy files automatically. If the project has conflicting or multiple Cloudflare configs, resolve them first. The project's installed `void` package must match the CLI version before Cloudflare deployment.
82
84
 
83
85
  ### `void init`
84
86
 
@@ -775,9 +777,11 @@ The installed platform needs a separate runtime token to provision resources for
775
777
 
776
778
  To enable email during install or upgrade, set both `VOID_EMAIL_SENDER_DOMAIN` and `VOID_EMAIL_SHARED_ZONE_ID`. Void records the pair for later upgrades; supplying only one is an error.
777
779
 
778
- `--plan` prints the actual resource names, selected login methods, login callback, and direct setup links without opening credential pages or saving a draft; Cloudflare browser login still opens if needed. New platform resources use `void-<name>-<role>` names without random suffixes. Existing installations keep their recorded names, and unowned name conflicts stop installation without overwriting resources. After you confirm an interactive install, Void opens each missing credential's setup page and shows a short permission/checklist fallback. The runtime-token link preselects all required account permissions, including Workers Tail, Hyperdrive, and AI Gateway when needed; domain installations must also select the indicated zone. Supplied credentials skip browser opening. Setup drafts pin Worker names and the login callback and save partial credentials encrypted locally. Interactive installs list unfinished installations, including interrupted provisioning, or offer a new install. Entering an existing unfinished name asks to resume it; declining returns to name entry. Starting new leaves previous setup, credentials, and resources untouched. Completed platforms are not offered for resumption. `--resume` skips the choice and is required for non-interactive recovery.
780
+ `--plan` shows resource names, login methods, the callback URL, and setup links without opening credential pages or saving a draft. Cloudflare browser login can still open if needed. It prints an install command with the resolved name, account, domain, and any supplied authentication file or runtime. Run that command later to recalculate and confirm the plan. If you chose login methods interactively, choose them again during installation. For unfinished installations, the plan prints the saved `--resume` command instead.
781
+
782
+ New resources use `void-<name>-<role>` names. Existing installations keep their recorded names; an unowned name conflict stops installation. After confirmation, Void opens setup pages for missing credentials. The runtime-token link preselects required account permissions, including Workers Tail, Hyperdrive, and AI Gateway when needed; select the indicated zone for domain installs. Supplied credentials skip those pages.
779
783
 
780
- At the end of a plan, Void prints a command to install with the resolved name, account, domain, and any supplied authentication file or runtime. Running that command later recalculates the plan; interactive use asks for confirmation and missing credentials. If you chose login methods interactively, choose them again during installation. A plan for an unfinished installation instead prints its checkpointed `--resume` command.
784
+ Setup drafts save Worker names, the login callback, and partial credentials encrypted locally. Interactive installs offer unfinished installations, including interrupted provisioning, or a new one. Choosing an unfinished name asks to resume it; choosing a new one leaves earlier setup, credentials, and resources untouched. Use `--resume` for non-interactive recovery. Completed platforms cannot be resumed.
781
785
 
782
786
  Use an empty PostgreSQL database dedicated to the installation. You can correct a failed initial connection, but after the database is claimed or Hyperdrive is provisioned, commands reject a different URL.
783
787
 
@@ -959,19 +963,21 @@ Email setup needs a browser session from `void cloudflare login`, which carries
959
963
 
960
964
  Sandbox apps need Docker, [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans), and Containers access. API tokens need Account / Containers: Edit and Account / Cloudchamber: Edit. Void checks access before provisioning or building; apps without Sandbox skip that check.
961
965
 
962
- Void provisions inferred resources, builds and validates the app, applies migrations, validates remote secrets, and checks the uploaded Worker Version before sending it traffic. After activation it synchronizes routes, custom domains, cron triggers, queue consumers, and the Email Routing rules derived from `addresses`. Static, hybrid, and SSR output from supported frameworks is also supported. A brand-new Worker may need one ordinary deployment before the Versions API can be used.
966
+ Void provisions inferred resources, builds and validates the app, applies migrations, checks required secrets, and verifies the uploaded Worker before sending it traffic. It then updates routes and triggers. Supported frameworks can deploy static, hybrid, and SSR output. A new Worker may need one initial deployment before versioned deployment is available.
967
+
968
+ During deployment, Void shows the current phase and an animated spinner in an interactive terminal. CI and redirected output receive plain progress lines. Cloudflare CLI setup notices and successful command output are hidden; Void reports deployment errors directly.
963
969
 
964
970
  If Cloudflare Access protects readiness URLs, supply an allowed `CF_ACCESS_CLIENT_ID` and `CF_ACCESS_CLIENT_SECRET` pair, or a short-lived local `CF_ACCESS_TOKEN`. These credentials are used only for matching HTTPS readiness requests. Versions without accessible previews can be checked at 0% traffic through the stable hostname.
965
971
 
966
972
  Secrets and migrations are validated after the build, so a failed check may leave provisioned resources. It doesn't apply remote D1 migrations or upload the application Worker. PostgreSQL migrations are transactional; MySQL schema changes may partially apply on error.
967
973
 
968
- Provisioning reuses known resource IDs and records newly resolved IDs in `void.lock.json`. Commit that file for other machines and CI. Run the first deploy from one machine at a time because provisioning locks are local. The old `--provision` flag is accepted but no longer needed.
974
+ Void records provisioned resource IDs in `void.lock.json`. Commit it for other machines and CI. Run the first deploy from one machine at a time; provisioning locks are local. The `--provision` flag is accepted but no longer needed.
969
975
 
970
- `.env` is local-only and isn't emitted into Worker vars. Store every schema-declared server key with `void secret put <NAME>`; Void emits required names through `secrets.required` and blocks plaintext server vars. On a new Worker, set required secrets before retrying if the initial remote check reports them missing. Custom D1 layouts are accepted only when Cloudflare's exact file set, bytes, and numeric order match the migrations Void validated. Direct deploy and operational commands use the top-level Cloudflare settings and reject named environments and alternate config-path overrides.
976
+ `.env` stays local. Store server keys declared in `env.ts` with `void secret put <NAME>`; Void rejects them as plaintext Worker vars. If the first deploy reports missing remote secrets, set them and retry. Custom D1 migration layouts must match the exact files, contents, and order Void validated. Direct deploy and Cloudflare commands use the top-level settings, not named environments or alternate config paths.
971
977
 
972
978
  Existing remote secrets are preserved. Void also preserves or creates `BETTER_AUTH_SECRET` for auth apps.
973
979
 
974
- **Email.** When the app uses email (`sendEmail()` or `email/` handlers) and `void.config.ts` has `email.from`, the deploy reads the state of that address's zone before the build — session scopes, zone, MX records, Email Routing, subaddressing, routing rules, Email Sending, and what Void's Cloudflare config holds — prints a checklist of what it would change in your account, and asks once (default Yes). On Yes it enables what is missing, writes `send_email: [{ "name": "SEND_EMAIL" }]`, the `__VOID_EMAIL_FROM` var and the `addresses` array into Void's Cloudflare config, and lets Cloudflare tooling create the routing rules when the activated version's triggers are synchronized; the deploy ends with the address map. A deploy with nothing left to set up asks nothing. Without `email.from` the deploy prints `set email.from in void.config.ts` and continues without email. Non-interactive runs (CI, or stdin/stdout not a terminal) never prompt: they print the checklist plus `Run void email setup --platform cloudflare once locally, commit void.lock.json, then redeploy` and deploy without email (or with the setup Void's Cloudflare config already carries, when the binding is committed) — unless `--require-email` is passed, which fails instead. If setup has committed the exact subdomain `addresses` plan but the deploy's resolver still sees no MX records, Void preserves the plan and stops before build or upload until DNS can be verified. A deploy whose account rows all read ready reconciles the two config rows — `addresses` against the current derivation and `vars.__VOID_EMAIL_FROM` against `email.from` — with a plain file write and no prompt. See [Your own Cloudflare account](../guide/email.md#your-own-cloudflare-account) for the whole flow, including the subdomain-vs-apex rule and what stays manual.
980
+ **Email.** If the app uses `sendEmail()` or `email/` handlers, set `email.from` in `void.config.ts`. Void shows the Cloudflare account changes and asks before applying them. Later deploys skip the prompt once setup is ready. Without `email.from`, deploy continues without email. For CI, run `void email setup --platform cloudflare` locally and commit `void.lock.json`; pass `--require-email` to fail when email is unavailable. DNS propagation may delay a deploy after setup. See [Email on your own Cloudflare account](../guide/email.md#your-own-cloudflare-account) for setup and recovery.
975
981
 
976
982
  See the [Cloudflare guide](../integrations/cloudflare.md#deploy-to-your-own-cloudflare-account) for the complete deployment sequence, first-deploy exceptions, secret precedence, and recovery behavior.
977
983
 
@@ -6,9 +6,9 @@ outline: deep
6
6
 
7
7
  ## Config File Format
8
8
 
9
- Use this page as the exact reference for `void.config.ts`. If you are still learning how the pieces fit together, start in the guide first and come back here when you need field-by-field details.
9
+ Use `void.config.ts` to configure your app. For a guided introduction, start with [What is Void?](../guide/).
10
10
 
11
- Project configuration lives in a typed `void.config.ts` at the project root. Import `defineConfig` from `void/config`; all fields are optional. `void init` creates this file, and `void init`, `void deploy`, or `void migrate` converts existing `void.json` and root Wrangler JSON/JSONC files. Void saves the originals under `.void/config-migration/`. Commit `void.config.ts` and `void.lock.json` when Void creates the lock file. You can edit the typed config at any time; the lock records Cloudflare resource IDs and migration history that Void resolves for you.
11
+ Put `void.config.ts` at the project root and import `defineConfig` from `void/config`. All fields are optional. `void init`, `void deploy`, and `void migrate` can convert older Void and Cloudflare JSON config files, saving backups under `.void/config-migration/`. Commit `void.config.ts` and `void.lock.json` when Void creates the lock; it records resource IDs and migration history.
12
12
 
13
13
  ```ts
14
14
  // void.config.ts
@@ -253,7 +253,7 @@ Enable and configure Cloudflare Sandboxes for Void apps. Importing from `void/sa
253
253
  | `instanceType` | `string` | `lite` on Void deploy |
254
254
  | `maxInstances` | `number` | `20` on Void deploy |
255
255
 
256
- Sandbox support currently applies to Void apps on the Cloudflare target. Native deployment requires [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans) because Cloudflare Containers are unavailable on Workers Free. `void deploy --platform cloudflare` verifies Containers access before provisioning resources or building the app and explains how to fix a missing plan or API-token permission. Managed deployment checks the platform account and runtime token only when a Sandbox app is deployed; the token needs Account / Containers: Edit and Account / Cloudchamber: Edit. Apps that do not import `void/sandbox` or configure `sandbox` emit no Container and perform no entitlement check. The default registry image is pinned to the installed `@cloudflare/sandbox` version, so local and native Cloudflare deploys run the same container as Void Platform. If `sandbox.image` is a custom local Dockerfile path, set `sandbox.platformImage` to the pushed image that the platform should run.
256
+ Sandbox is available to Void apps on the Cloudflare target and requires [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans) and Containers access. Void checks access before provisioning or building. For a managed platform, its runtime token needs Account / Containers: Edit and Account / Cloudchamber: Edit. Apps without Sandbox use neither Containers nor an entitlement check. The default image matches the installed `@cloudflare/sandbox` version. If `sandbox.image` points to a local Dockerfile, set `sandbox.platformImage` to the pushed image for the platform.
257
257
 
258
258
  ### `target`
259
259
 
@@ -316,7 +316,7 @@ Void writes a generated Cloudflare config for its tooling and records provisione
316
316
 
317
317
  If you need to remove a value that Void previously generated, remove it from the `resolved` object in `void.lock.json`. Void refreshes the generated Cloudflare file on the next command. Put ongoing custom settings in `cloudflare` in `void.config.ts`.
318
318
 
319
- `worker.limits.cpu_ms` caps Workers CPU time per request, in milliseconds. It must be an integer between 1 and 300000 (Cloudflare's hard maximum, 5 minutes). A deploy that requests more than your account plan's ceiling fails with an error naming both the requested value and the plan maximum. Only a rollback clamps: rolling back to a deployment whose configured limit now exceeds your plan applies the plan ceiling instead of failing. If your plan changes so that a previously valid value now exceeds the ceiling, deploys keep failing until you lower `cpu_ms` in `void.config.ts`. On the direct Cloudflare path, the value is written into the generated `dist/ssr/wrangler.json` as `limits.cpu_ms` and enforced by Cloudflare directly. The Void plan ceiling does not apply there, but your Cloudflare account's own CPU-time allowance still does: the Workers Free plan caps CPU at 10 ms per request, and the Workers Paid plan allows up to 300000 ms. A value above what your Cloudflare account permits is constrained or rejected by Cloudflare, not by Void.
319
+ `worker.limits.cpu_ms` sets the CPU time limit per request, from 1 to 300000 ms. On a Void platform, deploy fails if the limit exceeds the account plan; lower it in `void.config.ts` before retrying. Rollback instead caps the old limit at the current plan ceiling. On direct deploys, [Cloudflare enforces the value](https://developers.cloudflare.com/workers/platform/limits/#cpu-time): Workers Free allows up to 10 ms and Workers Paid up to 300000 ms per request.
320
320
 
321
321
  ```json
322
322
  {
@@ -493,9 +493,9 @@ Each binding accepts `true` (use default name), `false` (disable), or a string (
493
493
  | `ai` | `AI` | `Ai` | `"ai": "MY_AI"` |
494
494
  | `email` | — | — | Boolean only |
495
495
 
496
- Custom resource binding names flow through deploy manifests, Cloudflare config generation, remote binding proxying, internal migrations, and generated runtime helpers such as `void/db`, `void/kv`, and `void/storage`. Custom AI names apply to generated Cloudflare configuration and `void/ai` runtime resolution for direct Cloudflare builds; managed Workers AI continues to use Void's service proxy.
496
+ Custom binding names work with `void/db`, `void/kv`, and `void/storage` during development and deployment. Custom AI names also work with `void/ai` on direct Cloudflare deploys; managed Workers AI uses the platform's proxy.
497
497
 
498
- `email` is a feature switch rather than a Cloudflare binding, so it has no binding name or type. On the platform, outbound mail is sent through the Void proxy, which owns the `send_email` binding — none is written into your worker; on your own Cloudflare account, `void deploy --platform cloudflare` records a `send_email` binding named `SEND_EMAIL` in `void.lock.json` once email is set up (see [`email.from`](#email)). Set it to `true` to turn the [email integration](../guide/email.md) on — which registers the `void dev` inbox — even when no scanned file imports `void/email`, or `false` to turn it off.
498
+ `email` is a boolean feature switch. Set it to `true` to enable [email](../guide/email.md) and the `void dev` inbox without an import from `void/email`, or `false` to disable them. On a Void platform, sending uses the platform proxy. Direct Cloudflare setup records a `SEND_EMAIL` binding in `void.lock.json`; see [`email.from`](#email).
499
499
 
500
500
  #### `inference.build`
501
501
 
@@ -1,2 +0,0 @@
1
- import { r as runGenCommand } from "./gen-CFOEEc-t.mjs";
2
- export { runGenCommand };
@@ -1,2 +0,0 @@
1
- import { r as printHelpPage } from "./help-C46mnlUS.mjs";
2
- export { printHelpPage };
@@ -1,2 +0,0 @@
1
- import { r as selectPlatformLoginMethod } from "./login-CKk5NX4d.mjs";
2
- export { selectPlatformLoginMethod };
@@ -1,2 +0,0 @@
1
- import { n as runMigrateCommand } from "./migrate-DcW8F2W8.mjs";
2
- export { runMigrateCommand };