void 0.22.0 → 0.23.0

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 (276) hide show
  1. package/README.md +5 -1
  2. package/dist/{account-cmd-CjyxcGkM.mjs → account-cmd-C84Ee8cO.mjs} +4 -4
  3. package/dist/{scan-ClYmX3sa.mjs → application-analysis-BVsVqc11.mjs} +135 -18
  4. package/dist/application-routing-B7QEjqSR.mjs +27 -0
  5. package/dist/{auth-CZuiVsFh.mjs → auth-CCjt0hcq.mjs} +1 -1
  6. package/dist/{auth-DLNN0D3Z.mjs → auth-CSkdO2Bb.mjs} +4 -47
  7. package/dist/{auth-link-BLO4ptzo.mjs → auth-link-CioEg6uY.mjs} +4 -4
  8. package/dist/{auth-router-ZUg9MF_U.mjs → auth-router-BsR981d4.mjs} +4 -4
  9. package/dist/{better-auth-shared-rsBGBvWJ.mjs → better-auth-shared-hy6RPh9W.mjs} +13 -2
  10. package/dist/{build-cmd-BxR5FROK.mjs → build-cmd-LzvNJORH.mjs} +17 -5
  11. package/dist/{cache-D0sWhgKI.mjs → cache-C4MvnrMH.mjs} +2 -2
  12. package/dist/{cancel-deploy-D4NUqFbi.mjs → cancel-deploy-abUxpP2n.mjs} +2 -2
  13. package/dist/{cf-build-output-BJ6yGEIS.mjs → cf-build-output-BPqOT964.mjs} +2 -1
  14. package/dist/cf-build-output-_0HNWysu.mjs +2 -0
  15. package/dist/cli/cli.mjs +80 -455
  16. package/dist/cli/{cf-compat.mjs → cloudflare-operation-process.mjs} +442 -421
  17. package/dist/cli/env-schema-probe.d.mts +2 -1
  18. package/dist/cli/env-schema-probe.mjs +3 -3
  19. package/dist/client-Cu7jWiF1.mjs +2 -0
  20. package/dist/{client-BTZ3XkrB.mjs → client-RV8NVeB8.mjs} +140 -21
  21. package/dist/{cloudflare-auth-DQkqoMYa.mjs → cloudflare-auth-Qdc7tw8F.mjs} +41 -38
  22. package/dist/{cloudflare-cmd-BKlfGHAy.mjs → cloudflare-cmd-BcrVyTmJ.mjs} +5 -5
  23. package/dist/cloudflare-config-Bktvwtpf.mjs +182 -0
  24. package/dist/{cloudflare-connect-Ctmrw579.mjs → cloudflare-connect-B8uPZ4nx.mjs} +3 -3
  25. package/dist/{cloudflare-operations-BT6OWFBk.mjs → cloudflare-operations-AiWashgg.mjs} +1 -1
  26. package/dist/{cloudflare-operations-B9tzgjmf.mjs → cloudflare-operations-fxHb-byx.mjs} +116 -172
  27. package/dist/{preset-UHj9ARyP.mjs → cloudflare-process-B-wekeR6.mjs} +93 -6
  28. package/dist/{config-VavjpDnp.d.mts → config-BMHb8RCj.d.mts} +1 -0
  29. package/dist/config-C_XRIPx2.mjs +89 -0
  30. package/dist/config-entry.d.mts +1 -1
  31. package/dist/{connect-Dg-WkW-C.mjs → connect-Bd4kJd9U.mjs} +5 -5
  32. package/dist/{create-project-DdoqwFLF.mjs → create-project-Boczwj5r.mjs} +1 -1
  33. package/dist/{create-project-l9J7pbtm.mjs → create-project-bMf6ffLZ.mjs} +2 -2
  34. package/dist/{db-gp2sCXyN.mjs → db-8uG64XLl.mjs} +21 -21
  35. package/dist/{delete-TTedbH6B.mjs → delete-NvbiyeJf.mjs} +2 -2
  36. package/dist/{deploy-CH-o2CaZ.mjs → deploy-DzAIwqNU.mjs} +908 -582
  37. package/dist/{deploy-B19L2Bra.mjs → deploy-bjXdFCtn.mjs} +1 -1
  38. package/dist/{domain-JRF59P_r.mjs → domain-y5Tvydvo.mjs} +3 -3
  39. package/dist/{email-Bo6G9LOZ.mjs → email-B3umsW75.mjs} +13 -28
  40. package/dist/{env-BYOrWQnv.mjs → env-BS6qYHDb.mjs} +4 -4
  41. package/dist/{env-public-BxU_0yTL.d.mts → env-public-BX_r8HR6.d.mts} +1 -1
  42. package/dist/{env-validation-BB4GkLxn.mjs → env-validation-BPn7vk-V.mjs} +18 -71
  43. package/dist/{env-validation-BXge7uyK.mjs → env-validation-DbTg7-ar.mjs} +1 -1
  44. package/dist/{fetch-CXDChK7B.mjs → fetch-BIZJh7vR.mjs} +2 -2
  45. package/dist/{fetch-stream-AOByI7Ki.mjs → fetch-stream-IvCYKyQL.mjs} +24 -4
  46. package/dist/{gen-sCtlCOdA.mjs → gen-B580--vC.mjs} +2 -2
  47. package/dist/gen-BVaUUumi.mjs +2 -0
  48. package/dist/{github-cmd-0-7PexDq.mjs → github-cmd-v45BdfKX.mjs} +2 -2
  49. package/dist/{handler-HEcZsaij.d.mts → handler-CZ4nAylQ.d.mts} +1 -1
  50. package/dist/help-DofyZuY7.mjs +2 -0
  51. package/dist/{help-GKtwl07I.mjs → help-daGKjXGk.mjs} +229 -747
  52. package/dist/index.d.mts +1 -1
  53. package/dist/index.mjs +288 -1502
  54. package/dist/info-B97bTX9N.mjs +113 -0
  55. package/dist/{init-FZx3Elvz.mjs → init-Bvy7zrBo.mjs} +46 -15
  56. package/dist/limits-Bq5LG8Id.d.mts +27 -0
  57. package/dist/limits-Cjuk2VPm.mjs +68 -0
  58. package/dist/{link-BrQfb_CU.mjs → link-CDqqCjFl.mjs} +3 -3
  59. package/dist/{list-D44jmIAM.mjs → list-CZj0dzKY.mjs} +3 -3
  60. package/dist/{live-CKJlvlNp.d.mts → live-Chw1eIMv.d.mts} +1 -1
  61. package/dist/{local-d1-Bg9OzEEO.mjs → local-d1-2CMnpuW_.mjs} +2 -2
  62. package/dist/login-DYt_An22.mjs +2 -0
  63. package/dist/{login-CAsAsQ-_.mjs → login-UZKFM_u7.mjs} +3 -3
  64. package/dist/{logs-BjKvFnVM.mjs → logs-CUZ6t9t3.mjs} +3 -3
  65. package/dist/migrate-8_2u55MD.mjs +2 -0
  66. package/dist/{migrate-BPITvDJN.mjs → migrate-DHul7PRV.mjs} +2 -1
  67. package/dist/{node-Dt7z256D.mjs → node-BkyRWRx8.mjs} +1 -1
  68. package/dist/operator-args-CLgKGlwU.mjs +690 -0
  69. package/dist/{operator-cmd-BK5CCiT9.mjs → operator-cmd-DBA6dl0m.mjs} +68 -22
  70. package/dist/pages/client.d.mts +34 -2
  71. package/dist/pages/client.mjs +59 -3
  72. package/dist/pages/index.d.mts +1 -1
  73. package/dist/pages/index.mjs +1 -1
  74. package/dist/pages/islands-plugin.mjs +1 -1
  75. package/dist/pages/protocol.d.mts +2 -2
  76. package/dist/pages/protocol.mjs +2 -308
  77. package/dist/{parse-filename-DioPHiR9.mjs → parse-filename-CUbj-1MP.mjs} +35 -1
  78. package/dist/plan-D1Q5rf-r.mjs +2 -0
  79. package/dist/plan-NPpwZ_kc.mjs +58 -0
  80. package/dist/platform-args-BJdRtlLq.mjs +506 -0
  81. package/dist/platform-args-D3RXyR6h.mjs +2 -0
  82. package/dist/{platform-auth-config-BlN8xTdD.mjs → platform-auth-config-B56E9YP1.mjs} +3 -3
  83. package/dist/{platform-auth-protection-7d5aV2Jg.mjs → platform-auth-protection-BDWO_aER.mjs} +2 -2
  84. package/dist/{platform-auth-recovery-Dxij8ZbR.mjs → platform-auth-recovery-1gg4CSRe.mjs} +3 -3
  85. package/dist/{platform-cmd-E0FuL212.mjs → platform-cmd-Bt-1w6pY.mjs} +1 -1
  86. package/dist/{platform-cmd-B3hwKrFK.mjs → platform-cmd-DMcQStSc.mjs} +24 -3
  87. package/dist/{platform-domain-D6Xcy9ZX.mjs → platform-domain-BNkcz0OB.mjs} +2 -2
  88. package/dist/{platform-lifecycle-k0E0xoxx.mjs → platform-lifecycle-9OyBALhH.mjs} +327 -215
  89. package/dist/{platform-lifecycle-DMh_qrry.mjs → platform-lifecycle-BE6C_jxh.mjs} +1 -1
  90. package/dist/{platform-management-Brz_BDiT.mjs → platform-management-CjwLVQwN.mjs} +6 -3
  91. package/dist/{platform-management-DOtss0BN.mjs → platform-management-CnyTdcWX.mjs} +1 -1
  92. package/dist/platform-plans-config-BNGKGr4P.mjs +359 -0
  93. package/dist/{platform-recovery-BvtcXON5.mjs → platform-recovery-D6KSpuFm.mjs} +2 -2
  94. package/dist/{plugin-inference-BMfKRSqE.mjs → plugin-inference-CXWnn79A.mjs} +174 -64
  95. package/dist/{prepare-C-6YZyyg.mjs → prepare-B5Mkic5u.mjs} +1 -1
  96. package/dist/{prepare-CRhJbVrG.mjs → prepare-DOsL0CC9.mjs} +4 -20
  97. package/dist/prepare-cgvDMtSb.mjs +2 -0
  98. package/dist/{project-cmd-BZLCqOqw.mjs → project-cmd-CNzrqvBv.mjs} +16 -16
  99. package/dist/{project-team-BvgM0WoX.mjs → project-team-DQOWPfQT.mjs} +2 -2
  100. package/dist/{project-token-l5DqK6Az.mjs → project-token-CTDYU0Cc.mjs} +2 -2
  101. package/dist/{project-zero-trust-v6Mvpp8y.mjs → project-zero-trust-BNAkW-_0.mjs} +2 -2
  102. package/dist/{protocol-BBa6cstI.d.mts → protocol-CjF_iI9X.d.mts} +2 -2
  103. package/dist/protocol-U7bfjHmA.mjs +331 -0
  104. package/dist/{provision-Fr9pRqce.mjs → provision-C4ORE7G7.mjs} +1 -1
  105. package/dist/{provision-C4IGqkBf.mjs → provision-CJFgTZY8.mjs} +89 -198
  106. package/dist/{requests-DN-BbNiM.mjs → requests-MhxYnau8.mjs} +2 -2
  107. package/dist/resource-name-C7LVpcRm.mjs +11 -0
  108. package/dist/{rollback-D7rzSaZM.mjs → rollback-CJ6iSDoU.mjs} +3 -3
  109. package/dist/route-url-CG7U-cRN.mjs +15 -0
  110. package/dist/{runner-B8wXwWlo.mjs → runner-CXA9Fh8h.mjs} +1 -1
  111. package/dist/{runner-p-dMs2UN.mjs → runner-Ol0TNjk6.mjs} +2 -2
  112. package/dist/runtime/ai.d.mts +12 -8
  113. package/dist/runtime/ai.mjs +84 -17
  114. package/dist/runtime/better-auth-mysql.mjs +1 -1
  115. package/dist/runtime/better-auth-pg.mjs +1 -1
  116. package/dist/runtime/better-auth.mjs +1 -1
  117. package/dist/runtime/client-react.mjs +2 -2
  118. package/dist/runtime/client-solid.mjs +2 -2
  119. package/dist/runtime/client-svelte.mjs +2 -2
  120. package/dist/runtime/client-vue.mjs +2 -2
  121. package/dist/runtime/client.mjs +2 -2
  122. package/dist/runtime/durable.d.mts +3 -1
  123. package/dist/runtime/durable.mjs +4 -1
  124. package/dist/runtime/email/testing.mjs +1 -1
  125. package/dist/runtime/env-public.d.mts +1 -1
  126. package/dist/runtime/fetch-stream.mjs +1 -1
  127. package/dist/runtime/fetch.mjs +1 -1
  128. package/dist/runtime/handler.d.mts +1 -1
  129. package/dist/runtime/kv.mjs +0 -1
  130. package/dist/runtime/limits.d.mts +2 -0
  131. package/dist/runtime/limits.mjs +2 -0
  132. package/dist/runtime/live-client.d.mts +1 -1
  133. package/dist/runtime/live-server.mjs +25 -16
  134. package/dist/runtime/live.d.mts +1 -1
  135. package/dist/runtime/migration-handler.mjs +62 -42
  136. package/dist/runtime/route-url.d.mts +4 -0
  137. package/dist/runtime/route-url.mjs +2 -0
  138. package/dist/runtime/routing.d.mts +180 -0
  139. package/dist/runtime/routing.mjs +1082 -0
  140. package/dist/runtime/sandbox-container.d.mts +1 -1
  141. package/dist/runtime/sandbox-container.mjs +1 -1
  142. package/dist/runtime/sandbox.d.mts +3 -3
  143. package/dist/runtime/sandbox.mjs +75 -45
  144. package/dist/runtime/sse.mjs +1 -1
  145. package/dist/runtime/validator.d.mts +1 -1
  146. package/dist/runtime/ws-server.d.mts +4 -2
  147. package/dist/runtime/ws-server.mjs +27 -2
  148. package/dist/runtime/ws.d.mts +2 -2
  149. package/dist/runtime/ws.mjs +8 -6
  150. package/dist/{sandbox-qpNBT8a3.d.mts → sandbox-XZAqzFlG.d.mts} +11 -8
  151. package/dist/{sandbox-container-DdNEBfCc.d.mts → sandbox-container-Bo0eiFKz.d.mts} +2 -1
  152. package/dist/{sandbox-container-4fdqLnyb.mjs → sandbox-container-C6ItmVuN.mjs} +4 -2
  153. package/dist/{scan-4tfN-PSn.mjs → scan-C7okrLyM.mjs} +4 -35
  154. package/dist/{secret-BOtOl_cb.mjs → secret-Dli5fP0B.mjs} +4 -4
  155. package/dist/{sse-BaC1jXko.mjs → sse-CQNaDFFV.mjs} +6 -3
  156. package/dist/validate-Dq_L3s0S.mjs +2 -0
  157. package/dist/{validate-CIUwFpjB.mjs → validate-ctOrgiS3.mjs} +2 -1
  158. package/dist/{wrangler-DQF1vKyf.mjs → wrangler-7K-bW_DL.mjs} +8 -239
  159. package/dist/{ws-BoY7vQML.d.mts → ws-CL1w7GXU.d.mts} +13 -2
  160. package/package.json +15 -8
  161. package/skills/migrate-vite-cloudflare-to-void/SKILL.md +34 -157
  162. package/skills/void/SKILL.md +50 -135
  163. package/skills/void/docs/guide/ai.md +94 -84
  164. package/skills/void/docs/guide/app-types.md +3 -32
  165. package/skills/void/docs/guide/auth.md +12 -116
  166. package/skills/void/docs/guide/database/d1.md +9 -54
  167. package/skills/void/docs/guide/database/mysql.md +1 -1
  168. package/skills/void/docs/guide/database/postgresql.md +5 -26
  169. package/skills/void/docs/guide/database.md +23 -75
  170. package/skills/void/docs/guide/deployment.md +27 -113
  171. package/skills/void/docs/guide/durable-state.md +43 -18
  172. package/skills/void/docs/guide/edge/headers.md +3 -47
  173. package/skills/void/docs/guide/edge/prerendering.md +5 -20
  174. package/skills/void/docs/guide/edge/redirects.md +11 -64
  175. package/skills/void/docs/guide/edge/revalidation.md +5 -18
  176. package/skills/void/docs/guide/edge/rewrites.md +56 -284
  177. package/skills/void/docs/guide/edge/static-assets.md +22 -72
  178. package/skills/void/docs/guide/email/domains.md +112 -0
  179. package/skills/void/docs/guide/email/receiving.md +139 -0
  180. package/skills/void/docs/guide/email/sending.md +231 -0
  181. package/skills/void/docs/guide/email.md +13 -619
  182. package/skills/void/docs/guide/env-migration.md +11 -11
  183. package/skills/void/docs/guide/env-vars.md +9 -29
  184. package/skills/void/docs/guide/index.md +0 -15
  185. package/skills/void/docs/guide/jobs.md +3 -18
  186. package/skills/void/docs/guide/kv.md +5 -11
  187. package/skills/void/docs/guide/live.md +5 -56
  188. package/skills/void/docs/guide/pages-routing/actions-and-forms.md +78 -125
  189. package/skills/void/docs/guide/pages-routing/head.md +10 -10
  190. package/skills/void/docs/guide/pages-routing/islands.md +6 -36
  191. package/skills/void/docs/guide/pages-routing/layouts.md +6 -128
  192. package/skills/void/docs/guide/pages-routing/loaders.md +3 -19
  193. package/skills/void/docs/guide/pages-routing/markdown.md +13 -171
  194. package/skills/void/docs/guide/pages-routing/overview.md +7 -17
  195. package/skills/void/docs/guide/pages-routing/view-transitions.md +1 -1
  196. package/skills/void/docs/guide/platform/administration/access.md +1 -4
  197. package/skills/void/docs/guide/platform/administration/email.md +35 -8
  198. package/skills/void/docs/guide/platform/administration/operations.md +26 -4
  199. package/skills/void/docs/guide/platform/administration/plans.md +126 -0
  200. package/skills/void/docs/guide/platform/administration/projects.md +5 -2
  201. package/skills/void/docs/guide/platform/administration/zero-trust.md +23 -152
  202. package/skills/void/docs/guide/platform/development/runtime.md +3 -13
  203. package/skills/void/docs/guide/platform/development/schema-ci.md +0 -58
  204. package/skills/void/docs/guide/platform/installation/credentials.md +6 -4
  205. package/skills/void/docs/guide/platform/installation/domains.md +30 -2
  206. package/skills/void/docs/guide/platform/installation/first-deployment.md +2 -0
  207. package/skills/void/docs/guide/platform/installation/maintenance.md +3 -1
  208. package/skills/void/docs/guide/platform/installation/prerequisites.md +20 -15
  209. package/skills/void/docs/guide/platform/installation/setup.md +9 -5
  210. package/skills/void/docs/guide/platform-administration.md +1 -0
  211. package/skills/void/docs/guide/queues.md +7 -9
  212. package/skills/void/docs/guide/quickstart.md +38 -37
  213. package/skills/void/docs/guide/remote-dev.md +4 -9
  214. package/skills/void/docs/guide/sandboxes.md +29 -21
  215. package/skills/void/docs/guide/server-routing.md +9 -72
  216. package/skills/void/docs/guide/sse.md +4 -18
  217. package/skills/void/docs/guide/ssg.md +3 -15
  218. package/skills/void/docs/guide/ssr.md +14 -62
  219. package/skills/void/docs/guide/storage.md +9 -4
  220. package/skills/void/docs/guide/type-safety.md +3 -14
  221. package/skills/void/docs/guide/typed-fetch.md +3 -7
  222. package/skills/void/docs/guide/websockets.md +68 -40
  223. package/skills/void/docs/integrations/agents.md +3 -3
  224. package/skills/void/docs/integrations/cloudflare.md +85 -316
  225. package/skills/void/docs/integrations/frameworks/analog.md +5 -64
  226. package/skills/void/docs/integrations/frameworks/astro.md +4 -73
  227. package/skills/void/docs/integrations/frameworks/nuxt.md +5 -62
  228. package/skills/void/docs/integrations/frameworks/overview.md +11 -54
  229. package/skills/void/docs/integrations/frameworks/react-router.md +5 -60
  230. package/skills/void/docs/integrations/frameworks/sveltekit.md +6 -65
  231. package/skills/void/docs/integrations/frameworks/tanstack-start.md +4 -62
  232. package/skills/void/docs/integrations/nodejs-bun-deno.md +5 -69
  233. package/skills/void/docs/reference/api/auth.md +156 -0
  234. package/skills/void/docs/reference/api/client.md +87 -0
  235. package/skills/void/docs/reference/api/database.md +95 -0
  236. package/skills/void/docs/reference/api/durable.md +46 -0
  237. package/skills/void/docs/reference/api/env.md +50 -0
  238. package/skills/void/docs/reference/api/handlers.md +254 -0
  239. package/skills/void/docs/reference/api/pages.md +241 -0
  240. package/skills/void/docs/reference/api/plugin.md +39 -0
  241. package/skills/void/docs/reference/api/resources.md +109 -0
  242. package/skills/void/docs/reference/api/rewrites.md +76 -0
  243. package/skills/void/docs/reference/api/types.md +92 -0
  244. package/skills/void/docs/reference/api.md +56 -1218
  245. package/skills/void/docs/reference/cli/auth.md +88 -0
  246. package/skills/void/docs/reference/cli/database.md +128 -0
  247. package/skills/void/docs/reference/cli/deploy.md +85 -0
  248. package/skills/void/docs/reference/cli/domains.md +41 -0
  249. package/skills/void/docs/reference/cli/email.md +129 -0
  250. package/skills/void/docs/reference/cli/generate.md +116 -0
  251. package/skills/void/docs/reference/cli/github.md +189 -0
  252. package/skills/void/docs/reference/cli/platform-config.md +92 -0
  253. package/skills/void/docs/reference/cli/platform-email.md +81 -0
  254. package/skills/void/docs/reference/cli/platform-installation.md +127 -0
  255. package/skills/void/docs/reference/cli/platform-operations.md +90 -0
  256. package/skills/void/docs/reference/cli/platform-users.md +89 -0
  257. package/skills/void/docs/reference/cli/platform-zero-trust.md +45 -0
  258. package/skills/void/docs/reference/cli/platform.md +70 -0
  259. package/skills/void/docs/reference/cli/project.md +214 -0
  260. package/skills/void/docs/reference/cli/secrets.md +76 -0
  261. package/skills/void/docs/reference/cli/setup.md +70 -0
  262. package/skills/void/docs/reference/cli.md +32 -1682
  263. package/skills/void/docs/reference/config.md +12 -18
  264. package/skills/void/docs/reference/resource-inference.md +3 -58
  265. package/skills/void/docs/reference/structure.md +14 -41
  266. package/dist/canonical-json-DuDiiUsQ.mjs +0 -13
  267. package/dist/client-Czz8o5jP.mjs +0 -2
  268. package/dist/gen-CNJ62MM7.mjs +0 -2
  269. package/dist/help-CmZzxUba.mjs +0 -2
  270. package/dist/login-CGcRKEoi.mjs +0 -2
  271. package/dist/migrate-CYfbKkXh.mjs +0 -2
  272. package/dist/plan-BEZ8VJW0.mjs +0 -256
  273. package/dist/plan-DpuOr14e.mjs +0 -2
  274. package/dist/prepare-Bm3iq-u4.mjs +0 -2
  275. package/dist/validate-EKmJWxmy.mjs +0 -2
  276. /package/dist/cli/{cf-compat.d.mts → cloudflare-operation-process.d.mts} +0 -0
@@ -2,19 +2,43 @@
2
2
  outline: deep
3
3
  ---
4
4
 
5
- # CLI
5
+ <script setup>
6
+ import LegacyDocRedirect from "../.vitepress/theme/LegacyDocRedirect.vue";
7
+ import links from "../.vitepress/redirects/reference-cli.json";
8
+ </script>
9
+
10
+ <LegacyDocRedirect page="reference/cli.md" :links="links" />
11
+
12
+ # CLI Reference {#cli}
6
13
 
7
14
  `void` is a local binary from the installed `void` package.
8
15
 
9
16
  Use this page as a command reference. If you are setting up a project for the first time, start with [Quickstart](../guide/quickstart.md) and come back here when you need exact command behavior or flags.
10
17
 
11
- ## Cheat Sheet
18
+ ## Command Groups
19
+
20
+ | Command group | Reference |
21
+ | ------------------------------------------ | ------------------------------------------------------------- |
22
+ | `init`, `prepare`, `info`, `migrate` | [Project setup](./cli/setup.md) |
23
+ | `connect`, `auth`, `account`, `cloudflare` | [Connections and authentication](./cli/auth.md) |
24
+ | `project` | [Projects, teams, logs, and rollback](./cli/project.md) |
25
+ | `deploy` | [Deployment](./cli/deploy.md) |
26
+ | `db` | [Database](./cli/database.md) |
27
+ | `gen` | [Code generation](./cli/generate.md) |
28
+ | `secret`, `env` | [Secrets and environment](./cli/secrets.md) |
29
+ | `github`, `build` | [GitHub and builds](./cli/github.md) |
30
+ | `domain` | [Custom domains](./cli/domains.md) |
31
+ | `email` | [Email](./cli/email.md) |
32
+ | `platform` | [Platform installation and administration](./cli/platform.md) |
33
+
34
+ ## Cheat Sheet {#cheat-sheet}
12
35
 
13
36
  | Command | Purpose |
14
37
  | --------------------------------- | ----------------------------------------------------------------------------- |
15
38
  | `void deploy` | Build and deploy to the configured platform |
16
39
  | `void prepare` | Generate `.void` artifacts without starting Vite |
17
- | `void gen model <name> [cols...]` | Scaffold migration + CRUD routes |
40
+ | `void info [--json]` | Inspect persistent resource names before moving their code |
41
+ | `void gen model <name> [cols...]` | Scaffold a Drizzle table and API routes |
18
42
  | `void gen route <path>` | Create an API route |
19
43
  | `void db push` | Apply schema directly without migration files |
20
44
  | `void db generate` | Generate SQL migrations from schema changes |
@@ -25,7 +49,7 @@ Use this page as a command reference. If you are setting up a project for the fi
25
49
  | `void db studio` | Open Drizzle Studio (--remote for a deployed external database) |
26
50
  | `void secret put <name=value>` | Set a production secret |
27
51
  | `void secret list` | List production secrets |
28
- | `void secret sync .env` | Bulk upload secrets from dotenv file |
52
+ | `void secret sync <file>` | Bulk upload secrets from dotenv file |
29
53
  | `void env check [--remote]` | Validate env.ts schema |
30
54
  | `void env types` | Regenerate .void/env.d.ts from env.ts |
31
55
  | `void auth login` | Authenticate with the project’s saved destination, or choose one |
@@ -52,7 +76,7 @@ Use this page as a command reference. If you are setting up a project for the fi
52
76
  | `void init` | Setup wizard for new or existing projects |
53
77
  | `void migrate` | Convert legacy `void.json` and root Wrangler JSON/JSONC into `void.config.ts` |
54
78
 
55
- ## Binary Invocation
79
+ ## Binary Invocation {#binary-invocation}
56
80
 
57
81
  The docs use `void` for brevity. Outside package scripts, run it with your package manager: `npx void`, `pnpm void`, `yarn void`, or `bunx void`.
58
82
 
@@ -62,7 +86,7 @@ Alternatively, you can add `./node_modules/.bin` to your `PATH` so that you can
62
86
  Install `void` in your project so the CLI and runtime use the same version.
63
87
  :::
64
88
 
65
- ## Help
89
+ ## Help {#help}
66
90
 
67
91
  ```
68
92
  void --help
@@ -74,1683 +98,9 @@ void <group> <command> --help
74
98
  void <group> help <command>
75
99
  ```
76
100
 
77
- Use `void --help` for the command list. For a specific command, try `void deploy --help` or `void db execute --help`. Help runs without signing in, validating the project, or making network requests.
78
-
79
- ## Setup
80
-
81
- ### `void migrate`
82
-
83
- `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.
84
-
85
- `.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.
86
-
87
- ### `void init`
88
-
89
- ```
90
- void init [--tsconfig] [--github] [--agents] [--git | --no-git]
91
- ```
92
-
93
- Setup wizard for Void projects (new or existing).
94
-
95
- Outside an existing Git repository or workspace package, the interactive wizard first asks **Initialize a git repository?**, with Yes selected. Accepting runs `git init` using your Git default branch. At the end, Void suggests an optional `git add -A && git commit -m "chore: initial commit"` command; it does not stage files or commit automatically. Git initialization failures produce a warning and setup continues.
96
-
97
- Use `--git` to initialize without the Git prompt, or `--no-git` to skip it. In CI or without an interactive terminal, Git initialization requires `--git`. Existing repositories, including parent repositories, are preserved. Workspace packages skip Git initialization and do not accept these two flags.
98
-
99
- Void's `.gitignore` defaults exclude dependencies, generated files, `.env`, and `.env.*`, while allowing `.env.example` to be committed.
100
-
101
- In an empty project, `void init` asks you to choose:
102
-
103
- - **Toolchain:** Vite+ (the default) or plain Vite.
104
- - **Framework:** React, Vue, Svelte, or Solid. If one Pages adapter is already installed, Void uses it.
105
- - **Starter:** D1, PostgreSQL, MySQL, or Static Pages.
106
-
107
- Database starters include the framework config, a page and server loader, schema, seed, initial migration, and `routes/api/hello.ts`. Static Pages includes the framework config and home page. Vite+ starters use `vp dev`, `vp build`, and `vp preview`.
108
-
109
- If the directory contains other files but isn't an app yet, Void offers to create a subfolder. You can choose to continue in the current directory instead.
110
-
111
- In an existing app, Void adds missing dependencies and scripts, then updates `vite.config.*` with `voidPlugin()`. Existing scripts are preserved. If the config is too dynamic to edit, Void prints the snippet for you to add.
112
-
113
- After that, the full interactive flow walks through:
114
-
115
- 1. **TypeScript:** creates or updates `tsconfig.json`, including `extends .void/tsconfig.json`, `void/env` types, and root-level `files` / `compilerOptions.paths` merges when an existing config would otherwise replace Void's generated entries.
116
- 2. **Database:** asks whether you want D1, PostgreSQL, MySQL, or no database yet. PostgreSQL writes `"database": "pg"`; MySQL writes `"database": "mysql"`; D1 stays implicit.
117
- 3. **Agent instructions:** always creates or updates `AGENTS.md` with brief Void instructions and the bundled docs path, preserving content outside the versioned block.
118
- 4. **Skills:** links Void skills for detected coding agents.
119
- 5. **Demo code:** for existing non-Pages projects, optionally scaffolds a `db/migrations/` directory plus an API route and typed fetch example.
120
- 6. **Deployment platform:** asks where `void deploy` should send the app: Cloudflare (the default), Void, or Skip deployment setup. The choice is stored as `platform` in `.void/project.json`. Choosing Cloudflare records settings in `void.config.ts` and `void.lock.json`, checks the Cloudflare session through Void's bundled tooling, opens secure browser sign-in when needed, and writes the selected account as `account_id` (automatically when only one account is available).
121
- 7. **GitHub Actions:** optionally creates `.github/workflows/void-deploy.yml` for the selected target. Cloudflare workflows run `void deploy --platform cloudflare` with `CLOUDFLARE_API_TOKEN` and pass the optional `DATABASE_URL` secret needed by PostgreSQL/MySQL apps. Void workflows use the selected platform's API URL and are offered only when its discovery document advertises GitHub Actions support.
122
- 8. **`env.ts` scaffold:** if the project has no `env.ts` but has a root `.env`, generates an `env.ts` pre-populated with its keys. Values get conservative type inference (`boolean`/`url`/`number`/`string`) — the file carries a banner nudging you to tighten anything the heuristic got wrong.
123
- 9. **Void project setup:** when Void is selected, optionally logs you in, lets you select or create a project, and adds the link to `.void/project.json` so your first deploy can just be `void deploy`.
124
-
125
- If Cloudflare sign-in is declined or does not complete, initialization still finishes with the configuration in place. Rerun `void init`, or use `void cloudflare login`, when you are ready.
126
-
127
- Agent setup never asks which coding agent you use. If no agent is detected, skill linking is skipped; `AGENTS.md` still points to the complete docs at `node_modules/void/skills/void/docs/`.
128
-
129
- Use flags to run individual steps without prompts:
130
-
131
- | Flag | Purpose |
132
- | ------------ | ---------------------------------------------- |
133
- | `--tsconfig` | Only update `tsconfig.json` |
134
- | `--agents` | Set up agent instructions and skills |
135
- | `--github` | Only create the GitHub Actions deploy workflow |
136
-
137
- These step flags can be combined. When any of them is provided, only the specified steps run and interactive prompts are skipped. Git setup is skipped unless `--git` is also supplied. `--git` and `--no-git` alone keep the full setup wizard and control only its Git step.
138
-
139
- For Cloudflare, the generated workflow needs a `CLOUDFLARE_API_TOKEN` repository secret with access to your app's account and resources. PostgreSQL and MySQL apps also need `DATABASE_URL`.
140
-
141
- For a Void platform with GitHub Actions support, the workflow uses that platform's API URL and short-lived GitHub OIDC credentials. Authorize the repository with `void github connect <project> --repo <owner/repo> --executor github_actions`. Core self-hosted platforms don't yet support this integration, so Void explains that limitation instead of generating a workflow.
142
-
143
- For projects that already have `"extends"`, `void init --tsconfig` preserves the existing config and adds `./.void/tsconfig.json`. If the existing config defines `files` or `compilerOptions.paths`, Void also merges its generated declaration files and aliases into the root config because TypeScript replaces those fields across `extends` instead of deeply merging them.
144
-
145
- ### `void prepare`
146
-
147
- ```
148
- void prepare
149
- ```
150
-
151
- Generates the project-local `.void/` artifacts used by TypeScript and runtime codegen without starting `vite dev` or running a full `vite build`.
152
-
153
- This is the intended command for CI, fresh clones, editor bootstrap, and any workflow that needs `routes.d.ts`, `db.d.ts`, `queues.d.ts`, `env.d.ts`, and `.void/tsconfig.json` in place before typechecking.
154
-
155
- ## Connect
156
-
157
- ```sh
158
- void connect
159
- void connect https://platform.example.com
160
- void connect --platform cloudflare
161
- void connect --platform void
162
- ```
163
-
164
- Connect a project to its deployment destination. With no arguments, choose Cloudflare or a Void platform interactively. A URL selects a Void platform directly. `--platform void` offers saved platforms and an option to enter another URL.
165
-
166
- For Cloudflare, Void signs in through the browser when needed, selects an accessible account, and saves `cloudflare.account_id` in `void.config.ts` or resolved state in `void.lock.json`. It shares this setup with `void init`. An existing account selection is preserved; conflicting or inaccessible account settings must be resolved before continuing.
167
-
168
- For a Void platform, Void validates its discovery document, reuses a valid session or opens browser login using the platform's supported providers, and saves the verified API and proxy origins. Credentials are stored in the operating-system keychain for that API origin. A sole login provider is selected automatically.
169
-
170
- The deployment preference is saved in `.void/project.json`. Connecting to another Void platform preserves an existing project link; the CLI explains when that link or an environment override still selects a different destination. Use `void project link` to explicitly choose a project. Cloudflare selection also retains existing Void project metadata so you can switch back later.
171
-
172
- In a non-interactive shell, supply a URL or explicit target. Cloudflare requires usable credentials and an unambiguous account (`CLOUDFLARE_ACCOUNT_ID` when needed). For a Void platform, provide `VOID_TOKEN` with a matching `VOID_API_URL`, or reuse a valid origin-scoped keychain session. Use `void connect <url> --no-login` to save the verified connection without authenticating; this option is only available for Void platforms.
173
-
174
- ## Authentication
175
-
176
- `void auth login`, `void auth status`, and `void auth logout` use the destination
177
- saved for the current project by `void init` or `void connect`. If no destination
178
- is saved, interactive commands let you choose Cloudflare or a connected Void
179
- platform. In a non-interactive shell, pass `--platform cloudflare|void` or use
180
- the explicit `void cloudflare` and `void account` commands. Choosing a destination
181
- for authentication does not change the project's deploy target.
182
-
183
- `void auth whoami`, `void auth link`, and `void auth token` remain supported for
184
- existing scripts. `whoami` follows the selected destination; `link` and `token`
185
- are Void account operations. Prefer `void auth status`, `void account link`, and
186
- `void account token` in new scripts.
187
-
188
- ## Void platform account
189
-
190
- ### `void account login`
191
-
192
- Browser login through one of the platform's currently enabled methods. The token is saved in the operating-system keychain, scoped to the platform origin. Login fails closed when no keychain is available instead of writing the token to a plaintext file; headless environments use `VOID_TOKEN` from their secret manager.
193
-
194
- Set `VOID_API_URL` alongside `VOID_TOKEN` to identify the platform that issued it.
195
- A token without an API URL is only used for Void Cloud's production API; a saved
196
- connection or project cannot forward it to another platform. To use a platform's
197
- saved login instead, unset `VOID_TOKEN`.
198
-
199
- This is optional if you already completed auth during `void connect` or the interactive `void init` flow.
200
-
201
- ### `void account link [connection-id]`
202
-
203
- Link another enabled login method to your current account. Sign in again if your
204
- session is no longer recent, complete the additional provider's browser login,
205
- and confirm the displayed identity. With no connection ID, choose an enabled
206
- method interactively. The optional dashboard exposes the same flow in **Account**.
207
-
208
- ### `void account logout`
209
-
210
- Removes saved credentials.
211
-
212
- ### `void account whoami`
213
-
214
- Prints your current login.
215
-
216
- ### `void account token`
217
-
218
- Copies your human auth token to the system clipboard. It is intended for
219
- interactive troubleshooting and remains subject to login-method revocation. Do
220
- not combine it with a Cloudflare Access service token for CI; machine Access
221
- proof cannot turn a human Void token into an automation identity. Create a
222
- project-scoped credential with `void project token create` instead.
223
-
224
- ## Cloudflare authentication
225
-
226
- Void ships and invokes compatible Cloudflare tooling itself. Users do not need to install or run a separate Cloudflare CLI. Browser credentials are stored in an encrypted file protected by the operating-system keychain. When Void adopts an existing browser session, it persists the secure-storage preference so subsequent logins through compatible tooling use the same credential store.
227
-
228
- - `void cloudflare login` — open a fresh browser OAuth sign-in, including when already signed in. Use this to switch Cloudflare users without first logging out; Void does not remove the prior session before opening sign-in.
229
- - `void cloudflare status` — show the authenticated email, authentication method, accessible account names and IDs, and the pinned deployment account and its source. Credential values are never printed.
230
- - `void cloudflare logout` — remove the local browser session.
231
-
232
- Interactive `void connect --platform cloudflare`, `void init`, and `void deploy --platform cloudflare` invoke the same login flow automatically when necessary. Non-interactive CI must set `CLOUDFLARE_API_TOKEN`.
233
- When a browser session is required, Void opens Cloudflare login immediately and prints `Press Ctrl+C to cancel`; there is no redundant terminal confirmation.
234
-
235
- Signing in changes the browser session, not `account_id` in the project configuration. Check `void cloudflare status` after switching users; if the new user cannot access the pinned account, resolve the project target separately before deploying.
236
-
237
- An API token or global API key pair in the environment takes precedence over browser credentials. Explicit browser login stops with the names of these overrides; remove them from that shell before signing in. `status` reports the active credential source, and `logout` warns if environment credentials remain active. Explicit browser login requires an interactive terminal; automatic deployment checks continue to reuse valid sessions.
238
-
239
- ## Project commands
240
-
241
- ### `void project status [name]`
242
-
243
- Show deployments for the configured target.
244
-
245
- - Void targets show recent hosted deployments; `[name]` looks up a project by slug and otherwise the linked project is used.
246
- - Cloudflare targets list Worker Versions, identify the active version, and show the recorded migration count. A project name is not accepted because the Worker name comes from `cloudflare.name` in `void.config.ts`.
247
-
248
- ### `void project link [name]`
249
-
250
- Link current directory to an existing hosted Void project by slug, or select interactively if omitted. State is stored in `.void/project.json`. Direct Cloudflare apps use `cloudflare.name` in `void.config.ts` and do not need linking.
251
-
252
- ### `void project list`
253
-
254
- List all accessible hosted projects (slug, role, type, URL). Shared projects are included and the role column distinguishes them from projects you own. For a saved Cloudflare target, this displays the current Worker's versions instead because there is no Void project registry.
255
-
256
- ### `void project team`
257
-
258
- Manage access to a project hosted on a Void platform:
259
-
260
- ```sh
261
- void project team list [--project <slug>]
262
- void project team invite <email> --role <reader|collaborator|admin> [--project <slug>]
263
- void project team invitations [--project <slug>]
264
- void project team role <user-id> <reader|collaborator|admin> [--project <slug>]
265
- void project team remove <user-id> [--project <slug>]
266
- void project team revoke <invitation-id> [--project <slug>]
267
- void project team leave [--project <slug>]
268
- void project team pending
269
- void project team accept <invitation-id>
270
- void project team decline <invitation-id>
271
- ```
272
-
273
- Project-scoped commands use `--project`, then `VOID_PROJECT`, then the linked project. Invitations can target only an email address already registered to a user on that platform; they do not create accounts or grant signup access. Only the invited account can accept or decline its invitation.
274
-
275
- Readers can view the project but cannot deploy. Collaborators can deploy and manage deploy prerequisites. Project administrators can additionally manage domains, email destinations, GitHub configuration, and the project team. The owner alone can delete the project. See [Project Collaboration](../guide/project-collaboration.md) for the full role boundaries.
276
-
277
- Project-scoped team management commands are not available for projects deployed
278
- directly to Cloudflare. The account-scoped `pending`, `accept`, and `decline`
279
- commands use the active connection selected by `void connect <url>`, regardless
280
- of the current project's link or deploy target. `VOID_API_URL` takes precedence;
281
- an unscoped `VOID_TOKEN` selects Void Cloud. These commands display their
282
- platform, and accepting an invitation leaves directory links intact. To link
283
- the invited application, run `void project link` in an unlinked checkout of
284
- that application.
285
-
286
- ### `void project zero-trust`
287
-
288
- Inspect or override protection for a project on a Void platform:
289
-
290
- ```sh
291
- void project zero-trust status [--project <slug>]
292
- void project zero-trust protect [--project <slug>]
293
- void project zero-trust public [--project <slug>]
294
- void project zero-trust reconcile [--project <slug>]
295
- ```
296
-
297
- Project selection follows `--project`, then `VOID_PROJECT`, then the linked
298
- project.
299
-
300
- Readers can inspect the state. The owner or a project administrator can protect
301
- the project, make it public, or repair drift. `public` does not change the
302
- platform default for future projects. Deploys and rollbacks wait until a
303
- protection change is finished; if one is refused, the owner or a project
304
- administrator can run `void project zero-trust reconcile` before you retry.
305
- These commands do not apply to direct Cloudflare deployments.
306
-
307
- ### `void project token <create|list|renew|revoke>`
308
-
309
- Manage revocable `aud: deploy` credentials for one Void platform project. The
310
- credential can only call the endpoints used by `void deploy`; it cannot access
311
- operator, account, secret-writing, project-deletion, or other projects' routes.
312
-
313
- ```sh
314
- void project token create --name github-actions --expires-in 30
315
- void project token list
316
- void project token renew <credential-id> --expires-in 30
317
- void project token revoke <credential-id>
318
- ```
319
-
320
- Pass `--project <name>` outside a linked project. Expiry is bounded to 1–90
321
- days. Create and renew display the bearer value once; replace the stored secret
322
- immediately after renewal because the previous credential is revoked in the
323
- same operation. Project deletion and owner suspension also stop its use. Login
324
- method disablement does not revoke these independent deploy credentials.
325
-
326
- Store the printed `VOID_TOKEN` and `VOID_API_URL` in the CI secret manager. The
327
- Access pair passes the perimeter; the scoped Void credential authorizes only
328
- this project's deploy workflow. When prerendering or remote proxy bindings are
329
- used on an Access-protected platform, store `VOID_ACCESS_CREDENTIALS` as an
330
- origin-keyed JSON secret containing both exact HTTPS origins, even if both use
331
- the same service-token pair:
332
-
333
- ```json
334
- {
335
- "https://void-company-api.example.workers.dev": {
336
- "CF_ACCESS_CLIENT_ID": "<service-token client ID>",
337
- "CF_ACCESS_CLIENT_SECRET": "<service-token client secret>"
338
- },
339
- "https://void-company-proxy.example.workers.dev": {
340
- "CF_ACCESS_CLIENT_ID": "<service-token client ID>",
341
- "CF_ACCESS_CLIENT_SECRET": "<service-token client secret>"
342
- }
343
- }
344
- ```
345
-
346
- `VOID_ACCESS_ORIGIN` scopes a pair to one origin, so selecting only the API
347
- origin is insufficient for a workflow that calls the proxy. Use distinct pairs
348
- in the two entries when the Access policies require them.
349
-
350
- ### `void project logs`
351
-
352
- ```
353
- void project logs [--level <level>] [--filter <text>] [--range <duration>] [--deployment <id>]
354
- ```
355
-
356
- Show runtime logs from the deployed target. Hosted Void targets query retained log history. Cloudflare targets open a live tail for the Worker named in `void.config.ts`; they do not provide historical log storage.
357
-
358
- | Flag | Purpose | Default |
359
- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
360
- | `--range <duration>` | How far back to look. Format: `<number><unit>` (m/h/d). Max 7d. | `1h` |
361
- | `--level <level>` | Filter by log level. One of `error`, `warn`, `info`, `log`, `debug`, `all`. `error` also includes uncaught exceptions, non-`ok` outcomes, and any 5xx response — even when the worker neither threw nor logged. | `all` |
362
- | `--filter <text>` | Case-insensitive **substring** match against log message text and exception name/message — not a level filter. Shows the full request entry on any hit. | none |
363
- | `--deployment <id>` | Filter logs to a specific deployment ID. | none |
364
-
365
- Output shows one line per request (`HH:MM:SS METHOD URL STATUS`) with indented console log and exception lines beneath. Errors and exceptions are colored red, warnings yellow.
366
-
367
- Examples:
368
-
369
- ```
370
- void project logs --level error --range 12h
371
- void project logs --level error --filter websocket
372
- ```
373
-
374
- Logs include top-level `console.*` calls and uncaught errors captured by Cloudflare Tail. If you catch an error and save it only to your database, it won't appear here. Also log it with `console.error()` or `logger.error()` from `void/log`.
375
-
376
- For errors that never reach your Worker, such as edge routing errors or static site requests, use `void project requests --status 5xx`.
377
-
378
- On a direct Cloudflare target, `--filter` becomes Cloudflare's live search, `--deployment` selects a Worker Version, and `--level error` selects error invocations. Other individual console levels cannot be filtered, and `--range` does not select history. `void project requests` is hosted-only.
379
-
380
- ### `void project requests`
381
-
382
- ```
383
- void project requests [--status <filter>] [--range <duration>]
384
- ```
385
-
386
- Show request-level traffic recorded at the edge for the linked project: one line per request with time, method, HTTP status, request type, and server timing. Unlike `void project logs` (which only has rows for invoked user workers), this reads the edge request-metering data, so it also surfaces:
387
-
388
- - **5xx the edge router generated itself** — missing deployment manifest, static-asset read timeouts, SSR dispatch timeouts — which never invoke your worker and so never appear in logs.
389
- - **Requests to static/SPA projects**, which are served directly from storage and never run a worker.
390
-
391
- | Flag | Purpose | Default |
392
- | -------------------- | --------------------------------------------------------------------------------------------- | ------- |
393
- | `--status <filter>` | Filter by status: a class (`2xx`, `3xx`, `4xx`, `5xx`) or an exact 3-digit code (e.g. `500`). | none |
394
- | `--range <duration>` | How far back to look. Format: `<number><unit>` (m/h/d). Max 7d. | `1h` |
395
-
396
- Output shows one line per request (`HH:MM:SS METHOD STATUS TYPE DURATION`). 5xx are colored red, 4xx yellow. Note: request paths are not recorded, so this view shows status and type rather than URLs — use `void project logs` for per-URL, per-log detail on requests that do reach your worker.
397
-
398
- Examples:
399
-
400
- ```
401
- void project requests --status 5xx
402
- void project requests --range 24h
403
- ```
404
-
405
- ### `void project rollback [deployId]`
406
-
407
- ```
408
- void project rollback [deployId]
409
- ```
410
-
411
- Roll back to a previous deployment or Worker Version.
412
-
413
- - If `[deployId]` is omitted, shows an interactive select menu of retained deployments
414
- - If the target deployment has fewer applied migrations than the current one, a warning is shown listing the migration diff before confirmation
415
-
416
- On a Void platform, you can select a retained deployment. On Cloudflare, use a complete Worker Version ID or an unambiguous prefix. Void activates that version at 100%. When both versions have complete trigger snapshots, it also restores the selected version's schedules, queues, workflows, routes, and custom domains. Otherwise, rollback keeps the current triggers and restores the code, including versions originally deployed outside Void.
417
-
418
- Rollback doesn't reverse database migrations. If older code may run against a newer schema, or migration metadata is missing, Void explains the risk and asks for confirmation.
419
-
420
- ### `void project cancel [deployId]`
421
-
422
- ```
423
- void project cancel [deployId]
424
- ```
425
-
426
- Cancel an active deployment.
427
-
428
- - If `[deployId]` is omitted, shows an interactive select menu of active deployments for the linked project
429
- - If `[deployId]` is provided, cancels that deployment directly
430
-
431
- This command is hosted-only. Direct Cloudflare deploys are local operations and do not expose a remote build to cancel.
432
-
433
- ### `void project delete [name]`
434
-
435
- Permanently delete a hosted Void project and all its resources (databases, KV namespaces, R2 buckets, deployments). Requires typing the project slug to confirm.
436
-
437
- If `[name]` is omitted, uses the linked project.
438
-
439
- For direct Cloudflare targets this command refuses to run. Inferred resources can be shared, so Void never performs automatic teardown; verify ownership and remove resources explicitly with Cloudflare tooling.
440
-
441
- ### `void project purge-cache`
442
-
443
- ```
444
- void project purge-cache [--project <name>]
445
- ```
446
-
447
- Purge all cached pages for the linked project. The edge cache will clear within seconds.
448
-
449
- If `--project` is provided, purges that project's cache instead of the linked project.
450
-
451
- This command is currently hosted-only. Direct Cloudflare cache purge fails closed with guidance.
452
-
453
- ## Platform management
454
-
455
- Void-managed projects deploy to an explicitly selected platform. Join one with [`void connect`](#connect). Connections are stored per API origin, and credentials are scoped to that origin.
456
-
457
- ### Connection commands
458
-
459
- ```sh
460
- void platform list
461
- void platform use [id]
462
- void platform status [id]
463
- ```
464
-
465
- `use` and `status` auto-select the only configured platform; with multiple platforms they show a picker interactively and require an id or URL in non-interactive use. A project with a recorded platform URL keeps using that platform when the global default changes.
466
-
467
- ### Operator commands
468
-
469
- Use `void platform` to administer the users and apps on your selected platform. Start with the [Platform Administration guide](../guide/platform-administration.md) for signing in, giving people access, and investigating deployments.
470
-
471
- Every command below accepts `--connection <registered-id-or-url>` to select a platform and `--json` for structured output. Without `--connection`, Void uses `VOID_API_URL` if set, then the active platform connection. Application project files do not change this selection.
472
-
473
- #### Making Changes
474
-
475
- Commands that change users, projects, signup access, invitations, or Workers show a preview before asking for confirmation:
476
-
477
- ```sh
478
- void platform user plan <user-id> pro --plan
479
- void platform user plan <user-id> pro --yes
480
- ```
481
-
482
- `--plan` validates the change and prints its effect without applying it. `--yes` applies the change without prompting, which is required in scripts. Use one or the other; they cannot be combined. These flags also apply to deployment cancellation and maintenance commands, but not to authentication commands.
483
-
484
- Each preview and apply request allows five minutes. Set `--timeout <seconds>` to an integer from 1 to 3600 to change that limit. Read requests and individual log polls allow 30 seconds.
485
-
486
- Void does not automatically retry changes. If a request loses its connection or times out, inspect the affected objects and `void platform system events` before repeating it. Partial results describe the work that completed and exit with a nonzero status.
487
-
488
- #### Authentication {#operator-authentication}
489
-
490
- Sign in, inspect your session, or sign out:
491
-
492
- ```sh
493
- void platform auth login [--provider <connection-id>] [--token-stdin]
494
- void platform auth status
495
- void platform auth logout
496
- void platform auth token [--token-stdin]
497
- ```
498
-
499
- With no `--provider`, browser login offers the platform's enabled login methods.
500
-
501
- #### Authentication configuration
502
-
503
- `void platform config auth` opens interactive configuration. These commands use
504
- your administrator session from `void platform auth login`:
505
-
506
- ```sh
507
- void platform config auth list
508
- void platform config auth show company
509
- void platform config auth add google
510
- void platform config auth add oidc --id company
511
- void platform config auth add cloudflare-access --id access
512
- void platform config auth configure company
513
- void platform config auth test company
514
- void platform config auth link company
515
- void platform config auth enable company
516
- void platform config auth disable github
517
- void platform config auth admission
518
- void platform config auth protection show
519
- void platform config auth protection enable --installation <id>
520
- void platform config auth protection disable --installation <id>
521
- void platform config auth recover company --installation <id> --file recovery.json
522
- ```
523
-
524
- When configuring an existing installation for the first time, run
525
- `void platform config auth initialize`, then sign in again. Its current login
526
- methods and signup policy are preserved.
527
-
528
- Adding or editing a method saves a pending configuration. Enabling it verifies the
529
- login in your browser before applying it. Linking the verified identity to your
530
- account is a separate, explicit action. Before disabling a method, verify a linked
531
- alternative; the last method cannot be disabled. Disabling revokes human sessions
532
- created through that method, including operator sessions. Scoped deployment tokens
533
- remain valid; a human login token used as `VOID_TOKEN` is still revoked.
534
-
535
- Commands accept `--connection <registered-id-or-url>` and `--json`. Changes accept
536
- `--plan` or `--yes`. For scripted configuration, use `--file <path>` for the
537
- nonsecret fields and `--client-secret-env <name>` for the environment variable
538
- containing the secret. Omit the secret when editing to retain its saved value.
539
- For `enable` or `link` in scripts, supply `--test-id <id>` from a completed test.
540
- `test --json` returns a browser URL, test ID, and expiry without waiting for completion.
541
-
542
- `admission` chooses invited/allowlisted, company-approved, or public signup.
543
- Company-approved signup creates ordinary accounts automatically when a user
544
- passes a configured company rule. Select an enabled, company-restricted OIDC or
545
- Google Workspace method, or an enabled Cloudflare Access gate. In scripts,
546
- `admission --file <path> --yes` reads a policy such as
547
- `{"mode":"company","connections":["company"],"access":false}`.
548
-
549
- Browser login offers the platform's enabled methods; `--provider <connection-id>` selects one. Login saves a one-hour administrator session in your system keychain. Logout revokes that session and removes its local credential.
550
-
551
- `protection enable` creates or connects Cloudflare Access applications independently
552
- of login methods. Its `--file` accepts the `cloudflareAccess` object described in
553
- [installation setup](../guide/platform/installation/setup.md#choose-login-methods).
554
- Protection changes require installation ownership, the saved recovery credentials,
555
- and a human administrator session. They revoke current human sessions. Before
556
- removing protection, change any signup rule that depends on that gate. Cloudflare
557
- applications are retained for deliberate cleanup.
558
-
559
- `recover <connection-id>` restores an existing administrator when normal login is
560
- unavailable. Its file contains `administratorUserId`, optional nonsecret provider
561
- `configuration`, and an `expectedIdentity` object with exact `issuer` and `subject`
562
- when using `--yes`. Recovery requires Cloudflare management/database authority,
563
- original recovery keys, and a successful browser provider test. Use
564
- `--client-secret-env <name>` for new or rotated credentials.
565
-
566
- `auth token` prints your current operator token. With `--token-stdin`, it exchanges a full administrator API login session from standard input for a new operator token. `auth login --token-stdin` saves the exchanged token to the keychain instead of printing it.
567
-
568
- For automation, supply `VOID_OPERATOR_TOKEN` with an explicit `VOID_API_URL` or `--connection`. Operator tokens are stored separately from application deployment credentials. The API checks your current administrator access on every request. See [Using Scripts](../guide/platform/administration/operations.md#using-scripts) for an example.
569
-
570
- #### Users {#operator-users}
571
-
572
- Find a user by login, email, or ID, then inspect their projects and usage:
573
-
574
- ```sh
575
- void platform user list [--search <text>] [--page <n>] [--limit <n>]
576
- void platform user show <id>
577
- ```
578
-
579
- Use the same ID to change a plan, suspend or restore the account, or delete it:
580
-
581
- ```sh
582
- void platform user plan <id> <free|solo|pro|sponsored|custom>
583
- void platform user suspend <id> [--reason <text>]
584
- void platform user restore <id>
585
- void platform user delete <id>
586
- ```
587
-
588
- Suspending a user blocks their applications. Deleting a user also deletes their project resources. A plan change updates resource limits while preserving any administrator suspension.
589
-
590
- The last active administrator cannot be deleted or suspended. Both previews and
591
- actual mutations enforce this rule, including in the browser admin UI. Allowed
592
- administrator removals revoke administrator access before resource cleanup; if
593
- cleanup fails, access stays revoked and the partial result reports it.
594
-
595
- #### Projects {#operator-projects}
596
-
597
- List projects across the platform, filter them by owner, or inspect one project's resources:
598
-
599
- ```sh
600
- void platform project list [--user <user-id>] [--search <text>] [--page <n>] [--limit <n>]
601
- void platform project show <id>
602
- void platform project delete <id>
603
- void platform project owner <project-id> <user-id>
604
- ```
605
-
606
- Search matches a project's slug, ID, or owner's login. `show` includes resources, domains, the latest 10 deployments, and the latest 20 builds. `delete` removes the project and its resources.
607
-
608
- `owner` transfers a project to another registered user. Preview it with `--plan`; apply it interactively or with `--yes`. The preview reports active-work blockers and the account plan that will apply. The former owner becomes a project administrator, existing project-scoped CI deploy credentials are revoked, and usage already incurred remains with the former owner.
609
-
610
- #### Project Zero Trust {#operator-zero-trust}
611
-
612
- Configure the installation-wide Cloudflare Access policy and project overrides:
613
-
614
- ```sh
615
- void platform zero-trust status [--check]
616
- printf '%s' "$ACCESS_API_TOKEN" | void platform zero-trust configure \
617
- --identity-providers <id[,id...]> \
618
- --policies <id[,id...]> \
619
- [--existing-projects <protected|public>] \
620
- [--protect-new-projects] \
621
- --token-stdin \
622
- --yes
623
- void platform zero-trust reconcile
624
- void platform zero-trust disable
625
-
626
- void platform zero-trust project-status <project-id>
627
- void platform zero-trust project-protect <project-id>
628
- void platform zero-trust project-public <project-id>
629
- void platform zero-trust project-reconcile <project-id>
630
- ```
631
-
632
- Mutations support `--plan`, `--yes`, and `--timeout`; use `--plan` instead of
633
- `--yes` to inspect this change without applying it. The Access management token
634
- is accepted only on standard input. Zero Trust uses the Cloudflare account that
635
- hosts the platform. Omit `--protect-new-projects` to make new projects public
636
- by default. `--existing-projects` is required when you enable Zero Trust and
637
- rejected once it is enabled; later configuration changes keep each project's
638
- protection. `status` reports saved state; `--check` also compares it with
639
- Cloudflare Access. If status remains `configuring` or `disabling`, run
640
- `void platform zero-trust reconcile` to resume the saved operation. Protected
641
- projects support up to 100 custom domains.
642
-
643
- The token needs **Access: Apps and Policies Write** plus **Access:
644
- Organizations, Identity Providers, and Groups Read**, scoped to the platform's
645
- Cloudflare account. Select at least one Allow policy that matches people by
646
- identity; Void rejects Bypass and Service Auth policies and rules that allow
647
- Everyone or any service token. See [Project Zero Trust](../guide/platform/administration/zero-trust.md)
648
- for requirements and recovery.
649
-
650
- #### Deployments {#operator-deployments}
651
-
652
- Find a deployment, inspect its manifest, or request cancellation:
653
-
654
- ```sh
655
- void platform deployment list [--project <id-or-slug>] [--status <status>] [--search <text>] [--page <n>] [--limit <n>]
656
- void platform deployment show <id>
657
- void platform deployment cancel <id>
658
- ```
659
-
660
- Cancellation applies while a deployment is pending, uploading, migrating, or prerendering, and can be requested again while it is canceling. A deployment that has begun switching traffic, is compensating for a failure, or has finished cannot be canceled through this command.
661
-
662
- Read its runtime logs with:
663
-
664
- ```sh
665
- void platform deployment logs <id> [--since <time>] [--cursor <cursor>] [--limit <n>] [--follow]
666
- ```
667
-
668
- The default is the last hour, oldest first, with up to 100 records. `--since` accepts a duration such as `10m`, `2h`, or `1d`, an ISO date, or epoch milliseconds. Set `--limit` from 1 to 500 and pass the response's `nextCursor` as `--cursor` to read another page.
669
-
670
- `--follow` reads the remaining pages and checks for new logs every two seconds until you press Ctrl+C. It checks a five-minute overlap for delayed records and suppresses replayed rows. Records that arrive later may need a subsequent historical query. Following stops with an error if a window exceeds 10,000 records; use a narrower historical query in that case.
671
-
672
- #### Builds {#operator-builds}
673
-
674
- Inspect a build or read its output:
675
-
676
- ```sh
677
- void platform build show <id>
678
- void platform build logs <id> [--since <sequence>] [--limit <n>] [--follow]
679
- ```
680
-
681
- Build logs start at sequence `0` and return up to 500 lines. Use the returned `lastSeq` as `--since` to continue; `--limit` accepts 1 to 500. Container log retrieval requires managed builds to be enabled. GitHub Actions builds return an external log URL.
682
-
683
- Following waits for the final logs after the build becomes terminal. If completion cannot be confirmed within two minutes, the command exits with an error. Older builds without a completion signal may wait for 30 seconds without new lines before following stops.
684
-
685
- #### Signup Access {#operator-signup}
686
-
687
- Inspect signup restrictions, open signup to everyone, or require an allowlist match:
688
-
689
- ```sh
690
- void platform signup show
691
- void platform signup open
692
- void platform signup restrict
693
- ```
694
-
695
- Add and remove GitHub or email entries by their type and pattern:
696
-
697
- ```sh
698
- void platform signup allow <github|email> <pattern> [--note <text>]
699
- void platform signup disallow <github|email> <pattern>
700
- void platform signup remove <github|email> <pattern>
701
- ```
702
-
703
- `remove` remains available as an alias for existing scripts. GitHub entries match a login. Email entries match an address or a domain pattern such as `*@example.com`, across sign-in providers. Quote wildcard patterns in your shell.
704
-
705
- For an OIDC identity that has no verified email, grant access using its configured connection ID and stable provider subject:
706
-
707
- ```sh
708
- void platform signup allow identity <connection-id> <subject> [--note <text>]
709
- void platform signup disallow identity <connection-id> <subject>
710
- ```
711
-
712
- Connection IDs are shown by `void platform config auth list`. Identity subjects match exactly and case-sensitively; wildcards, email inference, and account linking are not applied. The login method's domain or group restrictions must still pass, and a newly admitted account has the ordinary user role. Under invited/allowlisted signup, an empty allowlist blocks new accounts. Under company-approved signup, explicit grants admit people in addition to the company rules.
713
-
714
- #### Invitations {#operator-invitations}
715
-
716
- Invite people by email and track whether they have joined:
717
-
718
- ```sh
719
- void platform invitation list [--page <n>] [--limit <n>]
720
- void platform invitation send <email[,email...]>
721
- void platform invitation revoke <id>
722
- ```
723
-
724
- Send accepts up to 100 comma-separated addresses. Invitations grant signup access even if email delivery is unavailable or fails; delivery is reported separately. Share the platform's `/invite` page or `void connect '<platform URL>'` command yourself when no email is sent. Revoking a pending invitation removes its exact email grant. A broader domain entry can still allow that person to sign up.
725
-
726
- #### Email {#operator-email}
727
-
728
- Decide who mail from the shared sender may reach, who registers email domains, and a project's outbound caps:
729
-
730
- ```sh
731
- void platform email policy
732
- void platform email policy-set <verified|domains|any> [--domains <domain[,domain...]>]
733
- void platform email settings
734
- void platform email settings-set --domains <self-serve|admin>
735
- void platform email limit <project-id|slug> [--monthly <n>] [--burst <n>]
736
- void platform email logs <project-id|slug> [--page <n>] [--limit <n>] [--json]
737
- void platform email attempts [--project <id|slug>] [--page <n>] [--limit <n>]
738
- void platform email attempt-resolve <attempt-id> --ended --reason <text>
739
- void platform email operation-resolve <operation-id> --ended --outcome <applied|not-applied> --reason <text>
740
- ```
741
-
742
- `policy` decides which recipients a project's `<slug>+tag@<mail domain>` sender reaches: `verified` (the default) means only that project's verified destinations; `domains` adds every address on the listed domains; `any` lifts the check. Neither widens delivery to addresses on the platform's own mail domain: those stay verified-destination-only, so no project reaches another project's inbox without its consent. Cloudflare still refuses a destination it has not verified until the platform mail domain is onboarded for Email Sending, so under `domains` or `any` such refusals arrive as per-recipient `UNVERIFIED_DESTINATION` results. Custom-domain sends are not affected.
743
-
744
- `settings-set --domains admin` tells `void email domain add` to print the administrator's command instead of starting token setup. `limit` overrides the project's monthly and rolling 60-second caps (defaults 200 and 10); a project page in the admin UI shows and clears them.
745
-
746
- `logs` inspects retained receipt and recipient outcomes, including operation IDs, provider references, error codes, and policy versions. Pages contain at most 100 records, newest first; use `--json` for all fields. After project deletion, use its project ID to inspect metadata until the 30-day retention period expires. Message content and credentials are never included.
747
-
748
- `attempts` lists interrupted provider calls and their earliest resolution time. Once
749
- the original Worker execution has ended and the attempt is at least 24 hours old,
750
- `attempt-resolve` records `outcome_unknown`, retains its quota charge, and releases
751
- the project/domain cleanup fence. `--ended` is your attestation that the call is no
752
- longer active; `--reason` is stored in the operator audit log. Keep recipient
753
- addresses and message content out of the reason. The send is never retried. Use
754
- `--plan` to preview and `--yes` to apply without a prompt.
755
-
756
- `operation-resolve` recovers a Cloudflare routing, Worker, secret, catch-all, or
757
- Sending mutation whose outcome remains unknown. After the original execution
758
- has ended and the operation is at least 24 hours old, inspect the exact resource
759
- named by the preview and attest whether its write was `applied` or `not-applied`.
760
- Applied writes continue at the next step; not-applied writes retry the same
761
- persisted intent. The running platform version must match that intent, so restore
762
- the matching version before recovering an operation created by older code. The
763
- preview pins the step, attempt, connection and route generations, resource
764
- identity, and digest used by the apply request. Time alone never retries a write.
765
-
766
- Register and maintain email domains for projects whose owners hold no Cloudflare credential:
767
-
768
- ```sh
769
- void platform email domains [--project <id|slug>]
770
- void platform email domain-add <domain> --project <id|slug> [--token-stdin]
771
- void platform email domain-status <domain>
772
- void platform email domain-sync <domain>
773
- void platform email domain-rotate-secret <domain>
774
- void platform email domain-remove <domain> [--token-stdin]
775
- ```
776
-
777
- `domain-add` uses the platform's Cloudflare credential for zones in its account. For another account, pipe a scoped Cloudflare API token on standard input with `--token-stdin --yes`. Name the exact mail domain (`mail.example.com`, or the apex when it receives no mail yet). `domain-status` shows inbound, outbound, and credential-management readiness with the latest operation. A blocked operation resumes through `domain-sync`; a blocked rotation resumes through `domain-rotate-secret`, preserving already confirmed steps and its staged credential. An uncertain operation remains stopped until read-back proves the result or an administrator uses `operation-resolve`. Domains an administrator adds show `managed_by: admin`; their owners can list and inspect them but use these commands for `sync`, `domain-rotate-secret`, and `remove`.
778
-
779
- If project deletion leaves cleanup blocked by an expired or revoked Cloudflare token, use `domain-remove <domain> --token-stdin --yes` with a replacement scoped to the same account and zone. This resumes the retained cleanup only when no other project uses the connection. For a live project, renew its token through `domain-add` instead.
780
-
781
- #### System {#operator-system}
782
-
783
- Inspect activity, check service health, or review administrative changes:
784
-
785
- ```sh
786
- void platform system overview
787
- void platform system health
788
- void platform system cli-versions
789
- void platform system events [--page <n>] [--limit <n>]
790
- void platform system backfill-queue-tokens
791
- void platform system sandbox-drain [--cursor <opaque-cursor>]
792
- ```
793
-
794
- `overview` shows platform totals and recent activity. `health` checks the configured services and database, and exits with a nonzero status if a check fails. `cli-versions` reports the CLI versions used by deployments.
795
-
796
- `events` shows the administrator, target, and outcome of changes. A pending event means the outcome has not been recorded. Previews and session login/logout do not create these events. `backfill-queue-tokens` repairs older queue entries that are missing authentication tokens and supports `--plan` before applying the repair.
797
-
798
- Use `sandbox-drain` when an upgrade from the legacy tenant-owned Sandbox runtime asks you to finish cleanup. Preview with `--plan`; pass the returned `nextCursor` as `--cursor` to inspect later pages. Apply with `--yes` and rerun until it reports `complete: true`, then rerun the interrupted upgrade. Application traffic stays paused during cleanup, while administrator login remains available. The completed upgrade enables the current managed Sandbox controller automatically.
799
-
800
- Use the [platform lifecycle commands](#lifecycle-commands) to maintain your installation's Workers.
801
-
802
- #### Hosted Workers {#operator-workers}
803
-
804
- The following commands manage the Workers of the hosted Void Cloud platform.
805
- They are unavailable on a self-hosted installation; use the
806
- [lifecycle commands](#lifecycle-commands) there instead.
807
-
808
- ```sh
809
- void platform worker list [--environment <production|staging>]
810
- void platform worker show <worker-name> [--environment <production|staging>]
811
- void platform worker rollback <worker-name> <version-id> [--environment <production|staging>]
812
- void platform worker rollback-all [--environment <production|staging>]
813
- void platform worker events [batch-id] [--environment <production|staging>]
814
- ```
815
-
816
- Use a name from `worker list`, such as `api` or `proxy`. `show` lists its
817
- versions and current deployment. Preview either rollback with `--plan`, then
818
- apply it interactively or with `--yes` in a script. `events` lists worker
819
- operation events or inspects one batch by ID.
820
-
821
- #### Pagination and JSON
822
-
823
- User, project, deployment, invitation, and event lists default to page `1` with 20 items. `--limit` accepts 1 to 100 for these lists. Their JSON responses include the page, limit, and total count.
824
-
825
- With `--json`, results go to standard output and command errors go to standard error as JSON. Errors and partial failures exit with a nonzero status. An unhealthy `system health` result stays on standard output and also exits nonzero. Log following writes one JSON object per response, including each page and empty responses.
826
-
827
- ### `void platform install`
828
-
829
- ```sh
830
- void platform install [options] [--yes]
831
- ```
832
-
833
- | Option | Purpose |
834
- | --------------------------------- | ------------------------------------------------------------------------------------ |
835
- | `--name <slug>` | Installation name used in `void-<name>-<role>` resource names; choose an unused name |
836
- | `--display-name <name>` | Human-readable platform name |
837
- | `--account <id>` | Cloudflare account id |
838
- | `--auth-config <path>` | Login methods, signup policy, and environment references for provider secrets |
839
- | `--application-domain <domain>` | Base domain for deployed apps |
840
- | `--workers-dev` | Explicit testing mode; add an application domain later |
841
- | `--zone <domain>` | Cloudflare zone containing the application domain |
842
- | `--dedicated-zone` | Add zone-wide catch-all routes; valid only when the app domain is the whole zone |
843
- | `--control-plane-domain <domain>` | Optional API custom hostname; defaults to `workers.dev` |
844
- | `--plan` | Resolve and print a read-only plan |
845
- | `--resume` | Continue the matching checkpointed installation |
846
- | `--runtime <path>` | Deploy a locally built, integrity-checked runtime directory |
847
- | `--yes` | Acknowledge Cloudflare changes in non-interactive use |
848
-
849
- For a first installation, follow [Install a Void Platform](../guide/self-hosted-platform.md). The interactive installer recommends using a domain and offers **Use workers.dev for testing** as a visible alternative. Void creates the platform infrastructure and tables. External PostgreSQL and a configured login method are required in either mode; GitHub OAuth is the default login choice, not a requirement. `--workers-dev` skips zone/DNS/certificate operations and cannot be combined with `--application-domain`, `--zone`, or `--dedicated-zone`.
850
-
851
- Read-only plans, workers.dev installations with the default API hostname, and supported lifecycle operations can use Cloudflare browser login and the system keychain. Installation that writes DNS or creates a zone needs an explicit management token through `CLOUDFLARE_API_TOKEN` or `CF_API_TOKEN`.
852
-
853
- The installed platform needs a separate runtime token to provision resources for apps. The interactive installer prompts for it and the other setup values. For non-interactive installs, inject the variables listed in [Install from CI](../guide/platform/installation/ci.md).
854
-
855
- 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.
856
-
857
- `--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.
858
-
859
- 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.
860
-
861
- 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.
862
-
863
- 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.
864
-
865
- During interactive installation, choose whether Void creates Hyperdrive or uses an existing one. The installer lists the account's Hyperdrive configurations, suggests a matching generated name when present, and lets you select any configuration. Review its database, host, port, runtime user, and cache setting before confirming; its name need not match the installation name. If you need to create a separately managed configuration, Void shows setup instructions and stops before provisioning. Supply an owner PostgreSQL URL at the normal prompt for database claims and migrations. Void adopts the selected Hyperdrive after verifying its database origin and disabled SQL result caching; its configuration stays under the external manager's control. Unattended installs can set `VOID_PLATFORM_HYPERDRIVE_ID`, `VOID_PLATFORM_HYPERDRIVE_ORIGIN_HOST`, and `VOID_PLATFORM_HYPERDRIVE_ORIGIN_USER` together.
866
-
867
- Recovery secrets are encrypted with AES-256-GCM using a key in your system keychain. The encrypted data is tied to the installation identity. Without a keychain, supply a canonical base64-encoded 32-byte `VOID_PLATFORM_RECOVERY_KEY`; otherwise Void stops before saving secrets. CI can generate a temporary key when its original credentials remain in protected secrets.
868
-
869
- If a newly created zone is waiting for registrar delegation, resume after it becomes active:
870
-
871
- ```sh
872
- void platform install --resume --name <installation-id>
873
- ```
874
-
875
- See [Self-host a Void platform](../guide/self-hosted-platform.md) for prerequisites, token scope, exact footprint, domain behavior, and an end-to-end walkthrough.
876
-
877
- ### `void platform domain set`
878
-
879
- ```sh
880
- void platform domain set <domain> [--installation <id>] [--zone <domain>] [--dedicated-zone] [--plan] [--yes]
881
- ```
882
-
883
- Add an application domain to a workers.dev test platform. Domain-based installations remain the recommended default. The command detects the zone when possible, creates missing DNS and routes after confirmation, and checks HTTPS and project Zero Trust protection before making the domain canonical. If DNS, certificates, or protection are pending, rerun the same command to resume. `--plan` is read-only; non-interactive mutations require `--yes`.
884
-
885
- Existing workers.dev URLs remain available, and the platform API origin, OAuth callback, projects, and deployments stay unchanged. The command verifies the running runtime token's Cache Purge permission for the new zone. A disabled platform stays disabled. Use the database URL from the original installation when administering from another machine. Replacing an already configured application domain is not supported. See [Adding a Domain](../guide/platform/installation/domains.md#adding-a-domain).
886
-
887
- ### Lifecycle commands
888
-
889
- Use these commands to recover, update, pause, or remove an installation:
890
-
891
- ```sh
892
- void platform discover [--account <id>] [--installation <id-or-name>]
893
- void platform upgrade [id] [--runtime <path>] [--plan] [--yes]
894
- void platform rollback [id] --runtime <earlier-path> [--from-runtime <current-path>] [--plan] [--yes]
895
- void platform repair [id] [--runtime <path>] [--plan] [--yes]
896
- void platform disable [id] [--plan] [--yes]
897
- void platform enable [id] [--runtime <path>] [--plan] [--yes]
898
- void platform uninstall [id] [--plan] [--purge-data] [--keep-zone] [--yes]
899
- ```
900
-
901
- `discover --installation` limits recovery and endpoint verification to one installation in a shared Cloudflare account.
902
-
903
- Omit `id` when only one installation is configured, or choose from the interactive picker. Non-interactive commands need an ID when several installations exist. Commands that make changes also require `--yes`; `--plan` only previews changes.
904
-
905
- After discovery on another machine, set `VOID_PLATFORM_DATABASE_URL`. An upgrade that preserves every deployed Worker also preserves its secrets. For an email-enabled installation without its encrypted recovery file, restore `VOID_PLATFORM_EMAIL_SIGNING_SECRET`; recreating only the email gateway needs that key and does not need the Cloudflare runtime token or JWT signing key. Recreating the API or proxy also requires the email key when email is enabled, in addition to their normal secrets. Recreating the API requires its original runtime-token, GitHub, R2, JWT, and project-encryption values; recreating the proxy requires the runtime token and JWT signing key.
906
-
907
- | Command | Behavior |
908
- | ----------- | --------------------------------------------------------------------------------------------- |
909
- | `discover` | Verifies remote ownership and restores local installation records without downloading secrets |
910
- | `repair` | Recreates missing resources owned by the installer |
911
- | `upgrade` | Deploys the selected runtime and supported pending migrations |
912
- | `rollback` | Restores a declared-compatible earlier runtime without reversing PostgreSQL migrations |
913
- | `disable` | Blocks platform traffic through routing storage without removing data |
914
- | `enable` | Restores traffic after checking the platform |
915
- | `uninstall` | Blocks traffic and removes eligible resources, retaining data by default |
916
-
917
- Repair and upgrade preserve disabled state. New, resumed, and previously disabled installations block user traffic until all target Workers pass verification; the installer's health probes can still run. Routes and custom domains remain attached.
918
-
919
- Commands preserve existing routes and domains, verify the configured database, and coordinate concurrent administrators before making changes.
920
-
921
- `--runtime` selects a custom platform build. Relative paths resolve from your current directory. Void verifies the build before making changes; see [Platform Development](../guide/platform/development/runtime.md#deploying-your-runtime) for creating one.
922
-
923
- Without `--runtime`, the CLI uses its packaged platform version.
924
-
925
- Platform migrations only move forward. Void checks compatibility before updating the database and tells you if an intermediate release is needed.
926
-
927
- An upgrade completes after the new Workers pass health checks. If rollout fails, Void attempts to restore the previous Workers. Retrying does not repeat completed migrations.
928
-
929
- `platform rollback` restores a compatible earlier runtime without reversing database migrations. Pass its files with `--runtime`. If the installed version is a custom build, also supply that version with `--from-runtime`. Void refuses targets that are incompatible with the current database or predate installed authentication, sandbox-drain, or ownership-aware usage protocols. A later `upgrade` can move forward again.
930
-
931
- Uninstall verifies remote ownership before removing anything. Data resources are retained unless you pass `--purge-data`. Workers, the Queues they use, R2, AI Gateway, DNS records, routes, custom domains, adopted resources, external PostgreSQL, and zones are always retained for manual review.
932
-
933
- Resources that may have been shared or repurposed are retained for manual review. Platform traffic stays blocked. External PostgreSQL and its data are never deleted.
934
-
935
- See [Disable and Uninstall](../guide/platform/installation/uninstall.md#remove-retained-resources) for the full removal policy and the cleanup order.
936
-
937
- ## Deploy
938
-
939
- ### `void deploy`
940
-
941
- ```
942
- void deploy [--project <name>] [--dir <path>] [--spa] [--skip-build] [--debug]
943
- void deploy [--platform <cloudflare|void>] [--require-email]
944
- void deploy --platform cloudflare --atomic
945
- ```
946
-
947
- Auto-detects your project type and chooses the right pipeline. See [Supported App Types](../guide/app-types.md) and [Deployment](../guide/deployment.md) for details.
948
-
949
- An unlinked project with a root `wrangler.jsonc`, `wrangler.json`, or a single root `wrangler*.json(c)` file explicitly referenced by a supported framework adapter gets a prompt to link and deploy to Cloudflare using its existing Worker and resources. Accepting verifies the target, saves Cloudflare as the destination, and continues deployment. A failed build retains the link for retry. Declining changes nothing. Explicit platform/project selections and saved destinations take precedence; CI must select a destination explicitly.
950
-
951
- The first handoff preserves production bindings, variables, secrets, event handlers, and triggers. The active version must be the latest uploaded version so inherited secrets have an unambiguous source. Apart from an explicitly enabled ISR cache, new resources, migrations, runtime features, auth setup, or local secret overrides must be handled separately. See [Deploy an existing Worker](../integrations/cloudflare.md#deploy-an-existing-worker).
952
-
953
- When prerendered or revalidated pages need a cache during migration, Void asks whether to enable ISR and saves `routing.isr` in `void.config.ts`. Yes provisions the KV cache during this handoff; No keeps ISR disabled on every later deploy until you change the setting. CI must set `routing.isr` explicitly if a pending migration has no saved choice. Existing ISR namespaces are reused; application KV bindings are still required.
954
-
955
- For Drizzle projects, deploy performs a read-only schema drift check. If a new migration would be generated, deploy stops and tells you to run `void db generate`, review the migration, commit it yourself, and rerun `void deploy`.
956
-
957
- | Flag | Purpose |
958
- | ------------------------------- | -------------------------------------------------------------------------------------------------- |
959
- | `--platform <cloudflare\|void>` | Override the platform stored in `.void/project.json` |
960
- | `--project <name>` | Target a specific Void project by slug; not supported with `--platform cloudflare` |
961
- | `--dir <path>` | Deploy a pre-built static directory (skips build) |
962
- | `--spa` | Use SPA mode instead of SSG for static deploys |
963
- | `--skip-build` | Skip the build step; on Cloudflare this is supported for static/SPA/SSG deploys only |
964
- | `--require-email` | Fail when email cannot be set up instead of deploying without it; requires `--platform cloudflare` |
965
- | `--atomic` | Publish an existing Durable Object Worker directly; readiness is checked after traffic changes |
966
- | `--debug` | Mirror the structured deploy log to stderr (also written to `~/.void/logs/`) |
967
-
968
- `--atomic` applies to one deployment. For an existing Durable Object Worker that consistently cannot stage, set `deploy: { cloudflare: { mode: 'atomic' } }` in `void.config.ts` so plain `void deploy` uses atomic publication. The default is `staged`.
969
-
970
- The older `--backend cloudflare` spelling remains available as a compatibility alias for `--platform cloudflare`.
971
-
972
- Every deploy writes a structured JSONL trace to `~/.void/logs/deploy-<timestamp>.jsonl` regardless of `--debug`. On failure the path is printed at the end of the error message so you can attach it when reporting platform issues. `VOID_DEPLOY_DEBUG=1` is accepted as an alternate trigger for stderr mirroring.
973
-
974
- Cloudflare upload failures include a detailed error message and stack locations when available. Use that message to identify the cause; the numeric error code alone may not be sufficient. The details are also available in the deploy log.
975
-
976
- When a deploy fails after it starts, the CLI also prints a summary of that trace under the error, so the cause is visible where the file is not — a CI runner, for example, is discarded with the job. The summary has two blocks: every `error` record with its flattened cause chain, then the last 20 records as a timeline.
977
-
978
- Pre-flight failures print no summary. A missing project, a rejected flag combination, or an unsupported `--platform cloudflare` feature stops before any trace exists, and each of those prints its own message explaining what to change. A build failure prints no summary either — the build streams its own output straight to the terminal.
979
-
980
- Void masks the credentials it emits itself: signed query parameters, bearer tokens, and any field whose key names a credential.
981
-
982
- Masking your own values is left to your CI platform, which holds the secrets and masks them before the log is written. GitHub Actions does this for everything under `secrets.*`. Void does not guess at credential-shaped variable names, and it does not parse credentials out of values you supplied — a password inside a `DATABASE_URL` in your build command prints as written. Register such values as CI secrets, or keep them out of the build command.
983
-
984
- ```
985
- ■ deploy: Deploy failed: deploy in progress
986
- │ Deployment: dpl_7zgitxdrxxz9
987
- │ Detailed log: ~/.void/logs/deploy-2026-08-21T03-24-19-764Z.jsonl
988
- │
989
- │ Errors
990
- │ 9.0s deploy_server_error
991
- │ deploymentId=dpl_7zgitxdrxxz9
992
- │ message=deploy in progress
993
- │
994
- │ Last 20 of 26 entries
995
- │ 8.4s info finalize_start assets=98 workers=0
996
- │ 8.6s info stream_deployment_id deploymentId=dpl_7zgitxdrxxz9
997
- │ 9.0s error deploy_server_error message=deploy in progress
998
- ```
999
-
1000
- Platform resolution precedence:
1001
-
1002
- 1. `--platform <cloudflare|void>` (or the legacy `--backend cloudflare` alias)
1003
- 2. `platform` in `.void/project.json`
1004
- 3. Void for projects initialized by an older SDK without a saved platform
1005
-
1006
- Selecting Skip deployment setup stores `"platform": "none"`; a later `void deploy` stops with guidance until a platform override is provided.
1007
-
1008
- For the Void platform, project resolution precedence is:
1009
-
1010
- 1. `--project <name>`
1011
- 2. `VOID_PROJECT`
1012
- 3. linked project in `.void/project.json`
1013
-
1014
- If no project is linked and no override is provided, CLI prompts to link or create one. In CI (non-TTY), `void deploy` errors out instead — set `VOID_PROJECT` or pass `--project <slug>`.
1015
-
1016
- A new project's slug is lowercase alphanumeric with interior dashes, at most 56 characters — it is also the project's email sender, `<slug>+noreply@<mail domain>`, and that local part must fit RFC 5321's 64 octets. Slugs of 5 characters or fewer need a paid plan. Creating a project also registers the owner's own email address as a recipient (see `void email allow`); the CLI says so, and `void email destinations` shows whether it is verified yet.
1017
-
1018
- That fallback is mainly for projects that skipped Void project setup during `void init`.
1019
-
1020
- ### `void deploy --platform cloudflare`
1021
-
1022
- Build and deploy to your Cloudflare account using `void.config.ts`:
1023
-
1024
- ```sh
1025
- void deploy --platform cloudflare
1026
- void deploy --platform cloudflare --require-email # fail instead of deploying without email
1027
- ```
1028
-
1029
- Void signs you in through your browser when needed and saves the selected account. In CI, set `CLOUDFLARE_API_TOKEN` and, if the token can access several accounts, `CLOUDFLARE_ACCOUNT_ID`.
1030
-
1031
- | Option or setting | Cloudflare behavior |
1032
- | ------------------------------ | -------------------------------------------------------------------------------------- |
1033
- | `--dir`, `--spa` | Deploy static output through a small Worker and Workers Assets |
1034
- | `--skip-build` | Reuse existing static, SPA, or SSG output; unavailable for Worker apps |
1035
- | `--project` | Unavailable; the Worker and account come from `void.config.ts` and `void.lock.json` |
1036
- | Named environments | Unavailable; use the top-level `cloudflare` config |
1037
- | `CLOUDFLARE_WORKERS_SUBDOMAIN` | Needed in fresh CI when versions have no preview URL; cached locally after a deploy |
1038
- | `--require-email` | Fail instead of deploying without email when the email step cannot run, as in CI |
1039
- | `DATABASE_URL` | Required in the deploy environment for PostgreSQL or MySQL provisioning and migrations |
1040
-
1041
- The token needs Workers Scripts: Edit, read access to bound resources, and edit permissions for products Void provisions. First-time Hyperdrive provisioning specifically needs `CLOUDFLARE_API_TOKEN` with Hyperdrive edit permission, or an existing config ID in `cloudflare.hyperdrive` in `void.config.ts`.
1042
-
1043
- Email setup needs a browser session from `void cloudflare login`, which carries the Email Routing and Email Sending scopes (a session created by older Cloudflare tooling lacks them: `void cloudflare logout`, then sign in again), or a `CLOUDFLARE_API_TOKEN` that also has Email Routing Edit and Email Sending Edit. A Global API Key pair is refused.
1044
-
1045
- 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.
1046
-
1047
- 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.
1048
-
1049
- 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.
1050
-
1051
- 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.
1052
-
1053
- 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.
1054
-
1055
- 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.
1056
-
1057
- `.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.
1058
-
1059
- Existing remote secrets are preserved. Void also preserves or creates `BETTER_AUTH_SECRET` for auth apps.
1060
- If a failed upload leaves a newer inactive version, later deployments inherit secret bindings from the live version without requiring their plaintext values.
1061
-
1062
- **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.
1063
-
1064
- 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.
1065
-
1066
- ## Database
1067
-
1068
- ### `void db push`
1069
-
1070
- Apply your Drizzle schema directly to the development database without creating migration files. D1 updates the local database; PostgreSQL and MySQL use `DATABASE_URL` from `.env`.
1071
-
1072
- Use this for quick schema iteration while prototyping. Before deploying, generate and review migration files with `void db generate`.
1073
-
1074
- ### `void db generate`
1075
-
1076
- Generate SQL migration files from schema changes.
1077
-
1078
- The command compares your current `db/schema.ts` or `db/schema/` modules against the last generated Drizzle snapshot and writes new migration artifacts under `db/migrations/`. When Void-managed auth is enabled, it also resolves the Better Auth schema in production mode and includes those tables automatically, including configured renames and plugin tables. This works for auth-only apps without an application schema. Review and commit the generated files before deploying.
1079
-
1080
- For SQLite, Void checks that the migration history applies to a fresh database. If generation fails this check, the previous SQL, snapshots, and journal are restored. If an existing migration fails, repair that unapplied migration first: rerunning generation compares snapshots and does not repair existing SQL. This check does not verify that a migration preserves existing data; review table rebuilds and foreign-key actions carefully.
1081
-
1082
- ### `void db status`
1083
-
1084
- Show migration status. Displays which migrations are applied or pending locally, then uses the saved deployment target for remote status: the hosted API for Void projects, the pinned D1 database and its configured migration table for direct Cloudflare SQLite projects, or the shell `DATABASE_URL` for direct Cloudflare PostgreSQL/MySQL projects. If the remote credential or service is unavailable, local status is still shown.
1085
-
1086
- ### `void db reset`
1087
-
1088
- Drop the local D1 database and re-apply all migrations. Does not affect the remote database.
1089
-
1090
- ### `void db seed`
1091
-
1092
- ```
1093
- void db seed [--file <path>]
1094
- ```
1095
-
1096
- Reset the local database, re-apply all migrations, then execute a seed file.
1097
-
1098
- If `--file` is omitted, Void looks for default seed files in this order: `db/seed.ts`, `db/seed.mts`, `db/seed.js`, `db/seed.mjs`, `db/seed.sql`.
1099
-
1100
- If more than one default seed file exists, the CLI stops and asks you to pass `--file <path>`.
1101
-
1102
- Programmatic seed modules must export either a default function or a named `seed` function.
1103
-
1104
- ### `void db execute`
1105
-
1106
- ```
1107
- void db execute <sql>
1108
- void db execute --file <path>
1109
- void db execute --remote <sql>
1110
- ```
1111
-
1112
- Run ad-hoc SQL against the database. Provide SQL inline or from a file. SELECT queries display results as a formatted table; other statements execute silently.
1113
-
1114
- By default, targets the local database. Pass `--remote` to run against the deployed database selected in `.void/project.json`:
1115
-
1116
- - **Void platform D1 projects**: routes the query through the selected platform's registered proxy using your auth token. Void Cloud's proxy is `proxy.void.cloud`; a self-hosted platform uses its own proxy URL.
1117
- - **Direct Cloudflare D1 projects**: invokes Cloudflare against the pinned D1 binding from `void.config.ts` or `void.lock.json`.
1118
- - **Hosted PostgreSQL and MySQL projects**: fetches the stored connection string from the platform and connects directly.
1119
- - **Direct Cloudflare PostgreSQL and MySQL projects**: uses `DATABASE_URL` from the current shell; Cloudflare cannot return the password from Hyperdrive.
1120
-
1121
- For destructive statements (`DELETE`, `UPDATE`, `DROP`, etc.) when running in a TTY, you will be prompted to confirm before the query is sent to the deployed database. Non-TTY environments (CI) skip the prompt.
1122
-
1123
- ### `void db migrate`
1124
-
1125
- ```
1126
- void db migrate [--remote]
1127
- ```
1128
-
1129
- Apply pending migrations to the local database without resetting. Unlike `void db reset`, this preserves existing data and only runs migrations that haven't been applied yet.
1130
-
1131
- Pass `--remote` to apply pending migrations to the saved target. Hosted projects require a Void login and link. Direct Cloudflare D1 projects use the binding's configured migration directory, table, and pattern; direct PostgreSQL and MySQL projects use the shell `DATABASE_URL`.
1132
-
1133
- ### `void db studio`
1134
-
1135
- ```
1136
- void db studio [--remote]
1137
- ```
1138
-
1139
- Open [Drizzle Studio](https://orm.drizzle.team/docs/drizzle-kit-studio) for the database. Launches a web-based GUI for browsing and editing your data.
1140
-
1141
- By default, targets the local database. Pass `--remote` to open Studio against the deployed database:
1142
-
1143
- - **PostgreSQL and MySQL projects**: fetch the stored connection string from the platform and open Studio against it. If the URL isn't stored yet, run `void db set-url` first.
1144
- - **D1 projects**: remote Studio is not yet supported. Use `void db execute --remote` for ad-hoc queries against your deployed D1 database.
1145
-
1146
- On direct Cloudflare PostgreSQL/MySQL targets, remote Studio uses `DATABASE_URL` from the current shell. Direct D1 Studio remains unsupported; use `void db execute --remote`.
1147
-
1148
- ### `void db rename-migrations`
1149
-
1150
- Rename existing migrations from the old numeric prefix format (`0001_name.sql`) to timestamp-based format (`20260410161500_name.sql`). Updates local tracking table and remote records if logged in with a linked project.
1151
-
1152
- ### `void db connect`
1153
-
1154
- Connect an existing PostgreSQL/MySQL database or provision one through an adapter:
1155
-
1156
- ```sh
1157
- void db connect 'postgresql://user:password@host/database'
1158
- NEON_API_KEY=... void db connect --provider neon --name my-app
1159
- void db connect --provider @acme/void-db-provider --region region-id
1160
- ```
1161
-
1162
- The command saves `DATABASE_URL` in `.env`. When authenticated with a linked Void project, it also updates the encrypted deployment URL; pass `--local-only` to skip that sync. `neon` is built in. Other adapters are project dependencies or local modules exporting a `DatabaseProviderAdapter` from `void/database-provider`.
1163
-
1164
- Provider-created credentials are never printed. For direct Cloudflare deploys, configure the same URL as a protected `DATABASE_URL` in the shell or CI environment that runs deploy.
1165
-
1166
- ### `void db set-url`
1167
-
1168
- Update the PostgreSQL or MySQL connection string for deployment. Available for projects with `"database": "pg"` or `"database": "mysql"`.
1169
-
1170
- Prompts for a connection string and sends it to the platform API to create or update the Hyperdrive configuration.
1171
-
1172
- ### `void db export`
1173
-
1174
- ```
1175
- void db export [--output <path>] [--no-data] [--no-schema] [--table <name>]
1176
- ```
1177
-
1178
- Dump the local database as SQL. Outputs to stdout by default (pipeable), or to a file with `--output`.
1179
-
1180
- Data exports preserve SQLite AUTOINCREMENT and PostgreSQL SERIAL and identity counters, including IDs consumed by deleted rows. SQLite schema exports include indexes, views, and triggers. PostgreSQL schema exports preserve column types, generated columns, identity definitions, serial sequences, constraints, and indexes. `--no-schema` restores counter values into an existing schema; `--no-data` starts counters at their schema-defined starting values.
1181
-
1182
- For PostgreSQL schemas with views, triggers, custom types, functions, or standalone sequences, use `pg_dump` for a complete backup. `void db export` reports these objects before writing a schema dump.
1183
-
1184
- | Flag | Purpose |
1185
- | ----------------- | ---------------------------------- |
1186
- | `--output <path>` | Write to a file instead of stdout |
1187
- | `--no-data` | Schema only (no INSERT statements) |
1188
- | `--no-schema` | Data only (no CREATE TABLE) |
1189
- | `--table <name>` | Export a single table |
1190
-
1191
- ## Code Generation
1192
-
1193
- ### `void gen model`
1194
-
1195
- ```
1196
- void gen model <name> [columns...]
1197
- ```
1198
-
1199
- Scaffold a complete model: migration file, CRUD API routes, and regenerated DB types in one command.
1200
-
1201
- ```sh
1202
- void gen model posts title:string body:text published:boolean
1203
- ```
1204
-
1205
- Creates:
1206
-
1207
- - `db/migrations/NNN_create_posts.sql`: `CREATE TABLE` with `id` (autoincrement), your columns, and `created_at`
1208
- - `routes/api/posts/index.ts`: `GET` for list and `POST` for insert with validation
1209
- - `routes/api/posts/[id].ts`: `GET` by id with `404` handling
1210
- - Regenerated `.void/db.d.ts`
1211
-
1212
- The generated routes automatically detect your validation library from `package.json` (`valibot`, `zod`, or `arktype`). If none is found, you will be prompted to choose one or skip validation. See [Database: Scaffolding](../guide/database.md#scaffolding) for the full type mapping.
1213
-
1214
- Column format: `name:type` or `name:type?` (nullable). Types: `string`, `text`, `datetime`, `integer`, `boolean`, `real`, `blob`.
1215
-
1216
- Model names must be lowercase alphanumeric with underscores (e.g. `posts`, `user_roles`). Existing files are never overwritten.
1217
-
1218
- ### `void gen migration`
1219
-
1220
- ```
1221
- void gen migration <name>
1222
- ```
1223
-
1224
- Create an empty migration file with a timestamp prefix (`YYYYMMDDHHMMSS`).
1225
-
1226
- ```sh
1227
- void gen migration add_avatar_to_users
1228
- # → db/migrations/20260410161500_add_avatar_to_users.sql
1229
- ```
1230
-
1231
- Existing projects using the old numeric prefix (`0001_`, `0002_`, ...) can rename with `void db rename-migrations`.
1232
-
1233
- ### `void gen route`
1234
-
1235
- ```
1236
- void gen route <path> [--methods get,post,...]
1237
- ```
1238
-
1239
- Create a route file with `defineHandler` exports. Defaults to GET.
1240
-
1241
- ```sh
1242
- void gen route api/health
1243
- void gen route api/users --methods get,post,delete
1244
- ```
1245
-
1246
- Creates `routes/<path>.ts` with an exported handler for each method. Supported methods: `get`, `post`, `put`, `patch`, `delete`.
1247
-
1248
- ### `void gen middleware`
1249
-
1250
- ```
1251
- void gen middleware <name>
1252
- ```
1253
-
1254
- Create a numbered middleware file with `defineMiddleware` default export.
1255
-
1256
- ```sh
1257
- void gen middleware auth
1258
- # → middleware/01.auth.ts (or 02, 03, etc.)
1259
- ```
1260
-
1261
- The prefix is auto-detected from existing middleware files.
1262
-
1263
- ### `void gen ssr`
1264
-
1265
- ```
1266
- void gen ssr [--react | --vue | --svelte | --solid]
1267
- ```
1268
-
1269
- Scaffold SSR entry points and a minimal App component for your framework.
1270
-
1271
- Creates three files:
1272
-
1273
- - `src/main.ssr.{tsx,ts}`: server entry with `defineRender`
1274
- - `src/main.client.{tsx,ts}`: client entry with hydration
1275
- - `src/App.{tsx,vue,svelte}`: minimal interactive component
1276
-
1277
- If no flag is provided, the framework is auto-detected from `package.json` dependencies.
1278
-
1279
- ### `void gen cron`
1280
-
1281
- ```
1282
- void gen cron <name>
1283
- ```
1284
-
1285
- Create a cron job file in `crons/` with `defineScheduled` and a placeholder cron expression.
1286
-
1287
- ```sh
1288
- void gen cron hourly-sync
1289
- ```
1290
-
1291
- ### `void gen queue`
1292
-
1293
- ```
1294
- void gen queue <name>
1295
- ```
1296
-
1297
- Create a queue consumer file in `queues/` with `defineQueue`, a `Message` interface, and commented-out batch options.
1298
-
1299
- ```sh
1300
- void gen queue emails
1301
- ```
1302
-
1303
- ## Secrets
1304
-
1305
- ### `void secret list`
1306
-
1307
- ```
1308
- void secret list [--project <name>]
1309
- ```
1310
-
1311
- List production secret names for the saved target. Secret values are never printed. Direct Cloudflare targets query the Worker named in `void.config.ts`; `--project` is hosted-only.
1312
-
1313
- ### `void secret put`
1314
-
1315
- On hosted projects, secret writes and deletes return a retryable conflict while a deployment or rollback is in progress. Wait for that operation to finish and retry; the rejected operation leaves the stored secret unchanged.
1316
-
1317
- ```
1318
- void secret put <name> [--project <name>]
1319
- void secret put <name=value> [--project <name>]
1320
- ```
1321
-
1322
- Value input modes:
1323
-
1324
- - inline: `void secret put API_KEY=abcd`
1325
- - prompt (TTY): `void secret put API_KEY` (masked input)
1326
- - stdin: `echo -n "abcd" | void secret put API_KEY`
1327
-
1328
- On a direct Cloudflare target, the value is sent to Cloudflare over stdin and stored as an encrypted Worker secret.
1329
-
1330
- ### `void secret sync`
1331
-
1332
- ```
1333
- void secret sync <file> [--project <name>]
1334
- ```
1335
-
1336
- Bulk upload secrets from a dotenv file. Each `KEY=value` line in the file is uploaded as a secret.
1337
-
1338
- ```sh
1339
- void secret sync .env # validates and uploads declared server values
1340
- ```
1341
-
1342
- Direct Cloudflare targets use Cloudflare's bulk-secret API. Existing remote secrets absent from the file are not pruned.
1343
- Every entry must be a non-client key declared in `env.ts`, and its plaintext value must pass the schema before upload.
1344
-
1345
- ### `void secret delete`
1346
-
1347
- ```
1348
- void secret delete <name> [--project <name>]
1349
- ```
1350
-
1351
- Secret commands use the platform saved in `.void/project.json`. Hosted project resolution follows the same order as deploy (`--project`, env var, linked project). Direct Cloudflare targets reject `--project` and use the pinned root Cloudflare config.
1352
-
1353
- ## Env Schema
1354
-
1355
- ### `void env check`
1356
-
1357
- ```
1358
- void env check [--remote]
1359
- ```
1360
-
1361
- Without `--remote`, validate `.env` plus the shell for local development. With `--remote`, validate build-shell client values and the remote server-secret names. Exits non-zero if a required key is missing or a readable value is invalid.
1362
-
1363
- ### `void env types`
1364
-
1365
- ```
1366
- void env types
1367
- ```
1368
-
1369
- Regenerate `.void/env.d.ts` from `env.ts`. Normally happens automatically on dev server start and HMR; use this command after a fresh clone or to refresh stale types in non-dev contexts.
1370
-
1371
- ::: tip Deploy validation
1372
- `void deploy` runs the same schema validation automatically (with remote secrets) and refuses to upload if any required key is missing — no need to call `env check` separately when deploying.
1373
- :::
1374
-
1375
- See [Environment Variables](../guide/env-vars.md) for the full guide.
1376
-
1377
- ## GitHub
1378
-
1379
- Deploy-on-GitHub works from **any** Void login — Google, GitHub, or other SSO. The first time you connect GitHub, Void links your GitHub identity to your current account (a one-time step, independent of how you logged in); it never creates a second account.
1380
-
1381
- ### `void github link`
1382
-
1383
- ```
1384
- void github link
1385
- ```
1386
-
1387
- Link your current Void account to a GitHub identity. Opens your browser to authorize Void on GitHub (a localhost + PKCE handshake, the same mechanics as `void account login`), then binds that GitHub identity to the logged-in account. Requires an authenticated CLI (`void account login` first).
1388
-
1389
- You normally don't need to run this directly — `void github install` runs the link automatically when your account has no GitHub identity yet. Run it on its own to link ahead of time, or to link a GitHub identity without installing the App.
1390
-
1391
- ::: warning Existing GitHub sign-in
1392
- Void accounts cannot be merged. If the GitHub account you authorize is already linked to a different Void account, including one created through GitHub sign-in, `void github link` is refused with `This GitHub account is already linked to another Void account.` Run `void account logout` and sign in to that existing account, or authorize a different GitHub account. The command is also refused if your current Void account is already linked to a different GitHub identity. Re-authorizing the GitHub account attached to your current Void account is allowed and reports `GitHub account already linked.`
1393
- :::
1394
-
1395
- ### `void github install`
1396
-
1397
- ```
1398
- void github install
1399
- ```
1400
-
1401
- Open the GitHub App install page in your browser. If your account has no linked GitHub identity yet, `void github install` first runs the GitHub link automatically (browser authorize), then continues. After installing, run `void github connect` to link a repository to your project.
1402
-
1403
- ### `void github installations`
1404
-
1405
- ```
1406
- void github installations
1407
- ```
1408
-
1409
- List all GitHub App installations linked to your account. Each entry includes the `[id: <installation_id>]` needed for `--installation` in non-interactive use.
1410
-
1411
- ### `void github join`
1412
-
1413
- ```
1414
- void github join
1415
- ```
1416
-
1417
- Join the GitHub App installations your organization already has. If a teammate installed the Void GitHub App on a shared GitHub organization, run `void github join` to discover those installations without re-installing. Void opens your browser to authorize (a localhost + PKCE handshake, the same mechanics as `void github link`), confirms which installations GitHub makes visible to you, and records that visibility. Afterwards `void github installations` lists them without exposing the installation-wide private repository list; `void github connect` separately proves access to the repository you name.
1418
-
1419
- In an interactive terminal you rarely need to run this yourself — `void github connect` runs the same join automatically when no active installations are linked to your account. Running `void github join` yourself matters mainly for non-interactive use (without a TTY, `void github connect` never opens a browser), or to link installations ahead of time.
1420
-
1421
- Requires an authenticated CLI (`void account login` first) and organization-installation sharing enabled on your Void instance; when it is not enabled the command fails closed with a clear message. You can only join installations your GitHub authorization actually returns — you cannot name or join one you cannot access on GitHub.
1422
-
1423
- ### `void github connect`
1424
-
1425
- ```
1426
- void github connect [project] [options]
1427
- ```
1428
-
1429
- Connect a GitHub repository to a Void project for automatic deploys. On every push to the configured branch, Void builds and deploys your project automatically.
1430
-
1431
- Interactively (TTY), if your account has no active installations linked, `void github connect` first runs the same browser authorize as `void github join` automatically — if a teammate already installed the Void GitHub App on your organization, you join it on the spot and the connect continues. Only when no shared installation is found does it ask you to run `void github install`. The same recovery runs when `--installation <id>` names an installation your account is not linked to yet. Without a TTY, connect never opens a browser: it fails closed and tells you to run `void github install`, or `void github join` if your organization already installed the App.
1432
-
1433
- **Options**
1434
-
1435
- | Flag | Description |
1436
- | --------------------- | --------------------------------------------------------------------------------- |
1437
- | `--project <name>` | Project name (alias for the positional argument) |
1438
- | `--installation <id>` | GitHub App installation ID (required when you have multiple installations) |
1439
- | `--repo <owner/repo>` | Repository full name — required unless the installation grants exactly one repo |
1440
- | `--branch <name>` | Branch to deploy from — **required in non-interactive mode** |
1441
- | `--executor <type>` | Build executor: `container` (default) or `github_actions` |
1442
- | `--workflow <path>` | Authorized deploy workflow file — defaults to `.github/workflows/void-deploy.yml` |
1443
-
1444
- The `--workflow` path is the workflow file the GitHub OIDC exchange authorizes to mint this project's deploy token. It defaults to the scaffolded `.github/workflows/void-deploy.yml`; set it only if your deploy step lives in a different workflow file (it must be under `.github/workflows/` and end in `.yml`/`.yaml`). Because the exchange is secretless, **only this one workflow** can mint a deploy token — any other workflow in the repo (including an unsafe `pull_request_target`) is rejected. Pointing it at a broad, multi-purpose workflow widens that trust, so prefer a dedicated file.
1445
-
1446
- Interactively (TTY), after resolving the repository and branch, `void github connect` prompts for the **build executor** (defaulting to `container`). If you pick `github_actions`, it then prompts for the **deploy workflow file**, defaulting to `.github/workflows/void-deploy.yml` and validated locally before it is sent. Pass `--executor` and/or `--workflow` to skip the respective prompt. The workflow prompt is skipped entirely for the `container` executor, which does not use a workflow file.
1447
-
1448
- **Non-interactive use (CI)**
1449
-
1450
- When stdin is not a TTY, `void github connect` never prompts — it fails closed and names any flag it needs. `--branch` is always required. `--project` must be resolvable (positional / `--project` / `VOID_PROJECT` / linked `.void/project.json`). `--installation` is required only when your account has more than one installation; otherwise the sole installation is used. `--repo` is required when the installation grants access to all repos or to more than one selected repo; when it grants exactly one repo that repo is used automatically. `--repo` is also required when the installation does not expose a repository list to your account (shared org installations hide it). Use `void github installations` to discover the `installation_id`.
1451
-
1452
- ```
1453
- void github connect my-app \
1454
- --installation 42 \
1455
- --repo owner/my-app \
1456
- --branch main
1457
- ```
1458
-
1459
- **Project resolution** follows the same order as deploy: positional / `--project`, `VOID_PROJECT`, linked project (`.void/project.json`).
1460
-
1461
- **Connecting as an organization member**
1462
-
1463
- For every organization installation, `void github connect` confirms that you personally have access to the specific repository, including when you originally installed the App. Interactively (TTY), it opens your browser once to authorize access to that repo on GitHub (a localhost + PKCE handshake), then completes the connection automatically. Without a TTY, this per-repo authorization never opens a browser: connect fails closed with an error explaining that the installation requires per-repo authorization and telling you to run `void github connect` locally. Interactively, connect joins the shared installation automatically when your account has no active installations linked, so running `void github join` first is optional. You can only connect repositories you can access on GitHub; seeing the organization installation never grants access to its other private repositories.
1464
-
1465
- A project has one GitHub connection. Running `void github connect` on a project that is already connected fails. To connect a different repository, run `void github disconnect` first.
1466
-
1467
- ### `void github update`
1468
-
1469
- ```
1470
- void github update [project] [options]
1471
- ```
1472
-
1473
- Update an existing connection's deploy **branch**, **build executor**, and/or authorized **workflow file**. Use this to change settings on a project that is already connected — for example, flipping the executor from `container` to `github_actions` for a monorepo whose Void app lives in a subdirectory, moving the deploy branch, or pointing the OIDC trust at a different workflow file. The project must already be connected (run `void github connect` first); the repository and installation are not changed.
1474
-
1475
- **Options**
1476
-
1477
- | Flag | Description |
1478
- | ------------------- | ---------------------------------------------------------------- |
1479
- | `--project <name>` | Project name (alias for the positional argument) |
1480
- | `--branch <name>` | New branch to deploy from |
1481
- | `--executor <type>` | New build executor: `container` or `github_actions` |
1482
- | `--workflow <path>` | New authorized deploy workflow file (under `.github/workflows/`) |
1483
-
1484
- Interactively (TTY), `void github update` shows the current branch and executor and prompts for new values, defaulting each to the current setting. If the resulting executor is `github_actions`, it then prompts for the **deploy workflow file**, defaulting to the current path and validated locally; pass `--workflow` to skip that prompt. The workflow prompt is skipped when the executor is `container`, which does not use a workflow file. When stdin is not a TTY, it never prompts: pass at least one of `--branch` / `--executor` / `--workflow`, or it fails closed. If nothing actually changes, the command reports "no changes" and does not call the API.
1485
-
1486
- ```
1487
- void github update my-app --executor github_actions
1488
- ```
1489
-
1490
- **Project resolution** follows the same order as deploy: positional / `--project`, `VOID_PROJECT`, linked project (`.void/project.json`).
1491
-
1492
- ### `void github status`
1493
-
1494
- ```
1495
- void github status [project]
1496
- ```
1497
-
1498
- Show a project's current GitHub connection: the connected **repository**, the deploy **branch**, the **build executor** (`container` or `github_actions`), and the authorized **deploy workflow file**. Read-only — it never changes anything. The workflow file is the OIDC pin used only for `github_actions` builds; on a `container` connection it is still shown but marked unused. The project must already be connected (run `void github connect` first, otherwise it reports that and exits).
1499
-
1500
- **Options**
1501
-
1502
- | Flag | Description |
1503
- | ------------------ | ------------------------------------------------ |
1504
- | `--project <name>` | Project name (alias for the positional argument) |
1505
-
1506
- ```
1507
- void github status my-app
1508
- ```
1509
-
1510
- **Project resolution** follows the same order as deploy: positional / `--project`, `VOID_PROJECT`, linked project (`.void/project.json`).
1511
-
1512
- ### `void github disconnect`
1513
-
1514
- ```
1515
- void github disconnect [project]
1516
- ```
1517
-
1518
- Disconnect a project from its GitHub repository, stopping automatic deploys. Any in-flight builds for the project are cancelled (their deploy tokens are revoked) before the connection is removed. If the project has no connection, it reports that and exits successfully. To point a project at a different repository, disconnect first, then run `void github connect`.
1519
-
1520
- You are asked to confirm before anything is removed. Pass `--yes` to skip the prompt; `--yes` is **required** in a non-interactive shell (CI), where there is no prompt to answer.
1521
-
1522
- **Options**
1523
-
1524
- | Flag | Description |
1525
- | ------------------ | ----------------------------------------------------------------- |
1526
- | `--project <name>` | Project name (alias for the positional argument) |
1527
- | `--yes` | Skip the confirmation prompt (required in non-interactive shells) |
1528
-
1529
- ```
1530
- void github disconnect my-app --yes
1531
- ```
1532
-
1533
- **Project resolution** follows the same order as deploy: positional / `--project`, `VOID_PROJECT`, linked project (`.void/project.json`).
1534
-
1535
- ## Build
1536
-
1537
- Inspect Deploy-on-GitHub builds.
1538
-
1539
- ### `void build logs`
1540
-
1541
- ```
1542
- void build logs [build] [--follow] [--output <file>] [--project <slug>]
1543
- ```
1544
-
1545
- Stream, tail, or download the build logs for a **container** build. With no
1546
- `[build]` argument, targets the project's most recent build.
1547
-
1548
- | Flag | Purpose | Default |
1549
- | ------------------------ | ----------------------------------------------------------------- | ------- |
1550
- | `--follow`, `-f` | Live-tail: poll until the build reaches a terminal status. | off |
1551
- | `--output <file>`, `-o` | Write logs to a file instead of stdout (appends while following). | stdout |
1552
- | `--project <slug>`, `-p` | Target project. | linked |
1553
-
1554
- **Project resolution** follows the same order as deploy: positional / `--project`,
1555
- `VOID_PROJECT`, linked project (`.void/project.json`).
1556
-
1557
- Builds run on **GitHub Actions** keep their logs on GitHub — the command prints
1558
- the Actions run URL instead of streaming. Only the last 10,000 log lines of a
1559
- container build are retained.
1560
-
1561
- Examples:
1562
-
1563
- ```
1564
- void build logs # print the latest build's logs
1565
- void build logs -f # follow the latest build until it finishes
1566
- void build logs bld_123 -o build.log # download a specific build's logs
1567
- ```
1568
-
1569
- ## Custom Domains
1570
-
1571
- ### `void domain add`
1572
-
1573
- ```
1574
- void domain add <hostname> [--project <name>]
1575
- ```
1576
-
1577
- Add a custom domain to the saved target. Hosted Void projects print the DNS records needed for SaaS hostname validation. Direct Cloudflare projects add a `custom_domain` route and immediately synchronize only the route configuration, leaving cron, queue, and workflow triggers unchanged; Cloudflare manages the DNS record and TLS certificate in a zone on the pinned account. Convert a legacy singular `route` field to a `routes` array first so adding the domain cannot shadow the existing route.
1578
-
1579
- > Wildcard custom hostnames (`*.example.com`) are not supported — register each subdomain individually.
1580
-
1581
- ### `void domain delete`
1582
-
1583
- ```
1584
- void domain delete <hostname> [--project <name>]
1585
- ```
1586
-
1587
- Direct Cloudflare projects apply the change immediately. Deleting the final custom domain uses your browser session from `void cloudflare login` or an API token with Workers Scripts: Edit permission. If Cloudflare rejects the change, Void attempts to restore the previous domain configuration and reports whether recovery succeeded.
1588
-
1589
- Remove a custom domain from the saved target. For Cloudflare, this removes the matching `custom_domain` route and synchronizes triggers. If Cloudflare rejects the update, Void restores the exact previous local config and immediately reapplies it remotely. If that second synchronization also fails, the CLI reports that remote route state may be partial instead of claiming a successful rollback.
1590
-
1591
- ### `void domain list`
1592
-
1593
- ```
1594
- void domain list [--project <name>]
1595
- ```
1596
-
1597
- List all custom domains. Hosted projects show active/pending state from the platform; direct Cloudflare projects list the custom-domain routes currently configured in `void.config.ts`.
1598
-
1599
- ### `void domain status`
1600
-
1601
- ```
1602
- void domain status <hostname> [--project <name>] [--verbose]
1603
- ```
1604
-
1605
- Check verification and SSL status for a specific domain. Prints a rolled-up state (`awaiting_dns`, `verifying_dns`, `issuing_cert`, `deploying_cert`, `awaiting_deployment`, `active`, `error`, or `pending`) with a one-line diagnostic explaining what Cloudflare is doing and any user action required. While the certificate is not yet active, the command also surfaces the records to configure — the traffic **CNAME** and the `_cf-custom-hostname` ownership **TXT** — so you can verify them. Activation is automatic: a background job reconciles pending domains (about every 2 minutes for the first 30 minutes after adding, then hourly), so this command is for instant feedback rather than required polling.
1606
-
1607
- Pass `--verbose` to additionally print the raw multi-line status breakdown (DB status, SSL status, ownership state, verification errors) underneath the rollup.
1608
-
1609
- Project resolution for domain commands follows the same order as deploy (`--project`, `VOID_PROJECT`, linked project).
1610
-
1611
- For direct Cloudflare projects, status reports whether the route is present in the Void Cloudflare config. It does not claim to inspect remote certificate issuance; Cloudflare owns that state and exposes it in the dashboard. `--project` is hosted-only.
1612
-
1613
- ## Email
1614
-
1615
- Inspect email usage and manage the recipients a project is allowed to send to. See [Email](../guide/email.md) for the runtime API.
1616
-
1617
- Project resolution for email commands follows the same order as deploy (`--project`, `VOID_PROJECT`, linked project). `void email setup` and `void email status --platform cloudflare` are the exception: they act on your own Cloudflare account through your Cloudflare sign-in (`void cloudflare login`) and need no Void project.
1618
-
1619
- ### `void email usage`
1620
-
1621
- ```
1622
- void email usage [--project <name>]
1623
- ```
1624
-
1625
- Show the current month's recipient attempts and inbound receipts, the monthly attempt limit, and how much of it is left. Reserved submissions count toward the limit; started attempts remain charged even if delivery fails or its outcome is unknown. A suspended project is flagged in the output.
1626
-
1627
- ### `void email logs`
1628
-
1629
- ```
1630
- void email logs [--limit <n>] [--project <name>]
1631
- ```
1632
-
1633
- Show recent email operation metadata retained for 30 days: timestamp, direction, operation ID, recipient, and state. `--limit` accepts 1–100. Subjects, bodies, and attachments are not stored. Provider acceptance does not confirm mailbox delivery; inspect unknown outcomes before retrying.
1634
-
1635
- ### `void email destinations`
1636
-
1637
- ```
1638
- void email destinations [--project <name>]
1639
- ```
1640
-
1641
- List the project's recipient addresses and their state (`verified`, `pending`, or `failed`). Outbound mail is only delivered to verified addresses.
1642
-
1643
- ### `void email allow`
1644
-
1645
- ```
1646
- void email allow <address> [--project <name>]
1647
- ```
1648
-
1649
- Add one recipient to the project's destination list. Cloudflare emails that address a verification link — the recipient clicks it, with no Void or Cloudflare account required. Then run `void email destinations`: the listing is what records the click, and until it has, a send to that address returns `UNVERIFIED_DESTINATION` for that recipient. If the link did not arrive or has expired, run `void email allow <address>` again while the address is still pending — the CLI re-sends the link, or tells you how to get a fresh one.
1650
-
1651
- The project owner's email is added automatically when the project is created, so it skips this step but not the verification: unless Cloudflare already had it verified for an earlier project of yours, click the link it mailed and run `void email destinations`; until then a send to yourself returns `UNVERIFIED_DESTINATION` for that recipient.
1652
-
1653
- ### `void email disallow`
1654
-
1655
- ```
1656
- void email disallow <address> [--project <name>]
1657
- ```
1658
-
1659
- Remove one recipient from the project's destination list. New sends to that address are refused immediately; previously admitted attempts may finish. No deploy is involved.
1660
-
1661
- ### `void email domain`
1662
-
1663
- ```
1664
- void email domain <add|status|list|sync|rotate-secret|remove> [<domain>] [--project <name>]
1665
- ```
1666
-
1667
- Send and receive at your own domain on a Cloudflare zone you own, registered to the project. Void platform only — on your own Cloudflare account the mail domain comes from `email.from` instead (see `void email setup`). The walkthrough is [Your own domain on the platform](../guide/email.md#your-own-domain-on-the-platform).
1668
-
1669
- #### `void email domain add`
1670
-
1671
- ```
1672
- void email domain add <domain> [--subdomain <label|host>] [--project <name>]
1673
- ```
1674
-
1675
- Register an exact domain with the project using a scoped Cloudflare API token. The CLI opens a token template, accepts a masked paste or newly copied token, and asks you to confirm account and zone restrictions. Credentials are encrypted for the zone connection. The CLI proposes `mail.<domain>` when the apex already has MX records; `--subdomain` overrides that proposal. Several domains can share a zone connection, but each domain belongs to one project. Setup returns an operation ID so an interrupted request can be checked without restarting the operation.
1676
-
1677
- #### `void email domain status`
1678
-
1679
- ```
1680
- void email domain status <domain> [--project <name>]
1681
- ```
1682
-
1683
- Show the recorded inbound, outbound, and management readiness, observation times, and latest operation. Use `sync` to reconcile setup and refresh readiness.
1684
-
1685
- #### `void email domain list`
1686
-
1687
- ```
1688
- void email domain list [--project <name>]
1689
- ```
1690
-
1691
- List the project's registered email domains and readiness.
1692
-
1693
- #### `void email domain sync`
1694
-
1695
- ```
1696
- void email domain sync <domain> [--project <name>]
1697
- ```
1698
-
1699
- Reconcile the domain connection and refresh readiness. Sync does not rotate its secret. A blocked or uncertain operation exits unsuccessfully and names the operation to inspect.
1700
-
1701
- #### `void email domain rotate-secret`
1702
-
1703
- ```sh
1704
- void email domain rotate-secret <domain> [--project <name>]
1705
- ```
1706
-
1707
- Rotate the ingress secret for the zone connection shared by this domain and its siblings. Inbound must be ready; run `void email domain sync <domain>` first if setup is incomplete. The platform accepts the staged secret before updating the Worker and promotes it only after verifying the deployed generation. An uncertain update stays recorded for reconciliation.
1708
-
1709
- #### `void email domain remove`
1710
-
1711
- ```
1712
- void email domain remove <domain> [--project <name>]
1713
- ```
1714
-
1715
- Disable the domain assignment and record cleanup. Zone resources used by another domain remain available. Unfinished or uncertain cleanup remains recorded until it can be reconciled safely.
1716
-
1717
- ### `void email status`
1718
-
1719
- ```
1720
- void email status --platform cloudflare
1721
- ```
1722
-
1723
- Read-only. Checks the email setup on your own Cloudflare account for the domain of `email.from` in `void.config.ts` — session scopes, zone, MX records, Email Routing (and its subaddressing setting), Email Sending, the routing rule for every `email/` handler, and the `send_email` binding — then prints the status rows and the address map (`inbound <address> → email/<handler>`, `outbound sendEmail() from <email.from>`). Exits 1 when anything is not ready. A domain still not onboarded for Email Sending reads as set up once the `send_email` binding is committed — the binding is written only after an onboarding attempt, so that pair is how a Workers Free refusal is remembered — and the sending row says so (`not onboarded — verified destinations only; after upgrading to Workers Paid run void email setup --platform cloudflare`). Takes no `--project`: it reads the local project and your Cloudflare session, never a Void project.
1724
-
1725
- Without `--platform cloudflare` (or with `--platform void`) the command is not available yet; on the Void platform use `void email usage` and `void email destinations`. The older `--backend cloudflare` spelling remains available as a compatibility alias on `void email status` and `void email setup`, with the same rules as `void deploy`: at most once, and never together with `--platform`.
1726
-
1727
- ### `void email setup`
1728
-
1729
- ```
1730
- void email setup --platform cloudflare
1731
- ```
1732
-
1733
- The same setup `void deploy --platform cloudflare` offers on its first deploy, on its own — for CI, which cannot press Enter: run it locally once, commit `void.lock.json`, then let CI run `void deploy --platform cloudflare --require-email`. Needs `email.from` in `void.config.ts` and a `void cloudflare login` session (a session created by older Cloudflare tooling lacks the email scopes: `void cloudflare logout`, then sign in again) or a `CLOUDFLARE_API_TOKEN` with Email Routing Edit + Email Sending Edit — the CI credential. It runs the preflight above, prints the checklist of what will change on your account, asks once, then:
1734
-
1735
- 1. enables Email Routing on the domain (on an apex through Void's bundled Cloudflare tooling; a subdomain through your session's bearer, borrowed for that one call and dropped),
1736
- 2. turns on subaddressing for the zone, so `support+anything@` reaches `support@`,
1737
- 3. onboards the domain for Email Sending (a Workers Free account keeps inbound and sends to verified destinations only),
1738
- 4. writes `send_email: [{ "name": "SEND_EMAIL" }]`, the derived `addresses` array, and `vars.__VOID_EMAIL_FROM` into `void.lock.json`.
1739
-
1740
- The routing rules themselves are created by the next `void deploy --platform cloudflare`: wrangler applies its Email Routing plan from `addresses` on deploy. `void email setup` never writes `addresses` unless routing is ready for the domain, prunes an address already routed to another worker or a forward (and says so), and skips the whole step when the existing `addresses` array holds entries it did not derive. A run that finds every row ready asks nothing and changes nothing on your account — with one exception: a domain still not onboarded for Email Sending while the `send_email` binding is committed (a remembered Workers Free refusal, see `void email status`) is offered as a retry on its own prompt, `Onboard <domain> for Email Sending? Inbound already works; onboarding needs Workers Paid.` — the step to run once after upgrading; answer No and nothing changes. The deploy never retries it. Needs an interactive terminal; exits 1 when the inbound rows are still not ready afterwards — routing not enabled, subaddressing still off, or `addresses` withheld — naming the row and saying to rerun. A Workers Free account's refused sending row is not a failure: inbound is complete, `addresses` is written, the plan hint is printed, and the binding written alongside is what makes the next deploy and `void email status` read the domain as set up. See [Your own Cloudflare account](../guide/email.md#your-own-cloudflare-account).
1741
-
1742
- ## Agent
1743
-
1744
- ### `void init --agents`
1745
-
1746
- Runs all agent setup steps:
1747
-
1748
- 1. **Instructions:** always creates or updates `AGENTS.md` with four brief bullets and versioned markers. Content outside the Void block and other instruction files are preserved.
1749
- 2. **Skills:** links skills for detected coding agents.
1750
-
1751
- There is no agent-selection prompt. If no agent is detected, skill linking is skipped; the instructions point directly to `node_modules/void/skills/void/docs/`.
101
+ Use `void --help` for the command list, or `void deploy --help` for a specific command. Help is available without signing in or setting up a project.
1752
102
 
1753
- ## Environment variables
103
+ ## Environment variables {#environment-variables}
1754
104
 
1755
105
  | Variable | Purpose | Default |
1756
106
  | -------------- | ------------------------------------------------------------------------- | ------- |