@pyric/cli 0.1.0-alpha.19 → 0.1.0-alpha.20

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 (317) hide show
  1. package/README.md +9 -9
  2. package/dist/cli/index.d.ts +2 -2
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +48 -42
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/cli/mcp-proxy.js +3 -3
  7. package/dist/cli/mcp-proxy.js.map +1 -1
  8. package/dist/cli/parse-args.d.ts +1 -1
  9. package/dist/cli/parse-args.d.ts.map +1 -1
  10. package/dist/cli/parse-args.js +51 -15
  11. package/dist/cli/parse-args.js.map +1 -1
  12. package/dist/cli/pyric-config.d.ts +24 -0
  13. package/dist/cli/pyric-config.d.ts.map +1 -0
  14. package/dist/cli/pyric-config.js +28 -0
  15. package/dist/cli/pyric-config.js.map +1 -0
  16. package/dist/cli/{dev-runner.d.ts → sandbox-runner.d.ts} +33 -36
  17. package/dist/cli/sandbox-runner.d.ts.map +1 -0
  18. package/dist/cli/{dev-runner.js → sandbox-runner.js} +90 -55
  19. package/dist/cli/sandbox-runner.js.map +1 -0
  20. package/dist/cli/serve.d.ts +6 -4
  21. package/dist/cli/serve.d.ts.map +1 -1
  22. package/dist/cli/serve.js +99 -40
  23. package/dist/cli/serve.js.map +1 -1
  24. package/dist/cli/snapshot.js +5 -5
  25. package/dist/cli/snapshot.js.map +1 -1
  26. package/dist/cli/verify.js +1 -1
  27. package/dist/cli/verify.js.map +1 -1
  28. package/dist/functions-rtdb/development-runtime.js +1 -1
  29. package/dist/functions-rtdb/development-runtime.js.map +1 -1
  30. package/dist/functions-rtdb/project.js +8 -8
  31. package/dist/functions-rtdb/project.js.map +1 -1
  32. package/dist/next/guard.js +1 -1
  33. package/dist/next/guard.js.map +1 -1
  34. package/dist/remote/index.d.ts +1 -1
  35. package/dist/remote/index.js +9 -9
  36. package/dist/remote/index.js.map +1 -1
  37. package/dist/serve/bundler.js +10 -10
  38. package/dist/serve/bundler.js.map +1 -1
  39. package/dist/serve/entries/ai.d.ts.map +1 -1
  40. package/dist/serve/entries/ai.js +27 -1
  41. package/dist/serve/entries/ai.js.map +1 -1
  42. package/dist/serve/entries/auth-helper-dom.js +1 -1
  43. package/dist/serve/entries/auth-helper-dom.js.map +1 -1
  44. package/dist/serve/entries/auth-helper-runtime.js +1 -1
  45. package/dist/serve/entries/auth-helper-runtime.js.map +1 -1
  46. package/dist/serve/entries/firestore.js +3 -3
  47. package/dist/serve/entries/firestore.js.map +1 -1
  48. package/dist/serve/entries/keepalive.js +1 -1
  49. package/dist/serve/entries/keepalive.js.map +1 -1
  50. package/dist/serve/entries/runtime.js +21 -14
  51. package/dist/serve/entries/runtime.js.map +1 -1
  52. package/dist/serve/entries/storage.js +1 -1
  53. package/dist/serve/entries/storage.js.map +1 -1
  54. package/dist/serve/entries/worker-runtime.js +1 -1
  55. package/dist/serve/entries/worker-runtime.js.map +1 -1
  56. package/dist/serve/init-payload.d.ts +4 -0
  57. package/dist/serve/init-payload.d.ts.map +1 -1
  58. package/dist/serve/namespace.d.ts +6 -0
  59. package/dist/serve/namespace.d.ts.map +1 -1
  60. package/dist/serve/namespace.js +36 -5
  61. package/dist/serve/namespace.js.map +1 -1
  62. package/dist/serve/rules.d.ts.map +1 -1
  63. package/dist/serve/rules.js +44 -21
  64. package/dist/serve/rules.js.map +1 -1
  65. package/dist/serve/runtime/chip.d.ts.map +1 -1
  66. package/dist/serve/runtime/chip.js +32 -1
  67. package/dist/serve/runtime/chip.js.map +1 -1
  68. package/dist/serve/runtime/manifest.d.ts +1 -1
  69. package/dist/serve/runtime/manifest.d.ts.map +1 -1
  70. package/dist/serve/runtime/manifest.js +1 -1
  71. package/dist/serve/runtime/manifest.js.map +1 -1
  72. package/dist/serve/runtime/status.d.ts.map +1 -1
  73. package/dist/serve/runtime/status.js +23 -0
  74. package/dist/serve/runtime/status.js.map +1 -1
  75. package/dist/serve/sandbox-session.d.ts +1 -0
  76. package/dist/serve/sandbox-session.d.ts.map +1 -1
  77. package/dist/serve/sandbox-session.js +10 -4
  78. package/dist/serve/sandbox-session.js.map +1 -1
  79. package/dist/serve/server.d.ts +7 -0
  80. package/dist/serve/server.d.ts.map +1 -1
  81. package/dist/serve/server.js +15 -1
  82. package/dist/serve/server.js.map +1 -1
  83. package/dist/serve/site-ui/404.html +1 -1
  84. package/dist/serve/site-ui/_astro/{RulesCodeEditor.Bl-XMkhD.js → RulesCodeEditor.XtDmHOlN.js} +1 -1
  85. package/dist/serve/site-ui/_astro/_slug_.Da5VLhW1.css +1 -0
  86. package/dist/serve/site-ui/_astro/_studio_.BnfYCKoI.css +1 -0
  87. package/dist/serve/site-ui/_astro/app.B52xr-DK.js +1 -0
  88. package/dist/serve/site-ui/_astro/app.DWBraPUw.js +12 -0
  89. package/dist/serve/site-ui/_astro/app.pMSnN6Qw.css +1 -0
  90. package/dist/serve/site-ui/_astro/{chess-showcase.Dh5D8kqe.js → chess-showcase.B72XYeoh.js} +1 -1
  91. package/dist/serve/site-ui/_astro/{example-runtime.CuyAjjiG.js → example-runtime.C25_lx6Z.js} +1 -1
  92. package/dist/serve/site-ui/_astro/index.Tb-31efc.css +1 -0
  93. package/dist/serve/site-ui/_astro/index.UkCBr-_0.css +1 -0
  94. package/dist/serve/site-ui/_astro/{sandbox-controls.BP4M5f1M.js → sandbox-controls.DEpnKg-O.js} +11 -11
  95. package/dist/serve/site-ui/_astro/{seed.CSUkloMi.js → seed.Co0yUJY5.js} +1 -1
  96. package/dist/serve/site-ui/_astro/{writes.C57paAj2.js → writes.rpjrFzmu.js} +7 -4
  97. package/dist/serve/site-ui/auth/index.html +5 -3
  98. package/dist/serve/site-ui/david-east.jpg +0 -0
  99. package/dist/serve/site-ui/docs/_rhythm/index.html +6 -3
  100. package/dist/serve/site-ui/docs/_rhythm.md +1 -1
  101. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +18 -15
  102. package/dist/serve/site-ui/docs/agent/set-up-your-agent.md +16 -16
  103. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +6 -5
  104. package/dist/serve/site-ui/docs/agent/watch-and-review.md +1 -5
  105. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +8 -5
  106. package/dist/serve/site-ui/docs/agent/work-with-an-agent.md +4 -4
  107. package/dist/serve/site-ui/docs/ai-compat/index.html +5 -2
  108. package/dist/serve/site-ui/docs/api-reference/index.html +6 -2
  109. package/dist/serve/site-ui/docs/api-reference.md +1 -0
  110. package/dist/serve/site-ui/docs/app-compat/index.html +5 -2
  111. package/dist/serve/site-ui/docs/auth-compat/index.html +5 -2
  112. package/dist/serve/site-ui/docs/build/ai-logic/index.html +5 -2
  113. package/dist/serve/site-ui/docs/build/authentication/index.html +7 -4
  114. package/dist/serve/site-ui/docs/build/authentication.md +2 -2
  115. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +5 -2
  116. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +5 -2
  117. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +6 -3
  118. package/dist/serve/site-ui/docs/build/cloud-storage.md +1 -1
  119. package/dist/serve/site-ui/docs/build/realtime-database/index.html +9 -6
  120. package/dist/serve/site-ui/docs/build/realtime-database.md +4 -4
  121. package/dist/serve/site-ui/docs/conformance-scores/index.html +5 -2
  122. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -3
  123. package/dist/serve/site-ui/docs/create-pyric-reference-api.md +1 -1
  124. package/dist/serve/site-ui/docs/database-compat/index.html +5 -2
  125. package/dist/serve/site-ui/docs/examples/chess/index.html +5 -2
  126. package/dist/serve/site-ui/docs/examples/index.html +5 -2
  127. package/dist/serve/site-ui/docs/firestore-compat/index.html +5 -2
  128. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +5 -2
  129. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +9 -6
  130. package/dist/serve/site-ui/docs/get-started/how-the-swap-works.md +5 -5
  131. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +9 -6
  132. package/dist/serve/site-ui/docs/get-started/nextjs.md +4 -4
  133. package/dist/serve/site-ui/docs/get-started/start-building/index.html +14 -9
  134. package/dist/serve/site-ui/docs/get-started/start-building.md +16 -10
  135. package/dist/serve/site-ui/docs/get-started/vite/index.html +6 -3
  136. package/dist/serve/site-ui/docs/get-started/vite.md +1 -1
  137. package/dist/serve/site-ui/docs/index.json +180 -150
  138. package/dist/serve/site-ui/docs/messaging-compat/index.html +5 -2
  139. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +5 -2
  140. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +6 -4
  141. package/dist/serve/site-ui/docs/observe/see-whats-happening.md +2 -4
  142. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +9 -6
  143. package/dist/serve/site-ui/docs/observe/shape-your-data.md +4 -4
  144. package/dist/serve/site-ui/docs/overview/index.html +16 -10
  145. package/dist/serve/site-ui/docs/overview.md +19 -11
  146. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +5 -2
  147. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +5 -2
  148. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +5 -2
  149. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +8 -5
  150. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +3 -3
  151. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +5 -2
  152. package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +501 -0
  153. package/dist/serve/site-ui/docs/pyric-admin-reference-api.md +587 -0
  154. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +5 -2
  155. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +5 -2
  156. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +5 -2
  157. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +5 -2
  158. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +5 -2
  159. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +5 -2
  160. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +5 -2
  161. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +5 -2
  162. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +5 -2
  163. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +5 -2
  164. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +5 -2
  165. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +5 -2
  166. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +5 -2
  167. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +5 -2
  168. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +5 -2
  169. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +5 -2
  170. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +5 -2
  171. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +6 -3
  172. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +1 -1
  173. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +5 -2
  174. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +5 -2
  175. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +5 -2
  176. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +166 -95
  177. package/dist/serve/site-ui/docs/pyric-database-reference-api.md +107 -1
  178. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +5 -2
  179. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +10 -4
  180. package/dist/serve/site-ui/docs/pyric-messaging-reference-api.md +5 -2
  181. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +10 -4
  182. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api.md +5 -2
  183. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +5 -2
  184. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +5 -2
  185. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +6 -3
  186. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api.md +2 -2
  187. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +5 -2
  188. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +5 -2
  189. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +5 -2
  190. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +5 -2
  191. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +5 -2
  192. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +5 -2
  193. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +5 -2
  194. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +5 -2
  195. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +5 -2
  196. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +5 -2
  197. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -2
  198. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +5 -2
  199. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +5 -2
  200. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +5 -2
  201. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +5 -2
  202. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +5 -2
  203. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +5 -2
  204. package/dist/serve/site-ui/docs/reference/cli/index.html +153 -0
  205. package/dist/serve/site-ui/docs/reference/cli.md +114 -0
  206. package/dist/serve/site-ui/docs/rules-compat/index.html +5 -2
  207. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +5 -2
  208. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +5 -2
  209. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +6 -3
  210. package/dist/serve/site-ui/docs/secure/read-a-denial.md +1 -1
  211. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +5 -2
  212. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +5 -2
  213. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +5 -2
  214. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +5 -2
  215. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +5 -2
  216. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +7 -4
  217. package/dist/serve/site-ui/docs/ship/ship-to-production.md +2 -2
  218. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +9 -6
  219. package/dist/serve/site-ui/docs/ship/test-in-node.md +4 -4
  220. package/dist/serve/site-ui/docs/storage-compat/index.html +5 -2
  221. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +5 -2
  222. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +5 -2
  223. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +5 -2
  224. package/dist/serve/site-ui/docs/tutorial/index.html +10 -7
  225. package/dist/serve/site-ui/docs/tutorial.md +4 -4
  226. package/dist/serve/site-ui/examples/chess/index.html +4 -2
  227. package/dist/serve/site-ui/firestore/index.html +5 -3
  228. package/dist/serve/site-ui/hero-charcoal.jpg +0 -0
  229. package/dist/serve/site-ui/index.html +9 -7
  230. package/dist/serve/site-ui/llms.txt +4 -3
  231. package/dist/serve/site-ui/pyric-campfire-full.png +0 -0
  232. package/dist/serve/site-ui/pyric-campfire.png +0 -0
  233. package/dist/serve/site-ui/rtdb/index.html +5 -3
  234. package/dist/serve/site-ui/settings/index.html +5 -3
  235. package/dist/serve/site-ui/storage/index.html +5 -3
  236. package/dist/serve/site-ui/studio/index.html +13 -0
  237. package/dist/serve/site-ui/studio-routes.json +1 -1
  238. package/dist/serve/site-ui/traffic/index.html +5 -3
  239. package/dist/serve/studio/routes.d.ts +9 -0
  240. package/dist/serve/studio/routes.d.ts.map +1 -1
  241. package/dist/serve/studio/routes.js +47 -7
  242. package/dist/serve/studio/routes.js.map +1 -1
  243. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  244. package/dist/serve/vite-ai-config.js +38 -8
  245. package/dist/serve/vite-ai-config.js.map +1 -1
  246. package/dist/serve/vite-module-swap.d.ts.map +1 -1
  247. package/dist/serve/vite-module-swap.js +0 -28
  248. package/dist/serve/vite-module-swap.js.map +1 -1
  249. package/dist/serve/vite-sandbox-generation.d.ts +1 -1
  250. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
  251. package/dist/serve/vite-sandbox-generation.js +1 -1
  252. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  253. package/dist/serve/worker/client/disconnect.js +1 -1
  254. package/dist/serve/worker/client/disconnect.js.map +1 -1
  255. package/dist/serve/worker/client/presence.d.ts.map +1 -1
  256. package/dist/serve/worker/client/presence.js +18 -5
  257. package/dist/serve/worker/client/presence.js.map +1 -1
  258. package/dist/serve/worker/host-ai.d.ts.map +1 -1
  259. package/dist/serve/worker/host-ai.js +15 -0
  260. package/dist/serve/worker/host-ai.js.map +1 -1
  261. package/dist/serve/worker/protocol.d.ts +4 -0
  262. package/dist/serve/worker/protocol.d.ts.map +1 -1
  263. package/dist/serve/worker/protocol.js.map +1 -1
  264. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  265. package/dist/serve/worker/serve-init.js +7 -1
  266. package/dist/serve/worker/serve-init.js.map +1 -1
  267. package/package.json +5 -5
  268. package/src/cli/cli.test.ts +2 -2
  269. package/src/cli/index.ts +48 -42
  270. package/src/cli/mcp-proxy.ts +4 -4
  271. package/src/cli/parse-args.ts +61 -15
  272. package/src/cli/pyric-config.ts +45 -0
  273. package/src/cli/{dev-runner.ts → sandbox-runner.ts} +117 -72
  274. package/src/cli/serve.ts +115 -47
  275. package/src/cli/snapshot.ts +5 -5
  276. package/src/cli/verify.ts +1 -1
  277. package/src/functions-rtdb/development-runtime.ts +1 -1
  278. package/src/functions-rtdb/project.ts +8 -8
  279. package/src/next/guard.ts +1 -1
  280. package/src/remote/index.ts +9 -9
  281. package/src/serve/bundler.ts +10 -10
  282. package/src/serve/entries/ai.ts +27 -1
  283. package/src/serve/entries/auth-helper-dom.ts +1 -1
  284. package/src/serve/entries/auth-helper-runtime.ts +1 -1
  285. package/src/serve/entries/firestore.ts +3 -3
  286. package/src/serve/entries/keepalive.ts +1 -1
  287. package/src/serve/entries/runtime.ts +19 -14
  288. package/src/serve/entries/storage.ts +1 -1
  289. package/src/serve/entries/worker-runtime.ts +1 -1
  290. package/src/serve/init-payload.ts +4 -0
  291. package/src/serve/namespace.ts +44 -5
  292. package/src/serve/rules.ts +47 -22
  293. package/src/serve/runtime/chip.ts +38 -1
  294. package/src/serve/runtime/manifest.ts +1 -1
  295. package/src/serve/runtime/status.ts +24 -0
  296. package/src/serve/sandbox-session.ts +10 -4
  297. package/src/serve/server.ts +18 -1
  298. package/src/serve/studio/routes.ts +63 -7
  299. package/src/serve/vite-ai-config.ts +37 -7
  300. package/src/serve/vite-module-swap.ts +0 -28
  301. package/src/serve/vite-sandbox-generation.ts +1 -1
  302. package/src/serve/worker/client/disconnect.ts +1 -1
  303. package/src/serve/worker/client/presence.ts +25 -5
  304. package/src/serve/worker/host-ai.ts +15 -0
  305. package/src/serve/worker/protocol.ts +2 -1
  306. package/src/serve/worker/serve-init.ts +5 -1
  307. package/README.md.orig +0 -145
  308. package/dist/cli/dev-runner.d.ts.map +0 -1
  309. package/dist/cli/dev-runner.js.map +0 -1
  310. package/dist/serve/site-ui/_astro/_slug_.CXh9yTP1.css +0 -1
  311. package/dist/serve/site-ui/_astro/_slug_.CupVK4TM.css +0 -1
  312. package/dist/serve/site-ui/_astro/_studio_.CfxiQWkk.css +0 -1
  313. package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +0 -1
  314. package/dist/serve/site-ui/_astro/app.Ce3MTLQm.js +0 -1
  315. package/dist/serve/site-ui/_astro/app.taqzyjD0.js +0 -11
  316. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +0 -582
  317. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +0 -448
package/src/cli/serve.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `pyric dev` local dev server with the pyric sandbox standing in for
2
+ * `pyric sandbox` is the local server with the Pyric sandbox standing in for
3
3
  * Firebase. Feels like `firebase serve` (banner, labeled lines, port 3473,
4
4
  * SIGINT shutdown) with the sandbox-flavored extras firebase can't do: the
5
5
  * served page runs an in-browser backend, your `firestore.rules` deploy into
@@ -28,17 +28,16 @@ import { formatActivityWarning } from '../serve/activity-warning.js';
28
28
  import { consoleServeLogger, startStaticServer, stderrServeLogger, type ServeHandle } from '../serve/server.js';
29
29
  import { createBridgeMount } from '../serve/bridge-mount.js';
30
30
  import { openBrowser, shouldAutoOpen } from '../serve/open-browser.js';
31
+ import { readPyricConfig, type PyricConfig } from './pyric-config.js';
31
32
  import {
32
33
  buildChildEnv,
33
- detectPackageManager,
34
34
  formatStartupEnvExport,
35
- readDevScript,
36
35
  registerModuleUrl,
37
- resolveDevChild,
38
- spawnDevChild,
36
+ resolveSandboxChild,
37
+ spawnSandboxChild,
39
38
  waitForSandboxPeer,
40
- type DevChildHandle,
41
- } from './dev-runner.js';
39
+ type SandboxChildHandle,
40
+ } from './sandbox-runner.js';
42
41
  import {
43
42
  createFunctionsDevelopmentRuntime,
44
43
  createHttpFunctionsPeerReadiness,
@@ -60,7 +59,7 @@ interface HostingConfig {
60
59
  rewrites?: Array<{ source?: string; destination?: string }>;
61
60
  }
62
61
 
63
- /** Extract the single hosting config `pyric dev` v1 supports. Arrays
62
+ /** Extract the single hosting config `pyric sandbox` supports. Arrays
64
63
  * (multi-site) take the first entry with a warning — multi-site is out of
65
64
  * scope (plan section 6). */
66
65
  export function extractHosting(config: FirebaseJson | null): HostingConfig | null {
@@ -84,7 +83,7 @@ export interface ServeRuntime {
84
83
  payload: () => InitPayload;
85
84
  /** HTTP MCP endpoint when `--bridge` is on; null otherwise. */
86
85
  mcpUrl: string | null;
87
- /** The Studio app URL (`/__pyric/ui/`) when `--ui` is on and the build is
86
+ /** The Studio hub URL (`/__pyric/ui/studio`) when `--ui` is on and the build is
88
87
  * present; null otherwise. */
89
88
  uiUrl: string | null;
90
89
  /** Persistence summary (null when `--persist` is off). */
@@ -147,6 +146,8 @@ export async function startServe(opts: {
147
146
  * (the served project's file tree) + `/__pyric/projects` (single-project
148
147
  * store over `cwd`). The Studio app's `local` mode talks to these. */
149
148
  ui?: boolean;
149
+ /** Explicit opt-in to permissive mode (default-allow RTDB rules when unconfigured). */
150
+ permissive?: boolean;
150
151
  logger?: Parameters<typeof startStaticServer>[0]['logger'];
151
152
  }): Promise<ServeRuntime> {
152
153
  const logger = opts.logger ?? consoleServeLogger();
@@ -157,7 +158,7 @@ export async function startServe(opts: {
157
158
  // Fail fast instead of pretending to reset something.
158
159
  if (opts.fresh && !opts.persist) {
159
160
  throw new Error(
160
- 'pyric dev: --fresh requires --persist (it discards .pyric/state/state.json). ' +
161
+ 'pyric sandbox: --fresh requires --persist (it discards .pyric/state/state.json). ' +
161
162
  'Browser-stored data is cleared from Studio → Settings → Reset, or DevTools → Clear site data.',
162
163
  );
163
164
  }
@@ -172,9 +173,29 @@ export async function startServe(opts: {
172
173
  logger.note(' ⚠ no firebase.json found — serving the current directory without hosting config');
173
174
  }
174
175
 
176
+ const pyricConfig = await readPyricConfig(opts.cwd);
177
+ if (pyricConfig.rules) {
178
+ if (!config) config = {};
179
+ if (typeof pyricConfig.rules === 'string') {
180
+ config.firestore = { ...config.firestore, rules: pyricConfig.rules };
181
+ } else {
182
+ if (pyricConfig.rules.firestore) {
183
+ config.firestore = { ...config.firestore, rules: pyricConfig.rules.firestore };
184
+ }
185
+ if (pyricConfig.rules.database) {
186
+ config.database = { ...config.database, rules: pyricConfig.rules.database };
187
+ }
188
+ if (pyricConfig.rules.storage) {
189
+ const baseStorage =
190
+ typeof config.storage === 'object' && !Array.isArray(config.storage) ? config.storage : {};
191
+ config.storage = { ...baseStorage, rules: pyricConfig.rules.storage };
192
+ }
193
+ }
194
+ }
195
+
175
196
  const hosting = extractHosting(config);
176
197
  if (Array.isArray(config?.hosting) && (config.hosting as unknown[]).length > 1) {
177
- logger.note(' ⚠ multiple hosting sites configured pyric dev v1 serves the first entry only');
198
+ logger.note(' ⚠ multiple hosting sites configured. pyric sandbox serves the first entry only');
178
199
  }
179
200
  const publicDir = resolve(opts.cwd, hosting?.public ?? '.');
180
201
  if (!existsSync(publicDir)) {
@@ -184,16 +205,16 @@ export async function startServe(opts: {
184
205
  const looksLikeBuildOutput = /(^|[\\/])(dist|build|out)$/.test(publicDir);
185
206
  const hint = looksLikeBuildOutput
186
207
  ? `\n No build yet? Run \`bun run dev\` for the live sandbox dev server, ` +
187
- `or \`bun run build\` then \`pyric dev\` to preview the production build.`
208
+ `or \`bun run build\` then \`pyric sandbox\` to preview the production build.`
188
209
  : '';
189
- throw new Error(`pyric dev: hosting.public directory does not exist: ${publicDir}${hint}`);
210
+ throw new Error(`pyric sandbox: hosting.public directory does not exist: ${publicDir}${hint}`);
190
211
  }
191
212
 
192
213
  // The import map can only remap BARE `firebase/*` specifiers. A plain bundler
193
214
  // build (`vite build`) inlines the real SDK into the app chunk, leaving
194
215
  // nothing to intercept — the page would then talk to REAL Firebase endpoints
195
216
  // with the sandbox's fake credentials while the injected banner claims
196
- // otherwise. That hole is structural, so `pyric dev` REFUSES such a dist
217
+ // otherwise. That hole is structural, so `pyric sandbox` refuses such a dist
197
218
  // rather than serving it. A pyric SANDBOX build (`vite build --mode
198
219
  // development`) carries the marker and bundles pyric's in-page adapters, so it
199
220
  // is trusted and the scan is skipped (marker present → no real SDK to find).
@@ -201,14 +222,14 @@ export async function startServe(opts: {
201
222
  const inlined = scanForInlinedFirebase(publicDir);
202
223
  if (inlined.length > 0) {
203
224
  throw new Error(
204
- `pyric dev: ${inlined[0]} bundles the REAL firebase SDK, so this dist cannot be ` +
225
+ `pyric sandbox: ${inlined[0]} bundles the real Firebase SDK, so this dist cannot be ` +
205
226
  `sandboxed — its firebase/* calls would reach LIVE Google endpoints, not the ` +
206
227
  `pyric sandbox. Two ways forward:\n` +
207
- ` (a) plain \`pyric dev\` runs the child dev-server flow (the @pyric/cli/vite ` +
228
+ ` (a) \`pyric sandbox -- <command>\` runs the child server with the @pyric/cli/vite ` +
208
229
  `plugin swaps firebase/* live) — use \`bun run dev\`;\n` +
209
230
  ` (b) rebuild as a self-contained sandbox bundle and serve THAT: ` +
210
231
  `\`vite build --mode development\` (or pyric({ swapInBuild: true })) then ` +
211
- `\`pyric dev\`.\n` +
232
+ `\`pyric sandbox\`.\n` +
212
233
  `A plain \`vite build\` is your production build — deploy it, don't sandbox it.`,
213
234
  );
214
235
  }
@@ -285,15 +306,16 @@ export async function startServe(opts: {
285
306
  studio: opts.ui ? { siteUiDir } : false,
286
307
  bridgeUrl: () => mount && origin.port > 0 ? mount.wsUrl(origin) : null,
287
308
  activity: (incident) => logger.note(formatActivityWarning(incident)),
309
+ permissive: opts.permissive,
288
310
  logger,
289
311
  });
290
312
  } catch (error) {
291
313
  bundle.dispose?.();
292
314
  if (error instanceof SandboxSeedError) {
293
315
  if (error.kind === 'read') {
294
- throw new Error(`pyric dev: failed to read --seed ${error.path}: ${error.detail}`);
316
+ throw new Error(`pyric sandbox: failed to read --seed ${error.path}: ${error.detail}`);
295
317
  }
296
- throw new Error(`pyric dev: --seed must be a JSON object of "collection/doc" fields, ${error.detail}`);
318
+ throw new Error(`pyric sandbox: --seed must be a JSON object of "collection/doc" to fields, ${error.detail}`);
297
319
  }
298
320
  throw error;
299
321
  }
@@ -376,7 +398,7 @@ export async function startServe(opts: {
376
398
  };
377
399
  if (bundle.dispose) handle.server.once('close', bundle.dispose);
378
400
  handle.server.once('close', () => void closeOwnedResources());
379
- const uiUrl = siteUiDir ? `${handle.url}/__pyric/ui/` : null;
401
+ const uiUrl = siteUiDir ? `${handle.url}/__pyric/ui/studio` : null;
380
402
  const docsUrl = siteUiDir ? `${handle.url}/__pyric/ui/docs/` : null;
381
403
 
382
404
  // Hot-reload: the static adapter observes the filesystem; the session owns
@@ -547,7 +569,7 @@ export function bridgeEnabledFromFlags(flags: { get(key: string): unknown }): bo
547
569
  * A dev child also implies the bridge: the runner injects
548
570
  * `PYRIC_SANDBOX=remote:<url>` into the child, whose remote client dials the
549
571
  * `/__pyric/sandbox` WS — without the bridge mount that upgrade 404s and
550
- * plain `pyric dev -- <cmd>` (or a detected dev script) breaks its own
572
+ * `pyric sandbox -- <cmd>` breaks its own
551
573
  * child. Pure + exported for unit coverage.
552
574
  */
553
575
  export function bridgeEnabledFor(
@@ -560,7 +582,7 @@ export function bridgeEnabledFor(
560
582
 
561
583
  /**
562
584
  * Process-level last line of defense for the dev server: a single bad
563
- * request/WS interaction must never take `pyric dev` down. Node kills the
585
+ * request/WS interaction must never take `pyric sandbox` down. Node kills the
564
586
  * process on an unhandled rejection (default `--unhandled-rejections=throw`
565
587
  * since v15) and on any uncaught exception — and the serve process hosts
566
588
  * long-lived, browser-driven machinery (WS peers, SSE streams, file watchers,
@@ -578,13 +600,13 @@ export function installServeProcessGuard(
578
600
  reason instanceof Error ? (reason.stack ?? reason.message) : String(reason);
579
601
  const onRejection = (reason: unknown): void => {
580
602
  log(
581
- ` ✖ pyric dev: UNHANDLED REJECTION (the server was kept alive please report this):\n` +
603
+ ` ✖ pyric sandbox: unhandled rejection. The server was kept alive. Please report this:\n` +
582
604
  ` ${describe(reason).split('\n').join('\n ')}`,
583
605
  );
584
606
  };
585
607
  const onException = (err: unknown): void => {
586
608
  log(
587
- ` ✖ pyric dev: UNCAUGHT EXCEPTION (the server was kept alive please report this):\n` +
609
+ ` ✖ pyric sandbox: uncaught exception. The server was kept alive. Please report this:\n` +
588
610
  ` ${describe(err).split('\n').join('\n ')}`,
589
611
  );
590
612
  };
@@ -596,10 +618,49 @@ export function installServeProcessGuard(
596
618
  };
597
619
  }
598
620
 
621
+ function resolveServePort(flagPort: unknown, configPort?: number): number {
622
+ if (typeof flagPort === 'string') return Number(flagPort);
623
+ if (typeof flagPort === 'number') return flagPort;
624
+ if (typeof configPort === 'number') return configPort;
625
+ return 3473;
626
+ }
627
+
628
+ function resolveProjectIdentifier(
629
+ flagProject?: unknown,
630
+ envProject?: string,
631
+ configProject?: string,
632
+ rcDefault?: string,
633
+ ): string {
634
+ if (typeof flagProject === 'string' && flagProject.length > 0) return flagProject;
635
+ if (typeof envProject === 'string' && envProject.length > 0) return envProject;
636
+ if (typeof configProject === 'string' && configProject.length > 0) return configProject;
637
+ if (typeof rcDefault === 'string' && rcDefault.length > 0) return rcDefault;
638
+ return 'demo-project';
639
+ }
640
+
641
+ function resolveExplicitCommand(parsed: ParsedArgs): string[] | null {
642
+ if (parsed.passthrough && parsed.passthrough.length > 0) {
643
+ return parsed.passthrough;
644
+ }
645
+ if (parsed.positional.length > 0) {
646
+ return parsed.positional;
647
+ }
648
+ return null;
649
+ }
650
+
599
651
  /** CLI entry. Resolves on SIGINT/SIGTERM after a clean stop. */
600
652
  export async function runServe(parsed: ParsedArgs): Promise<number> {
653
+ const cwd = process.cwd();
654
+ let pyricConfig: PyricConfig = {};
655
+ try {
656
+ pyricConfig = await readPyricConfig(cwd);
657
+ } catch (error) {
658
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
659
+ return 2;
660
+ }
661
+
601
662
  const flagPort = parsed.flags.get('port');
602
- const port = typeof flagPort === 'string' ? Number(flagPort) : 3473;
663
+ const port = resolveServePort(flagPort, pyricConfig.port);
603
664
  if (!Number.isFinite(port) || port < 0 || port > 65535) {
604
665
  process.stderr.write(`pyric: invalid --port '${flagPort}'.\n`);
605
666
  return 1;
@@ -610,7 +671,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
610
671
  const only = parsed.flags.get('only');
611
672
  if (typeof only === 'string' && only !== 'hosting') {
612
673
  process.stderr.write(
613
- `pyric: --only '${only}' is not supported pyric dev v1 serves hosting (with the in-page sandbox standing in for firestore/auth).\n`,
674
+ `pyric: --only '${only}' is not supported. pyric sandbox serves hosting with the in-page sandbox standing in for Firestore and Auth.\n`,
614
675
  );
615
676
  return 1;
616
677
  }
@@ -623,7 +684,6 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
623
684
  // Resolve the child plan BEFORE the server starts: a planned child implies
624
685
  // the bridge (see bridgeEnabledFor) — the child's injected PYRIC_SANDBOX
625
686
  // is useless without the /__pyric/sandbox WS mount.
626
- const cwd = process.cwd();
627
687
  let functionsProject: FunctionsRtdbProject | null;
628
688
  let functionsProjectId: string | null = null;
629
689
  try {
@@ -631,22 +691,25 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
631
691
  if (functionsProject) {
632
692
  const flagProject = parsed.flags.get('project');
633
693
  const rc = await readFirebaseRc(cwd);
634
- functionsProjectId =
635
- (typeof flagProject === 'string' ? flagProject : undefined) ??
636
- process.env.PYRIC_PROJECT ??
637
- rc?.projects?.default ??
638
- 'demo-project';
694
+ functionsProjectId = resolveProjectIdentifier(
695
+ flagProject,
696
+ process.env.PYRIC_PROJECT,
697
+ pyricConfig.project,
698
+ rc?.projects?.default,
699
+ );
639
700
  }
640
701
  } catch (error) {
641
702
  process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
642
703
  return 2;
643
704
  }
644
- const plan = resolveDevChild({
645
- passthrough: parsed.passthrough ?? [],
705
+
706
+ const explicitCommand = resolveExplicitCommand(parsed);
707
+
708
+ const plan = resolveSandboxChild({
709
+ explicitCommand,
710
+ configCommand: pyricConfig.command,
646
711
  noRun: Boolean(parsed.flags.get('no-run')),
647
712
  json,
648
- devScript: readDevScript(cwd),
649
- packageManager: detectPackageManager(cwd),
650
713
  });
651
714
  const bridgeOn = bridgeEnabledFor(parsed.flags, plan, functionsProject);
652
715
 
@@ -663,6 +726,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
663
726
  watch: parsed.flags.get('no-watch') ? false : undefined,
664
727
  persist: Boolean(parsed.flags.get('persist')),
665
728
  fresh: Boolean(parsed.flags.get('fresh')),
729
+ permissive: Boolean(parsed.flags.get('permissive')),
666
730
  // --ui mounts the Pyric Studio storage routes (workspace + projects).
667
731
  ui: uiOn,
668
732
  // --no-capture disables the default-on session capture. The pattern
@@ -675,7 +739,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
675
739
  project:
676
740
  typeof parsed.flags.get('project') === 'string'
677
741
  ? (parsed.flags.get('project') as string)
678
- : process.env.PYRIC_PROJECT ?? functionsProjectId ?? undefined,
742
+ : process.env.PYRIC_PROJECT ?? pyricConfig.project ?? functionsProjectId ?? undefined,
679
743
  });
680
744
  } catch (e) {
681
745
  process.stderr.write(`${e instanceof Error ? e.message : String(e)}\n`);
@@ -691,7 +755,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
691
755
  // (the banner went to stderr). Readiness probe: GET /__pyric/init.json.
692
756
  if (json) process.stdout.write(serveJsonLine(runtime) + '\n');
693
757
 
694
- // Footgun guard (hybrid-MCP plan Phase 3): plain `dev` mounts no MCP bridge,
758
+ // A host-only sandbox mounts no MCP bridge unless one is needed.
695
759
  // so a `pyric mcp-proxy` in an editor cannot attach. Nudge toward --bridge.
696
760
  if (!bridgeOn && !json) {
697
761
  process.stderr.write(
@@ -714,7 +778,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
714
778
  void openBrowser(targetUrl);
715
779
  }
716
780
 
717
- let devChild: DevChildHandle | null = null;
781
+ let devChild: SandboxChildHandle | null = null;
718
782
  let functionsRuntime: FunctionsDevelopmentRuntime | null = null;
719
783
  let resolveFunctionsExit!: (code: number) => void;
720
784
  const functionsExited = new Promise<number>((resolve) => { resolveFunctionsExit = resolve; });
@@ -793,7 +857,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
793
857
  if (result.kind === 'no-peer') {
794
858
  process.stderr.write(
795
859
  ` ⚠ functions not started — no browser tab connected after 30s. ` +
796
- `Open ${runtime.handle.url} and restart pyric dev.\n`,
860
+ `Open ${runtime.handle.url} and restart pyric sandbox.\n`,
797
861
  );
798
862
  } else if (result.kind === 'failed') {
799
863
  process.stderr.write(`${result.error.message}\n`);
@@ -810,16 +874,15 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
810
874
  for (const unsupported of ready.unsupportedTriggers) {
811
875
  process.stderr.write(
812
876
  ` ⚠ functions export ${unsupported.exportName} uses unsupported trigger ` +
813
- `${unsupported.eventType}; it will not run in pyric dev.\n`,
877
+ `${unsupported.eventType}; it will not run in pyric sandbox.\n`,
814
878
  );
815
879
  }
816
880
  }
817
881
  }
818
882
 
819
- // The child runner ("one command, not two"): run the user's own dev
820
- // command with the sandbox environment injected. Precedence: `-- <cmd>`
821
- // wins; else the package.json dev script; else host-only. --no-run forces
822
- // host-only; --json defaults to host-only (explicit `--` still wins).
883
+ // Run the explicit or configured command with the sandbox environment.
884
+ // `--no-run` forces host-only. `--json` skips the configured command, but an
885
+ // explicit command still runs.
823
886
  // (`plan` was resolved above so it could imply the bridge mount.)
824
887
  if (plan) {
825
888
  const info = json ? process.stderr : process.stdout;
@@ -838,11 +901,16 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
838
901
  ` ⚠ no browser tab connected after 30s — starting your command anyway; sandbox ops will fail until ${runtime.handle.url} is open.\n`,
839
902
  );
840
903
  }
904
+ } else if (!json) {
905
+ info.write(
906
+ ` ⓘ Auto-open is disabled (--no-open/CI). The pyric sandbox is browser-resident: ` +
907
+ `open ${runtime.handle.url} to connect if your command performs Firebase operations.\n`,
908
+ );
841
909
  }
842
910
  info.write(
843
911
  `✔ run \`${plan.label}\` — firebase-admin/firebase imports are routed to the sandbox at ${runtime.handle.url}\n`,
844
912
  );
845
- devChild = spawnDevChild(plan, {
913
+ devChild = spawnSandboxChild(plan, {
846
914
  cwd,
847
915
  json,
848
916
  env: buildChildEnv(process.env, {
@@ -895,7 +963,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
895
963
  if (functionsRuntime) {
896
964
  void functionsExited.then((code) => {
897
965
  if (!settled && !shuttingDown) {
898
- process.stderr.write(`pyric dev: Functions child exited unexpectedly (code ${code}).\n`);
966
+ process.stderr.write(`pyric sandbox: Functions child exited unexpectedly (code ${code}).\n`);
899
967
  finish(code === 0 ? 1 : code);
900
968
  }
901
969
  });
@@ -6,13 +6,13 @@
6
6
  * pyric snapshot [--out FILE] [--port N] [--force] [--json]
7
7
  *
8
8
  * Source preference:
9
- * 1. LIVE state from a running `pyric dev --persist`
9
+ * 1. Live state from a running `pyric sandbox --persist`
10
10
  * (`GET /__pyric/state` — `--port`, else the 3473+ scan window),
11
11
  * 2. else the on-disk `.pyric/state/state.json`,
12
12
  * 3. else exit 2 with a clear message.
13
13
  *
14
14
  * The output is a `PyricStateFile` envelope — directly re-servable:
15
- * `pyric dev --seed <out>` (the state-file shape is detected by its
15
+ * `pyric sandbox --seed <out>` (the state-file shape is detected by its
16
16
  * `version` key and seeds docs + users).
17
17
  */
18
18
  import { existsSync, writeFileSync } from 'node:fs';
@@ -44,7 +44,7 @@ async function fetchLive(port: number): Promise<LiveState | null> {
44
44
  if (!body || typeof body !== 'object' || !('version' in body)) return null;
45
45
  return { envelope: body, projectDir: res.headers.get('x-pyric-project-dir') };
46
46
  } catch {
47
- return null; // nothing listening / not a pyric dev — fall through
47
+ return null; // No Pyric sandbox is listening. Fall through.
48
48
  }
49
49
  }
50
50
 
@@ -110,7 +110,7 @@ export async function runSnapshot(parsed: ParsedArgs, deps: SnapshotDeps = {}):
110
110
  }
111
111
  if (!envelope) {
112
112
  err.write(
113
- 'pyric snapshot: no state found no `pyric dev --persist` is running here and ' +
113
+ 'pyric snapshot: no state found. No `pyric sandbox --persist` is running here and ' +
114
114
  'no .pyric/state/state.json exists. Run with --persist (and use the app) first.\n',
115
115
  );
116
116
  return 2;
@@ -158,7 +158,7 @@ export async function runSnapshot(parsed: ParsedArgs, deps: SnapshotDeps = {}):
158
158
  if (redactedCount > 0) {
159
159
  report.write(` ⓘ redacted ${redactedCount} password(s) — re-run with --include-passwords to keep them\n`);
160
160
  }
161
- report.write(` Re-serve it: pyric dev --seed ${typeof outFlag === 'string' ? outFlag : 'pyric-state.json'}\n`);
161
+ report.write(` Re-serve it: pyric sandbox --seed ${typeof outFlag === 'string' ? outFlag : 'pyric-state.json'}\n`);
162
162
  if (json) out.write(JSON.stringify({ out: outPath, docs, users, source, redactedPasswords: redactedCount }) + '\n');
163
163
  return 0;
164
164
  }
package/src/cli/verify.ts CHANGED
@@ -108,7 +108,7 @@ export async function runVerify(parsed: ParsedArgs, deps: VerifyCliDeps = {}): P
108
108
  } else {
109
109
  process.stderr.write(
110
110
  `pyric verify: no captured session at ${SERVE_CAPTURE_PATH}.\n` +
111
- ' Run `pyric dev`, exercise your app, then `pyric verify`, or pass a fixture path.\n',
111
+ ' Run `pyric sandbox`, exercise your app, then `pyric verify`, or pass a fixture path.\n',
112
112
  );
113
113
  }
114
114
  return 2;
@@ -6,7 +6,7 @@ import {
6
6
  type FunctionsRtdbChildReady,
7
7
  type SpawnFunctionsRtdbChildOptions,
8
8
  } from './child.js';
9
- import { buildChildEnv, createLinePrefixer } from '../cli/dev-runner.js';
9
+ import { buildChildEnv, createLinePrefixer } from '../cli/sandbox-runner.js';
10
10
 
11
11
  const INITIAL_PEER_TIMEOUT_MS = 30_000;
12
12
  const RELOAD_PEER_TIMEOUT_MS = 5_000;
@@ -22,7 +22,7 @@ export function discoverFunctionsRtdbProject(cwd: string): FunctionsRtdbProject
22
22
  config = JSON.parse(readFileSync(firebaseJsonPath, 'utf8')) as FirebaseJson;
23
23
  } catch (error) {
24
24
  throw new Error(
25
- `pyric dev: failed to parse firebase.json while discovering Functions: ` +
25
+ `pyric sandbox: failed to parse firebase.json while discovering Functions: ` +
26
26
  `${error instanceof Error ? error.message : String(error)}`,
27
27
  );
28
28
  }
@@ -33,23 +33,23 @@ export function discoverFunctionsRtdbProject(cwd: string): FunctionsRtdbProject
33
33
  : [config.functions as FunctionsConfig];
34
34
  if (declared.length !== 1) {
35
35
  throw new Error(
36
- 'pyric dev: multiple Functions codebases are not supported by the first ' +
36
+ 'pyric sandbox: multiple Functions codebases are not supported by the first ' +
37
37
  'onValueCreated slice; configure one source for this development session.',
38
38
  );
39
39
  }
40
40
  const functions = declared[0];
41
41
  if (typeof functions !== 'object' || functions === null) {
42
- throw new Error('pyric dev: firebase.json `functions` must be an object with a source.');
42
+ throw new Error('pyric sandbox: firebase.json `functions` must be an object with a source.');
43
43
  }
44
44
  if (functions.source !== undefined && typeof functions.source !== 'string') {
45
- throw new Error('pyric dev: firebase.json `functions.source` must be a string.');
45
+ throw new Error('pyric sandbox: firebase.json `functions.source` must be a string.');
46
46
  }
47
47
 
48
48
  const sourceDir = resolve(cwd, functions.source ?? 'functions');
49
49
  const packageJsonPath = join(sourceDir, 'package.json');
50
50
  if (!existsSync(packageJsonPath)) {
51
51
  throw new Error(
52
- `pyric dev: Functions source is declared but ${packageJsonPath} does not exist.`,
52
+ `pyric sandbox: Functions source is declared but ${packageJsonPath} does not exist.`,
53
53
  );
54
54
  }
55
55
 
@@ -58,17 +58,17 @@ export function discoverFunctionsRtdbProject(cwd: string): FunctionsRtdbProject
58
58
  packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as { main?: unknown };
59
59
  } catch (error) {
60
60
  throw new Error(
61
- `pyric dev: failed to parse ${packageJsonPath}: ` +
61
+ `pyric sandbox: failed to parse ${packageJsonPath}: ` +
62
62
  `${error instanceof Error ? error.message : String(error)}`,
63
63
  );
64
64
  }
65
65
  if (packageJson.main !== undefined && typeof packageJson.main !== 'string') {
66
- throw new Error(`pyric dev: ${packageJsonPath} \`main\` must be a string.`);
66
+ throw new Error(`pyric sandbox: ${packageJsonPath} \`main\` must be a string.`);
67
67
  }
68
68
 
69
69
  const entry = resolve(sourceDir, packageJson.main ?? 'index.js');
70
70
  if (!existsSync(entry) || !statSync(entry).isFile()) {
71
- throw new Error(`pyric dev: Functions entry does not exist: ${entry}`);
71
+ throw new Error(`pyric sandbox: Functions entry does not exist: ${entry}`);
72
72
  }
73
73
  return { sourceDir, entry };
74
74
  }
package/src/next/guard.ts CHANGED
@@ -54,7 +54,7 @@ export function enforceSandboxGuard(options?: PyricNextOptions): void {
54
54
  const errorMessage =
55
55
  '[Pyric] Next.js development server started without active Pyric sandbox environment variables.\n' +
56
56
  'To prevent accidental connections to production Firebase databases, launch this server using:\n' +
57
- ' pyric dev -- next dev\n' +
57
+ ' pyric sandbox -- next dev\n' +
58
58
  'or source environment keys via `pyric env`.\n' +
59
59
  'To disable this guard, pass { guard: false } to withPyric(config, options).';
60
60
  throw new Error(errorMessage);
@@ -5,7 +5,7 @@
5
5
  * Server-side Node code (ultimately `pyric-admin`'s remote dispatch arm)
6
6
  * reaches the ONE sandbox the app + Studio + agent share:
7
7
  *
8
- * Node process ──ws──> `pyric dev --bridge` ──ws──> browser tab
8
+ * Node process -> `pyric sandbox --bridge` -> browser tab
9
9
  * (attach/consumer leg) (peer leg)
10
10
  * ──MessagePort──> SharedWorker
11
11
  *
@@ -320,7 +320,7 @@ export function createRemoteSandboxCore(
320
320
  reject(
321
321
  remoteError(
322
322
  'deadline-exceeded',
323
- `remote sandbox op timed out after ${opTimeoutMs}ms (op: ${payload.method}) is pyric dev still running?` +
323
+ `remote sandbox op timed out after ${opTimeoutMs}ms (op: ${payload.method}). Is pyric sandbox still running?` +
324
324
  // A version-skewed old worker accepts frames it cannot
325
325
  // handle and never responds — a timeout is its signature.
326
326
  (versionSkewGuidance ? ` ${versionSkewGuidance}` : ''),
@@ -379,8 +379,8 @@ export function createRemoteSandboxCore(
379
379
  msg.serveVersion !== cliVersion()
380
380
  ) {
381
381
  versionSkewGuidance =
382
- `pyric dev is running version ${msg.serveVersion}, this client is ` +
383
- `${cliVersion()} restart pyric dev and reload the browser tab.`;
382
+ `pyric sandbox is running version ${msg.serveVersion}, this client is ` +
383
+ `${cliVersion()}. Restart pyric sandbox and reload the browser tab.`;
384
384
  process.stderr.write(`pyric: ${versionSkewGuidance}\n`);
385
385
  }
386
386
  if (msg.peerConnected) readyResolve();
@@ -405,7 +405,7 @@ export function createRemoteSandboxCore(
405
405
  // Version skew: a live tab whose SharedWorker predates this op.
406
406
  // Other open pages of this origin keep the old worker alive.
407
407
  message +=
408
- ' the running sandbox may predate this feature; restart pyric dev ' +
408
+ '. The running sandbox may predate this feature. Restart pyric sandbox ' +
409
409
  'and close other open pages of this origin, then reload.';
410
410
  }
411
411
  call.reject(remoteError(code, message, msg.error?.denialContext, (msg.error as any)?.envelope));
@@ -721,7 +721,7 @@ export function createRemoteSandboxHandle(opts: {
721
721
  enablePersistence: () =>
722
722
  throwMember(
723
723
  'enablePersistence',
724
- 'the browser worker owns persistence; it is already enabled by `pyric dev`',
724
+ 'the browser worker owns persistence; it is already enabled by `pyric sandbox`',
725
725
  ),
726
726
  flush: () =>
727
727
  throwMember('flush()', 'the browser worker owns persistence and flushes itself'),
@@ -742,7 +742,7 @@ export function createRemoteSandboxHandle(opts: {
742
742
  // ─── connect ───────────────────────────────────────────────────────────────
743
743
 
744
744
  /**
745
- * Discover the running `pyric dev --bridge`, attach to its bridge WS as a
745
+ * Discover the running `pyric sandbox --bridge`, attach to its bridge WS as a
746
746
  * worker-relay CONSUMER (never a peer — attaching cannot kick the browser
747
747
  * tab out of last-connection-wins), and return the typed remote handle.
748
748
  *
@@ -770,7 +770,7 @@ export async function connectRemoteSandbox(
770
770
  if (!found) {
771
771
  throw remoteError(
772
772
  'not-found',
773
- 'no running `pyric dev --bridge` found (looked for .pyric/serve.json in ' +
773
+ 'no running `pyric sandbox --bridge` found (looked for .pyric/serve.json in ' +
774
774
  `${cwd} and the default ports) — start your dev server with the bridge enabled and retry.`,
775
775
  );
776
776
  }
@@ -953,7 +953,7 @@ export function createLazyRemoteSandbox(
953
953
  // Before discovery the URL is unknown; op-level errors always carry the
954
954
  // real URL (they come from the inner connect), and `serveUrl` is patched
955
955
  // to the discovered value as soon as the first connect succeeds.
956
- serveUrl: options.url?.replace(/\/$/, '') ?? '<pyric dev url (pending discovery)>',
956
+ serveUrl: options.url?.replace(/\/$/, '') ?? '<pyric sandbox url (pending discovery)>',
957
957
  close() {
958
958
  if (closed) return;
959
959
  closed = true;