frizz 0.7.5 → 0.7.8

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 (95) hide show
  1. package/README.md +31 -53
  2. package/dist/dev-child.js +476 -303
  3. package/dist/frizz.js +13476 -6556
  4. package/package.json +5 -3
  5. package/runtime/cc-worker/DECISIONS.md +12 -0
  6. package/runtime/cc-worker/bin/frizz-mcp.mjs +3 -2
  7. package/web-dist/assets/{TerminalPane-Cyao7kTi.js → TerminalPane-ubcEP7X3.js} +1 -1
  8. package/web-dist/assets/{abnfDiagram-VRR7QNED-D1U0Q_zY.js → abnfDiagram-VRR7QNED-0brfnieb.js} +1 -1
  9. package/web-dist/assets/architecture-TIHT7OUA-DksosNDW.js +1 -0
  10. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-CtUBwBcU.js → architectureDiagram-ZJ3FMSHR-Dji-XBdF.js} +1 -1
  11. package/web-dist/assets/{blockDiagram-677ZJIJ3-OzqrN18g.js → blockDiagram-677ZJIJ3-BQMyz3Q9.js} +1 -1
  12. package/web-dist/assets/{c4Diagram-LMCZKHZV-DgYAtD7L.js → c4Diagram-LMCZKHZV-BMNws0Oi.js} +1 -1
  13. package/web-dist/assets/channel-DqoPvfQz.js +1 -0
  14. package/web-dist/assets/{chunk-32BRIVSS-CKwBruPa.js → chunk-32BRIVSS-CVv1ae7n.js} +1 -1
  15. package/web-dist/assets/{chunk-52WLFC77-gvoNW_ar.js → chunk-52WLFC77-BYhPlKCT.js} +1 -1
  16. package/web-dist/assets/{chunk-C7G6YPKG-EJ5BdmRQ.js → chunk-C7G6YPKG-Cn4HhNwb.js} +1 -1
  17. package/web-dist/assets/{chunk-EX3LRPZG-DJQF-VwN.js → chunk-EX3LRPZG-P3ZYFC1W.js} +1 -1
  18. package/web-dist/assets/{chunk-FWX5IMBZ-CXBLvjvR.js → chunk-FWX5IMBZ-Ba3NpEQa.js} +2 -2
  19. package/web-dist/assets/{chunk-HOUHSVGY-De3ULdBq.js → chunk-HOUHSVGY-BCWyMhwJ.js} +1 -1
  20. package/web-dist/assets/{chunk-ICXQ74PX-aUbMdGsl.js → chunk-ICXQ74PX-DWAAqHL7.js} +1 -1
  21. package/web-dist/assets/{chunk-MOJQB5TN-BLK44SUW.js → chunk-MOJQB5TN-pc5VJ4Nq.js} +1 -1
  22. package/web-dist/assets/{chunk-OGEWGWER-CQZ3zQ2q.js → chunk-OGEWGWER-DUxmbiuX.js} +1 -1
  23. package/web-dist/assets/{chunk-PUDLZKDR-DcdN44K2.js → chunk-PUDLZKDR-DRdZWzxX.js} +1 -1
  24. package/web-dist/assets/{chunk-Q4XR5HBZ-Db2ge7fW.js → chunk-Q4XR5HBZ-Bafzu7s-.js} +1 -1
  25. package/web-dist/assets/{chunk-V7JOEXUC-D80jxcmB.js → chunk-V7JOEXUC-Bj0A8ftW.js} +1 -1
  26. package/web-dist/assets/{chunk-VAUOI2AC-nDGsXZZE.js → chunk-VAUOI2AC-DBgVQKIO.js} +1 -1
  27. package/web-dist/assets/{chunk-VR4S4FIN-BGXgLAsD.js → chunk-VR4S4FIN-DU-1KtuM.js} +1 -1
  28. package/web-dist/assets/{chunk-WYO6CB5R-BbGEK50o.js → chunk-WYO6CB5R-DzVb3-Rj.js} +1 -1
  29. package/web-dist/assets/{chunk-ZGVPDNZ5-CjEI23Vu.js → chunk-ZGVPDNZ5-BPKQvduj.js} +1 -1
  30. package/web-dist/assets/classDiagram-OUVF2IWQ-DwUs74RB.js +1 -0
  31. package/web-dist/assets/classDiagram-v2-EOCWNBFH-DwUs74RB.js +1 -0
  32. package/web-dist/assets/{cynefin-VYW2F7L2-CR69iDgw.js → cynefin-VYW2F7L2-lo8PqVCk.js} +1 -1
  33. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-Le_FSC65.js → cynefinDiagram-TSTJHNR4-BtQLaDV0.js} +1 -1
  34. package/web-dist/assets/{dagre-VKFMJZFB-CxAlFDI9.js → dagre-VKFMJZFB-BJ2-f-A0.js} +1 -1
  35. package/web-dist/assets/{diagram-FQU43EPY-BFMwv6Pj.js → diagram-FQU43EPY-CLM-8r74.js} +1 -1
  36. package/web-dist/assets/{diagram-G47NLZAW-mWAc5hJ0.js → diagram-G47NLZAW-CfuoJGpN.js} +1 -1
  37. package/web-dist/assets/{diagram-NH7WQ7WH-CC-QXuir.js → diagram-NH7WQ7WH-DfxxRwH8.js} +1 -1
  38. package/web-dist/assets/{diagram-OA4YK3LP-Cqs5o39q.js → diagram-OA4YK3LP-D7knxZee.js} +1 -1
  39. package/web-dist/assets/{diagram-WEI45ONY-B9PF6IpG.js → diagram-WEI45ONY-C2WfMXWl.js} +1 -1
  40. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-C1DkTGUE.js → ebnfDiagram-CCIWWBDH-DRSZ24tF.js} +1 -1
  41. package/web-dist/assets/{erDiagram-Q63AITRT-CbCG5w3K.js → erDiagram-Q63AITRT-DXe0OrbY.js} +1 -1
  42. package/web-dist/assets/eventmodeling-45OFAUF4-CUIjQ7kE.js +1 -0
  43. package/web-dist/assets/flowDiagram-23GEKE2U-Dka-3F3n.js +1 -0
  44. package/web-dist/assets/{ganttDiagram-NO4QXBWP-CaywKz56.js → ganttDiagram-NO4QXBWP-wGqOgjvs.js} +1 -1
  45. package/web-dist/assets/{gitGraph-TEB2WS4Q-DhbijOBs.js → gitGraph-TEB2WS4Q-BygokG6y.js} +1 -1
  46. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-DHngf1QZ.js → gitGraphDiagram-IHSO6WYX-CV1933_M.js} +1 -1
  47. package/web-dist/assets/index-CmrDpsD8.css +1 -0
  48. package/web-dist/assets/{index-CxwWndgM.js → index-DB1d3eMJ.js} +107 -102
  49. package/web-dist/assets/{info-DKCQHKI2-D2uo8Yq_.js → info-DKCQHKI2-DLavbzui.js} +1 -1
  50. package/web-dist/assets/{infoDiagram-FWYZ7A6U-Bixn1mvJ.js → infoDiagram-FWYZ7A6U-Biouxd9G.js} +1 -1
  51. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-DG48ASOp.js → ishikawaDiagram-FXEZZL3T-DJxwwS3R.js} +1 -1
  52. package/web-dist/assets/{journeyDiagram-5HDEW3XC-DpQOwYAS.js → journeyDiagram-5HDEW3XC-Clx_WkdW.js} +1 -1
  53. package/web-dist/assets/{kanban-definition-HUTT4EX6-Dph0AMZo.js → kanban-definition-HUTT4EX6-Bf7bX_96.js} +1 -1
  54. package/web-dist/assets/{line-hnYRfUMr.js → line-CV2v49IN.js} +1 -1
  55. package/web-dist/assets/{mermaid-parser.core-DdD3ClpS.js → mermaid-parser.core-BPsFhEi6.js} +3 -3
  56. package/web-dist/assets/{mermaid.core-C2DMq9ss.js → mermaid.core-0EWDNL_R.js} +3 -3
  57. package/web-dist/assets/{mindmap-definition-LN4V7U3C-CirJBG-x.js → mindmap-definition-LN4V7U3C-C1y4yy3Z.js} +1 -1
  58. package/web-dist/assets/{packet-7NZHBO7P-kD-OtFAF.js → packet-7NZHBO7P-CpcpxruB.js} +1 -1
  59. package/web-dist/assets/{pegDiagram-2B236MQR-DGmi8fl-.js → pegDiagram-2B236MQR-CVlVP4cH.js} +1 -1
  60. package/web-dist/assets/{pie-RZYD4A2V-DpKplj-N.js → pie-RZYD4A2V-BcVPOhTZ.js} +1 -1
  61. package/web-dist/assets/{pieDiagram-ENE6RG2P-CW-zVLyR.js → pieDiagram-ENE6RG2P-DZv4Tfae.js} +1 -1
  62. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-fxSaIvo2.js → quadrantDiagram-ABIIQ3AL-DOzS_U_a.js} +1 -1
  63. package/web-dist/assets/{radar-I7S5WNFK-BPu7ClHP.js → radar-I7S5WNFK-8YADxkdT.js} +1 -1
  64. package/web-dist/assets/{railroad-3IZDKUUU-CoQXFYm6.js → railroad-3IZDKUUU-DzndPrRy.js} +1 -1
  65. package/web-dist/assets/railroad-abnf-AHOZXSZD-CCnWa6K9.js +1 -0
  66. package/web-dist/assets/railroad-ebnf-EBAXGLYW-jtVdzv7e.js +1 -0
  67. package/web-dist/assets/railroad-peg-LSFZ7HO6-B8D6TyEe.js +1 -0
  68. package/web-dist/assets/{railroadDiagram-RFXS5EU6-Bqnz_3Bc.js → railroadDiagram-RFXS5EU6-CPJAH-r7.js} +1 -1
  69. package/web-dist/assets/{requirementDiagram-TGXJPOKE-DJHMdBhh.js → requirementDiagram-TGXJPOKE-BVFJZfwl.js} +1 -1
  70. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-BlxzmT-W.js → sankeyDiagram-HTMAVEWB-CUhvFPmE.js} +1 -1
  71. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-BT7Rn1Uo.js → sequenceDiagram-DBY2YBRQ-Cy9CGhNq.js} +1 -1
  72. package/web-dist/assets/{stateDiagram-2N3HPSRC-CDoiFcke.js → stateDiagram-2N3HPSRC-CqOnmPLp.js} +1 -1
  73. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DWKW-4qu.js +1 -0
  74. package/web-dist/assets/{swimlanes-5IMT3BWC-DtzTgSSP.js → swimlanes-5IMT3BWC-c_zBqkb9.js} +1 -1
  75. package/web-dist/assets/swimlanesDiagram-G3AALYLV-DZKoB7ae.js +8 -0
  76. package/web-dist/assets/{timeline-definition-FHXFAJF6-Dn63VmSO.js → timeline-definition-FHXFAJF6-y_QM62SK.js} +1 -1
  77. package/web-dist/assets/{treeView-QDETBFTQ-DIfJIc9R.js → treeView-QDETBFTQ-T3y_1KXV.js} +1 -1
  78. package/web-dist/assets/{treemap-6X3UGDF4-n9Fwqngl.js → treemap-6X3UGDF4-CzvqucqY.js} +1 -1
  79. package/web-dist/assets/{vennDiagram-L72KCM5P-C1thEMxE.js → vennDiagram-L72KCM5P-6-HNOpN0.js} +1 -1
  80. package/web-dist/assets/{wardley-OPB4EBWU-Dl6RiScD.js → wardley-OPB4EBWU-BrsaqsLL.js} +1 -1
  81. package/web-dist/assets/{wardleyDiagram-EHGQE667-DBelgTwB.js → wardleyDiagram-EHGQE667-Cr_rCzwd.js} +1 -1
  82. package/web-dist/assets/{xychartDiagram-FW5EYKEG-DFGVnPLj.js → xychartDiagram-FW5EYKEG-BnX6ccx4.js} +1 -1
  83. package/web-dist/index.html +2 -2
  84. package/web-dist/assets/architecture-TIHT7OUA-BS8x9TQa.js +0 -1
  85. package/web-dist/assets/channel-DHZV3ADN.js +0 -1
  86. package/web-dist/assets/classDiagram-OUVF2IWQ-Dcx3TDdU.js +0 -1
  87. package/web-dist/assets/classDiagram-v2-EOCWNBFH-Dcx3TDdU.js +0 -1
  88. package/web-dist/assets/eventmodeling-45OFAUF4-DAhP7KCX.js +0 -1
  89. package/web-dist/assets/flowDiagram-23GEKE2U-Be2iuqwq.js +0 -1
  90. package/web-dist/assets/index-C-3lsl4q.css +0 -1
  91. package/web-dist/assets/railroad-abnf-AHOZXSZD-BiqkuXNr.js +0 -1
  92. package/web-dist/assets/railroad-ebnf-EBAXGLYW-CDaukY4Z.js +0 -1
  93. package/web-dist/assets/railroad-peg-LSFZ7HO6-CsUPdvVL.js +0 -1
  94. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DiLnjG8k.js +0 -1
  95. package/web-dist/assets/swimlanesDiagram-G3AALYLV-BqvWOcR2.js +0 -8
package/README.md CHANGED
@@ -42,10 +42,10 @@ $ npx frizz
42
42
  press ctrl-c to stop · run with --debug for the full event feed
43
43
  ```
44
44
 
45
- A browser tab opens on localhost a dedicated workspace for this directory. **One tab per project!** One Frizz serves every project on the machine, each at its own `/project/<name>` URL, so running it in a second directory joins the server already running rather than starting another. Runs on macOS, Linux, and Windows.
45
+ A browser tab opens at `http://127.0.0.1:9393/project/acme/`. Frizz always listens on port 9393 (19393 if something else holds it), and one server serves every project on the machine. Each directory you run it in becomes a **project** with its own board at `/project/<name>`, so running `npx frizz` in a second repo registers that project and opens its board in the server already running rather than starting another. Runs on macOS, Linux, and Windows.
46
46
 
47
47
  <p align="center">
48
- <img src="assets/board.png" alt="Frizz running in a browser tab at 127.0.0.1:4921: a sidebar of threads on the left, and on the right a card where an agent is asking an answerable question with lettered options, above Snooze and Mark as done." width="100%">
48
+ <img src="assets/board.png" alt="The Frizz board: the project rail down the left, the composer and the queue of threads beside it, and on the right a card where an agent is asking an answerable question with lettered options, above Snooze and Mark as done." width="100%">
49
49
  </p>
50
50
 
51
51
  <br/>
@@ -55,14 +55,25 @@ A browser tab opens on localhost — a dedicated workspace for this directory. *
55
55
  Frizz is a browser tab, a queue, and the agent CLIs you already pay for. It brings no model of its own, automates none of your workflow, and keeps every opinion it does have in a text file you can edit.
56
56
 
57
57
  - 🗂️ **A task queue, not a sidebar.** Every agent that comes to rest needing you becomes a card. Work the queue top to bottom instead of polling ten terminals.
58
+ - 📁 **Projects.** Every directory you run it in gets its own board, all on one server. The home page lists them, and the project rail switches between them with each queue's count on its icon.
58
59
  - 🔌 **Headless.** Every thread's agent runs in its own detached background process. Close the tab, quit the browser, ctrl-c the server, reboot — your threads are all still there when you come back, and Frizz reconnects to the ones still running rather than replaying them from disk.
59
60
  - 🤖 **Claude Code *and* Codex.** Pick the backend per thread and run both against the same repo at once. Frizz supports Claude Code and Codex subscriptions — the CLIs you already have installed and signed in.
60
61
  - 😴 **Snooze.** Not everything needs an answer now. Park a card for an hour, until tomorrow morning, or until a date you pick — optionally with a follow-up prompt attached, so the thread wakes up already working on what you told it to do next.
61
- - 🔄 **Heartbeats.** Give a thread a prompt that repeats — every time it comes to rest, on a clock you set in minutes, or both. Good for "keep going until CI is green" without you re-asking. A scheduled one reaches the agent even mid-turn, so it can nudge a thread that never stops. Switch it off whenever, or let the agent say it's finished.
62
+ - 🎯 **Goals.** Give a thread a standing goal that Frizz re-sends as a prompt — every time it comes to rest, on a clock you set in minutes, or both. Good for "keep going until CI is green" without you re-asking. A scheduled one reaches the agent even mid-turn, so it can nudge a thread that never stops. Switch it off whenever, or let the agent say it's finished.
62
63
  - 🐙 **GitHub integration.** Browse your repo's issues and pull requests without leaving the composer, and turn a selection of them into threads. Workers can read issues, diffs, and CI on their own.
63
64
  - 👀 **Built-in CI and PR watchers.** A worker waiting on a build or a review doesn't hand the thread back to you to be told "keep going." It watches, and picks the work back up when the run goes green or a review lands.
64
65
  - 📝 **No magic.** A thread behaves like a Claude Code session you started yourself. Frizz adds no worktrees, no branches, no dev server, no build integration, no workflow engine to fight with.
65
- - 🔒 **Local only.** No cloud, no account, no telemetry. The server binds `127.0.0.1` by default and its state lives in your user directory, never in your checkout. To reach a board from a phone, put your own tunnel or proxy in front of it — see [Remote access](docs/remote-access.md).
66
+ - 🔒 **Local only.** No cloud, no account, no telemetry. The server binds `127.0.0.1` by default and its state lives in your user directory, never in your checkout. To reach a board from a phone, press R in its terminal — see [Remote access](docs/remote-access.md).
67
+
68
+ ### Projects
69
+
70
+ Every directory you run `npx frizz` in becomes a project with its own board, all served by the one Frizz on your machine. The home page at `http://127.0.0.1:9393/` lists them.
71
+
72
+ <p align="center">
73
+ <img src="assets/projects.png" alt="The Frizz home page: a rail of project icons down the left, and four project cards — design-system, acme-web, acme-api, frizz — each with its home-relative path and when it was last opened, plus an Add a project card." width="100%">
74
+ </p>
75
+
76
+ The project rail keeps every project one click away, with each queue's count on its icon. It is off by default; switch it on under **Settings → Project sidebar**.
66
77
 
67
78
  ### The queue
68
79
 
@@ -104,12 +115,12 @@ Park a card for an hour, until tomorrow morning, or until a date you pick. Attac
104
115
  <img src="assets/snooze.png" alt="The snooze menu open on a queue card, offering 1 hour, tomorrow at 9am, 1 day, 3 days, 1 week, and a custom time and prompt." width="100%">
105
116
  </p>
106
117
 
107
- ### Heartbeats
118
+ ### Goal
108
119
 
109
- Give a thread a prompt that repeats. Send it every time the agent comes to rest, on a clock you set in minutes, or both — a scheduled send reaches the agent even mid-turn, without cutting off work in progress.
120
+ Give a thread a standing goal. Frizz sends it as a prompt every time the agent comes to rest, on a clock you set in minutes, or both — a scheduled send reaches the agent even mid-turn, without cutting off work in progress.
110
121
 
111
122
  <p align="center">
112
- <img src="assets/recurring.png" alt="The recurring prompt panel: one prompt saying to keep going until the test suite is green, with both triggers switched on — every time it stops, and every 30 minutes." width="100%">
123
+ <img src="assets/goal.png" alt="The goal panel open on a thread card: a goal saying to keep going until the test suite is green, sent at every rest and every 30 minutes." width="100%">
113
124
  </p>
114
125
 
115
126
  <br/>
@@ -129,33 +140,17 @@ npm-resolved immutable Frizz package, then opens it in your default browser. Use
129
140
  for a source checkout.
130
141
 
131
142
  Options:
132
- --app use the legacy dedicated app window instead of a browser tab
133
143
  --no-app print the URL without opening a browser
134
144
  --port <port> request a fixed port for a new workspace server
135
- --host [address] serve on a network address instead of loopback (bare --host means 0.0.0.0)
136
- --allowed-host <name> with --host, also accept this DNS name as the board's address (repeatable)
137
- --public-origin <url> serve behind a proxy/tunnel reachable at this exact origin
138
- --cloud serve at the saved hostname and run its Cloudflare tunnel as a child
139
- process; asked once, then remembered
140
145
  --link print a fresh single-use access link for the running board
141
146
  --debug stream the full event feed to the terminal instead of the compact readout
142
147
  -h, --help show this help
143
148
 
144
- Environment:
145
- FRIZZ_HOST same as --host
146
- FRIZZ_ALLOWED_HOSTS same as --allowed-host, comma separated
147
- FRIZZ_PUBLIC_ORIGIN same as --public-origin
148
- FRIZZ_PUBLIC_TOKEN standing secret for HEADLESS boxes that cannot show a QR
149
-
150
- --host puts a board that can run shell commands as you on the network, and Frizz has no login: anyone
151
- who reaches the port controls it. Only do this on a network you trust. An IP address and this
152
- machine's own hostname work as-is; any other DNS name must be listed with --allowed-host ("*"
153
- allows any).
154
-
155
- --public-origin serves the board through a tunnel or reverse proxy without putting it on the LAN
156
- at all — Frizz stays on loopback and the tunnel dials it. It prints a SINGLE-USE access link, and
157
- shows it as a QR so you can scan it from a phone; press L for a fresh one at any time. Scanning it
158
- trades the code for a session cookie, so the link itself stops working the moment it is used.
149
+
150
+ To reach the board from a phone or another machine, press R in the terminal running it: a short
151
+ walkthrough sets up a frizz.sh name, a Cloudflare Tunnel, Tailscale, or a proxy of your own, and
152
+ remembers the choice, so a plain launch serves it from then on. The board stays on loopback and
153
+ shows a single-use sign-in link as a QR; press L for a fresh one, or run --link from another shell.
159
154
  ```
160
155
 
161
156
  <br/>
@@ -172,7 +167,7 @@ trades the code for a session cookie, so the link itself stops working the momen
172
167
  <details>
173
168
  <summary><b>Does anything leave my machine?</b></summary>
174
169
 
175
- > Nothing from Frizz. There's no account, no telemetry, and the server binds to `127.0.0.1` unless you ask for otherwise with `--host`. The agents themselves talk to their providers, and `gh` talks to GitHub, but Frizz is a local process looking at local files.
170
+ > Nothing from Frizz. There's no account, no telemetry, and the server binds to `127.0.0.1`; reaching it from another device is something you switch on yourself (press R in its terminal). The agents themselves talk to their providers, and `gh` talks to GitHub, but Frizz is a local process looking at local files.
176
171
 
177
172
  </details>
178
173
 
@@ -200,43 +195,25 @@ trades the code for a session cookie, so the link itself stops working the momen
200
195
  <details>
201
196
  <summary><b>Can I run it on several repos at once?</b></summary>
202
197
 
203
- > Yes. One Frizz server serves every project on your machine — you don't start one per repo. Run `frizz` in any of them and switch projects from the board; each project's threads, settings and state stay separate.
198
+ > Yes. One Frizz server serves every project on your machine — you don't start one per repo. Run `npx frizz` in any of them and switch projects from the board; each project's threads, settings and state stay separate.
204
199
 
205
200
  </details>
206
201
 
207
202
  <details>
208
203
  <summary><b>Can I reach it from another machine?</b></summary>
209
204
 
210
- > Yes, with `--host`the flag every dev server has, and it means the same thing here:
205
+ > Yes. Press **R** in the terminal running Frizz. A short walkthrough sets up one of four ways to reach the board — a name on frizz.sh, a Cloudflare Tunnel you own, Tailscale, or any proxy you run checks what each needs, prints the commands, and remembers your choice. From then on a plain `npx frizz` serves it; pick **Off** in the same place to go back to loopback only.
211
206
  >
212
- > ```sh
213
- > npx frizz --host # every interface, i.e. 0.0.0.0
214
- > npx frizz --host 192.168.1.5 # one interface
215
- > ```
216
- >
217
- > Frizz prints the addresses to use and warns you as it starts. Reaching it by IP or by the machine's own hostname (`http://pupper:9393/`, `http://pupper.local:9393/`) works as-is; any other name you have to say so — `--host --allowed-host frizz.home.arpa` — because an unlisted name is how DNS rebinding gets a browser to treat an attacker's page as same-origin with your board, and the machine's own name is the one nobody off your network can point elsewhere. `FRIZZ_HOST` and `FRIZZ_ALLOWED_HOSTS` do the same thing when the launch command lives in an image or a unit file.
218
- >
219
- > Understand what you're turning on. Frizz has no login: reaching the port *is* the authorization, and the board runs shell commands as you. Only do this on a network you trust, and prefer a tunnel (`ssh -L 9393:127.0.0.1:9393 you@box`, using the port Frizz printed, the same on both ends) if you just want your own board from your own laptop — that needs no flag at all.
207
+ > The board stays bound to `127.0.0.1` in every case. Something in front of it — the frizz.sh relay, the tunnel, Tailscale, your proxy — carries the traffic, and Frizz gates the first visit with a single-use sign-in link shown as a QR. Press **L** for a fresh link any time, or `npx frizz --link` from another shell (over SSH, for a headless box). See [Remote access](docs/remote-access.md) for what each option needs.
220
208
 
221
209
  </details>
222
210
 
223
211
  <details>
224
212
  <summary><b>Can I reach it from anywhere, not just my LAN?</b></summary>
225
213
 
226
- > Yes put it behind a tunnel and tell Frizz the address the tunnel answers on, with `--public-origin`:
227
- >
228
- > ```sh
229
- > npx frizz --public-origin https://frizz.example.com
230
- > cloudflared tunnel --url http://127.0.0.1:9393 # the port Frizz printed
231
- > ```
214
+ > Same answer: press **R** and pick a frizz.sh name, a Cloudflare Tunnel, or Tailscale. Each is reachable from anywhere the transport is — a frizz.sh name and a Cloudflare Tunnel from the open internet, Tailscale from your own devices.
232
215
  >
233
- > Frizz stays bound to `127.0.0.1` — `--public-origin` is not `--host` and does not put anything on your LAN. The tunnel runs on the same machine and dials the loopback port, so the only way in is through the tunnel. That is also what makes this the *good* remote option rather than merely a working one: the tunnel terminates TLS, so the board is a real `https://` origin and therefore a secure context, which plain `--host` over a LAN IP is not. Copy buttons and desktop notifications work again, and it works on a phone.
234
- >
235
- > The address you pass must be the exact origin your browser shows — scheme and host, no path. Frizz accepts that one origin, and accepts `X-Forwarded-*` only on requests that actually arrived as it.
236
- >
237
- > Frizz prints a **single-use** access link and renders it as a QR in your terminal, so you can scan it from a phone without typing forty characters. Scanning trades the code for a session cookie and the link immediately stops working; press **L** any time for a fresh one. A code expires in five minutes, and a spent one says so rather than failing silently.
238
-
239
- **Even so: Frizz has no accounts, so that link — and anything you put in front of the tunnel — *is* your access control.** A bare tunnel publishes a shell-capable board to the open internet for anyone who has the URL. Require authentication at the proxy — with Cloudflare, that means a [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/policies/access/) application over the hostname, with a policy allowing only your own email, created *before* the hostname resolves. Tailscale Serve is the same idea with device identity instead of SSO. Frizz prints this warning on every launch that names a public origin, and it is not boilerplate.
216
+ > Frizz has no accounts, so the single-use sign-in link **is** the door: a phone that scans it gets a session; nobody else gets in. Sessions are per device and can be listed and revoked with `npx frizz --sessions` and `npx frizz --sign-out`.
240
217
 
241
218
  </details>
242
219
 
@@ -262,13 +239,14 @@ Frizz has its own small vocabulary. Most of it names a feature, so this doubles
262
239
 
263
240
  | Term | What it means |
264
241
  | --- | --- |
242
+ | **Project** | A directory you ran Frizz in. Each has its own board at `/project/<name>`; one server holds all of them. |
265
243
  | **Thread** | One effort, start to finish. Not a chat tab and not a branch. The session *is* the thread — there's no sidecar document to keep in sync, and dispatching doesn't write a file into your repo. |
266
244
  | **Worker** | The agent driving a thread: a real Claude Code or Codex process, running as *you*, with your credentials and your CLI config. |
267
245
  | **Sub-agent** | A helper a worker dispatches for an independent prong of its own task. Frizz binds each one back to its parent, so the fan-out is visible under the parent's card. |
268
246
  | **Rested** | An agent that has ended its turn and is waiting on a human. A rested thread isn't idle, it's *your move*. |
269
247
  | **The queue** | The single list of threads that need you. A thread only earns a card when it genuinely wants a human. |
270
248
  | **Snooze** | Hide a card until later — an hour, tomorrow morning, or a date you pick — optionally with a follow-up prompt attached. |
271
- | **Heartbeat** | A prompt that repeats on its own — every time a thread rests, on a clock, or both — until you switch it off or the agent says it's done. |
249
+ | **Goal** | A standing prompt a thread receives on its own — every time it rests, on a clock, or both — until you switch it off or the agent says it's done. |
272
250
  | **Scratchpad** | A thread's durable working memory, readable under its **Doc** tab. Where a worker keeps what a summary would otherwise lose: the approach, the alternatives it rejected, the decisions you made and reversed. |
273
251
  | **`FRIZZ.md`** | An optional file at your repo root whose contents are injected into every thread, for when you want agents to follow your repo's own norms. |
274
252