wherdr 2.5.0 → 2.6.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 (262) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/{CXbAL3Yu.js → 2fsYF-LK.js} +41 -42
  3. package/.output/public/_nuxt/2fsYF-LK.js.br +0 -0
  4. package/.output/public/_nuxt/2fsYF-LK.js.gz +0 -0
  5. package/.output/public/_nuxt/{qODuBH5E.js → 3bE7s96N.js} +1 -1
  6. package/.output/public/_nuxt/6YTlf8ot.js +1 -0
  7. package/.output/public/_nuxt/6YTlf8ot.js.br +0 -0
  8. package/.output/public/_nuxt/6YTlf8ot.js.gz +0 -0
  9. package/.output/public/_nuxt/{BYZVrreW.js → 7KozZy5Y.js} +1 -1
  10. package/.output/public/_nuxt/{AgentView.B6zltno1.css → AgentView.BwyQIUef.css} +1 -1
  11. package/.output/public/_nuxt/AgentView.BwyQIUef.css.br +0 -0
  12. package/.output/public/_nuxt/AgentView.BwyQIUef.css.gz +0 -0
  13. package/.output/public/_nuxt/{BdJIc1Xf.js → B40shTLf.js} +1 -1
  14. package/.output/public/_nuxt/{BdJIc1Xf.js.br → B40shTLf.js.br} +0 -0
  15. package/.output/public/_nuxt/B40shTLf.js.gz +0 -0
  16. package/.output/public/_nuxt/B5cSia3P.js +62 -0
  17. package/.output/public/_nuxt/B5cSia3P.js.br +0 -0
  18. package/.output/public/_nuxt/B5cSia3P.js.gz +0 -0
  19. package/.output/public/_nuxt/BK1_9FXg.js +1 -0
  20. package/.output/public/_nuxt/BK1_9FXg.js.br +0 -0
  21. package/.output/public/_nuxt/BK1_9FXg.js.gz +0 -0
  22. package/.output/public/_nuxt/{CgUSTIM1.js → Bqz3nVVB.js} +1 -1
  23. package/.output/public/_nuxt/{CgUSTIM1.js.br → Bqz3nVVB.js.br} +0 -0
  24. package/.output/public/_nuxt/Bqz3nVVB.js.gz +0 -0
  25. package/.output/public/_nuxt/{DOVT2Tt8.js → ByLPJEo6.js} +1 -1
  26. package/.output/public/_nuxt/ByLPJEo6.js.br +0 -0
  27. package/.output/public/_nuxt/ByLPJEo6.js.gz +0 -0
  28. package/.output/public/_nuxt/C8tHIeGN.js +3 -0
  29. package/.output/public/_nuxt/C8tHIeGN.js.br +0 -0
  30. package/.output/public/_nuxt/C8tHIeGN.js.gz +0 -0
  31. package/.output/public/_nuxt/CAkH_IfS.js +9 -0
  32. package/.output/public/_nuxt/CAkH_IfS.js.br +0 -0
  33. package/.output/public/_nuxt/CAkH_IfS.js.gz +0 -0
  34. package/.output/public/_nuxt/COWXF9OU.js +123 -0
  35. package/.output/public/_nuxt/COWXF9OU.js.br +0 -0
  36. package/.output/public/_nuxt/COWXF9OU.js.gz +0 -0
  37. package/.output/public/_nuxt/{DMzjoyW_.js → CiG2Lovu.js} +1 -1
  38. package/.output/public/_nuxt/CiG2Lovu.js.br +0 -0
  39. package/.output/public/_nuxt/CiG2Lovu.js.gz +0 -0
  40. package/.output/public/_nuxt/CnjxEm0H.js +27 -0
  41. package/.output/public/_nuxt/CnjxEm0H.js.br +0 -0
  42. package/.output/public/_nuxt/CnjxEm0H.js.gz +0 -0
  43. package/.output/public/_nuxt/{PjGJWal8.js → DNs2cMBZ.js} +15 -15
  44. package/.output/public/_nuxt/DNs2cMBZ.js.br +0 -0
  45. package/.output/public/_nuxt/DNs2cMBZ.js.gz +0 -0
  46. package/.output/public/_nuxt/D_x7Rysx.js +31 -0
  47. package/.output/public/_nuxt/D_x7Rysx.js.br +0 -0
  48. package/.output/public/_nuxt/D_x7Rysx.js.gz +0 -0
  49. package/.output/public/_nuxt/{Bd0Z2zzq.js → T-qXNaMY.js} +1 -1
  50. package/.output/public/_nuxt/builds/latest.json +1 -1
  51. package/.output/public/_nuxt/builds/meta/e2ee8d99-6a6a-4754-934f-8b7dbecfcdcb.json +1 -0
  52. package/.output/public/_nuxt/entry.C_hImCpq.css +2 -0
  53. package/.output/public/_nuxt/entry.C_hImCpq.css.br +0 -0
  54. package/.output/public/_nuxt/entry.C_hImCpq.css.gz +0 -0
  55. package/.output/public/_nuxt/useViewport.D9mmYA6A.css +1 -0
  56. package/.output/public/_nuxt/useWorktrees.BWpb3OO0.css +1 -0
  57. package/.output/public/_nuxt/useWorktrees.BWpb3OO0.css.br +0 -0
  58. package/.output/public/_nuxt/useWorktrees.BWpb3OO0.css.gz +0 -0
  59. package/.output/public/sw.js +6 -2
  60. package/.output/server/chunks/_/branding.mjs +1 -1
  61. package/.output/server/chunks/_/fileDownload.mjs +1 -1
  62. package/.output/server/chunks/_/files.mjs +26 -3
  63. package/.output/server/chunks/_/machineOrder.mjs +1 -1
  64. package/.output/server/chunks/_/onboarding.mjs +1 -1
  65. package/.output/server/chunks/_/package.mjs +1 -1
  66. package/.output/server/chunks/_/plugins.mjs +1 -1
  67. package/.output/server/chunks/_/restart.mjs +1 -1
  68. package/.output/server/chunks/_/revoke.mjs +22 -0
  69. package/.output/server/chunks/_/selfupdate.mjs +2 -1
  70. package/.output/server/chunks/_/splitShell.mjs +1 -1
  71. package/.output/server/chunks/_/updates.mjs +18 -4
  72. package/.output/server/chunks/_/uploadHashes.mjs +46 -0
  73. package/.output/server/chunks/_/worktrees.mjs +1 -1
  74. package/.output/server/chunks/_/ws.mjs +3 -3
  75. package/.output/server/chunks/nitro/nitro.mjs +15525 -15000
  76. package/.output/server/chunks/raw/herdr-plugin.mjs +1 -1
  77. package/.output/server/chunks/routes/api/_..._.mjs +2 -2
  78. package/.output/server/chunks/routes/api/agents.post.mjs +2 -2
  79. package/.output/server/chunks/routes/api/ask-tab.post.mjs +2 -2
  80. package/.output/server/chunks/routes/api/attach.post.mjs +2 -2
  81. package/.output/server/chunks/routes/api/auth/disable.post.mjs +11 -4
  82. package/.output/server/chunks/routes/api/auth/lock-all.post.mjs +9 -3
  83. package/.output/server/chunks/routes/api/auth/lock.post.mjs +2 -2
  84. package/.output/server/chunks/routes/api/auth/login/options.post.mjs +4 -4
  85. package/.output/server/chunks/routes/api/auth/login/verify.post.mjs +2 -2
  86. package/.output/server/chunks/routes/api/auth/max-session.post.mjs +2 -2
  87. package/.output/server/chunks/routes/api/auth/register/options.post.mjs +2 -2
  88. package/.output/server/chunks/routes/api/auth/register/verify.post.mjs +2 -2
  89. package/.output/server/chunks/routes/api/auth/status.get.mjs +7 -7
  90. package/.output/server/chunks/routes/api/changes.get.mjs +3 -3
  91. package/.output/server/chunks/routes/api/chat/image.get.mjs +3 -3
  92. package/.output/server/chunks/routes/api/chat.get.mjs +17 -46
  93. package/.output/server/chunks/routes/api/choose.post.mjs +3 -3
  94. package/.output/server/chunks/routes/api/claude-setup.post.mjs +3 -3
  95. package/.output/server/chunks/routes/api/claude-statusline.post.mjs +3 -3
  96. package/.output/server/chunks/routes/api/clear-queued-input.post.mjs +3 -3
  97. package/.output/server/chunks/routes/api/close/status.get.mjs +3 -3
  98. package/.output/server/chunks/routes/api/close-preview.get.mjs +2 -2
  99. package/.output/server/chunks/routes/api/close.post.mjs +2 -2
  100. package/.output/server/chunks/routes/api/codex-update.post.mjs +3 -3
  101. package/.output/server/chunks/routes/api/commands.get.mjs +3 -3
  102. package/.output/server/chunks/routes/api/config.get.mjs +3 -3
  103. package/.output/server/chunks/routes/api/dirs.get.mjs +3 -3
  104. package/.output/server/chunks/routes/api/dismiss-stopped.post.mjs +3 -3
  105. package/.output/server/chunks/routes/api/dismiss.post.mjs +3 -3
  106. package/.output/server/chunks/routes/api/effort.post.mjs +3 -3
  107. package/.output/server/chunks/routes/api/efforts.get.mjs +3 -3
  108. package/.output/server/chunks/routes/api/file.post.mjs +3 -3
  109. package/.output/server/chunks/routes/api/files/download.get.mjs +2 -2
  110. package/.output/server/chunks/routes/api/files/download.head.mjs +2 -2
  111. package/.output/server/chunks/routes/api/files/read.get.mjs +3 -3
  112. package/.output/server/chunks/routes/api/files.get.mjs +3 -3
  113. package/.output/server/chunks/routes/api/health.get.mjs +2 -2
  114. package/.output/server/chunks/routes/api/input.post.mjs +3 -3
  115. package/.output/server/chunks/routes/api/interrupt.post.mjs +3 -3
  116. package/.output/server/chunks/routes/api/isgit.get.mjs +3 -3
  117. package/.output/server/chunks/routes/api/machine/awake.get.mjs +3 -3
  118. package/.output/server/chunks/routes/api/machine/awake.post.mjs +3 -3
  119. package/.output/server/chunks/routes/api/machine/order.get.mjs +2 -2
  120. package/.output/server/chunks/routes/api/machine/order.post.mjs +2 -2
  121. package/.output/server/chunks/routes/api/machine/reconnect.post.mjs +3 -3
  122. package/.output/server/chunks/routes/api/machine/rename.post.mjs +3 -3
  123. package/.output/server/chunks/routes/api/machine/status.post.mjs +3 -3
  124. package/.output/server/chunks/routes/api/menu-left.post.mjs +3 -3
  125. package/.output/server/chunks/routes/api/menu.post.mjs +3 -3
  126. package/.output/server/chunks/routes/api/model.post.mjs +3 -3
  127. package/.output/server/chunks/routes/api/models.get.mjs +3 -3
  128. package/.output/server/chunks/routes/api/nav.post.mjs +3 -3
  129. package/.output/server/chunks/routes/api/onboarding.get.mjs +2 -2
  130. package/.output/server/chunks/routes/api/onboarding.post.mjs +2 -2
  131. package/.output/server/chunks/routes/api/phone.get.mjs +3 -3
  132. package/.output/server/chunks/routes/api/phone.post.mjs +3 -3
  133. package/.output/server/chunks/routes/api/plugins/actions.get.mjs +2 -2
  134. package/.output/server/chunks/routes/api/plugins/invoke.post.mjs +2 -2
  135. package/.output/server/chunks/routes/api/plugins/projects.get.mjs +3 -3
  136. package/.output/server/chunks/routes/api/plugins/projects.post.mjs +3 -3
  137. package/.output/server/chunks/routes/api/prompt.post.mjs +3 -3
  138. package/.output/server/chunks/routes/api/push/devices.post.mjs +3 -3
  139. package/.output/server/chunks/routes/api/push/quiet.post.mjs +3 -3
  140. package/.output/server/chunks/routes/api/push/subscribe.post.mjs +5 -4
  141. package/.output/server/chunks/routes/api/push/test.post.mjs +3 -3
  142. package/.output/server/chunks/routes/api/push/unsubscribe.post.mjs +3 -3
  143. package/.output/server/chunks/routes/api/quotas.get.mjs +3 -3
  144. package/.output/server/chunks/routes/api/rename.post.mjs +2 -2
  145. package/.output/server/chunks/routes/api/requeue.post.mjs +3 -3
  146. package/.output/server/chunks/routes/api/restart.get.mjs +2 -2
  147. package/.output/server/chunks/routes/api/restart.post.mjs +2 -2
  148. package/.output/server/chunks/routes/api/reveal.post.mjs +3 -3
  149. package/.output/server/chunks/routes/api/screen-key.post.mjs +3 -3
  150. package/.output/server/chunks/routes/api/screen.get.mjs +3 -3
  151. package/.output/server/chunks/routes/api/search.get.mjs +3 -3
  152. package/.output/server/chunks/routes/api/seen.post.mjs +3 -3
  153. package/.output/server/chunks/routes/api/send-now.post.mjs +3 -3
  154. package/.output/server/chunks/routes/api/sessions.get.mjs +3 -3
  155. package/.output/server/chunks/routes/api/sessions.post.mjs +3 -3
  156. package/.output/server/chunks/routes/api/settings-tab.post.mjs +3 -3
  157. package/.output/server/chunks/routes/api/settings.get.mjs +3 -3
  158. package/.output/server/chunks/routes/api/settings.post.mjs +3 -3
  159. package/.output/server/chunks/routes/api/space.post.mjs +3 -3
  160. package/.output/server/chunks/routes/api/split-command.post.mjs +3 -3
  161. package/.output/server/chunks/routes/api/state.get.mjs +3 -3
  162. package/.output/server/chunks/routes/api/tasks/action.post.mjs +3 -3
  163. package/.output/server/chunks/routes/api/tasks/add.post.mjs +3 -3
  164. package/.output/server/chunks/routes/api/tasks/after.post.mjs +3 -3
  165. package/.output/server/chunks/routes/api/tasks/approve.post.mjs +3 -3
  166. package/.output/server/chunks/routes/api/tasks/archive-done.post.mjs +3 -3
  167. package/.output/server/chunks/routes/api/tasks/archived.get.mjs +3 -3
  168. package/.output/server/chunks/routes/api/tasks/autopilot.get.mjs +3 -3
  169. package/.output/server/chunks/routes/api/tasks/autopilot.post.mjs +3 -3
  170. package/.output/server/chunks/routes/api/tasks/board-settings.get.mjs +3 -3
  171. package/.output/server/chunks/routes/api/tasks/board-settings.post.mjs +3 -3
  172. package/.output/server/chunks/routes/api/tasks/coordinator.get.mjs +3 -3
  173. package/.output/server/chunks/routes/api/tasks/coordinator.post.mjs +3 -3
  174. package/.output/server/chunks/routes/api/tasks/describe.post.mjs +3 -3
  175. package/.output/server/chunks/routes/api/tasks/details.get.mjs +3 -3
  176. package/.output/server/chunks/routes/api/tasks/limit.post.mjs +3 -3
  177. package/.output/server/chunks/routes/api/tasks/links.get.mjs +4 -4
  178. package/.output/server/chunks/routes/api/tasks/models.get.mjs +3 -3
  179. package/.output/server/chunks/routes/api/tasks/pick.post.mjs +3 -3
  180. package/.output/server/chunks/routes/api/tasks/project.get.mjs +3 -3
  181. package/.output/server/chunks/routes/api/tasks/project.post.mjs +3 -3
  182. package/.output/server/chunks/routes/api/tasks/question.post.mjs +3 -3
  183. package/.output/server/chunks/routes/api/tasks/scheduled.get.mjs +3 -3
  184. package/.output/server/chunks/routes/api/tasks/settings.get.mjs +3 -3
  185. package/.output/server/chunks/routes/api/tasks/start.get.mjs +3 -3
  186. package/.output/server/chunks/routes/api/tasks/tell.post.mjs +3 -3
  187. package/.output/server/chunks/routes/api/tasks/transcript-image.get.mjs +47 -0
  188. package/.output/server/chunks/routes/api/tasks/transcript.get.mjs +48 -0
  189. package/.output/server/chunks/routes/api/tasks.get.mjs +3 -3
  190. package/.output/server/chunks/routes/api/unqueue.post.mjs +3 -3
  191. package/.output/server/chunks/routes/api/update/status.get.mjs +2 -2
  192. package/.output/server/chunks/routes/api/update.get.mjs +2 -2
  193. package/.output/server/chunks/routes/api/update.post.mjs +2 -2
  194. package/.output/server/chunks/routes/api/upload.post.mjs +3 -3
  195. package/.output/server/chunks/routes/api/worktrees/remove.post.mjs +2 -2
  196. package/.output/server/chunks/routes/api/worktrees.get.mjs +2 -2
  197. package/.output/server/chunks/routes/favicon.ico.get.mjs +2 -2
  198. package/.output/server/chunks/routes/icons/_name_.get.mjs +3 -3
  199. package/.output/server/chunks/routes/renderer.mjs +4 -4
  200. package/.output/server/chunks/routes/uploads/_...name_.get.mjs +3 -3
  201. package/.output/server/chunks/routes/ws/_..._.mjs +3 -3
  202. package/.output/server/chunks/routes/ws/events.mjs +3 -3
  203. package/.output/server/chunks/routes/ws/term.mjs +3 -3
  204. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  205. package/.output/server/index.mjs +3 -3
  206. package/.output/server/package.json +1 -1
  207. package/README.md +1 -1
  208. package/bin/lib/tailnet.d.mts +7 -4
  209. package/bin/lib/tailnet.mjs +76 -18
  210. package/bin/lib/updater.mjs +6 -0
  211. package/docs/README.md +2 -0
  212. package/docs/conversation.md +9 -0
  213. package/docs/home.md +29 -0
  214. package/docs/installation.md +14 -5
  215. package/docs/networks.md +9 -4
  216. package/docs/plugins.md +1 -1
  217. package/docs/quick-start.md +7 -6
  218. package/docs/quotas.md +6 -3
  219. package/docs/release-notes-2.6.0.md +29 -0
  220. package/docs/security.md +54 -11
  221. package/docs/troubleshooting.md +4 -0
  222. package/package.json +1 -1
  223. package/.output/public/_nuxt/1gzTzt3j.js +0 -9
  224. package/.output/public/_nuxt/1gzTzt3j.js.br +0 -0
  225. package/.output/public/_nuxt/1gzTzt3j.js.gz +0 -0
  226. package/.output/public/_nuxt/AgentView.B6zltno1.css.br +0 -0
  227. package/.output/public/_nuxt/AgentView.B6zltno1.css.gz +0 -0
  228. package/.output/public/_nuxt/BdJIc1Xf.js.gz +0 -0
  229. package/.output/public/_nuxt/BrxmYJEM.js +0 -1
  230. package/.output/public/_nuxt/BrxmYJEM.js.br +0 -0
  231. package/.output/public/_nuxt/BrxmYJEM.js.gz +0 -0
  232. package/.output/public/_nuxt/C6fXOTRV.js +0 -3
  233. package/.output/public/_nuxt/C6fXOTRV.js.br +0 -0
  234. package/.output/public/_nuxt/C6fXOTRV.js.gz +0 -0
  235. package/.output/public/_nuxt/CXbAL3Yu.js.br +0 -0
  236. package/.output/public/_nuxt/CXbAL3Yu.js.gz +0 -0
  237. package/.output/public/_nuxt/Cf1C5Vkb.js +0 -27
  238. package/.output/public/_nuxt/Cf1C5Vkb.js.br +0 -0
  239. package/.output/public/_nuxt/Cf1C5Vkb.js.gz +0 -0
  240. package/.output/public/_nuxt/CgUSTIM1.js.gz +0 -0
  241. package/.output/public/_nuxt/CmTpxyM2.js +0 -62
  242. package/.output/public/_nuxt/CmTpxyM2.js.br +0 -0
  243. package/.output/public/_nuxt/CmTpxyM2.js.gz +0 -0
  244. package/.output/public/_nuxt/DMzjoyW_.js.br +0 -0
  245. package/.output/public/_nuxt/DMzjoyW_.js.gz +0 -0
  246. package/.output/public/_nuxt/DOVT2Tt8.js.br +0 -0
  247. package/.output/public/_nuxt/DOVT2Tt8.js.gz +0 -0
  248. package/.output/public/_nuxt/PjGJWal8.js.br +0 -0
  249. package/.output/public/_nuxt/PjGJWal8.js.gz +0 -0
  250. package/.output/public/_nuxt/WPcHpWhL.js +0 -31
  251. package/.output/public/_nuxt/WPcHpWhL.js.br +0 -0
  252. package/.output/public/_nuxt/WPcHpWhL.js.gz +0 -0
  253. package/.output/public/_nuxt/builds/meta/d4aab09d-c1c4-4743-b8aa-35541006e853.json +0 -1
  254. package/.output/public/_nuxt/entry.DosS87kQ.css +0 -2
  255. package/.output/public/_nuxt/entry.DosS87kQ.css.br +0 -0
  256. package/.output/public/_nuxt/entry.DosS87kQ.css.gz +0 -0
  257. package/.output/public/_nuxt/nfsDZG4P.js +0 -123
  258. package/.output/public/_nuxt/nfsDZG4P.js.br +0 -0
  259. package/.output/public/_nuxt/nfsDZG4P.js.gz +0 -0
  260. package/.output/public/_nuxt/tYQOxjM1.js +0 -1
  261. package/.output/public/_nuxt/tYQOxjM1.js.br +0 -0
  262. package/.output/public/_nuxt/tYQOxjM1.js.gz +0 -0
@@ -58,7 +58,7 @@ The script ([read it first](https://wherdr.dev/install), source in
58
58
  Mac with Homebrew, otherwise the official Node.js 22 build from nodejs.org, its checksum
59
59
  checked, unpacked in `~/wherdr/node` (used by wherdr only: your `PATH` is not changed). With
60
60
  musl libc (Alpine) it gives the install links instead;
61
- 4. runs `herdr plugin install afloury/wherdr --yes`: the [Herdr plugin](plugins.md#install-as-a-herdr-plugin)
61
+ 4. runs `herdr plugin install afloury/wherdr --ref 2.x --yes`: the [Herdr plugin](plugins.md#install-as-a-herdr-plugin)
62
62
  downloads the GitHub release package of its version (checksum checked, no wait for npm),
63
63
  installs it in `~/wherdr/app`, starts it on `http://localhost:7683`, opens the setup guide in
64
64
  your browser (first install) and binds **prefix+i** to its panel;
@@ -87,7 +87,7 @@ Settings, as environment variables (`curl -fsSL https://wherdr.dev/install | WHE
87
87
  | `WHERDR_SERVICE` | — | `off`: no login service; wherdr then starts with Herdr only (the plugin's startup hook). |
88
88
  | `WHERDR_YES` | — | `1` answers yes to every question (non-interactive use), installing Node.js included. |
89
89
  | `WHERDR_NO_BROWSER` | — | `1` never opens a browser. |
90
- | `WHERDR_REF` | main | Git tag or branch of the plugin. |
90
+ | `WHERDR_REF` | `2.x` | Git tag or branch of the plugin (`2.x` is the wherdr 2 release branch). |
91
91
  | `WHERDR_PLUGIN` | `afloury/wherdr` | A local checkout to link and build instead (development, tests). |
92
92
 
93
93
  Update: run the command again (it offers the update), **U** in the wherdr panel, or **Update** in
@@ -134,6 +134,13 @@ home screen and in Settings › About, with the release notes and the exact comm
134
134
  Hide it until the next version with ×. Set `WHERDR_UPDATE_CHECK=off` to disable the check. The
135
135
  installed version is shown in Settings › About.
136
136
 
137
+ Updates stay within the running major version: wherdr 2 only offers 2.x releases, and the
138
+ one-tap update refuses to install a new major. When wherdr 3 is published, the home screen shows
139
+ a **“wherdr 3 is out”** card instead of the banner, with its release notes, its migration guide and a
140
+ Copy button for the command that installs wherdr 3 **beside** wherdr 2 (it only prints its plan
141
+ until you add `--yes`). wherdr 2 keeps running with its data, and 2.x fixes are still offered in
142
+ Settings › About.
143
+
137
144
  GitHub release packages (including the bundled agent skill) and Homebrew
138
145
  updates are published without waiting for npm moderation. Native plugin installs and updates
139
146
  use the GitHub `.tgz` and verify its SHA-256 checksum before extraction. A failed one-tap
@@ -142,7 +149,9 @@ GitHub first, then the prebuilt npm package of the exact same version (with its
142
149
  This also keeps older 1.3.x releases without GitHub archives installable with Node.js or Bun.
143
150
  Packages predating the bundled skill retain the plugin checkout's commands and skill, so
144
151
  skill refresh, installation and uninstallation remain available.
145
- The installer fetches `main` explicitly unless you set `WHERDR_REF`.
152
+ The installer fetches the `2.x` branch unless you set `WHERDR_REF`. The plugin update command
153
+ adds `--ref 2.x`, and a git checkout follows `2.x` (`git checkout 2.x`) before pulling: `main`
154
+ holds wherdr 3.
146
155
 
147
156
  The SHA-256 checksum detects damaged downloads. It is served beside the archive, so someone
148
157
  who can replace both files can make them match; it does not prove the publisher’s identity
@@ -175,10 +184,10 @@ and the app says so. Every step is logged in `~/wherdr/update.log`.
175
184
  | Setup | Update command (in the wherdr folder) |
176
185
  | --- | --- |
177
186
  | The one command | Run `curl -fsSL https://wherdr.dev/install \| sh` again: it offers the update (GitHub release package) |
178
- | Herdr plugin, Node.js | **U** in the **wherdr** panel, or `herdr plugin install afloury/wherdr --yes` (wherdr restarts on the new version) |
187
+ | Herdr plugin, Node.js | **U** in the **wherdr** panel, or `herdr plugin install afloury/wherdr --ref 2.x --yes` (wherdr restarts on the new version) |
179
188
  | `wherdr` command (npm) | `npm install -g wherdr@latest && wherdr restart` (npx: stop it, then `npx wherdr@latest`) |
180
189
  | `wherdr` command (Homebrew) | `brew upgrade wherdr`, then `brew services restart wherdr` |
181
- | From source | `git pull && npm ci && npm run build`, then restart wherdr |
190
+ | From source | `git checkout 2.x && git pull && npm ci && npm run build`, then restart wherdr |
182
191
 
183
192
  Update notices also show the number of newer stable releases and up to four
184
193
  additional version numbers besides the latest. This measures published releases,
package/docs/networks.md CHANGED
@@ -26,7 +26,10 @@ tailscale serve --bg --https=7683 http://127.0.0.1:7683
26
26
  ```
27
27
 
28
28
  Tailscale Serve listens on HTTPS port 7683 of your tailnet name, with a valid certificate, and
29
- forwards to wherdr's local HTTP port. Only devices of your tailnet can reach it.
29
+ forwards to wherdr's local HTTP port. Only devices of your tailnet can reach it, and wherdr
30
+ answers only **your own** devices among them: another user's device in a team tailnet, a node
31
+ shared in from another tailnet or a tagged node is refused until you set up a passkey (see
32
+ [Your own devices only](security.md#own-devices)).
30
33
 
31
34
  **wherdr enables that address by itself**, on a server without a screen too: at startup, every
32
35
  30 seconds, and when an address it does not know yet is opened, it reads what `tailscale serve`
@@ -59,9 +62,11 @@ desktop layout can replace the Herdr terminal client for daily work.
59
62
  **5. Passkey lock** (optional): Settings → Security → **Enable passkey lock**. The
60
63
  first passkey asks for a bootstrap token, printed in the server log (`~/wherdr/wherdr.log`,
61
64
  **L** in the wherdr panel); it changes on each restart and is only needed for that first passkey. Add a passkey on each of
62
- your devices after that (see [New device](security.md#new-device)). Without one, every device of your
63
- tailnet can control your agents: enough when the tailnet is yours alone, a passkey adds a lock
64
- on each device when someone else shares the tailnet or your devices.
65
+ your devices after that (see [New device](security.md#new-device)). Without one, wherdr
66
+ answers this computer and your own tailnet devices; devices of other people on your tailnet are
67
+ always refused (with a passkey, they reach the lock screen). A passkey adds an automatic lock on
68
+ each device if you want one, for example on a computer other people log in to (see
69
+ [Shared computers](security.md#shared-computers)).
65
70
 
66
71
  **6. More machines** (optional): register your other computers in Herdr over SSH
67
72
  (`herdr machine add`, see [Several machines (SSH)](machines.md#several-machines-ssh)). Their agents show
package/docs/plugins.md CHANGED
@@ -7,7 +7,7 @@
7
7
  This is what [the one command](installation.md#the-one-command) installs; you can also run it yourself, on Linux
8
8
  and macOS, with Herdr ≥ 0.9.1 (no checks for Herdr or Node.js first). In three lines:
9
9
 
10
- 1. Run `herdr plugin install afloury/wherdr`: it installs wherdr, starts it
10
+ 1. Run `herdr plugin install afloury/wherdr --ref 2.x`: it installs wherdr, starts it
11
11
  (`✓ wherdr is running → http://localhost:7683`) and, at the first install on a computer with a
12
12
  screen, opens the setup guide in your browser (`open` on macOS, `xdg-open` on Linux with a
13
13
  display; a headless server, or `WHERDR_NO_BROWSER=1` in the environment of the install, just
@@ -33,20 +33,21 @@ address and the phone steps instead. See [The one command](installation.md#the-o
33
33
 
34
34
  **wherdr 2.0 runs only natively**, as your user, so it can act on the
35
35
  [herdr-projects Board](board.md#works-great-with-herdr-projects) (Coordinator, reply, start, stop,
36
- approve). Other ways, after it: `herdr plugin install afloury/wherdr` (the same plugin, without
36
+ approve). Other ways, after it: `herdr plugin install afloury/wherdr --ref 2.x` (the same plugin, without
37
37
  the checks), and [the `wherdr` command](command.md#the-wherdr-command) from npm or Homebrew (npm can hold a
38
38
  new release for up to two days; the installer gets it from GitHub at once).
39
39
 
40
40
  At first launch, wherdr opens a **setup guide**: the Herdr agents it found, your phone
41
- (Tailscale), then the passkey lock and notifications. Skip it any time; finishing or skipping is
41
+ (Tailscale), then notifications. Skip it any time; finishing or skipping is
42
42
  saved on the server (`data/onboarding.json`), so your other devices do not show it again. Reopen
43
43
  it from Settings › About › **Setup guide**. On a phone that already opens wherdr through its
44
44
  tailnet address, the phone step becomes Add to Home Screen.
45
45
 
46
- **Passkeys are tied to the address they are created on.** Once wherdr's tailnet address is
47
- published and answers, the guide opened on `localhost` shows **Continue on
48
- <machine>.<tailnet>.ts.net**, which reopens it at the same step on that address, and its Security
49
- step (like Settings › Security) sends the passkey lock there. Nothing redirects on its own:
46
+ Once wherdr's tailnet address is published and answers, the guide opened on `localhost` shows
47
+ **Continue on <machine>.<tailnet>.ts.net**, which reopens it at the same step on that address
48
+ (notifications and the installed app need it). The guide does not propose a passkey: the
49
+ optional passkey lock is in Settings › Security, which also sends it to that address, since
50
+ **passkeys are tied to the address they are created on**. Nothing redirects on its own:
50
51
  `localhost` stays valid on the computer. The installer, the Herdr plugin and `wherdr open` open
51
52
  that address too when it is already published.
52
53
 
package/docs/quotas.md CHANGED
@@ -30,9 +30,12 @@ week, with reset times), for every online machine.
30
30
 
31
31
  - **Codex**: nothing to do, Codex writes its limits in its session files. Machines on different
32
32
  Codex accounts get one block each (told apart by a short hash of the account ID found in the
33
- session files; `~/.codex/auth.json` is never read). If a session has no recognized account
34
- fingerprint, its reading stays under its own machine and is never merged with another
35
- conversation or machine. A new conversation identifies an account switch even before it
33
+ session files; `~/.codex/auth.json` is never read). Codex only writes that account ID in
34
+ conversations created with a ChatGPT login by a recent Codex version. A reading without it
35
+ joins another machine's reading only when both show the same 5-hour window and the same
36
+ weekly window (resets within a minute, week already started), a sign of one account: the
37
+ machines then share one Codex row at the top, like Claude. Otherwise it stays under its own
38
+ machine and is never merged with another conversation or machine. A new conversation identifies an account switch even before it
36
39
  logs limits; until a reading for that account is available, no Codex gauge is shown. Failed reads do not
37
40
  reuse an older machine snapshot, and remembered weekly limits cannot cross account
38
41
  identities. Without a known fingerprint, remembered weekly corrections are not reused,
@@ -0,0 +1,29 @@
1
+ ## New
2
+
3
+ 2.6 is the last new version of wherdr 2. It gets you ready for wherdr 3, which installs **beside** wherdr 2 rather than replacing it.
4
+
5
+ - **Updates stay on wherdr 2.** The update check only offers 2.x versions. When wherdr 3 is published, the Update button never installs it, and wherdr 2 fixes (2.6.1, 2.6.2…) are still offered.
6
+ - **A "wherdr 3 is out" card.** Once wherdr 3 is released, Home shows a card instead of the update banner, with links to its release notes and its migration guide, and a Copy button for the command that installs wherdr 3 beside this version. That command shows its plan first and changes nothing until you add `--yes`. wherdr 2 keeps running with its data, so you can compare both and go back at any time.
7
+ - **Installs follow the 2.x branch.** The Herdr plugin now updates from the `2.x` branch (**U** in the panel, and the update command, add `--ref 2.x`), and the curl installer installs `2.x` by default (`WHERDR_REF` still picks another branch or tag). If you run wherdr from a git checkout, switch it to the release branch once with `git checkout 2.x` before pulling; the update banner shows that command.
8
+ - **SVG diagrams in conversations.** A static `svg` code block shows as a theme-aware preview you can enlarge or copy; unsafe or incomplete content stays plain code. Thanks to [@guileen](https://github.com/guileen).
9
+ - **omp context at a glance.** Agent rows and the composer show how much of omp's context is used.
10
+
11
+ ## Improved
12
+
13
+ - **Tighter security on the tailnet.** Without a passkey, only your own Tailscale devices can open wherdr; another user's device in a team tailnet, or a shared-in or tagged node, is refused until a passkey is set. A locked device learns nothing before unlocking (no passkey names, machine name or server clock). **Lock all devices** now invalidates every session, push subscription and open connection at once.
14
+ - **Lighter conversation reads.** While an agent writes, wherdr reads only what was added to its transcript.
15
+
16
+ ## Fixed
17
+
18
+ - A finished task's Agent tab shows the agent's conversation instead of the shell left behind.
19
+ - Conversations reopen at their reading position, are not redrawn when nothing changed, and keep a sent message visible while reads fail for a while.
20
+ - A repeated Enter (from a dictation app, for example) no longer sends the same message twice, and a single stray Escape no longer stops the agent.
21
+ - Home counters and badges agree on task states, the Board grouping appears right after a reload, and two machines on one Codex account share one quota row.
22
+ - Reconnecting after a suspend or a redeploy no longer hangs on a stalled read.
23
+ - On macOS, when wherdr runs as a service, Settings › Phone no longer says *not connected* while Tailscale runs, and Web Push works.
24
+
25
+ ## Update
26
+
27
+ No migration is required from 2.5.0. Node.js 22 or newer and Herdr 0.9.1 or newer remain required. Git checkouts: run `git checkout 2.x` once before your next `git pull`.
28
+
29
+ [Full changelog](https://github.com/afloury/wherdr/blob/v2.6.0/CHANGELOG.md)
package/docs/security.md CHANGED
@@ -10,7 +10,7 @@ wherdr drives Herdr, so **it can run anything as your user**.
10
10
  network** (Tailscale or [equivalent](networks.md#other-private-networks)). Never add a public route
11
11
  (port forwarding, public reverse proxy, ngrok…); the only exception is a Cloudflare Tunnel
12
12
  behind Cloudflare Access, with its risks (it needs `WHERDR_TRUSTED_NETWORKS=any`).
13
- - It answers only this computer and the tailnet: see [Network access](security.md#network-access).
13
+ - It answers only this computer and your own tailnet devices: see [Network access](security.md#network-access).
14
14
  - Requests are accepted only for `localhost`, loopback addresses, the runtime's hostname, the
15
15
  hostname in `APP_URL`, the tailnet name `tailscale serve` publishes for wherdr's own port
16
16
  (read from Tailscale on the machine, never from a request, and only while it is published),
@@ -29,17 +29,37 @@ wherdr drives Herdr, so **it can run anything as your user**.
29
29
 
30
30
  A network error or a server restart never locks the app. **Lock all devices** (Settings →
31
31
  Security, for a lost or stolen device) ends every session, this one included, and keeps the
32
- passkeys: each device unlocks again with its own. Turning the lock off removes the passkeys and
33
- invalidates every session. Lost passkey: delete `data/auth.json` on the server; the app is open
34
- again to whoever can reach it.
32
+ passkeys: each device unlocks again with its own. It draws a new signing secret and a new random
33
+ session generation, so even a cookie forged by someone who once read `data/auth.json` stops
34
+ working; open WebSockets close at once, and every push subscription is removed (a device
35
+ subscribes again by itself once unlocked; its own quiet setting is reset). Turning the lock off
36
+ does the same and removes the passkeys; every open app then posts its push subscription again
37
+ at once, and an app that was closed or asleep does so when it opens or reconnects. The first start after upgrading to this version ends the open
38
+ sessions once (the old numeric generation is replaced); the passkeys stay. Lost passkey: delete
39
+ `data/auth.json` on the server; the app is open again to whoever can reach it.
40
+ - **Before the unlock**, a locked device only learns that the app is locked: no passkey names or
41
+ dates, no machine name, no server clock. Unlocking lists no key: the device offers its own
42
+ passkey for the site (passkeys are registered as discoverable credentials). Unlock attempts
43
+ are limited to 10 per minute per client, and at most 100 unlock challenges wait at once.
44
+ - **Protected files**: the file browser and the file paths shown in conversations never preview,
45
+ download or stream wherdr's data folder (`DATA_DIR`, with `auth.json`, the push keys and
46
+ subscriptions), `~/.ssh` or `~/.config/herdr`, on any machine, even through a symlink or inside
47
+ a browsed project. Agents themselves can still read them: the lock protects the app, not the
48
+ machine.
35
49
  - <a id="new-device"></a>**New device**: it can only get in with an existing passkey. Unlock it
36
50
  with a passkey synced by your password manager (iCloud Keychain, Google Password Manager,
37
51
  1Password…), or with the passkey of another device through the browser's "use a phone or
38
52
  tablet" QR code, then Settings → Security → **Add this device** to give it its own passkey.
39
- - Without a passkey, **anyone who can reach the address can control your agents**: every device
40
- on your tailnet, and every user of your tailnet if you share it.
53
+ - By default, with no passkey, wherdr answers **this computer and your own tailnet devices**:
54
+ devices of other people on your tailnet are always filtered out (no setting turns this off).
55
+ Whoever uses this computer or one of your devices can control your agents, other OS users of
56
+ this computer included (see [Shared computers](security.md#shared-computers)). The passkey is
57
+ optional: it adds an automatic lock on each device if you want one, and then lets other
58
+ people's tailnet devices reach that lock.
41
59
  - Writes require `Content-Type: application/json` (or `image/*` for photos, `application/octet-stream` for attached files) and an `Origin`
42
- matching the host, WebSockets included. API reads sent from another site (links, images,
60
+ matching the host, WebSockets included. Request bodies are read with a size limit (256 KB for
61
+ JSON, 20 MB for photos, 30 MB for attached files), chunked bodies included: past it the server
62
+ stops reading, answers `too_large` and closes the connection. API reads sent from another site (links, images,
43
63
  `no-cors` fetches, reported by the browser's `Sec-Fetch-Site`) are refused too.
44
64
  - A strict Content Security Policy limits scripts to the app's own origin and hashed inline
45
65
  scripts, and connections to that origin and its WebSockets. It also blocks embedded objects
@@ -58,17 +78,19 @@ See [SECURITY.md](../SECURITY.md) to report a vulnerability.
58
78
 
59
79
  ### Network access
60
80
 
61
- wherdr answers **this computer and your tailnet only**. A device on any other network (a coffee shop
81
+ wherdr answers **this computer and your own tailnet devices only**. A device on any other network (a coffee shop
62
82
  Wi-Fi, an office LAN, the Internet) gets HTTP 403 (`network`), with a page that says why, even
63
- when it knows the address and the port. The passkey lock is never required, on any network: it
64
- is an extra lock on top, and it needs HTTPS (or `localhost`).
83
+ when it knows the address and the port. The passkey lock is never required for this computer
84
+ and your own devices: it is an extra lock on top, and it needs HTTPS (or `localhost`). Other
85
+ people's tailnet devices get in only once a passkey is set up (see below).
65
86
 
66
87
  **Good practices**
67
88
 
68
89
  - Prefer **Tailscale** (`tailscale serve`): a private HTTPS address, only for your devices.
69
90
  - A network you add **without HTTPS** gets no passkey, no installed app and no notifications, and
70
91
  any device on that network can control your agents.
71
- - **Create a passkey** as soon as wherdr is reached over HTTPS.
92
+ - **Passkey** (optional, over HTTPS): an automatic lock on each device, if you want one. Your
93
+ own devices get in without it.
72
94
 
73
95
  How a request is judged, before anything else (WebSockets included):
74
96
 
@@ -81,6 +103,20 @@ How a request is judged, before anything else (WebSockets included):
81
103
  reads that from Tailscale every 10 seconds (the CLI or Tailscale's socket); an
82
104
  interface address in that range proves nothing, since a LAN may use it too. When Tailscale is
83
105
  stopped, missing or unreadable for 30 seconds, no direct connection counts as tailnet.
106
+ - <a id="own-devices"></a>*Your own devices only*: a peer counts when Tailscale lists it under
107
+ the same user as this machine (`UserID`), is not tagged, and is not a node of someone you
108
+ shared this machine with (`ShareeNode`). Every other peer is refused with HTTP 403 (`network`, `why: foreign`) while
109
+ no passkey is set up: another user's device in a team tailnet, a machine someone
110
+ [shared](https://tailscale.com/kb/1084/sharing) with you (it belongs to another user), a
111
+ device of someone you shared this machine with, a tagged node (tagged devices
112
+ belong to no user, your own tagged servers included). When the machine running wherdr is
113
+ itself tagged, its owner is unknown: no peer counts as yours, so only this computer gets in
114
+ until a passkey is set up. The same rule applies to the client `tailscale serve` names in
115
+ `X-Forwarded-For`: without a passkey, it must be one of your devices in the latest reading
116
+ (a device that joined in the last seconds, or any device while Tailscale cannot be read, is
117
+ refused). The other peers are remembered from the last valid reading, so a failed reading
118
+ does not let them in. Once a passkey is set up, they are let through to the lock screen and
119
+ need that passkey like any device.
84
120
  - **Proxy headers**, only when the peer is this computer (a proxy on the machine, such as
85
121
  `tailscale serve`): every address in `X-Forwarded-For`, `Forwarded`, `X-Real-IP`,
86
122
  `CF-Connecting-IP` must be loopback, the tailnet or a trusted range too. They can only refuse
@@ -106,6 +142,13 @@ How a request is judged, before anything else (WebSockets included):
106
142
  loopback or this machine's tailnet address as Tailscale reports it, with Tailscale running
107
143
  (`HOST=0.0.0.0`, a LAN address), and says how to fix it.
108
144
 
145
+ > [!IMPORTANT]
146
+ > <a id="shared-computers"></a>**Every user of this computer counts as this computer.** Loopback
147
+ > connections are not tied to an OS user: on a machine where other people have an account (a
148
+ > shared server, a lab machine), any of them can open `http://127.0.0.1:7683/` and control
149
+ > your agents. wherdr keeps loopback open so you can always reach it on your own machine. On a
150
+ > machine others log in to, the optional passkey locks loopback too.
151
+
109
152
  > [!IMPORTANT]
110
153
  > **A relay on this computer counts as this computer.** A reverse proxy or TCP forward you run
111
154
  > on the machine (nginx without forwarded headers, `socat`, an SSH tunnel, a tunnel client) opens
@@ -20,6 +20,10 @@
20
20
  - **HTTP 403 "wherdr only answers this computer and your tailnet"**: the device is on another
21
21
  network (Wi-Fi, LAN). Open wherdr through Tailscale, or name that private network in
22
22
  `WHERDR_TRUSTED_NETWORKS` ([Network access](security.md#network-access)).
23
+ - **HTTP 403 "This device is not one of the owner's"**: Tailscale lists the device under another
24
+ user (a team tailnet), as shared in from another tailnet, or as a tagged node. Without a passkey,
25
+ wherdr only answers your own devices: log that device in to Tailscale with your own account, or
26
+ set up a passkey ([Your own devices only](security.md#own-devices)).
23
27
  - **HTTP 403 "Tailscale Funnel opens wherdr to the Internet"**: turn Funnel off for wherdr’s port (`tailscale funnel status`).
24
28
  - **wherdr stops at startup with "Refusing to listen on …"**: `HOST` is not loopback nor this
25
29
  machine's tailnet address. Set `HOST=127.0.0.1` and use `tailscale serve`, or see
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wherdr",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Unofficial mobile web client (PWA) to drive the coding agents running in Herdr",