acrylblends 1.0.10 → 1.2.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 (252) hide show
  1. package/README.md +9 -0
  2. package/dist/index.d.ts +60 -2
  3. package/dist/index.js +1992 -33
  4. package/dist/index.js.map +1 -1
  5. package/docs/framework/agents/index.md +1 -1
  6. package/docs/framework/api/summary.md +1 -1
  7. package/docs/framework/getting-started/desktop.md +23 -4
  8. package/docs/framework/guides/create-acrylblends.md +1 -1
  9. package/docs/framework/guides/production.md +20 -0
  10. package/docs/framework/workshop/README.md +174 -285
  11. package/docs/framework/workshop/facilitator.md +81 -90
  12. package/legacy/README.md +9 -0
  13. package/legacy/agent/157ce3db1112/src/app.ts +98 -0
  14. package/legacy/agent/157ce3db1112/src/routes.ts +63 -0
  15. package/legacy/agent/24c681a00fca/src/app.ts +160 -0
  16. package/legacy/agent/24c681a00fca/src/routes.ts +83 -0
  17. package/legacy/agent/2e790da977b2/src/app.ts +98 -0
  18. package/legacy/agent/2e790da977b2/src/routes.ts +63 -0
  19. package/legacy/agent/6307045545dc/src/app.ts +168 -0
  20. package/legacy/agent/6307045545dc/src/routes.ts +83 -0
  21. package/legacy/agent/6a5fb9c15c53/src/app.ts +158 -0
  22. package/legacy/agent/6a5fb9c15c53/src/routes.ts +83 -0
  23. package/legacy/agent/71fb54a5a942/src/app.ts +111 -0
  24. package/legacy/agent/71fb54a5a942/src/routes.ts +63 -0
  25. package/legacy/agent/74ece148269c/src/app.ts +168 -0
  26. package/legacy/agent/74ece148269c/src/routes.ts +93 -0
  27. package/legacy/agent/855359304707/src/app.ts +168 -0
  28. package/legacy/agent/855359304707/src/routes.ts +126 -0
  29. package/legacy/agent/b5ef3c786ae4/src/app.ts +127 -0
  30. package/legacy/agent/b5ef3c786ae4/src/routes.ts +76 -0
  31. package/legacy/agent/c2f30958043b/src/app.ts +98 -0
  32. package/legacy/agent/c2f30958043b/src/routes.ts +53 -0
  33. package/legacy/blank/5a91c558af22/src/routes.ts +18 -0
  34. package/legacy/blank/9c650cf52bf3/src/routes.ts +14 -0
  35. package/legacy/blank/aea589283445/src/routes.ts +16 -0
  36. package/legacy/blank/b2cbb759c889/src/routes.ts +16 -0
  37. package/legacy/blank/d6d371c9a65e/src/routes.ts +18 -0
  38. package/legacy/chat/7076cc821e2c/src/app.ts +72 -0
  39. package/legacy/chat/7076cc821e2c/src/routes.ts +13 -0
  40. package/legacy/chat/7dbe6d5170df/src/app.ts +107 -0
  41. package/legacy/chat/7dbe6d5170df/src/routes.ts +19 -0
  42. package/legacy/chat/a9a9ab44c58e/src/app.ts +107 -0
  43. package/legacy/chat/a9a9ab44c58e/src/routes.ts +15 -0
  44. package/legacy/chat/f20ad9a51b06/src/app.ts +106 -0
  45. package/legacy/chat/f20ad9a51b06/src/routes.ts +15 -0
  46. package/legacy/layouts.json +524 -0
  47. package/legacy/nodejs/1d477f37aaf4/src/app.ts +92 -0
  48. package/legacy/nodejs/1d477f37aaf4/src/routes.ts +40 -0
  49. package/legacy/nodejs/b1bd9462496c/src/app.ts +61 -0
  50. package/legacy/nodejs/b1bd9462496c/src/routes.ts +37 -0
  51. package/legacy/nodejs/d5bab75076ef/src/app.ts +95 -0
  52. package/legacy/nodejs/d5bab75076ef/src/routes.ts +40 -0
  53. package/legacy/notes/4edc36949c15/src/app.ts +107 -0
  54. package/legacy/notes/4edc36949c15/src/routes.ts +14 -0
  55. package/legacy/notes/6cab2d09747c/src/app.ts +72 -0
  56. package/legacy/notes/6cab2d09747c/src/routes.ts +12 -0
  57. package/legacy/notes/7ca2dfed623a/src/app.ts +106 -0
  58. package/legacy/notes/7ca2dfed623a/src/routes.ts +14 -0
  59. package/legacy/todo/02e613b3625c/src/app.ts +71 -0
  60. package/legacy/todo/02e613b3625c/src/todo.ts +123 -0
  61. package/legacy/todo/45694a8d9e15/src/app.ts +71 -0
  62. package/legacy/todo/45694a8d9e15/src/todo.ts +96 -0
  63. package/legacy/todo/5923d3a6099f/src/app.ts +71 -0
  64. package/legacy/todo/5923d3a6099f/src/todo.ts +125 -0
  65. package/legacy/todo/849a18d66dc1/src/app.ts +91 -0
  66. package/legacy/todo/849a18d66dc1/src/todo.ts +125 -0
  67. package/legacy/todo/8e64211312f3/src/app.ts +71 -0
  68. package/legacy/todo/8e64211312f3/src/todo.ts +125 -0
  69. package/legacy/todo/b79078a87565/src/app.ts +71 -0
  70. package/legacy/todo/b79078a87565/src/todo.ts +125 -0
  71. package/lib/{audit-Dw-siYTp.d.ts → audit-Bok_UNCn.d.ts} +41 -6
  72. package/lib/{client-modules-drj4mjhj.js → client-modules-Bkdr83jO.js} +1 -1
  73. package/lib/cordis/door.d.ts +44 -7
  74. package/lib/cordis/door.js +214 -60
  75. package/lib/cordis/inspect.js +1 -1
  76. package/lib/cordis/node-server.d.ts +101 -3
  77. package/lib/cordis/node-server.js +3 -3
  78. package/lib/cordis/router-http.d.ts +7 -1
  79. package/lib/cordis/router-http.js +44 -3
  80. package/lib/cordis/router.d.ts +1 -1
  81. package/lib/cordis/router.js +1 -1
  82. package/lib/cordis/state.d.ts +3 -2
  83. package/lib/cordis/state.js +371 -7
  84. package/lib/door/host.d.ts +2 -2
  85. package/lib/door/host.js +1 -1
  86. package/lib/door/page.d.ts +20 -1
  87. package/lib/door/page.js +75 -14
  88. package/lib/door/protocol.d.ts +1 -1
  89. package/lib/drivers.d.ts +10 -1
  90. package/lib/{index-DMOtA-NJ.d.ts → index-DGq7H0lb.d.ts} +11 -1
  91. package/lib/node-server.d.ts +7 -1
  92. package/lib/node-server.js +2 -2
  93. package/lib/{protocol-a2aqrp2X.d.ts → protocol-BeIYCgTo.d.ts} +4 -0
  94. package/lib/{snapshot-text-BfEbEOjA.js → snapshot-text-CXTnjxGx.js} +121 -9
  95. package/lib/src-CtkIX_Gg.js +427 -0
  96. package/lib/{src-BTBm4OPD.js → src-iBJ2ysV9.js} +77 -14
  97. package/lib/{test-websocket-BLeEvybj.js → test-websocket-CQOSvBth.js} +17 -7
  98. package/lib/{test-websocket-DyeS50Tr.d.ts → test-websocket-GUTAkFQT.d.ts} +3 -1
  99. package/package.json +2 -1
  100. package/plugins/acryl-door/src/host/channel.ts +124 -9
  101. package/plugins/acryl-door/src/host/chat-tools.ts +8 -6
  102. package/plugins/acryl-door/src/host/door-file.ts +7 -2
  103. package/plugins/acryl-door/src/host/door.ts +58 -23
  104. package/plugins/acryl-door/src/host/page-routes.ts +3 -1
  105. package/plugins/acryl-door/src/host/page-socket.ts +18 -8
  106. package/plugins/acryl-door/src/host/verbs.ts +3 -0
  107. package/plugins/acryl-door/src/index.ts +166 -29
  108. package/plugins/acryl-door/src/page/base.ts +32 -0
  109. package/plugins/acryl-door/src/page/channel.ts +11 -1
  110. package/plugins/acryl-door/src/page/driver/accessibility.ts +11 -0
  111. package/plugins/acryl-door/src/page/driver/actions.ts +4 -0
  112. package/plugins/acryl-door/src/page/driver/driver.ts +49 -7
  113. package/plugins/acryl-door/src/page/driver/snapshot.ts +5 -2
  114. package/plugins/acryl-door/src/page/index.ts +46 -2
  115. package/plugins/acryl-door/src/page/indicator.ts +14 -6
  116. package/plugins/acryl-door/src/page/outline.ts +56 -0
  117. package/plugins/acryl-door/src/page/protocol.ts +4 -0
  118. package/plugins/acryl-door/src/page/snapshot-text.ts +2 -1
  119. package/plugins/acryl-node-server/src/adapter/listener.ts +4 -0
  120. package/plugins/acryl-node-server/src/adapter/raw.ts +18 -0
  121. package/plugins/acryl-node-server/src/adapter/websocket.ts +15 -9
  122. package/plugins/acryl-node-server/src/client-modules.ts +7 -1
  123. package/plugins/acryl-node-server/src/index.ts +304 -16
  124. package/plugins/acryl-node-server/src/upgrade-hub.ts +2 -2
  125. package/plugins/acryl-page/plugin.json +12 -0
  126. package/plugins/acryl-page/src/index.ts +163 -0
  127. package/plugins/acryl-router/src/service.ts +77 -14
  128. package/plugins/acryl-router-http/src/index.ts +15 -1
  129. package/plugins/acryl-router-http/src/serve.ts +31 -0
  130. package/plugins/acryl-state/plugin.json +4 -3
  131. package/plugins/acryl-state/src/client-source.ts +244 -0
  132. package/plugins/acryl-state/src/service.ts +33 -6
  133. package/plugins/acryl-state/src/socket.ts +96 -0
  134. package/plugins/acryl-web-server/plugin.json +14 -0
  135. package/plugins/acryl-web-server/src/index.ts +164 -0
  136. package/plugins/agent/agent.ts +38 -7
  137. package/plugins/agent/index.ts +1 -1
  138. package/plugins/agent/model.ts +10 -2
  139. package/plugins/agent/tools.ts +9 -3
  140. package/plugins/agent-panel/client/describe.ts +57 -0
  141. package/plugins/agent-panel/client/driver-pick.ts +22 -0
  142. package/plugins/agent-panel/client/frame.ts +51 -0
  143. package/plugins/agent-panel/client/main.ts +343 -81
  144. package/plugins/agent-panel/drivers.ts +7 -2
  145. package/plugins/agent-panel/headless.ts +5 -2
  146. package/plugins/agent-panel/index.ts +187 -61
  147. package/plugins/agent-panel/mount.ts +27 -0
  148. package/plugins/agent-panel/visitors.ts +231 -0
  149. package/plugins/desktop/frame.ts +231 -0
  150. package/plugins/desktop/launch.ts +44 -9
  151. package/plugins/desktop/main.ts +100 -32
  152. package/plugins/desktop/window.ts +21 -4
  153. package/plugins/driver-pty/client/terminal.ts +4 -1
  154. package/plugins/driver-pty/index.ts +38 -11
  155. package/plugins/driver-pty/spawn.ts +38 -0
  156. package/plugins/driver-pty/terminal.ts +2 -0
  157. package/plugins/extensions/index.ts +26 -1
  158. package/plugins/extensions/resolve.ts +13 -0
  159. package/plugins/feedback/client.d.ts +22 -0
  160. package/plugins/feedback/client.js +471 -0
  161. package/plugins/feedback/index.ts +143 -0
  162. package/plugins/feedback/plugin.json +11 -0
  163. package/plugins/feedback/store.ts +307 -0
  164. package/plugins/home/index.ts +122 -0
  165. package/plugins/home/plugin.json +11 -0
  166. package/plugins/instance/index.ts +12 -3
  167. package/plugins/manifest/app-plugins.ts +86 -0
  168. package/plugins/manifest/index.ts +12 -2
  169. package/plugins/manifest/snapshot.ts +275 -0
  170. package/plugins/openai/index.ts +64 -5
  171. package/plugins/openai/prompt.ts +23 -0
  172. package/shared/AGENTS.core.md +36 -16
  173. package/shared/skills/acryl-add-ui/SKILL.md +19 -0
  174. package/shared/skills/acryl-app/SKILL.md +13 -0
  175. package/shared/skills/acryl-build-plugin/SKILL.md +22 -0
  176. package/shared/skills/acryl-change-plugin/SKILL.md +14 -0
  177. package/shared/skills/acryl-diagnose-plugin/SKILL.md +13 -0
  178. package/shared/skills/acryl-fix-plugin/SKILL.md +13 -0
  179. package/shared/skills/acryl-remove-plugin/SKILL.md +12 -0
  180. package/shared/skills/acryl-share-plugin/SKILL.md +16 -0
  181. package/shared/skills/cordis-plugin/SKILL.md +26 -0
  182. package/templates/agent/AGENTS.md +4 -2
  183. package/templates/agent/blend.yaml +4 -0
  184. package/templates/agent/gitignore +1 -0
  185. package/templates/agent/package.json +1 -0
  186. package/templates/agent/src/app.ts +150 -33
  187. package/templates/agent/src/frame.ts +17 -0
  188. package/templates/agent/src/main.ts +5 -3
  189. package/templates/agent/src/routes.ts +73 -21
  190. package/templates/agent/template.json +2 -0
  191. package/templates/agent/test/app.test.ts +83 -5
  192. package/templates/blank/AGENTS.md +3 -2
  193. package/templates/blank/blend.yaml +11 -0
  194. package/templates/blank/gitignore +1 -0
  195. package/templates/blank/package.json +1 -0
  196. package/templates/blank/src/app.ts +100 -29
  197. package/templates/blank/src/door.ts +7 -0
  198. package/templates/blank/src/first-page.ts +5 -0
  199. package/templates/blank/src/frame.ts +17 -0
  200. package/templates/blank/src/routes.ts +65 -8
  201. package/templates/blank/template.json +14 -1
  202. package/templates/blank/test/app.test.ts +103 -16
  203. package/templates/chat/blend.yaml +2 -1
  204. package/templates/chat/gitignore +1 -0
  205. package/templates/chat/package.json +1 -0
  206. package/templates/chat/src/app.ts +72 -22
  207. package/templates/chat/src/chat-app.ts +11 -2
  208. package/templates/chat/src/client/chat.tsx +4 -2
  209. package/templates/chat/src/frame.ts +17 -0
  210. package/templates/chat/src/main.ts +1 -6
  211. package/templates/chat/src/page.tsx +6 -4
  212. package/templates/chat/src/routes.ts +14 -4
  213. package/templates/chat/src/runtime.ts +9 -3
  214. package/templates/chat/template.json +3 -1
  215. package/templates/chat/test/chat.test.ts +46 -1
  216. package/templates/chat/test/server.test.ts +17 -3
  217. package/templates/nodejs/blend.yaml +2 -1
  218. package/templates/nodejs/gitignore +1 -0
  219. package/templates/nodejs/package.json +1 -0
  220. package/templates/nodejs/src/app.ts +76 -21
  221. package/templates/nodejs/src/frame.ts +17 -0
  222. package/templates/nodejs/src/main.ts +1 -6
  223. package/templates/nodejs/src/page.tsx +3 -3
  224. package/templates/nodejs/src/routes.ts +32 -13
  225. package/templates/nodejs/template.json +3 -1
  226. package/templates/nodejs/test/app.test.ts +38 -3
  227. package/templates/nodejs/test/server.test.ts +17 -3
  228. package/templates/notes/blend.yaml +2 -1
  229. package/templates/notes/gitignore +1 -0
  230. package/templates/notes/package.json +1 -0
  231. package/templates/notes/src/app.ts +72 -22
  232. package/templates/notes/src/frame.ts +17 -0
  233. package/templates/notes/src/main.ts +1 -6
  234. package/templates/notes/src/notes-app.ts +24 -17
  235. package/templates/notes/src/routes.ts +11 -4
  236. package/templates/notes/src/runtime.ts +9 -3
  237. package/templates/notes/src/views.tsx +26 -17
  238. package/templates/notes/template.json +3 -1
  239. package/templates/notes/test/notes.test.ts +39 -1
  240. package/templates/notes/test/server.test.ts +17 -3
  241. package/templates/todo/blend.yaml +3 -0
  242. package/templates/todo/gitignore +1 -0
  243. package/templates/todo/package.json +1 -0
  244. package/templates/todo/src/app.ts +81 -27
  245. package/templates/todo/src/door.ts +7 -0
  246. package/templates/todo/src/frame.ts +17 -0
  247. package/templates/todo/src/page.ts +13 -6
  248. package/templates/todo/src/todo.ts +18 -6
  249. package/templates/todo/template.json +11 -1
  250. package/templates/todo/test/todo.test.ts +67 -9
  251. package/lib/src-LX0E4ec4.js +0 -117
  252. package/shared/SKILL.md +0 -14
@@ -1,381 +1,270 @@
1
- # From nothing to your own app: the ACRYL Blends workshop
1
+ # Build your app inside the ACRYL frame: the ACRYL Blends workshop
2
2
 
3
- Ninety minutes, starting from an empty folder. **Acryl** is a small web framework built on Web Standards: a handler takes a `Request` and returns a
4
- `Response`, exactly as in the browser. **ACRYL Blends** puts that framework inside an app you own: a folder whose `blend.yaml` lists its plugins, whose
5
- `plugins/` folder holds their code, and which runs in a browser or in a desktop window. A coding agent can change the app while it runs. By the end you
6
- will have built an app from the blank template, added a feature to it with an agent, opened it as a desktop window, upgraded it, and published it as a
7
- starter other people can pull from the registry.
3
+ Ninety minutes, from an empty folder to an app that opens in ACRYL's own IDE: projects on the left, your app's page in the middle, files,
4
+ changes, checks and terminals on the right, a chat model that works on your app beside it, and Claude, Codex or Pi running in terminal tabs in
5
+ the same folder. **Acryl** is the small web framework underneath (a handler takes a `Request` and returns a `Response`); **ACRYL Blends** is the
6
+ app around it: a folder of Cordis plugins with a `blend.yaml`, running on your machine, opened by the frame.
8
7
 
9
- Every command below is copy-pasteable and was run on the published packages. Each step says how long it takes; the checkpoints tell you whether you
10
- are on time.
8
+ The frame is the workshop's point. You do not edit a folder and alt-tab to a browser: your app is a page inside the workspace, the agents work in
9
+ the same folder the frame shows, and every change you or an agent makes is one restart away from the page.
11
10
 
12
- ## What you need (10 minutes)
11
+ This guide is for **acrylblends 1.2.0 or newer**; `npm create acrylblends@latest` gives you that. An app you made with an older release gets the
12
+ frame with the upgrade in block 6.
13
13
 
14
- | | macOS | Windows | Linux |
15
- | --- | --- | --- | --- |
16
- | Node.js 22.19 or newer (24 LTS or 26 tested) | `node -v` | `node -v` | `node -v` |
17
- | npm, which comes with Node | `npm -v` | `npm -v` | `npm -v` |
18
- | git | `git --version` | `git --version` | `git --version` |
19
- | a coding agent, logged in | `codex login status` or `claude --version` | same | same |
20
- | a GitHub account and the `gh` CLI, logged in | `gh auth status` | same | same |
14
+ ## 0. Before you start (10 minutes)
21
15
 
22
- Install what is missing: Node from <https://nodejs.org> (the LTS), git from <https://git-scm.com>, the GitHub CLI (`brew install gh`, `winget
23
- install GitHub.cli`, or <https://cli.github.com>), and one agent with `npm i -g @openai/codex` (then `codex login` once) or Claude Code. Run
24
- `gh auth login` once, in any repository: step 10 publishes your app with a pull request. No prior knowledge of ACRYL, Cordis or Blends is needed;
25
- every new word is explained where it appears.
26
-
27
- Make a folder and open a terminal in it:
28
-
29
- ```sh
30
- mkdir ~/acryl-workshop && cd ~/acryl-workshop
31
- ```
32
-
33
- ## The path
34
-
35
- | Minutes | Step | What you get |
36
- | --- | --- | --- |
37
- | 0-10 | Before you start | tools installed and checked |
38
- | 10-15 | 1. Create and run | a blank app answering in a browser |
39
- | 15-22 | 2. Change one thing | a route of your own, live, without a restart |
40
- | 22-30 | 3. Tests and the typecheck | the app proves itself |
41
- | 30-38 | 4. Data: JSON, then SQLite *(optional)* | a counter kept in a file, then in SQL |
42
- | 38-45 | 5. A desktop window | the same app as a window |
43
- | 45-53 | 6. Pull a starter from the registry | someone else's app in your folder |
44
- | 53-60 | 7. Create from a template | the six starters, one table, one run |
45
- | 60-75 | 8. An agent builds a feature | your app changed by the agent, still running |
46
- | 75-82 | 9. Upgrade | the app moved to the current framework |
47
- | 82-90 | 10. Publish it | your app as a registry starter |
48
-
49
- > **Checkpoint 15 minutes:** your app answers in a browser. Without that, read the "Stuck?" line of step 1.
50
- > **Checkpoint 45 minutes:** your app is open in a desktop window. Behind? Step 4 is the optional one; skip it and carry on.
51
- > **Checkpoint 75 minutes:** the agent's page is live. Still waiting? Give it five more minutes, then skip step 9.
52
-
53
- ## 1. Create and run (5 minutes)
16
+ Run this first. It checks everything below and prints one line per check, with the exact command for anything missing:
54
17
 
55
18
  ```sh
56
- npm create acrylblends@latest my-hero blank
57
- cd my-hero
58
- npm install
59
- npm run dev
60
- ```
61
-
62
- You should see:
63
-
64
- ```
65
- created my-hero (blank) in /Users/you/acryl-workshop/my-hero: … files, plugins instance, acryl-router, acryl-node-server, manifest, save
66
-
67
- Next:
68
- cd my-hero
69
- npm install
70
- npm run dev
71
- ```
72
-
73
- then, from `npm run dev`:
74
-
19
+ npx acrylblends@latest preflight
75
20
  ```
76
- my-hero listening on http://127.0.0.1:3080 (data in /Users/you/acryl-workshop/my-hero/.acrylblends)
77
- ```
78
-
79
- Open that address: `{"app":"my-hero","ok":true}`. `/health` answers `{"ok":true}` too. Leave the terminal running.
80
21
 
81
- **Stuck?** A busy port gets the next free one: use the address the app printed. The first `npm create` downloads the initializer, so give it a few
82
- seconds.
22
+ It ends with `Ready for the workshop.`, or with how many lines say `FIX`: run each `FIX` line, then the preflight again. `NOTE` lines are things the
23
+ first blocks do without.
83
24
 
84
- ## 2. Change one thing (7 minutes)
25
+ | | macOS | Windows | Linux |
26
+ | --- | --- | --- | --- |
27
+ | Node.js 22.19 or newer (24 and 26 work) | `node -v` | `node -v` | `node -v` |
28
+ | git | `git --version` | `git --version` | `git --version` |
29
+ | one coding agent, logged in | `codex login status` or `claude --version` or `pi --version` | same | same |
30
+ | GitHub account and `gh`, for the last block | `gh auth status` | same | same |
85
31
 
86
- Open `src/routes.ts`. It builds an `Acryl` app and mounts it on the router. Add one line to that chain, just above `.get('/health', …)`, and keep the
87
- indentation of the lines around it:
32
+ Install what is missing: Node from <https://nodejs.org> (the LTS), git from <https://git-scm.com>, the GitHub CLI from <https://cli.github.com> (`gh auth
33
+ login` once), and one agent:
88
34
 
89
- ```ts
90
- .get('/hello', (c) => c.json({ hello: 'workshop' }))
91
- ```
35
+ - **Claude Code**: <https://claude.com/claude-code>, then run `claude` once to log in.
36
+ - **Codex**: `npm i -g @openai/codex`, then `codex login`. If a run answers `model_not_found`, your account does not have the default model: pick one
37
+ your account supports (`/model` inside codex, or `model = "..."` in `~/.codex/config.toml`).
38
+ - **pi with DeepSeek**: `npm i -g @earendil-works/pi-coding-agent`, and set your DeepSeek key in the terminal you start the app from (the terminal
39
+ tabs inherit that environment). The preflight checks the key: `PASS agent pi (DeepSeek key found)`.
92
40
 
93
- Save. The terminal prints `Change detected … Restarting 'src/main.ts'`, and `http://127.0.0.1:3080/hello` answers `{"hello":"workshop"}`. No restart
94
- command, no build step: the app watches its own source.
41
+ | macOS and Linux | Windows PowerShell | Windows cmd.exe |
42
+ | --- | --- | --- |
43
+ | `export DEEPSEEK_API_KEY=sk-...` | `$env:DEEPSEEK_API_KEY="sk-..."` | `set DEEPSEEK_API_KEY=sk-...` |
95
44
 
96
- **Stuck?** No message means the file is not where the app watches; the message names the path it saw. A red error names the file and line.
45
+ **One model key for the chat.** The frame's chat needs a model: a DeepSeek API key from <https://platform.deepseek.com> is the shortest path (you add
46
+ it in block 3). A Claude or ChatGPT subscription works too, through **Sign in with an account** on the same Settings page.
97
47
 
98
- ## 3. Tests and the typecheck (8 minutes)
48
+ No prior knowledge of ACRYL, Cordis or Blends is needed; every new word is explained where it appears.
99
49
 
100
- Stop the server with `Ctrl-C`, then:
50
+ Make the workshop folder:
101
51
 
102
- ```sh
103
- npm test
104
- npm run check
105
- ```
106
-
107
- `npm test` ends with `ℹ pass 5`, `ℹ fail 0`. `npm run check` prints nothing when the types are clean.
52
+ | macOS and Linux | Windows PowerShell | Windows cmd.exe |
53
+ | --- | --- | --- |
54
+ | `mkdir ~/acryl-workshop && cd ~/acryl-workshop` | `mkdir ~/acryl-workshop` then `cd ~/acryl-workshop` | `mkdir %USERPROFILE%\acryl-workshop` then `cd %USERPROFILE%\acryl-workshop` |
108
55
 
109
- Now add a test for your route in `test/`: copy the style of the existing test file, request `/hello` and expect `{"hello":"workshop"}`. `npm test`
110
- again; a failure names the file and line.
56
+ **On Windows.** Windows PowerShell 5.1 (the one Windows ships) has no `&&`: where this guide joins two commands with `&&`, type them as two lines, or join
57
+ them with `;`. PowerShell 7 (`pwsh`) accepts `&&`. In cmd.exe, `Ctrl-C` asks `Terminate batch job (Y/N)?`: answer `Y`.
111
58
 
112
- **Stuck?** `npm run check` complaining about your new line is the typechecker doing its job; the message says which type it expected.
59
+ **The agent setting that matters all day.** The agents are configured to act rather than to describe: when you ask for something, they write the
60
+ files and check the result. If your agent stops to ask "shall I proceed?", answer "do it now" and it continues; that one sentence is the difference
61
+ between watching and building.
113
62
 
114
- ## 4. Data: JSON, then SQLite (8 minutes, optional)
63
+ ## The path
115
64
 
116
- An app keeps data through a **port**: a small interface a plugin provides. The smallest is `kv`, a JSON file in the app's own folder.
65
+ | Minutes | Block | What you get |
66
+ | --- | --- | --- |
67
+ | 0-10 | 0. Before you start | a checked machine, one model key, a folder |
68
+ | 10-20 | 1. Create the app, open the frame | the app running and shown inside the ACRYL frame |
69
+ | 20-25 | 2. Your first change | the app's page in the frame showing your edit |
70
+ | 25-30 | 3. Connect your model in Settings > Models | a chat that answers |
71
+ | 30-50 | 4. Chat: your model builds a page | a board page the model wrote and you saw at /app/board |
72
+ | 50-65 | 5. A coding agent in a terminal tab | Claude, Codex or Pi working in the app's folder |
73
+ | 65-80 | 6. Upgrade an older app onto the frame | an app from before today, opened by the frame |
74
+ | 80-90 | 7. Publish it as a starter | the app listed in the workshop registry |
75
+
76
+ > **Checkpoint 20 minutes:** the app's page is in the frame.
77
+ > **Checkpoint 30 minutes:** the chat answers.
78
+ > **Checkpoint 50 minutes:** the model's board is at /app/board.
79
+ > **Checkpoint 65 minutes:** an agent in a terminal has changed the app.
80
+
81
+ ## 1. Create the app; the frame opens on it (10 minutes)
117
82
 
118
83
  ```sh
119
- npx acrylblends add acryl-kv-json
84
+ npm create acrylblends@latest my-app agent
85
+ cd my-app
120
86
  npm install
87
+ npm run dev
121
88
  ```
122
89
 
123
- `add` copies the plugin into `plugins/` and prints how to mount it. Three edits:
90
+ `npm install` is bigger than a framework-only app: it brings the frame and the chat engine (about 500 MB together, much less on a warm package
91
+ cache). `npm run dev` starts the app inside the frame and prints one line:
124
92
 
125
- 1. `blend.yaml`, before `- id: server`: add the provider row (the row's id is yours to pick; the name is the plugin):
126
-
127
- ```yaml
128
- - id: kv
129
- name: acryl-kv-json
130
- ```
93
+ ```text
94
+ acrylblends host: http://127.0.0.1:3489/?token=...
95
+ ```
131
96
 
132
- 2. `src/app.ts`: import the plugin and register it under that name:
97
+ Open that address (it is a free port on your machine; never a fixed one). It stays the same every time you start the app, and it is the way back in
98
+ later: `npx acrylblends open` prints it again while the frame is running. The first time, DeepSeek Harness shows a **Preview Notice**: press **Continue**. Then the frame opens **on your app**: the page in the middle is `my-app`'s own page, in a tab named after the app.
133
99
 
134
- ```ts
135
- import * as kvJson from '../plugins/acryl-kv-json/src/index.ts'
136
- ```
100
+ ![The frame on first run: projects on the left with the app selected, the app's page in the canvas, the tab strip with the app's tab](/docs-assets/workshop/s1-frame.webp)
137
101
 
138
- ```ts
139
- export const registry = { 'acryl-router': router, 'acryl-node-server': nodeServer, 'acryl-kv-json': kvJson, routes }
140
- ```
102
+ The three columns are ACRYL's IDE:
141
103
 
142
- 3. `src/routes.ts`: declare the port and count visits in your route:
104
+ - **Left:** your workspaces and projects. `my-app` is selected; the account row above and **Settings** below.
105
+ - **Middle:** tabs. `my-app` is your app's page; the `+` at the left of the tab strip opens more (terminal, browser, files, chat, agents).
106
+ - **Right:** open it with the panel button at the top right (or `Cmd/Ctrl+B`): **Files**, **Changes**, **Review**, **Checks**, **Comments** and a
107
+ terminal. The bottom bar is the terminal dock.
143
108
 
144
- ```ts
145
- import type {} from '../plugins/acryl-kv/src/cordis.ts'
146
- ```
109
+ The app's page also has an agent of its own: **Ask the agent** at the bottom right opens the app's panel (the offline agent unless the app is given
110
+ a model). The frame's chat in the next blocks is the tool you will use; the panel is there for the app to ship with.
147
111
 
148
- ```ts
149
- inject: ['router', 'kv'],
150
- ```
112
+ **Stuck?** A busy port means the terminal printed a different address; use that. `npm install` failing on the native terminal package needs a C++
113
+ toolchain: on macOS `xcode-select --install`, on Windows the "Desktop development with C++" workload of Visual Studio Build Tools, on Ubuntu
114
+ `sudo apt install build-essential python3`.
151
115
 
152
- ```ts
153
- .get('/hello', async (c) => {
154
- const visits = await ctx.kv.update('visits', (n) => (n ?? 0) + 1)
155
- return c.json({ hello: 'workshop', visits })
156
- })
157
- ```
116
+ ## 2. Your first change, seen at /app (5 minutes)
158
117
 
159
- `npm run dev` again and open `/hello` twice: `visits` goes 1, 2. The file is `my-hero/.acrylblends/kv.json`.
118
+ Open the right panel (**Files**), expand `src`, click `routes.ts`. Find the sentence the page shows ("This app runs an agent unless it is switched
119
+ off...") and change it to something that is yours. Press **Save** in the editor's bar (or `Cmd/Ctrl+S`).
160
120
 
161
- The relational port is `db`, with numbered SQL migrations:
121
+ The running app does not pick a source change up by itself. Stop the host with `Ctrl-C` in the terminal where `npm run dev` runs (in cmd.exe answer
122
+ `Y`), then start it again:
162
123
 
163
124
  ```sh
164
- npx acrylblends add acryl-db-sqlite
165
- mkdir migrations
166
- printf 'CREATE TABLE visits (id INTEGER PRIMARY KEY, at TEXT NOT NULL);\n' > migrations/001-visits.sql
167
- npm install
125
+ npm run dev
168
126
  ```
169
127
 
170
- A row in `blend.yaml` (`- id: db`, `name: acryl-db-sqlite`), then the migration folder in `src/app.ts`, where the app is composed: the path is set
171
- there, not in the manifest, because a relative path in the manifest has no folder to resolve against.
128
+ The frame reconnects on its own, on the same address (the port is stable per app), in a few seconds. If a chat tab opened in front, press the
129
+ `my-app` tab: the page shows your sentence. That is the whole development loop for the rest of the day: edit, restart, look.
172
130
 
173
- ```ts
174
- import * as dbSqlite from '../plugins/acryl-db-sqlite/src/index.ts'
175
- // in the registry: 'acryl-db-sqlite': dbSqlite
176
- const projectRoot = fileURLToPath(new URL('..', import.meta.url))
177
- // in the compose options next to server:
178
- db: { migrations: join(projectRoot, 'migrations') },
131
+ ```sh
132
+ npm test
133
+ npm run check
179
134
  ```
180
135
 
181
- Then `inject: ['router', 'kv', 'db']` with `import type {} from '../plugins/acryl-db/src/cordis.ts'`, and in the route
182
- `await ctx.db.run('INSERT INTO visits (at) VALUES (?)', new Date().toISOString())` before the reply. The database is `my-hero/.acrylblends/data.sqlite`,
183
- and the migrations run at start, in order.
136
+ Both pass: the app is TypeScript, with tests and a type check, and the scaffold made the folder a git repository, so **Changes** shows what you
137
+ edited.
184
138
 
185
- **Stuck?** `migrations "migrations" is relative, but this app has no file base URL` means the app has `acrylblends` older than 1.0.3, where a relative path in `blend.yaml` was not read
186
- from the app folder; move it into `src/app.ts` as above, or update (`npx acrylblends@latest upgrade`). "no such table" means the file is not in `migrations/` at the app root.
139
+ **Stuck?** If the page looks unchanged, the host did not restart (the terminal says `Restarting` or it is waiting on `Ctrl-C`). If the frame still
140
+ says `Reconnecting...` after ten seconds, reload the tab: the address is the same one it was opened with. If the tab was closed, `npx acrylblends open`
141
+ in the app's folder prints the address again.
187
142
 
188
- ## 5. A desktop window (7 minutes)
143
+ ## 3. Connect your model: Settings > Models (5 minutes)
189
144
 
190
- ```sh
191
- npx acrylblends add desktop
192
- npm install
193
- npm run desktop
194
- ```
145
+ Press **Settings** at the bottom of the left column, then **Models** in its sidebar. The page lists DeepSeek as a provider: paste your API key into
146
+ **API key** and press **Apply**. It answers `Saved DeepSeek (deepseek-official).`; the key goes to the frame's own credentials store, never into the
147
+ app folder.
195
148
 
196
- A window opens, showing the same routes and the same data. The app's own code never imports Electron; every Electron call lives in `plugins/desktop`,
197
- and the window's browser data stays inside `my-hero/.acrylblends/electron`. Close the window when you are done (`Cmd-Q`, `Alt-F4`).
149
+ ![Settings > Models with the DeepSeek key field](/docs-assets/workshop/s2-settings-models.webp)
198
150
 
199
- **Stuck?** The first `npm run desktop` downloads Electron (about 200 MB). No display (a bare server)? Skip this step; nothing later needs it.
151
+ Then reload the frame (`Cmd/Ctrl+R`): the page you already had open picks the key up on its next load. A Claude or ChatGPT subscription instead of a
152
+ key: **Sign in with an account** on the same page.
200
153
 
201
- ## 6. Pull a starter from the registry (8 minutes)
154
+ If the frame greets you with DeepSeek Harness's **Add an API key to get started** card first, you can paste the key there and press **Save and
155
+ continue**, or press **Configure later** and use Settings > Models; both write the same store.
202
156
 
203
- The registry is where people publish starters: <https://acrylblends.github.io/blends> (the starters written for this framework say
204
- `runtime: acrylblends`; older ACRYL app starters are refused with a line saying so). Pull one by id, straight into a new folder:
157
+ **Stuck?** "Loading the provider directory failed" means the host is not answering; start `npm run dev` again. A key that stays red is usually an
158
+ extra space: paste it again.
205
159
 
206
- ```sh
207
- cd ~/acryl-workshop
208
- npm create acrylblends@latest from-the-registry -- --from <starter-id>
209
- cd from-the-registry
210
- npm install
211
- npm run dev
212
- ```
160
+ ## 4. Chat: your model works on the app (20 minutes)
213
161
 
214
- The same command takes a git repository or a folder: `--from github:you/starter` or `--from ../a-template`. You get a complete app someone else
215
- published, with its plugins, its dependencies and its `blend.yaml`, in your folder and yours to change. Nothing is installed for you: the starter's
216
- `Next:` block asks for the same `npm install` as step 1.
162
+ Press `+` at the left of the tab strip and choose **AcrylDSH Chat**; on the `my-app` row in the left pane, **New chat on my-app** does the same and
163
+ binds the chat to the app's folder (the chat's workspace selector says `my-app`). Then ask, in one message:
217
164
 
218
- For the workshop's own registry, name it:
165
+ > Do it now, without asking for approval. Build a board page at /board in this app: three columns (backlog, doing, done) with cards that have a
166
+ > checkbox to mark them done, a sidebar with filters (all, mine, done) and a count on each filter, a button that opens and closes the sidebar, and
167
+ > a header button "New card" that adds one. Use the app's own state so the counts update live. Read AGENTS.md and the app's docs first. When you are
168
+ > done, tell me what you changed.
219
169
 
220
- ```sh
221
- npm create acrylblends@latest from-the-workshop -- --from <id> --registry github:acryldev/workshop-2026-11-20
222
- ```
170
+ The chat writes into `my-app` (watch the **Changes** panel fill), and the app's page at `/app` shows it after the loop from block 2: `Ctrl-C`, `npm
171
+ run dev`, the frame reconnects. The board is at `/app/board`: type the address in the app tab's bar (the same address with `/board` at the end) and
172
+ press **Go**.
223
173
 
224
- Starters for this workshop: `acrylblends.notes-desktop` (notes with a desktop window), `acrylblends.chat`, `acrylblends.agent`.
174
+ ![The AcrylDSH Chat tab with the request, beside the app](/docs-assets/workshop/s3-chat.webp)
225
175
 
226
- **Stuck?** The `--` before `--from` is npm's, not ours: without it npm swallows the flag. A refused id prints its reason first (`error: acryl.gtd is an
227
- ACRYL app starter: open it in the ACRYL app`) and then npm's own error block; read the first lines, not the last.
176
+ Every model builds a slightly different board: yours may need a title typed before "New card" adds one, or keep the sidebar always open.
228
177
 
229
- ## 7. Create from a template (7 minutes)
178
+ **Stuck?** If the chat asks for a model, block 3 did not finish (or the page was not reloaded after Apply). If the model describes the plan and
179
+ stops, reply "do it now, without asking for approval".
230
180
 
231
- Every app begins from one of six templates, the same list in `npm create acrylblends` and `acrylblends init`:
181
+ ## 5. A coding agent in a terminal tab (15 minutes)
232
182
 
233
- | Template | What you get |
234
- | --- | --- |
235
- | `blank` | the router, the server and one route: what you just built |
236
- | `nodejs` | a page rendered with JSX and a client component, without a bundler |
237
- | `notes` | a multi-user notes app on the `db` port: sign-up, sessions, migrations, search, a typed client |
238
- | `chat` | an answer streamed over server-sent events from an OpenAI-compatible API, history in SQLite |
239
- | `todo` | a to-do list on the router and live state |
240
- | `agent` | the blank app with an offline agent that writes and installs plugins into the running app |
183
+ Press `+` and choose **Claude**, **Codex** or **Pi** (or **New Terminal** and type the command yourself). The tab starts the agent in the app's
184
+ folder: the terminal's prompt is `my-app`, and `pwd` prints the folder. Ask it, in the terminal:
241
185
 
242
- Try the one with a database and accounts, in a window:
186
+ > Do it now, without asking for approval. Add a GET /time route that returns the current time as JSON, and a line on the app's page that shows it.
187
+ > Then check it at http://127.0.0.1:3489/app/time.
243
188
 
244
- ```sh
245
- cd ~/acryl-workshop
246
- npm create acrylblends@latest notes-app notes
247
- cd notes-app && npm install
248
- npx acrylblends add desktop && npm install && npm run desktop
249
- ```
189
+ The port in that address is the one the frame printed. The agent edits the files, and the same loop shows them: `Ctrl-C`, `npm run dev`, the frame
190
+ reconnects, the `my-app` tab.
250
191
 
251
- Sign up, add a note, close the window; run `npm run dev` and the note is still there, because it lives in `notes-app/.acrylblends/data.sqlite`.
192
+ An agent that works in this folder can also use the app's **door**, the page channel the app carries in development: `.acryl/bin/acryl look` prints
193
+ what is on the page with refs, and `act` clicks, types, selects, presses, scrolls, waits, navigates and reloads. Ask the terminal agent to look at
194
+ the page before it tells you it is done; the app's own docs (`AGENTS.md`, `plugins/acryl-door`) say how.
252
195
 
253
- **Stuck?** The sign-in page is at `/login`; the root redirects there. Delete the folder when you are done with it.
196
+ **Stuck?** An agent that says the terminal is not a TTY needs the tab, not a script. If the agent cannot log in, sign in in a terminal first
197
+ (`claude`, `codex login`, pi with `DEEPSEEK_API_KEY`), then open the tab again.
254
198
 
255
- ## 8. An agent builds a feature (15 minutes)
199
+ ## 6. Upgrade an older app onto the frame (10 minutes)
256
200
 
257
- The agent panel turns a coding agent you already use into a chat in the corner of the page. It needs the plugins the `agent` template ships (its model,
258
- tools and memory), so this step builds a second, small app from that template; it is the app you publish in step 10.
201
+ An app made with an older acrylblends runs the framework only. The current release moves it onto the frame-hosted layout: the generated launcher,
202
+ the frame's row and the app's plugins beside it, the mount config. **Your source stays yours**: the upgrade only touches the files acrylblends
203
+ generated, plus the library plugins the app carries.
259
204
 
260
205
  ```sh
261
- cd ~/acryl-workshop
262
- npm create acrylblends@latest agent-app agent
263
- cd agent-app
264
- npm install
265
- npx acrylblends add agent-panel driver-pty
266
- npx acrylblends add desktop
206
+ cd old-app
207
+ npx acrylblends@latest upgrade
267
208
  npm install
268
209
  npm run dev
269
210
  ```
270
211
 
271
- `add agent-panel` adds the plugin rows the panel needs and registers it for you, and prints what it changed. (On a `blank` app it refuses and says
272
- which rows are missing: that is why this step uses the `agent` template.) Open the page, click the panel button in the corner, pick `codex` (or
273
- `claude`, or `pi` when pi has its DeepSeek login in your home folder), and ask:
274
-
275
- > Add a page at /board that lists the app's tasks, newest first, and a test for it.
276
-
277
- The agent reads `AGENTS.md`, reads `docs/framework` (which is in your app), edits your files, runs your tests, and the app reloads itself. It takes a
278
- few minutes; the panel shows each step, and has a stop button. Open `/board` when it is done.
212
+ The report names every file it changed and ends with a `frame` line (for an app that already has the frame: `everything is up to date`). An app made
213
+ today answers "everything is up to date" too. An app from a release **before 0.7.8** cannot start at all (its `src/main.ts` imports a `plugins/`
214
+ folder that release did not write); the upgrade says so instead of touching it.
279
215
 
280
- A terminal agent works too: choose `pty:codex` (or `pty:claude`, `pty:pi`) for its normal interactive session inside the app folder, where it can use
281
- the door (`.acryl/bin/acryl`) to look at the page it built.
216
+ **Stuck?** "is not the previous release's scaffold" means you edited a generated file: run with `--diff` to see it, save your version aside, and
217
+ run again (or `--force`; the app's versions are backed up under `.acrylblends/upgrade-backup/`).
282
218
 
283
- **Stuck?** The panel uses your own agent account: `codex login` (or `claude`) in a terminal first. Your own agent settings travel with it: skills or hooks of your own can make it stop and ask for approval instead of acting, so write the task as "do it now, without asking for approval", or start the agent from a clean configuration (a fresh `CODEX_HOME`, or no personal skills). If `npm install` warns that npm blocked
284
- `node-pty`'s install script, ignore it: prebuilt binaries ship. Only if the panel lists no `pty:` terminal, run `npm approve-scripts node-pty` and
285
- `npm rebuild node-pty` (the `add` output says the same).
219
+ ## 7. Publish it as a starter (10 minutes, take-home)
286
220
 
287
- ## 9. Upgrade (7 minutes)
288
-
289
- Your app carries its framework plugins as source, so a new release moves them in place and leaves your code alone. Run the tool by its full name:
290
- **`npx acrylblends@latest`**, because an app's own copy of `acrylblends` shadows the bare command and an older copy has no `upgrade` at all.
221
+ Your app already is a starter: `blend.yaml` names it, `plugins/` holds its code.
291
222
 
292
223
  ```sh
293
- cd ~/acryl-workshop/my-hero
294
- npx acrylblends@latest upgrade --dry-run
295
- npx acrylblends@latest upgrade
296
- npm install && npm test
224
+ cd ~/acryl-workshop
225
+ gh repo fork acryldev/workshop-2026-11-20 --clone
226
+ cd workshop-2026-11-20
227
+ node scripts/make-entry.mjs ../my-app <your-github-login>.my-app --description "the board my agent built"
228
+ git add blends && git commit -m "add <your-github-login>.my-app"
229
+ git push
230
+ gh pr create --fill --repo acryldev/workshop-2026-11-20
297
231
  ```
298
232
 
299
- The dry run lists what would be replaced; the real run replaces untouched files and stops with a diff if you edited one (move your change into a plugin
300
- of your own, or use `--force`, which backs the edited copies up first). An app made by this version is already current, so both commands answer
301
- `everything is up to date`: that is the mechanism working, and an app made by an earlier release lists what it would move. Your tests still pass
302
- afterwards.
303
-
304
- ## 10. Publish it, and the hero moment (8 minutes)
305
-
306
- The app you publish is `agent-app`, the one the agent changed in step 8 (keep `my-hero` too: it is yours, saved the same way). It is already a
307
- **starter**: `blend.yaml` names it, lists its rows, and `plugins/` holds its code. Two parts make it public: your own copy, then the registry.
308
-
309
- **Your own copy first.** `npm run save` commits the app and pushes it to its remote (it refuses a file that looks like a secret, and refuses to push a
310
- private app to a public remote). Create an empty repository on your git host, set it as `origin`, run `npm run save`.
311
-
312
- **The registry.** Publishing is a pull request to the workshop registry, `github.com/acryldev/workshop-2026-11-20`, and it is four commands.
313
-
314
- 1. Fork and clone it, then let its script build the entry from your app:
315
-
316
- ```sh
317
- cd ~/acryl-workshop
318
- gh repo fork acryldev/workshop-2026-11-20 --clone
319
- cd workshop-2026-11-20
320
- node scripts/make-entry.mjs ../agent-app <your-github-login>.agent-app --description "the app I built in the workshop"
321
- ```
322
-
323
- `make-entry` copies the app into `blends/<your-github-login>.agent-app/` without `node_modules`, `.git` or the app's data, marks its `blend.yaml`
324
- public and licensed under that id, and writes the `acryl.template.json` that makes it pullable. The entry is the whole app: its dependencies come with
325
- it, so whoever pulls it gets the desktop shell without adding it again. The id is lowercase, `<login>.<name>` with letters, digits and dashes.
326
-
327
- 2. Commit, push and open the pull request:
233
+ (On Windows PowerShell 5.1, `cd ~/acryl-workshop` works as written; in cmd.exe use `cd %USERPROFILE%\acryl-workshop`. Type the `git add` and `git
234
+ commit` as two lines, or join them with `;`.)
328
235
 
329
- ```sh
330
- git add blends && git commit -m "add <your-github-login>.agent-app"
331
- git push
332
- gh pr create --fill --repo acryldev/workshop-2026-11-20
333
- ```
236
+ A check runs on the pull request and merges it: your starter is listed in about two minutes, and anyone can start from it with
237
+ `npm create acrylblends@latest another-app -- --from <your-github-login>.my-app --registry github:acryldev/workshop-2026-11-20`.
334
238
 
335
- 3. A check runs on the pull request, and when it passes the pull request is merged: your starter is listed, usually well under two minutes. If it
336
- refuses, it comments what to change; fix, commit, push again and it re-checks. To take an app down, open a pull request that removes the folder:
337
- `git rm -r blends/<your-github-login>.agent-app`.
239
+ **Stuck?** The registry's check comments what to change; fix, commit, push again. `gh auth status` not logged in means `gh auth login`.
338
240
 
339
- Anyone can then start from it, in the browser or in a window:
340
-
341
- ```sh
342
- npm create acrylblends@latest my-app -- --from <your-github-login>.agent-app --registry github:acryldev/workshop-2026-11-20
343
- ```
344
-
345
- **Stuck?** The check's comment is the answer: read it, fix, push again. An id with a capital or a dot inside a part is refused by `make-entry`; use
346
- lowercase `<login>.<name>`. `gh: not found` means the GitHub CLI is not installed, and `gh auth status` saying not logged in means `gh auth login`.
241
+ ## Browser only (WebBoxes.ai) TODO(M9)
347
242
 
348
- > **The hero moment.** An app you created, with a page an agent wrote for it, running as a desktop window, saved in your own repository, and published
349
- > as a starter in the registry so the next person can pull it with one command. Along the way you built a second app from blank, a route, a test, a JSON
350
- > store and a SQLite database. Note what you did not write: the router, the server, the JSON file, the SQLite migrations, the window, the page.
243
+ No local install? The same app, and the same agents working on it, will run as a hosted workspace: open it in a browser, pick a starter, and work in
244
+ the same folders. Nothing to install, nothing to keep on your machine. Until it is live this section is a stub.
351
245
 
352
246
  ## Where next
353
247
 
354
- - **Read the docs you already have**: every app carries `docs/framework`, the same pages as <https://acrylblends.github.io/docs>. Start with
355
- `cordis/acryl-in-a-cordis-app.md`, then `guides/data.md`, then `guides/production.md` (what runs in production, and what does not).
356
- - **Swap a provider by editing one row**: SQLite to Postgres (`npx acrylblends add acryl-db-postgres`), the browser to a window (`desktop`), one agent
357
- to another (the panel's driver list).
358
- - **Teach your agent**: `AGENTS.md` in your app is what it reads first; add your team's conventions there and the next run follows them.
248
+ - **Read the docs you already have**: every app carries `docs/framework`, the same pages as <https://acrylblends.github.io/docs>.
249
+ - **Teach the agents your app**: `AGENTS.md` is what they read first; add your team's conventions there and they follow them in the next run.
250
+ - **Swap a provider by editing one row**: SQLite to Postgres, the browser to a window, one agent to another in the frame's agent list.
359
251
  - **Bring your own tool**: <https://acrylblends.github.io/docs/guides/bring-your-own-tool> wraps an outside library as a provider of a port.
360
252
 
361
- ## Browser only (WebBoxes.ai) TODO(M9)
362
-
363
- No local install? The same app, and the same agent, will run as a hosted workspace: open it in a browser, pick a starter, and work in the same three
364
- folders. Nothing to install, nothing to keep on your machine.
365
-
366
- The hosted workspace is milestone M9 and is due before the workshop, so this section is a stub until it is live: write the address, the sign-in it
367
- needs, and the two or three clicks that replace steps 1-2 here, then let the local steps stand for anyone who wants the app on their own disk.
368
-
369
253
  ---
370
254
 
371
255
  ## If something goes wrong
372
256
 
373
257
  | Symptom | Do |
374
258
  | --- | --- |
259
+ | The preflight prints `FIX` lines | run each one, then `npx acrylblends@latest preflight` again |
375
260
  | `npm create` fails or hangs | check the network; the facilitator has prepared apps |
261
+ | `npm install` fails building node-pty | install the C++ toolchain (block 1's **Stuck?**) and run it again |
376
262
  | A port is taken | use the address the app printed |
377
- | The agent cannot log in | `codex login` / `claude` in a terminal, then retry in the panel |
378
- | You want to start over | delete your app folder and repeat step 1; nothing lives outside it |
263
+ | The frame says `Reconnecting...` | wait ten seconds; then `npx acrylblends open` and open the address it prints |
264
+ | Settings > Models shows no provider | the host is not running: `Ctrl-C`, `npm run dev` |
265
+ | The chat asks for a model | finish block 3, then reload the page |
266
+ | The model plans and stops | reply "do it now, without asking for approval" |
267
+ | An agent cannot log in | `codex login` / `claude` / pi with `DEEPSEEK_API_KEY`, then open the tab again |
268
+ | The app's page is unchanged after an edit | the host did not restart: `Ctrl-C`, `npm run dev` |
269
+ | `&&` is an error in PowerShell | Windows PowerShell 5.1: type the two commands as two lines, or join them with `;` |
379
270
  | Anything else | the **Stuck?** line of the step, then your facilitator |
380
-
381
- Behind at a checkpoint? Skip step 4 (data) first, then the second app in step 7. Steps 1-3, 5, 8-10 are the spine.