@fungi.computer/oyster 0.0.0-stage → 0.1.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 (339) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1134 -2
  3. package/dist/agents.d.ts +114 -0
  4. package/dist/agents.js +322 -0
  5. package/dist/app-builds.d.ts +210 -0
  6. package/dist/app-builds.js +499 -0
  7. package/dist/app-sandbox.d.ts +2 -0
  8. package/dist/app-sandbox.js +2 -0
  9. package/dist/app-sources.d.ts +31 -0
  10. package/dist/app-sources.js +370 -0
  11. package/dist/app-storage.d.ts +141 -0
  12. package/dist/app-storage.js +281 -0
  13. package/dist/apps/gate.d.ts +105 -0
  14. package/dist/apps/gate.js +273 -0
  15. package/dist/apps/index.d.ts +5 -0
  16. package/dist/apps/index.js +5 -0
  17. package/dist/apps/installation.d.ts +248 -0
  18. package/dist/apps/installation.js +307 -0
  19. package/dist/apps/operations.d.ts +8 -0
  20. package/dist/apps/operations.js +98 -0
  21. package/dist/apps/tools.d.ts +33 -0
  22. package/dist/apps/tools.js +17 -0
  23. package/dist/auth.d.ts +11 -0
  24. package/dist/auth.js +93 -0
  25. package/dist/backend-request.d.ts +3 -0
  26. package/dist/backend-request.js +53 -0
  27. package/dist/build/artifact-writer.d.ts +40 -0
  28. package/dist/build/artifact-writer.js +181 -0
  29. package/dist/build/build-jobs.d.ts +128 -0
  30. package/dist/build/build-jobs.js +203 -0
  31. package/dist/build/build-policy.d.ts +10 -0
  32. package/dist/build/build-policy.js +10 -0
  33. package/dist/build/build-step.d.ts +37 -0
  34. package/dist/build/build-step.js +28 -0
  35. package/dist/build/bundled-html.d.ts +7 -0
  36. package/dist/build/bundled-html.js +64 -0
  37. package/dist/build/candidate-builder.d.ts +68 -0
  38. package/dist/build/candidate-builder.js +91 -0
  39. package/dist/build/candidate-cli.d.ts +1 -0
  40. package/dist/build/candidate-cli.js +119 -0
  41. package/dist/build/candidate-cli.mjs +28170 -0
  42. package/dist/build/content-objects.d.ts +37 -0
  43. package/dist/build/content-objects.js +53 -0
  44. package/dist/build/definition-emission.d.ts +34 -0
  45. package/dist/build/definition-emission.js +201 -0
  46. package/dist/build/effect.d.ts +249 -0
  47. package/dist/build/effect.js +436 -0
  48. package/dist/build/git-environment.d.ts +9 -0
  49. package/dist/build/git-environment.js +60 -0
  50. package/dist/build/html-recipe.d.ts +20 -0
  51. package/dist/build/html-recipe.js +51 -0
  52. package/dist/build/local-build.d.ts +67 -0
  53. package/dist/build/local-build.js +1128 -0
  54. package/dist/build/snapshot-package-store.d.ts +12 -0
  55. package/dist/build/snapshot-package-store.js +36 -0
  56. package/dist/build/snapshot-program-scripts.d.ts +6 -0
  57. package/dist/build/snapshot-program-scripts.js +2 -0
  58. package/dist/build/snapshot-programs/snapshot-path.d.ts +2 -0
  59. package/dist/build/snapshot-programs/snapshot-path.js +6 -0
  60. package/dist/build/submission-contract.d.ts +828 -0
  61. package/dist/build/submission-contract.js +180 -0
  62. package/dist/build/workspace-build.d.ts +55 -0
  63. package/dist/build/workspace-build.js +200 -0
  64. package/dist/build-contract.d.ts +7 -0
  65. package/dist/build-contract.js +7 -0
  66. package/dist/build-egress.d.ts +62 -0
  67. package/dist/build-egress.js +148 -0
  68. package/dist/build-jobs.d.ts +2 -0
  69. package/dist/build-jobs.js +2 -0
  70. package/dist/build.d.ts +12 -0
  71. package/dist/build.js +14 -0
  72. package/dist/capability-descriptor.d.ts +46 -0
  73. package/dist/capability-descriptor.js +51 -0
  74. package/dist/catalog-frame.d.ts +39 -0
  75. package/dist/catalog-frame.js +72 -0
  76. package/dist/cause-class.d.ts +19 -0
  77. package/dist/cause-class.js +54 -0
  78. package/dist/cloudflare.d.ts +123 -0
  79. package/dist/cloudflare.js +391 -0
  80. package/dist/computer-terminal.d.ts +38 -0
  81. package/dist/computer-terminal.js +410 -0
  82. package/dist/computer.d.ts +60 -0
  83. package/dist/computer.js +33 -0
  84. package/dist/event-recipients.d.ts +57 -0
  85. package/dist/event-recipients.js +144 -0
  86. package/dist/facet-invocation.d.ts +4 -0
  87. package/dist/facet-invocation.js +45 -0
  88. package/dist/files.d.ts +42 -0
  89. package/dist/files.js +123 -0
  90. package/dist/frame-binding-wire-script.d.ts +2 -0
  91. package/dist/frame-binding-wire-script.js +1 -0
  92. package/dist/frame-binding-wire.d.ts +28 -0
  93. package/dist/frame-binding-wire.js +54 -0
  94. package/dist/git-admission.d.ts +52 -0
  95. package/dist/git-admission.js +188 -0
  96. package/dist/git-auth.d.ts +11 -0
  97. package/dist/git-auth.js +27 -0
  98. package/dist/git-door.d.ts +35 -0
  99. package/dist/git-door.js +108 -0
  100. package/dist/git-journal.d.ts +31 -0
  101. package/dist/git-journal.js +188 -0
  102. package/dist/git.d.ts +31 -0
  103. package/dist/git.js +64 -0
  104. package/dist/guest-policy.d.ts +9 -0
  105. package/dist/guest-policy.js +13 -0
  106. package/dist/host.d.ts +244 -0
  107. package/dist/host.js +1043 -0
  108. package/dist/index.d.ts +166 -0
  109. package/dist/index.js +320 -0
  110. package/dist/installation-consent.d.ts +79 -0
  111. package/dist/installation-consent.js +82 -0
  112. package/dist/internal/background-origins.d.ts +3 -0
  113. package/dist/internal/background-origins.js +8 -0
  114. package/dist/internal/delivery.d.ts +12 -0
  115. package/dist/internal/delivery.js +167 -0
  116. package/dist/internal/host-gate.d.ts +14 -0
  117. package/dist/internal/host-gate.js +62 -0
  118. package/dist/internal/registry-installations.d.ts +6 -0
  119. package/dist/internal/registry-installations.js +12 -0
  120. package/dist/invocation.d.ts +251 -0
  121. package/dist/invocation.js +377 -0
  122. package/dist/keys.d.ts +48 -0
  123. package/dist/keys.js +52 -0
  124. package/dist/mcp-owner.d.ts +27 -0
  125. package/dist/mcp-owner.js +155 -0
  126. package/dist/mcp.d.ts +89 -0
  127. package/dist/mcp.js +429 -0
  128. package/dist/media.d.ts +23 -0
  129. package/dist/media.js +12 -0
  130. package/dist/pack.d.ts +79 -0
  131. package/dist/pack.js +151 -0
  132. package/dist/page/capabilities.d.ts +23 -0
  133. package/dist/page/capabilities.js +256 -0
  134. package/dist/page/computer-handles.d.ts +79 -0
  135. package/dist/page/computer-handles.js +44 -0
  136. package/dist/page/gill-observation.d.ts +4 -0
  137. package/dist/page/gill-observation.js +31 -0
  138. package/dist/page/lifetime.d.ts +6 -0
  139. package/dist/page/lifetime.js +19 -0
  140. package/dist/page/mount.d.ts +163 -0
  141. package/dist/page/mount.js +390 -0
  142. package/dist/page/storage.d.ts +3 -0
  143. package/dist/page/storage.js +82 -0
  144. package/dist/page/terminal.d.ts +5 -0
  145. package/dist/page/terminal.js +7 -0
  146. package/dist/page/window-launch.d.ts +18 -0
  147. package/dist/page/window-launch.js +11 -0
  148. package/dist/page-script.d.ts +14 -0
  149. package/dist/page-script.js +5 -0
  150. package/dist/r2-files.d.ts +3 -0
  151. package/dist/r2-files.js +79 -0
  152. package/dist/release.d.ts +83 -0
  153. package/dist/release.js +167 -0
  154. package/dist/root-data.d.ts +86 -0
  155. package/dist/root-data.js +69 -0
  156. package/dist/shell/app-directory.d.ts +542 -0
  157. package/dist/shell/app-directory.js +199 -0
  158. package/dist/shell/browser-actions.d.ts +7 -0
  159. package/dist/shell/browser-actions.js +56 -0
  160. package/dist/shell/command-host.d.ts +112 -0
  161. package/dist/shell/command-host.js +502 -0
  162. package/dist/shell/commands.d.ts +25 -0
  163. package/dist/shell/commands.js +78 -0
  164. package/dist/shell/index.d.ts +8 -0
  165. package/dist/shell/index.js +8 -0
  166. package/dist/shell/keys.d.ts +41 -0
  167. package/dist/shell/keys.js +134 -0
  168. package/dist/shell/shell-module.d.ts +55 -0
  169. package/dist/shell/shell-module.js +86 -0
  170. package/dist/shell/window-manager.d.ts +124 -0
  171. package/dist/shell/window-manager.js +711 -0
  172. package/dist/shell/workbench-contract.d.ts +68 -0
  173. package/dist/shell/workbench-contract.js +1 -0
  174. package/dist/shell/workbench-directory.d.ts +332 -0
  175. package/dist/shell/workbench-directory.js +35 -0
  176. package/dist/shell/workbench-host-types.d.ts +96 -0
  177. package/dist/shell/workbench-host-types.js +1 -0
  178. package/dist/shell/workbench-host.d.ts +34 -0
  179. package/dist/shell/workbench-host.js +347 -0
  180. package/dist/shell/workbench-model.d.ts +192 -0
  181. package/dist/shell/workbench-model.js +53 -0
  182. package/dist/shell/workbench.d.ts +4 -0
  183. package/dist/shell/workbench.js +2 -0
  184. package/dist/source/fork.d.ts +27 -0
  185. package/dist/source/fork.js +46 -0
  186. package/dist/source/index.d.ts +10 -0
  187. package/dist/source/index.js +10 -0
  188. package/dist/source/seed-receipt.d.ts +53 -0
  189. package/dist/source/seed-receipt.js +18 -0
  190. package/dist/source/team-source.d.ts +32 -0
  191. package/dist/source/team-source.js +42 -0
  192. package/dist/source/template-push.d.ts +33 -0
  193. package/dist/source/template-push.js +223 -0
  194. package/dist/source/template-repository.d.ts +4 -0
  195. package/dist/source/template-repository.js +21 -0
  196. package/dist/source/template-seed.d.ts +68 -0
  197. package/dist/source/template-seed.js +80 -0
  198. package/dist/standalone/agent-directory.d.ts +4 -0
  199. package/dist/standalone/agent-directory.js +4 -0
  200. package/dist/standalone/agents.d.ts +220 -0
  201. package/dist/standalone/agents.js +795 -0
  202. package/dist/standalone/app-builds-binding.d.ts +36 -0
  203. package/dist/standalone/app-builds-binding.js +119 -0
  204. package/dist/standalone/app-set.d.ts +91 -0
  205. package/dist/standalone/app-set.js +395 -0
  206. package/dist/standalone/app-source.d.ts +41 -0
  207. package/dist/standalone/app-source.js +59 -0
  208. package/dist/standalone/builds.d.ts +18 -0
  209. package/dist/standalone/builds.js +101 -0
  210. package/dist/standalone/computer-egress.d.ts +37 -0
  211. package/dist/standalone/computer-egress.js +111 -0
  212. package/dist/standalone/computer.d.ts +122 -0
  213. package/dist/standalone/computer.js +714 -0
  214. package/dist/standalone/install-apps-cli.d.ts +2 -0
  215. package/dist/standalone/install-apps-cli.js +126 -0
  216. package/dist/standalone/instance.d.ts +35 -0
  217. package/dist/standalone/instance.js +74 -0
  218. package/dist/standalone/media.d.ts +76 -0
  219. package/dist/standalone/media.js +227 -0
  220. package/dist/standalone/preview.d.ts +51 -0
  221. package/dist/standalone/preview.js +167 -0
  222. package/dist/standalone/registry.d.ts +102 -0
  223. package/dist/standalone/registry.js +193 -0
  224. package/dist/standalone/tenancy.d.ts +42 -0
  225. package/dist/standalone/tenancy.js +241 -0
  226. package/dist/standalone/worker.d.ts +55 -0
  227. package/dist/standalone/worker.js +147 -0
  228. package/dist/standalone/workflow-authority-readers.d.ts +16 -0
  229. package/dist/standalone/workflow-authority-readers.js +35 -0
  230. package/dist/standalone/workflow-binding.d.ts +216 -0
  231. package/dist/standalone/workflow-binding.js +217 -0
  232. package/dist/standalone/workflow-events.d.ts +46 -0
  233. package/dist/standalone/workflow-events.js +39 -0
  234. package/dist/standalone/workflow-git-capture.d.ts +7 -0
  235. package/dist/standalone/workflow-git-capture.js +62 -0
  236. package/dist/standalone/workflow-host.d.ts +931 -0
  237. package/dist/standalone/workflow-host.js +751 -0
  238. package/dist/standalone/workflow-node-capture.d.ts +13 -0
  239. package/dist/standalone/workflow-node-capture.js +72 -0
  240. package/dist/standalone/workflow-root-authority.d.ts +27 -0
  241. package/dist/standalone/workflow-root-authority.js +87 -0
  242. package/dist/standalone/workflow-schedules.d.ts +52 -0
  243. package/dist/standalone/workflow-schedules.js +40 -0
  244. package/dist/standalone/workflow-trigger-host.d.ts +1694 -0
  245. package/dist/standalone/workflow-trigger-host.js +52 -0
  246. package/dist/standalone/workflows.d.ts +657 -0
  247. package/dist/standalone/workflows.js +554 -0
  248. package/dist/storage-frame.d.ts +64 -0
  249. package/dist/storage-frame.js +28 -0
  250. package/dist/tenancy/auth0.d.ts +64 -0
  251. package/dist/tenancy/auth0.js +198 -0
  252. package/dist/tenancy/cloudflare/rate-limit.d.ts +8 -0
  253. package/dist/tenancy/cloudflare/rate-limit.js +19 -0
  254. package/dist/tenancy/cloudflare/registry.d.ts +50 -0
  255. package/dist/tenancy/cloudflare/registry.js +301 -0
  256. package/dist/tenancy/cloudflare.d.ts +2 -0
  257. package/dist/tenancy/cloudflare.js +2 -0
  258. package/dist/tenancy/cold-directory.d.ts +13 -0
  259. package/dist/tenancy/cold-directory.js +43 -0
  260. package/dist/tenancy/contracts.d.ts +195 -0
  261. package/dist/tenancy/contracts.js +1 -0
  262. package/dist/tenancy/index.d.ts +19 -0
  263. package/dist/tenancy/index.js +156 -0
  264. package/dist/tenancy/owner-key.d.ts +26 -0
  265. package/dist/tenancy/owner-key.js +63 -0
  266. package/dist/tenancy/oyster.d.ts +4 -0
  267. package/dist/tenancy/oyster.js +25 -0
  268. package/dist/tenancy/registry-record.d.ts +7 -0
  269. package/dist/tenancy/registry-record.js +44 -0
  270. package/dist/tenancy/registry.d.ts +27 -0
  271. package/dist/tenancy/registry.js +138 -0
  272. package/dist/tenancy/resolve.d.ts +7 -0
  273. package/dist/tenancy/resolve.js +64 -0
  274. package/dist/tenant.d.ts +81 -0
  275. package/dist/tenant.js +71 -0
  276. package/dist/testing/capabilities.d.ts +29 -0
  277. package/dist/testing/capabilities.js +130 -0
  278. package/dist/testing/catalog.d.ts +3 -0
  279. package/dist/testing/catalog.js +53 -0
  280. package/dist/testing/index.d.ts +10 -0
  281. package/dist/testing/index.js +10 -0
  282. package/dist/testing/installation.d.ts +11 -0
  283. package/dist/testing/installation.js +25 -0
  284. package/dist/testing/native-worker.d.ts +21 -0
  285. package/dist/testing/native-worker.js +106 -0
  286. package/dist/testing/worker.d.ts +18 -0
  287. package/dist/testing/worker.js +67 -0
  288. package/dist/testing/workers-runtime.d.ts +24 -0
  289. package/dist/testing/workers-runtime.js +33 -0
  290. package/dist/webhook-delivery.d.ts +14 -0
  291. package/dist/webhook-delivery.js +17 -0
  292. package/dist/workers-git.d.ts +285 -0
  293. package/dist/workers-git.js +1174 -0
  294. package/dist/workers.d.ts +352 -0
  295. package/dist/workers.js +868 -0
  296. package/docs/api/README.md +82 -0
  297. package/docs/api/agents.md +332 -0
  298. package/docs/api/app-storage.md +209 -0
  299. package/docs/api/apps.md +1375 -0
  300. package/docs/api/auth.md +63 -0
  301. package/docs/api/build-contract.md +1304 -0
  302. package/docs/api/build.md +1712 -0
  303. package/docs/api/cloudflare.md +421 -0
  304. package/docs/api/computer.md +203 -0
  305. package/docs/api/files.md +117 -0
  306. package/docs/api/git.md +470 -0
  307. package/docs/api/host.md +1328 -0
  308. package/docs/api/index.md +430 -0
  309. package/docs/api/invocation.md +738 -0
  310. package/docs/api/keys.md +175 -0
  311. package/docs/api/mcp.md +301 -0
  312. package/docs/api/media.md +40 -0
  313. package/docs/api/modules.md +50 -0
  314. package/docs/api/pack.md +141 -0
  315. package/docs/api/page/mount.md +298 -0
  316. package/docs/api/root-data.md +111 -0
  317. package/docs/api/shell/app-directory.md +599 -0
  318. package/docs/api/shell/command-host.md +224 -0
  319. package/docs/api/shell/commands.md +197 -0
  320. package/docs/api/shell/keys.md +183 -0
  321. package/docs/api/shell/shell-module.md +204 -0
  322. package/docs/api/shell/window-manager.md +267 -0
  323. package/docs/api/shell/workbench-directory.md +119 -0
  324. package/docs/api/shell/workbench.md +205 -0
  325. package/docs/api/shell.md +1915 -0
  326. package/docs/api/tenancy/auth0.md +110 -0
  327. package/docs/api/tenancy/cloudflare.md +221 -0
  328. package/docs/api/tenancy/cold-directory.md +46 -0
  329. package/docs/api/tenancy/owner-key.md +63 -0
  330. package/docs/api/tenancy/registry.md +77 -0
  331. package/docs/api/tenancy/resolve.md +69 -0
  332. package/docs/api/tenancy.md +430 -0
  333. package/docs/api/tenant.md +194 -0
  334. package/docs/api/workers-git.md +1646 -0
  335. package/docs/api/workers.md +1691 -0
  336. package/docs/site/agent-quickstart.mdx +346 -0
  337. package/examples/standalone/worker.ts +7 -0
  338. package/examples/standalone/wrangler.jsonc +82 -0
  339. package/package.json +300 -3
@@ -0,0 +1,346 @@
1
+ ---
2
+ title: Agent quick start
3
+ description:
4
+ Hand this guide to a coding agent to install Oyster from npm, run it locally,
5
+ install an App, connect over MCP and deploy.
6
+ ---
7
+
8
+ You are an agent setting up Oyster for a person. Follow these steps in order.
9
+ Run every command exactly as written, from the directory each step names.
10
+ Compare its output with the expected output before you go on. When a step fails,
11
+ read the "If it fails" notes under it before trying anything else.
12
+
13
+ ## What Oyster is
14
+
15
+ - Oyster hosts Apps on one Cloudflare Worker, or on celld, a Workers-compatible
16
+ runtime you host yourself.
17
+ - Each App is an immutable Release built from an exact git commit. Its backend
18
+ runs in its own Durable Object with its own SQLite, and it gets only the
19
+ bindings it declares.
20
+ - People use Apps in a browser. Agents call the same App methods over HTTP or
21
+ through one MCP endpoint, `/mcp`.
22
+
23
+ ## 1. Check prerequisites
24
+
25
+ You need Node 24 or newer, pnpm, Git, curl and openssl. You do not need a
26
+ Cloudflare account until step 7. Docker is needed only in step 7, where Wrangler
27
+ builds the Computer's container image.
28
+
29
+ ```sh
30
+ node --version
31
+ pnpm --version
32
+ git --version
33
+ ```
34
+
35
+ Expected output: a `v24.` or later Node version, any pnpm version, then any
36
+ `git version 2.x` line.
37
+
38
+ If it fails:
39
+
40
+ - Wrong Node: install Node 24 with your version manager, for example
41
+ `mise use node@24` or `nvm install 24`.
42
+ - No pnpm: run `corepack enable`, or use `npm install` wherever this guide says
43
+ `pnpm add`.
44
+
45
+ ## 2. Create a project
46
+
47
+ Make a new directory, install Oyster, its Computer and Wrangler, and copy the
48
+ example Worker out of the package:
49
+
50
+ ```sh
51
+ mkdir my-oyster
52
+ cd my-oyster
53
+ pnpm add @fungi.computer/oyster @fungi.computer/computer
54
+ pnpm add -D wrangler
55
+ cp node_modules/@fungi.computer/oyster/examples/standalone/worker.ts .
56
+ cp node_modules/@fungi.computer/oyster/examples/standalone/wrangler.jsonc .
57
+ ```
58
+
59
+ Expected output: pnpm lists the added package after each `add`, and `ls` now
60
+ shows `node_modules`, `package.json`, `worker.ts` and `wrangler.jsonc`.
61
+
62
+ Every later command runs from this `my-oyster` directory unless the step says
63
+ otherwise.
64
+
65
+ If it fails:
66
+
67
+ - `ERR_PNPM_IGNORED_BUILDS` naming packages such as `esbuild`, `workerd` or
68
+ `protobufjs`: pnpm installed them without running their install scripts, and
69
+ nothing in this guide needs those scripts. Go on.
70
+ - `cp: cannot stat …/examples/standalone/…`: the install did not finish. Run
71
+ `pnpm add @fungi.computer/oyster @fungi.computer/computer` again and read its
72
+ first error.
73
+
74
+ ## 3. Run a local Oyster
75
+
76
+ `worker.ts` and `wrangler.jsonc` are the whole Oyster. Run it under
77
+ `wrangler dev` on your machine, without its Computer container. Oyster serves an
78
+ HTTPS origin; `--local-upstream` presents your loopback requests to it at
79
+ `https://oyster.test`. Choose an owner key and keep this terminal open:
80
+
81
+ ```sh
82
+ export OYSTER_OWNER_KEY=$(openssl rand -hex 24)
83
+ export OYSTER_URL=http://127.0.0.1:8787
84
+ echo "$OYSTER_OWNER_KEY" > .oyster-owner-key
85
+ npx wrangler dev --local --enable-containers=false --ip 127.0.0.1 --port 8787 \
86
+ --local-upstream oyster.test --upstream-protocol https \
87
+ --var OYSTER_OWNER_KEY:$OYSTER_OWNER_KEY --var OYSTER_ORIGIN:https://oyster.test
88
+ ```
89
+
90
+ Expected output: warnings that the AI and Artifacts bindings reach remote
91
+ resources, a bindings table listing `env.REGISTRY (OysterRegistry)`,
92
+ `env.INSTANCES (StandaloneInstance)`, `env.COMPUTER (ComputerDO)` and the rest,
93
+ then `Ready on http://127.0.0.1:8787`. Locally there is no Computer, git storage
94
+ or Workers AI; steps 3 to 5 need none of them.
95
+
96
+ Keep it running. Open a second terminal in `my-oyster`, set the same two
97
+ variables there, and check that Oyster answers:
98
+
99
+ ```sh
100
+ export OYSTER_OWNER_KEY=$(cat .oyster-owner-key)
101
+ export OYSTER_URL=http://127.0.0.1:8787
102
+ curl -s -o /dev/null -w '%{http_code}\n' $OYSTER_URL/login
103
+ curl -s -o /dev/null -w '%{http_code}\n' $OYSTER_URL/api/installations
104
+ curl -s -H "Authorization: Bearer $OYSTER_OWNER_KEY" $OYSTER_URL/api/installations
105
+ ```
106
+
107
+ Expected output: `200`, then `401` (no key), then `[]` (no Apps installed yet).
108
+
109
+ If it fails:
110
+
111
+ - `Address already in use`: another process holds port 8787. Pick another port
112
+ and use it in both `--port` and `OYSTER_URL`.
113
+ - `curl` prints `000`: the server is not ready yet. Wait for the `Ready on`
114
+ line.
115
+ - `401` with the key: the two terminals hold different keys. Set
116
+ `OYSTER_OWNER_KEY` from `.oyster-owner-key` in both.
117
+ - An agent runtime that cannot keep a process in the foreground starts the same
118
+ command in the background with its output in a log, then waits until the
119
+ `/login` check prints `200`:
120
+
121
+ ```sh
122
+ npx wrangler dev --local --enable-containers=false --ip 127.0.0.1 --port 8787 \
123
+ --local-upstream oyster.test --upstream-protocol https \
124
+ --var OYSTER_OWNER_KEY:$OYSTER_OWNER_KEY --var OYSTER_ORIGIN:https://oyster.test \
125
+ > oyster-dev.log 2>&1 &
126
+ ```
127
+
128
+ To stop the server, press Ctrl-C in its terminal. A background server runs as
129
+ several processes (`npm exec`, `wrangler.js` and `workerd`); stop them all by
130
+ ending `wrangler.js`, then check that `/login` prints `000`:
131
+
132
+ ```sh
133
+ pkill -f 'wrangler[.]js dev .*--port 8787'
134
+ ```
135
+
136
+ ## 4. Add an App
137
+
138
+ An App is a git repository with a `package.json` that declares it under
139
+ `fungi.app`. Make the smallest one, a single committed HTML page:
140
+
141
+ ```sh
142
+ mkdir -p hello-app/bundle
143
+ cat > hello-app/package.json <<'EOF'
144
+ {
145
+ "name": "hello-app",
146
+ "private": true,
147
+ "fungi": { "app": { "displayName": "Hello", "capabilities": [] } }
148
+ }
149
+ EOF
150
+ cat > hello-app/bundle/index.html <<'EOF'
151
+ <!doctype html>
152
+ <title>Hello</title>
153
+ <h1>Hello from my first Oyster App</h1>
154
+ EOF
155
+ git -C hello-app init -q
156
+ git -C hello-app add .
157
+ git -C hello-app -c user.name=Oyster -c user.email=oyster@example.invalid \
158
+ commit -qm "Hello App"
159
+ ```
160
+
161
+ Then pack that commit into a Release and install it as installation `hello` with
162
+ `@fungi.computer/oyster/pack`:
163
+
164
+ ```sh
165
+ cat > install-hello.mjs <<'EOF'
166
+ import { execFileSync } from "node:child_process";
167
+ import { mkdtemp, rm } from "node:fs/promises";
168
+ import { tmpdir } from "node:os";
169
+ import { join, resolve } from "node:path";
170
+ import process from "node:process";
171
+ import { installRelease, packRelease } from "@fungi.computer/oyster/pack";
172
+
173
+ const source = resolve("hello-app");
174
+ const commit = execFileSync("git", ["-C", source, "rev-parse", "HEAD"], {
175
+ encoding: "utf8",
176
+ }).trim();
177
+ const out = await mkdtemp(join(tmpdir(), "oyster-hello-"));
178
+ try {
179
+ await packRelease({
180
+ appId: "app_hello",
181
+ sourceDirectory: source,
182
+ sourceRevision: `git:${commit}`,
183
+ recipe: {
184
+ kind: "bundled-html",
185
+ entry: "bundle/index.html",
186
+ assets: {
187
+ maxManifestBytes: 65_536,
188
+ maxObjects: 16,
189
+ maxObjectBytes: 1_048_576,
190
+ maxTotalBytes: 4_194_304,
191
+ },
192
+ assetBase: "./",
193
+ backend: null,
194
+ maxOutputBytes: 4_194_304,
195
+ },
196
+ outDirectory: join(out, "release"),
197
+ });
198
+ const response = await installRelease({
199
+ directory: join(out, "release"),
200
+ url: process.env.OYSTER_URL,
201
+ key: process.env.OYSTER_OWNER_KEY,
202
+ installationId: "hello",
203
+ });
204
+ console.log(`installed hello: ${response.status} ${await response.text()}`);
205
+ } finally {
206
+ await rm(out, { recursive: true, force: true });
207
+ }
208
+ EOF
209
+ node install-hello.mjs
210
+ curl -s -o /dev/null -w '%{http_code}\n' \
211
+ -H "Authorization: Bearer $OYSTER_OWNER_KEY" $OYSTER_URL/apps/hello/
212
+ ```
213
+
214
+ Expected output: one line starting
215
+ `installed hello: 201 {"installationId":"hello",` and containing
216
+ `"status":"enabled"`, then `200`. Running `node install-hello.mjs` again prints
217
+ `installed hello: 200`: the installation already exists, and Oyster switches it
218
+ to the Release just packed.
219
+
220
+ A person can open `$OYSTER_URL/login`, sign in with the owner key, and open
221
+ Hello from the installation list at `$OYSTER_URL/`.
222
+
223
+ If it fails:
224
+
225
+ - `installed hello: 401`: `OYSTER_OWNER_KEY` in this terminal differs from the
226
+ server's. Set it from `.oyster-owner-key`.
227
+ - `fetch failed` or `ECONNREFUSED`: the server from step 3 is not running.
228
+ - The build reads committed files only. To install an edit, commit it in
229
+ `hello-app` and run `node install-hello.mjs` again; Oyster switches the
230
+ installation to the new Release and keeps its data.
231
+
232
+ An App with a backend, typed methods and its own SQLite adds
233
+ `fungi.backendDefinition` and a `backend` entry to its recipe. The
234
+ [Notes example App](https://github.com/fungi-computer/oyster/tree/main/examples/notes-app)
235
+ is one, and the Oyster README's "Pack an App" and "Build App Releases" sections
236
+ describe the recipe.
237
+
238
+ ## 5. Connect over MCP
239
+
240
+ `/mcp` serves every installed App to MCP clients through one `execute` tool, in
241
+ which each App's methods are `env.<APP>`. The owner key signs in. For Claude
242
+ Code:
243
+
244
+ ```sh
245
+ claude mcp add --transport http oyster "$OYSTER_URL/mcp" \
246
+ --header "Authorization: Bearer $OYSTER_OWNER_KEY"
247
+ ```
248
+
249
+ To check `/mcp` without an MCP client, open a session and list its tools:
250
+
251
+ ```sh
252
+ MCP=(-H "Authorization: Bearer $OYSTER_OWNER_KEY" -H 'content-type: application/json' -H 'accept: application/json, text/event-stream')
253
+ SESSION=$(curl -s "${MCP[@]}" -D - -o /dev/null \
254
+ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}' \
255
+ $OYSTER_URL/mcp | grep -i '^mcp-session-id' | cut -d' ' -f2 | tr -d '\r')
256
+ curl -s "${MCP[@]}" -H "mcp-session-id: $SESSION" -H 'mcp-protocol-version: 2025-11-25' \
257
+ -d '{"jsonrpc":"2.0","method":"notifications/initialized"}' $OYSTER_URL/mcp
258
+ curl -s "${MCP[@]}" -H "mcp-session-id: $SESSION" -H 'mcp-protocol-version: 2025-11-25' \
259
+ -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' $OYSTER_URL/mcp
260
+ ```
261
+
262
+ Expected output: the last command prints an `event: message` block whose `data:`
263
+ line contains `"name":"execute"`.
264
+
265
+ If it fails:
266
+
267
+ - `SESSION` is empty: the `initialize` call was refused. Check the key as in
268
+ step 3.
269
+ - Named keys for each agent (`POST /api/keys`) come with the Git worker in
270
+ step 6. The plain standalone Worker answers `404` there.
271
+
272
+ ## 6. Add Git
273
+
274
+ Git is already part of the host: people and agents `clone`, `fetch` and `push`
275
+ App repositories with ordinary `git` at `/git/<installation>/<repo>.git`, with
276
+ repositories in Cloudflare Artifacts. Artifacts runs only once the Worker is
277
+ deployed in step 7. There, give each agent its own key:
278
+
279
+ ```sh
280
+ curl -s -X POST -H "Authorization: Bearer $OYSTER_OWNER_KEY" \
281
+ -H 'content-type: application/json' \
282
+ -d '{"name":"morel","grants":[{"capability":"apps.use","targets":{"kind":"all"}}]}' \
283
+ $OYSTER_URL/api/keys
284
+ ```
285
+
286
+ Expected output: JSON with a `plaintext` field starting `oyk_`. Oyster shows it
287
+ once; that key signs in to `git` and to `/mcp`.
288
+
289
+ ## 7. Deploy to Cloudflare Workers
290
+
291
+ This step needs a Cloudflare account on Workers Paid with Containers, Artifacts,
292
+ Workers AI and Workflows enabled, and Docker running on this machine. Ask the
293
+ person before you deploy anything.
294
+
295
+ `wrangler.jsonc` names the Worker `oyster`, its R2 bucket `oyster-releases` and
296
+ its Artifacts namespace `oyster`. The Worker's address is
297
+ `https://oyster.<your-subdomain>.workers.dev`, or a custom domain:
298
+
299
+ ```sh
300
+ npx wrangler login
301
+ npx wrangler r2 bucket create oyster-releases
302
+ export OYSTER_URL=https://oyster.<your-subdomain>.workers.dev
303
+ npx wrangler deploy --var OYSTER_ORIGIN:$OYSTER_URL
304
+ printf '%s' "$OYSTER_OWNER_KEY" | npx wrangler secret put OYSTER_OWNER_KEY
305
+ ```
306
+
307
+ Expected output: `wrangler deploy` builds the Computer image, uploads it and
308
+ prints the deployed `https://` URL, and `wrangler secret put` reports the secret
309
+ uploaded.
310
+
311
+ Then install Fungi's seven starter Apps, each built on this Oyster's Computer
312
+ from its own repository:
313
+
314
+ ```sh
315
+ npx oyster install-apps
316
+ ```
317
+
318
+ Expected output: a `source recorded` line per App, `Building … on the Computer`
319
+ and `Installed …` lines (two builds at a time, Tourtois first), a timing table,
320
+ and `Installed 7 Apps`. Open `$OYSTER_URL/login` with the owner key to see the
321
+ Tourtois desktop.
322
+
323
+ To keep `OYSTER_ORIGIN` across later deploys, set `vars.OYSTER_ORIGIN` in
324
+ `wrangler.jsonc`; every deploy replaces the Worker's variables.
325
+
326
+ If it fails:
327
+
328
+ - `R2 bucket … already exists`: use that bucket, or pick a new name and put it
329
+ in `wrangler.jsonc`.
330
+ - A secret prompt on stdin: pipe the key as shown; never type it into a log.
331
+ - Bindings or migrations refused: deploy the copied `wrangler.jsonc` unchanged
332
+ except for `vars` and the bucket name.
333
+ - `docker` not found or not running: start Docker; Wrangler builds the Computer
334
+ image from `node_modules/@fungi.computer/computer/Dockerfile`.
335
+ - A build `failed` in `install-apps`: run it again; finished Apps are kept and
336
+ replaced in place.
337
+
338
+ ## Where to go next
339
+
340
+ - The Oyster README (`node_modules/@fungi.computer/oyster/README.md`) explains
341
+ the host, Apps, capabilities, MCP and the shell in depth.
342
+ - [oyster.shiit.app](https://oyster.shiit.app/) runs this same host with the
343
+ seven starter Apps.
344
+ - Oyster is built from the other Fungi packages, each its own repository under
345
+ [github.com/fungi-computer](https://github.com/fungi-computer) and on npm as
346
+ `@fungi.computer/<name>`. The README's "Part of Fungi" section lists them.
@@ -0,0 +1,7 @@
1
+ // The whole Oyster: Apps installed from Releases, each with its own Durable
2
+ // Object and SQLite; git through Artifacts; a Computer in a Cloudflare
3
+ // Container that builds App sources and runs terminals and files; Agents on
4
+ // Workers AI; Workflows; and media. Runs on Cloudflare Workers
5
+ // (`wrangler deploy`) and on celld from the same code.
6
+ export * from "@fungi.computer/oyster/standalone";
7
+ export { default } from "@fungi.computer/oyster/standalone";
@@ -0,0 +1,82 @@
1
+ {
2
+ "$schema": "./node_modules/wrangler/config-schema.json",
3
+ // The whole Oyster. Copy it beside worker.ts, set OYSTER_ORIGIN, and deploy.
4
+ "name": "oyster",
5
+ "main": "worker.ts",
6
+ "compatibility_date": "2026-09-04",
7
+ "compatibility_flags": ["nodejs_compat"],
8
+ "workers_dev": true,
9
+ "preview_urls": false,
10
+ "observability": { "enabled": true },
11
+ "workflows": [
12
+ {
13
+ "binding": "GRAPH_WORKFLOWS",
14
+ "name": "oyster-graphs",
15
+ "class_name": "StandaloneGraphWorkflow",
16
+ },
17
+ ],
18
+ "worker_loaders": [{ "binding": "LOADER" }],
19
+ "containers": [
20
+ {
21
+ "class_name": "ComputerDO",
22
+ "image": "./node_modules/@fungi.computer/computer/Dockerfile",
23
+ "instance_type": "standard-4",
24
+ "max_instances": 1,
25
+ "rollout_active_grace_period": 0,
26
+ "rollout_step_percentage": [100],
27
+ },
28
+ ],
29
+ "ai": { "binding": "AI" },
30
+ "images": { "binding": "IMAGES" },
31
+ "r2_buckets": [
32
+ { "binding": "RELEASES", "bucket_name": "oyster-releases" },
33
+ { "binding": "APP_ARTIFACTS", "bucket_name": "oyster-releases" },
34
+ ],
35
+ "artifacts": [{ "binding": "ARTIFACTS", "namespace": "oyster" }],
36
+ "vars": {
37
+ "OYSTER_COMPUTER_ID": "workspace",
38
+ "OYSTER_HOME_INSTALLATION": "tourtois",
39
+ "OYSTER_ORIGIN": "https://oyster.example",
40
+ "OYSTER_OWNER_NAME": "owner",
41
+ // Names the AI Gateway that Prints' third-party models (GPT Image 2,
42
+ // Seedance, Veo) and the background media retry owner route through.
43
+ // Not a secret: Cloudflare creates the gateway by this id on first use.
44
+ "AI_GATEWAY_ID": "oyster",
45
+ },
46
+ "durable_objects": {
47
+ "bindings": [
48
+ { "name": "TENANTS", "class_name": "StandaloneTenants" },
49
+ { "name": "MCP", "class_name": "OysterMcp" },
50
+
51
+ { "name": "REGISTRY", "class_name": "OysterRegistry" },
52
+ { "name": "WORKFLOW_RUNS", "class_name": "StandaloneWorkflowRuns" },
53
+ { "name": "INSTANCES", "class_name": "StandaloneInstance" },
54
+ { "name": "COMPUTER", "class_name": "ComputerDO" },
55
+ { "name": "KEYS", "class_name": "OysterKeys" },
56
+ { "name": "WEBHOOKS", "class_name": "OysterWebhooks" },
57
+ { "name": "AGENTS", "class_name": "StandaloneAgent" },
58
+ { "name": "AGENT_DIRECTORY", "class_name": "AgentDirectory" },
59
+ { "name": "MEDIA_OPERATION", "class_name": "MediaOperationDO" },
60
+ ],
61
+ },
62
+ // One initial tag: pre-launch history was collapsed (Levi 10-14, data wipe
63
+ // authorized), so a fresh Worker creates every bound class at once.
64
+ "migrations": [
65
+ {
66
+ "tag": "oyster-v1",
67
+ "new_sqlite_classes": [
68
+ "StandaloneTenants",
69
+ "OysterMcp",
70
+ "OysterRegistry",
71
+ "StandaloneWorkflowRuns",
72
+ "StandaloneInstance",
73
+ "ComputerDO",
74
+ "OysterKeys",
75
+ "OysterWebhooks",
76
+ "StandaloneAgent",
77
+ "AgentDirectory",
78
+ "MediaOperationDO",
79
+ ],
80
+ },
81
+ ],
82
+ }