wherdr 1.3.3 → 2.0.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.
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/BDNMzG2s.js +1 -0
- package/.output/public/_nuxt/BETID3_E.js +1 -0
- package/.output/public/_nuxt/BHenDMeH.js +1 -0
- package/.output/public/_nuxt/BYZVrreW.js +1 -0
- package/.output/public/_nuxt/BhgehRdJ.js +1 -0
- package/.output/public/_nuxt/{yzABg5xl.js → Bpoxvzh6.js} +1 -1
- package/.output/public/_nuxt/BtH82ZuZ.js +9 -0
- package/.output/public/_nuxt/C25ROUa9.js +3 -0
- package/.output/public/_nuxt/C3Bkn4ac.js +62 -0
- package/.output/public/_nuxt/CDWjMk9C.js +2 -0
- package/.output/public/_nuxt/{Ci8N4mWR.js → CXJnLmWv.js} +1 -1
- package/.output/public/_nuxt/CuUQ4mEf.js +1 -0
- package/.output/public/_nuxt/DFGEl0v2.js +23 -0
- package/.output/public/_nuxt/{CKhgznq4.js → DFmgQVme.js} +42 -39
- package/.output/public/_nuxt/DZGKxROq.js +6 -0
- package/.output/public/_nuxt/DmkWvmnE.js +2 -0
- package/.output/public/_nuxt/DrKKeFFE.js +31 -0
- package/.output/public/_nuxt/DyfFwwGq.js +1 -0
- package/.output/public/_nuxt/FaNto0ga.js +105 -0
- package/.output/public/_nuxt/NIF0VwHk.js +25 -0
- package/.output/public/_nuxt/R0Y4VoeX.js +1 -0
- package/.output/public/_nuxt/board.CEEcFc6M.css +1 -0
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/0b28b3e9-664e-4347-a35b-afb0a711d5c5.json +1 -0
- package/.output/public/_nuxt/entry.CKoXcwRa.css +2 -0
- package/.output/public/_nuxt/pdf.min.t82Z80JU.mjs +28 -0
- package/.output/public/_nuxt/pdf.worker.min.wgc6bjNh.mjs +28 -0
- package/.output/public/_nuxt/settings.Cdb21nNw.css +1 -0
- package/.output/public/sw.js +1 -1
- package/.output/server/chunks/_/branding.mjs +1 -1
- package/.output/server/chunks/_/changes.mjs +4 -4
- package/.output/server/chunks/_/fileDownload.mjs +278 -0
- package/.output/server/chunks/_/files.mjs +60 -20
- package/.output/server/chunks/_/machineOrder.mjs +1 -1
- package/.output/server/chunks/_/onboarding.mjs +1 -1
- package/.output/server/chunks/_/package.mjs +11 -3
- package/.output/server/chunks/_/plugins.mjs +92 -122
- package/.output/server/chunks/_/restart.mjs +1 -1
- package/.output/server/chunks/_/selfupdate.mjs +1 -1
- package/.output/server/chunks/_/settingstabs.mjs +36 -0
- package/.output/server/chunks/_/updates.mjs +1 -1
- package/.output/server/chunks/_/worktrees.mjs +1 -1
- package/.output/server/chunks/_/ws.mjs +43 -6
- package/.output/server/chunks/nitro/nitro.mjs +14126 -10238
- package/.output/server/chunks/raw/check-doc-links.mjs +5 -0
- package/.output/server/chunks/raw/check-leaks.mjs +1 -1
- package/.output/server/chunks/raw/check-release-notes.mjs +5 -0
- package/.output/server/chunks/raw/herdr-plugin.mjs +1 -1
- package/.output/server/chunks/raw/install-claude-statusline.mjs +1 -1
- package/.output/server/chunks/raw/prerelease-summary.mjs +5 -0
- package/.output/server/chunks/raw/prerelease.mjs +7 -0
- package/.output/server/chunks/raw/reveal.mjs +1 -1
- package/.output/server/chunks/raw/test-affected.mjs +5 -0
- package/.output/server/chunks/routes/api/_..._.mjs +6 -5
- package/.output/server/chunks/routes/api/agents.post.mjs +6 -5
- package/.output/server/chunks/routes/api/ask-tab.post.mjs +6 -5
- package/.output/server/chunks/routes/api/attach.post.mjs +6 -5
- package/.output/server/chunks/routes/api/auth/disable.post.mjs +6 -5
- package/.output/server/chunks/routes/api/auth/lock-all.post.mjs +6 -5
- package/.output/server/chunks/routes/api/auth/lock.post.mjs +6 -5
- package/.output/server/chunks/routes/api/auth/login/options.post.mjs +6 -5
- package/.output/server/chunks/routes/api/auth/login/verify.post.mjs +6 -5
- package/.output/server/chunks/routes/api/auth/max-session.post.mjs +6 -5
- package/.output/server/chunks/routes/api/auth/register/options.post.mjs +6 -5
- package/.output/server/chunks/routes/api/auth/register/verify.post.mjs +6 -5
- package/.output/server/chunks/routes/api/auth/status.get.mjs +6 -5
- package/.output/server/chunks/routes/api/changes.get.mjs +7 -6
- package/.output/server/chunks/routes/api/chat/image.get.mjs +7 -6
- package/.output/server/chunks/routes/api/chat.get.mjs +44 -11
- package/.output/server/chunks/routes/api/choose.post.mjs +44 -30
- package/.output/server/chunks/routes/api/claude-setup.post.mjs +42 -0
- package/.output/server/chunks/routes/api/claude-statusline.post.mjs +7 -6
- package/.output/server/chunks/routes/api/clear-queued-input.post.mjs +42 -0
- package/.output/server/chunks/routes/api/close/status.get.mjs +7 -6
- package/.output/server/chunks/routes/api/close.post.mjs +6 -5
- package/.output/server/chunks/routes/api/codex-update.post.mjs +7 -6
- package/.output/server/chunks/routes/api/commands.get.mjs +9 -7
- package/.output/server/chunks/routes/api/config.get.mjs +10 -13
- package/.output/server/chunks/routes/api/dirs.get.mjs +7 -6
- package/.output/server/chunks/routes/api/dismiss-stopped.post.mjs +7 -6
- package/.output/server/chunks/routes/api/dismiss.post.mjs +7 -6
- package/.output/server/chunks/routes/api/effort.post.mjs +7 -6
- package/.output/server/chunks/routes/api/efforts.get.mjs +7 -6
- package/.output/server/chunks/routes/api/file.post.mjs +7 -6
- package/.output/server/chunks/routes/api/files/download.get.mjs +12 -24
- package/.output/server/chunks/routes/api/files/download.head.mjs +41 -0
- package/.output/server/chunks/routes/api/files/read.get.mjs +8 -7
- package/.output/server/chunks/routes/api/files.get.mjs +7 -6
- package/.output/server/chunks/routes/api/health.get.mjs +6 -5
- package/.output/server/chunks/routes/api/input.post.mjs +33 -15
- package/.output/server/chunks/routes/api/interrupt.post.mjs +24 -21
- package/.output/server/chunks/routes/api/isgit.get.mjs +8 -8
- package/.output/server/chunks/routes/api/machine/awake.get.mjs +7 -6
- package/.output/server/chunks/routes/api/machine/awake.post.mjs +7 -6
- package/.output/server/chunks/routes/api/machine/order.get.mjs +6 -5
- package/.output/server/chunks/routes/api/machine/order.post.mjs +6 -5
- package/.output/server/chunks/routes/api/machine/reconnect.post.mjs +40 -0
- package/.output/server/chunks/routes/api/machine/rename.post.mjs +7 -6
- package/.output/server/chunks/routes/api/machine/status.post.mjs +39 -0
- package/.output/server/chunks/routes/api/menu-left.post.mjs +40 -0
- package/.output/server/chunks/routes/api/menu.post.mjs +10 -6
- package/.output/server/chunks/routes/api/model.post.mjs +7 -6
- package/.output/server/chunks/routes/api/models.get.mjs +7 -6
- package/.output/server/chunks/routes/api/nav.post.mjs +40 -26
- package/.output/server/chunks/routes/api/onboarding.get.mjs +6 -5
- package/.output/server/chunks/routes/api/onboarding.post.mjs +6 -5
- package/.output/server/chunks/routes/api/phone.get.mjs +8 -10
- package/.output/server/chunks/routes/api/phone.post.mjs +8 -10
- package/.output/server/chunks/routes/api/plugins/actions.get.mjs +6 -8
- package/.output/server/chunks/routes/api/plugins/invoke.post.mjs +6 -8
- package/.output/server/chunks/routes/api/plugins/projects.get.mjs +10 -8
- package/.output/server/chunks/routes/api/plugins/projects.post.mjs +11 -7
- package/.output/server/chunks/routes/api/prompt.post.mjs +22 -13
- package/.output/server/chunks/routes/api/push/quiet.post.mjs +7 -6
- package/.output/server/chunks/routes/api/push/subscribe.post.mjs +7 -7
- package/.output/server/chunks/routes/api/push/test.post.mjs +7 -6
- package/.output/server/chunks/routes/api/push/unsubscribe.post.mjs +7 -6
- package/.output/server/chunks/routes/api/quotas.get.mjs +7 -6
- package/.output/server/chunks/routes/api/rename.post.mjs +6 -5
- package/.output/server/chunks/routes/api/requeue.post.mjs +7 -6
- package/.output/server/chunks/routes/api/restart.get.mjs +6 -5
- package/.output/server/chunks/routes/api/restart.post.mjs +6 -5
- package/.output/server/chunks/routes/api/reveal.post.mjs +91 -8
- package/.output/server/chunks/routes/api/screen-key.post.mjs +19 -15
- package/.output/server/chunks/routes/api/screen.get.mjs +8 -40
- package/.output/server/chunks/routes/api/search.get.mjs +7 -6
- package/.output/server/chunks/routes/api/seen.post.mjs +7 -6
- package/.output/server/chunks/routes/api/sessions.get.mjs +7 -6
- package/.output/server/chunks/routes/api/sessions.post.mjs +7 -6
- package/.output/server/chunks/routes/api/settings-tab.post.mjs +90 -0
- package/.output/server/chunks/routes/api/{plugins/thread-limits.get.mjs → settings.get.mjs} +10 -9
- package/.output/server/chunks/routes/api/settings.post.mjs +40 -0
- package/.output/server/chunks/routes/api/space.post.mjs +34 -18
- package/.output/server/chunks/routes/api/state.get.mjs +7 -6
- package/.output/server/chunks/routes/api/tasks/action.post.mjs +39 -0
- package/.output/server/chunks/routes/api/{plugins/profiles.get.mjs → tasks/add.post.mjs} +12 -14
- package/.output/server/chunks/routes/api/tasks/after.post.mjs +39 -0
- package/.output/server/chunks/routes/api/tasks/approve.post.mjs +39 -0
- package/.output/server/chunks/routes/api/{project/report.get.mjs → tasks/archived.get.mjs} +12 -13
- package/.output/server/chunks/routes/api/{gitroot.get.mjs → tasks/autopilot.get.mjs} +13 -14
- package/.output/server/chunks/routes/api/tasks/autopilot.post.mjs +39 -0
- package/.output/server/chunks/routes/api/{index.get.mjs → tasks/board-settings.get.mjs} +12 -13
- package/.output/server/chunks/routes/api/tasks/board-settings.post.mjs +39 -0
- package/.output/server/chunks/routes/api/tasks/coordinator.get.mjs +40 -0
- package/.output/server/chunks/routes/api/tasks/coordinator.post.mjs +39 -0
- package/.output/server/chunks/routes/api/tasks/details.get.mjs +40 -0
- package/.output/server/chunks/routes/api/tasks/limit.post.mjs +39 -0
- package/.output/server/chunks/routes/api/tasks/links.get.mjs +39 -0
- package/.output/server/chunks/routes/api/tasks/models.get.mjs +40 -0
- package/.output/server/chunks/routes/api/tasks/pick.post.mjs +39 -0
- package/.output/server/chunks/routes/api/tasks/question.post.mjs +39 -0
- package/.output/server/chunks/routes/api/tasks/scheduled.get.mjs +40 -0
- package/.output/server/chunks/routes/api/{project → tasks}/settings.get.mjs +10 -11
- package/.output/server/chunks/routes/api/tasks/start.get.mjs +40 -0
- package/.output/server/chunks/routes/api/tasks/tell.post.mjs +39 -0
- package/.output/server/chunks/routes/api/tasks.get.mjs +39 -0
- package/.output/server/chunks/routes/api/unqueue.post.mjs +7 -6
- package/.output/server/chunks/routes/api/update/status.get.mjs +6 -5
- package/.output/server/chunks/routes/api/update.get.mjs +8 -10
- package/.output/server/chunks/routes/api/update.post.mjs +8 -10
- package/.output/server/chunks/routes/api/upload.post.mjs +7 -6
- package/.output/server/chunks/routes/api/worktrees/remove.post.mjs +6 -5
- package/.output/server/chunks/routes/api/worktrees.get.mjs +6 -5
- package/.output/server/chunks/routes/favicon.ico.get.mjs +6 -5
- package/.output/server/chunks/routes/icons/_name_.get.mjs +7 -6
- package/.output/server/chunks/routes/renderer.mjs +8 -7
- package/.output/server/chunks/routes/uploads/_...name_.get.mjs +7 -6
- package/.output/server/chunks/routes/ws/_..._.mjs +7 -6
- package/.output/server/chunks/routes/ws/events.mjs +9 -7
- package/.output/server/chunks/routes/ws/term.mjs +7 -6
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/index.mjs +7 -6
- package/.output/server/package.json +1 -1
- package/README.md +44 -1424
- package/bin/lib/commands.mjs +44 -9
- package/bin/lib/panel.mjs +3 -11
- package/bin/lib/service.mjs +41 -2
- package/bin/lib/skill.mjs +1 -1
- package/bin/lib/tailnet.d.mts +6 -3
- package/bin/lib/tailnet.mjs +70 -32
- package/bin/lib/userpath.d.mts +14 -0
- package/bin/lib/userpath.mjs +142 -0
- package/docs/README.md +58 -0
- package/docs/RELEASING.md +174 -0
- package/docs/board.md +164 -0
- package/docs/command.md +58 -0
- package/docs/configuration.md +39 -0
- package/docs/conversation.md +132 -0
- package/docs/development.md +38 -0
- package/docs/devices.md +58 -0
- package/docs/files.md +29 -0
- package/docs/herdr-projects-1x.md +278 -0
- package/docs/home.md +52 -0
- package/docs/installation.md +174 -0
- package/docs/machines.md +69 -0
- package/docs/migrate-from-1.x-docker.md +160 -0
- package/docs/networks.md +154 -0
- package/docs/notifications.md +83 -0
- package/docs/overview.md +71 -0
- package/docs/phone.md +26 -0
- package/docs/plugins.md +109 -0
- package/docs/quick-start.md +89 -0
- package/docs/quotas.md +65 -0
- package/docs/release-notes-2.0.0.md +84 -0
- package/docs/security.md +117 -0
- package/docs/terminal.md +15 -0
- package/docs/troubleshooting.md +45 -0
- package/package.json +11 -3
- package/skills/wherdr/SKILL.md +24 -167
- package/.output/public/_nuxt/B4Yk2tB1.js +0 -23
- package/.output/public/_nuxt/BBw_0a4M.js +0 -6
- package/.output/public/_nuxt/BSy6OCIY.js +0 -1
- package/.output/public/_nuxt/BX5PM2JQ.js +0 -1
- package/.output/public/_nuxt/BgPDnf2S.js +0 -1
- package/.output/public/_nuxt/BkOxQzbS.js +0 -2
- package/.output/public/_nuxt/CP8o925U.js +0 -1
- package/.output/public/_nuxt/CWwyK2XK.js +0 -2
- package/.output/public/_nuxt/CkbmecwS.js +0 -1
- package/.output/public/_nuxt/Cr3SrGky.js +0 -1
- package/.output/public/_nuxt/DAg9fiVh.js +0 -89
- package/.output/public/_nuxt/DT8qZ0Wv.js +0 -1
- package/.output/public/_nuxt/DaaJIRB3.js +0 -1
- package/.output/public/_nuxt/DcJi16XA.js +0 -1
- package/.output/public/_nuxt/SiL1FJ5s.js +0 -3
- package/.output/public/_nuxt/VpjCgSXu.js +0 -36
- package/.output/public/_nuxt/builds/meta/c735b6c0-1bd0-47d7-a208-d310f0a06287.json +0 -1
- package/.output/public/_nuxt/dPxB2L94.js +0 -89
- package/.output/public/_nuxt/entry.CGWKmYU3.css +0 -2
- package/.output/public/_nuxt/xYX85SPI.js +0 -1
- package/.output/server/chunks/_/pluginPolicy.mjs +0 -93
- package/.output/server/chunks/_/projectBoard.mjs +0 -366
- package/.output/server/chunks/_/projectDocs.mjs +0 -106
- package/.output/server/chunks/_/projectInbox.mjs +0 -135
- package/.output/server/chunks/_/projectThreads.mjs +0 -46
- package/.output/server/chunks/_/projectThreads2.mjs +0 -61
- package/.output/server/chunks/_/projectsActions.mjs +0 -143
- package/.output/server/chunks/_/projectsPlugin.mjs +0 -56
- package/.output/server/chunks/_/reveal.mjs +0 -115
- package/.output/server/chunks/raw/dev.wherdr.open.mjs +0 -7
- package/.output/server/chunks/raw/docker-entrypoint.mjs +0 -7
- package/.output/server/chunks/raw/install-host-open.mjs +0 -7
- package/.output/server/chunks/raw/wherdr-open.mjs +0 -7
- package/.output/server/chunks/routes/api/board.get.mjs +0 -147
- package/.output/server/chunks/routes/api/plugins/thread-limits.post.mjs +0 -45
- package/.output/server/chunks/routes/api/project/inbox.get.mjs +0 -43
- package/.output/server/chunks/routes/api/project/inbox.post.mjs +0 -43
- package/.output/server/chunks/routes/api/project/memory.get.mjs +0 -42
- package/.output/server/chunks/routes/api/project/routines.get.mjs +0 -43
- package/.output/server/chunks/routes/api/project/thread.get.mjs +0 -44
- package/.output/server/chunks/routes/api/project/thread.post.mjs +0 -45
- package/bin/install-docker-skill.sh +0 -20
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Releasing wherdr
|
|
2
|
+
|
|
3
|
+
Publishing a version requires the user's explicit approval. Never republish a package held
|
|
4
|
+
for npm review. No new secret is needed: GitHub uses `GITHUB_TOKEN`, npm uses OIDC Trusted
|
|
5
|
+
Publishing (`npm.yml`), and the tap uses the existing optional `HOMEBREW_TAP_TOKEN`.
|
|
6
|
+
|
|
7
|
+
1. Merge reviewed changes, including the release workflows, into `main`. The site workflow
|
|
8
|
+
deploys relevant changes on pushes to `main`, independently of tags and npm.
|
|
9
|
+
2. Set the same version in `package.json`, `package-lock.json` and `herdr-plugin.toml`.
|
|
10
|
+
Move the Unreleased changelog into a dated version entry. Run tests, typecheck and leak
|
|
11
|
+
checks; review and merge this version commit before tagging it.
|
|
12
|
+
3. Create the GitHub release as a **draft**, with reviewed English notes under one or more of New / Improved /
|
|
13
|
+
Fixed / Update. Write at least two readable sentences explaining what changed for users,
|
|
14
|
+
then link to the tagged CHANGELOG.md (see the example below). A link alone, including
|
|
15
|
+
"See CHANGELOG.md", is never sufficient. Push its version tag only after these notes are ready.
|
|
16
|
+
The workflow validates the draft before attaching the package and again immediately before
|
|
17
|
+
publication; missing or insufficient notes fail the job. It never generates stable release notes.
|
|
18
|
+
4. The tag starts `release.yml` and `npm.yml` independently. `release.yml` runs `npm pack`
|
|
19
|
+
(prepack builds Nitro, includes `skills/wherdr`, resolves linked packages). It attaches
|
|
20
|
+
`wherdr-X.Y.Z.tgz` and `wherdr-X.Y.Z.tgz.sha256` to the draft. After the package job
|
|
21
|
+
succeeds, it publishes the release with `latest=false`. The public GitHub package is now
|
|
22
|
+
usable; native plugins compare the archive checksum. A failed package job leaves the
|
|
23
|
+
release draft; fix and rerun the failed job.
|
|
24
|
+
5. The Homebrew job updates the formula URL and SHA from GitHub, without waiting for npm.
|
|
25
|
+
**The manual Homebrew step is MANDATORY while `HOMEBREW_TAP_TOKEN` is absent**. Wait for `release.yml` to finish successfully first, so its
|
|
26
|
+
archive is public; then run `scripts/bump-homebrew.sh`. Otherwise the legacy update channel
|
|
27
|
+
cannot advance even when npm is ready. A skipped Homebrew job does not complete this step.
|
|
28
|
+
Homebrew still uses npm to install the local archive and fetch its third-party dependency;
|
|
29
|
+
it does not need the new **wherdr version** to be available on npm.
|
|
30
|
+
6. `npm.yml` waits for the attached archive (up to 30 minutes), verifies it, then publishes
|
|
31
|
+
that exact file with provenance. npm moderation may still delay registry availability.
|
|
32
|
+
If the assets were too slow to arrive, rerun the failed download job before any successful
|
|
33
|
+
publication; never retry a successful `npm publish` merely because moderation is pending.
|
|
34
|
+
To recover a workflow fix without moving a tag, run `gh workflow run npm.yml --ref main -f version=vX.Y.Z` after merging the fix; it checks out that tag and publishes its existing release archive.
|
|
35
|
+
7. `release-ready.yml` checks hourly and after npm/release workflow completion. Once npm's
|
|
36
|
+
tarball and `latest` tag, and the Homebrew formula are ready, it marks the GitHub release
|
|
37
|
+
`latest`. Existing 1.3.x apps read this marker and can then safely use their npm updater.
|
|
38
|
+
New apps read published stable releases directly, checking npm or the formula for their
|
|
39
|
+
own installation mode. No update notice is offered while that channel is unavailable.
|
|
40
|
+
|
|
41
|
+
An old plugin can get the release immediately via **U** in Herdr or the one-command installer;
|
|
42
|
+
its old in-app Update button waits for the legacy channel. Plugin installation tries the exact
|
|
43
|
+
version from GitHub, then npm, then compiles only when neither prebuilt source works. This
|
|
44
|
+
includes older releases with no GitHub archive. Keep the previous npm version, GitHub assets,
|
|
45
|
+
and Homebrew keg available for automatic health-check rollback.
|
|
46
|
+
|
|
47
|
+
SHA-256 checks download integrity, not authenticity: the archive and checksum share an origin.
|
|
48
|
+
Replacing both defeats this check. npm fallback compares the archive to the SHA-512 integrity
|
|
49
|
+
in registry metadata, with the same limitation. There is no signature or build attestation check.
|
|
50
|
+
|
|
51
|
+
npm provenance identifies the publishing workflow (`npm.yml`); the archive was built by
|
|
52
|
+
`release.yml` in the same repository at the requested tagged commit. On a manual run from
|
|
53
|
+
`main`, provenance identifies the workflow's `main` commit, while checkout and version checks
|
|
54
|
+
use the requested tag. It does not independently attest that separate build workflow (M8);
|
|
55
|
+
this limitation is intentionally retained.
|
|
56
|
+
|
|
57
|
+
Readiness logs name each missing npm or Homebrew condition, and an already-current `latest`
|
|
58
|
+
marker is left alone. GitHub disables scheduled workflows in public repositories after 60 days
|
|
59
|
+
without repository activity. Check that `release-ready.yml` remains enabled; re-enable it and
|
|
60
|
+
run it manually if needed. After re-enabling, workflow-completion and manual checks work too.
|
|
61
|
+
|
|
62
|
+
## herdr-projects tested version
|
|
63
|
+
|
|
64
|
+
wherdr installs one herdr-projects release, and offers an update to it on machines with an older
|
|
65
|
+
one: `PROJECTS_TESTED` in `shared/projectsPlugin.ts`. `PROJECTS_MIN` (1.2.1) is the oldest
|
|
66
|
+
release wherdr still reads; it moves only when wherdr drops one.
|
|
67
|
+
|
|
68
|
+
To move to a newer herdr-projects release:
|
|
69
|
+
|
|
70
|
+
1. Download its binary from GitHub (`gh release download vX.Y.Z -R eliasstravik/herdr-projects`)
|
|
71
|
+
and check it against its `.sha256`. Run it with `HOME` set to an empty temporary folder and
|
|
72
|
+
Herdr unreachable. Record `version`, `list --json`, `list --json --archived`,
|
|
73
|
+
`details --json -- <id>`, `show --json -- <id>` and `coordinator --machine --json status`
|
|
74
|
+
into `tests/recordings/herdr-projects-X.Y.Z/` (no personal paths or machine names).
|
|
75
|
+
Also check that `tell`, `approve`, `after`, `archive`, `restore` and `coordinator … tell`
|
|
76
|
+
still take the same arguments.
|
|
77
|
+
2. Set `PROJECTS_TESTED` to `X.Y.Z`, and point the recordings test in
|
|
78
|
+
`tests/projectsTasks.test.ts` at the new folder.
|
|
79
|
+
3. If the release adds a feature worth naming, add it to `FEATURES` in
|
|
80
|
+
`app/components/ProjectsPluginSettings.vue` (the update's one-line summary, FR + EN).
|
|
81
|
+
4. Run `npx vitest related --run shared/projectsPlugin.ts`: `tests/projectsPlugin.test.ts`
|
|
82
|
+
fails until the install commands in `docs/board.md`, `docs/herdr-projects-1x.md` and
|
|
83
|
+
`website/public/agent.md` name the new release.
|
|
84
|
+
|
|
85
|
+
## Release notes checklist
|
|
86
|
+
|
|
87
|
+
- Summarize the changes in English under `## New`, `## Improved`, `## Fixed` or `## Update`;
|
|
88
|
+
omit categories with no relevant changes. Use complete sentences, at least two in total
|
|
89
|
+
(at least twelve words), describing the user-visible behavior and any required upgrade action.
|
|
90
|
+
- Put the full changelog link after the summary, using the release tag rather than `main`.
|
|
91
|
+
- Review the text against that version's changelog. The automated check enforces structure
|
|
92
|
+
and minimum content; the reviewer checks accuracy and clarity.
|
|
93
|
+
- Validate the exact draft text locally before pushing the tag:
|
|
94
|
+
`GITHUB_REPOSITORY=example/wherdr GITHUB_REF_NAME=vX.Y.Z node scripts/check-release-notes.mjs < /tmp/wherdr-X.Y.Z.md`.
|
|
95
|
+
If the workflow refuses the notes, edit the draft and rerun the failed jobs.
|
|
96
|
+
|
|
97
|
+
Example (replace `example/wherdr` and the version, and describe the actual release):
|
|
98
|
+
|
|
99
|
+
```markdown
|
|
100
|
+
## Improved
|
|
101
|
+
File downloads now work with the supported Node versions. Temporary download links
|
|
102
|
+
are released after the browser saves the file, keeping repeated downloads reliable.
|
|
103
|
+
|
|
104
|
+
[Full changelog](https://github.com/example/wherdr/blob/vX.Y.Z/CHANGELOG.md)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Rolling v2 prerelease
|
|
108
|
+
|
|
109
|
+
`v2-prerelease.yml` rebuilds one prerelease on every push to the `v2` branch, so a machine
|
|
110
|
+
can install v2 from a prebuilt package (the plugin's GitHub download) and never compile it.
|
|
111
|
+
It publishes the version of `herdr-plugin.toml` (for example `2.0.0-dev`, before the stable version bump) as `v<version>`:
|
|
112
|
+
|
|
113
|
+
- the tag moves to the pushed commit; the release is a prerelease, never `latest`. The update
|
|
114
|
+
checks of every version, the legacy channel and `release-ready.yml` only read stable
|
|
115
|
+
`vX.Y.Z` releases, so none of them offers it;
|
|
116
|
+
- `wherdr-<version>.tgz` and `.tgz.sha256` are made as in `release.yml` (`npm pack`,
|
|
117
|
+
`sha256sum`) and replaced; the archive must hold the built server, `bin` with
|
|
118
|
+
`bin/lib/install-skill.sh`, `package.json` and `skills/wherdr/SKILL.md`, and no native code
|
|
119
|
+
(`.node`, `binding.gyp`, `prebuilds`, ELF or Mach-O files): the same file runs on
|
|
120
|
+
linux-arm64 and x64;
|
|
121
|
+
- `COMMIT` holds the full SHA of the packaged commit, also written in the notes. It is removed
|
|
122
|
+
before the archive is replaced and attached last: when `COMMIT` is there and names the
|
|
123
|
+
branch head, the archive is that commit's.
|
|
124
|
+
|
|
125
|
+
Once the version is stable, the workflow skips packaging and publication; it must not create a stable tag.
|
|
126
|
+
|
|
127
|
+
The rolling notes start with an Update summary of the first three top-level Unreleased
|
|
128
|
+
changelog entries and a link to the changelog at the packaged commit, followed by build
|
|
129
|
+
metadata. Keep these entries readable and current; packaging fails if they are absent or fail the same minimum-content check.
|
|
130
|
+
|
|
131
|
+
`scripts/prerelease.sh` does the checks and the publication. It refuses a version without a
|
|
132
|
+
prerelease suffix (`X.Y.Z-something`) and a release of that tag that is not a published
|
|
133
|
+
prerelease: stable versions keep going through the steps above. The tag is moved with
|
|
134
|
+
`GITHUB_TOKEN`, which starts neither `release.yml` nor `npm.yml`. The workflow runs from the
|
|
135
|
+
`v2` branch: it acts once this file is on `v2`.
|
|
136
|
+
|
|
137
|
+
## Commands for 2.0.0
|
|
138
|
+
|
|
139
|
+
Run in a release checkout after explicit approval. These commands are documentation, not a
|
|
140
|
+
request to publish. The version commit must go through the usual reviewed PR process.
|
|
141
|
+
|
|
142
|
+
```sh
|
|
143
|
+
git switch main
|
|
144
|
+
git pull --ff-only
|
|
145
|
+
git switch -c release/2.0.0
|
|
146
|
+
npm version 2.0.0 --no-git-tag-version
|
|
147
|
+
sed -i.bak 's/^version = ".*"/version = "2.0.0"/' herdr-plugin.toml
|
|
148
|
+
rm herdr-plugin.toml.bak
|
|
149
|
+
# Move Unreleased notes to the dated 2.0.0 entry, run the project checks, then commit.
|
|
150
|
+
git add package.json package-lock.json herdr-plugin.toml CHANGELOG.md
|
|
151
|
+
git commit -m "Prepare release 2.0.0"
|
|
152
|
+
git push -u origin release/2.0.0
|
|
153
|
+
gh pr create --base main --head release/2.0.0 --title "Prepare release 2.0.0" --body "Prepare the reviewed 2.0.0 release versions and changelog."
|
|
154
|
+
# Open, review and merge the version PR; refresh main before continuing.
|
|
155
|
+
git switch main
|
|
156
|
+
git pull --ff-only
|
|
157
|
+
# Use the reviewed notes committed with the version preparation.
|
|
158
|
+
GITHUB_REPOSITORY="$(gh repo view --json nameWithOwner -q .nameWithOwner)" GITHUB_REF_NAME=v2.0.0 node scripts/check-release-notes.mjs < docs/release-notes-2.0.0.md
|
|
159
|
+
gh release create v2.0.0 --target "$(git rev-parse HEAD)" --draft --title "wherdr 2.0.0" --notes-file docs/release-notes-2.0.0.md
|
|
160
|
+
git tag v2.0.0
|
|
161
|
+
git push origin v2.0.0
|
|
162
|
+
release_run=$(gh run list --workflow release.yml --commit "$(git rev-parse HEAD)" --json databaseId --jq '.[0].databaseId')
|
|
163
|
+
# If no run appears yet, wait for GitHub to register the tag and repeat the lookup.
|
|
164
|
+
gh run watch "$release_run" --exit-status
|
|
165
|
+
gh run list --workflow npm.yml --limit 3
|
|
166
|
+
# MANDATORY while the tap secret is absent. Run only after release.yml succeeds:
|
|
167
|
+
sh scripts/bump-homebrew.sh 2.0.0 "$(gh repo view --json owner -q .owner.login)"
|
|
168
|
+
# Inspect the readiness workflow; optionally request an immediate check:
|
|
169
|
+
gh workflow run release-ready.yml --ref main
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Use Node.js 22 for npm commands. Do not manually publish the draft or mark it latest ahead
|
|
173
|
+
of these checks. A GitHub release created by `GITHUB_TOKEN` does not trigger other workflows;
|
|
174
|
+
all publication work is driven by the pushed tag, not `release: published` events.
|
package/docs/board.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Board and coordinators
|
|
2
|
+
|
|
3
|
+
[Documentation](README.md) · [Project](../README.md)
|
|
4
|
+
|
|
5
|
+
On desktop, drag the ticket panel’s divider to adjust its width. It uses the same
|
|
6
|
+
handle as the navigation list: arrow keys (Shift for a larger step), double-click,
|
|
7
|
+
Home or Enter to restore the default width. The width is saved on this device;
|
|
8
|
+
the Board keeps at least 280 px when space permits. Phone panels stay full screen.
|
|
9
|
+
|
|
10
|
+
## Works great with herdr-projects
|
|
11
|
+
|
|
12
|
+
[herdr-projects](https://github.com/eliasstravik/herdr-projects) is a work board for Herdr: one
|
|
13
|
+
list of tasks, each handed to an ordinary agent in its own space, reviewed when it finishes and
|
|
14
|
+
merged on your yes. wherdr shows it on the **Board** (the button next to Settings, or `H`), for
|
|
15
|
+
every machine at once. It needs **herdr-projects 1.2.1 or later**; the plugin is optional.
|
|
16
|
+
|
|
17
|
+
**Install herdr-projects** in **Settings → Plugins → herdr-projects**, or on the machine. wherdr
|
|
18
|
+
installs the release it was tested with (1.2.21):
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
herdr plugin install eliasstravik/herdr-projects --ref v1.2.21 --yes
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
A machine with an older 1.x (1.2.1 or later) still works. Settings says **Update available**
|
|
25
|
+
there, with what the update adds, and **Update to 1.2.21** replaces Herdr's copy of the plugin;
|
|
26
|
+
the tasks and settings stay. wherdr reads the program's own version (`herdr-projects version`),
|
|
27
|
+
so a machine that ran `herdr-projects update` to a newer release is never taken back.
|
|
28
|
+
|
|
29
|
+
> **Breaking change in wherdr 2.0: herdr-projects 0.2 is no longer read.** The Project panel,
|
|
30
|
+
> the `TASKS.md` board, threads, thread limits and **New project** belonged to herdr-projects
|
|
31
|
+
> 0.2 and are gone. With 0.2 (or a 1.x older than 1.2.1), Settings and the Board say
|
|
32
|
+
> **Update herdr-projects to 1.2.1 or later, or downgrade wherdr to 1.3.4**, with the commands.
|
|
33
|
+
> The step-by-step move, with a backup and the way back, is in
|
|
34
|
+
> [docs/herdr-projects-1x.md](herdr-projects-1x.md). wherdr 1.3.4 is the last version
|
|
35
|
+
> that reads herdr-projects 0.2.
|
|
36
|
+
|
|
37
|
+
What the Board shows and does:
|
|
38
|
+
|
|
39
|
+
- **The board's groups**: needs you, ready to approve, working, to do. **Done** is history, so it
|
|
40
|
+
is hidden by default: **Done · 9** at the end of the column heads (the last tab on a phone)
|
|
41
|
+
shows it, newest first, the latest five then **Show all**, and hides it again; the choice is
|
|
42
|
+
saved on the server and shared across devices. Headings still count done tasks. Side by side
|
|
43
|
+
on a computer, one at a time on a phone. A card shows
|
|
44
|
+
the task's key (`DEMO-12`), title, the line its agent reports, the agent program, progress, its
|
|
45
|
+
pull request and its review (pass or fail, with the findings by severity).
|
|
46
|
+
- **A task** opens one compact side panel from the Board or its home row. The header names
|
|
47
|
+
the machine, repo, task and agent program, with the Board's one state: Needs you, Ready to
|
|
48
|
+
approve, Working, To do or Done. **Conversation**, **Terminal**, **Task** and **Settings** sit below it.
|
|
49
|
+
Task holds the description, closing note, report, pull request, review findings, limits,
|
|
50
|
+
token use and actions; a dot marks a new closing note or review. The agent's own Herdr state
|
|
51
|
+
is in a tooltip, separate from the task's state. The panel sits beside the Board on a
|
|
52
|
+
computer (with a full-screen button) and fills the screen on a phone.
|
|
53
|
+
- **Settings** reads the effective task settings from `show --json` on its machine when
|
|
54
|
+
opened. Agent, review, plan and attempts, limits, merge and workspace settings show their
|
|
55
|
+
value and source: task, repository, you, repository file or default. Source details,
|
|
56
|
+
CLI notes and problems stay visible. This view is read-only; unavailable or missing data
|
|
57
|
+
is stated explicitly. Board refreshes do not reread the settings.
|
|
58
|
+
- **Needs you** shows where the task stands now: the Board's failure or question, its command
|
|
59
|
+
output and next-step hint. A failure the task has moved on from (a later stage, or its agent
|
|
60
|
+
started again) is not the banner, and gets no buttons: it stays in Task as an earlier failure.
|
|
61
|
+
It offers **Retry**, **Send the error to the agent** (`fix`), **Open terminal** and, when
|
|
62
|
+
allowed, **Approve anyway** with confirmation. After a failed review, it lists the open
|
|
63
|
+
findings (severity and subject, worst first) and offers **Send the review back to the agent**
|
|
64
|
+
(`review`) first, as herdr-projects does, with **Approve anyway** after it. While the reviewer
|
|
65
|
+
shows a dialog (`reviewneeds`), a reply goes to the reviewer, and wherdr says so. **Finish** (`finish`, after a confirmation)
|
|
66
|
+
takes the work as it is, then runs its checks and review: offered when the agent stopped at
|
|
67
|
+
a limit (Retry gives it the same limit again) or without a summary, and when its agent is at
|
|
68
|
+
rest while the row stays on "Finishing". A setup failure offers **Start again**:
|
|
69
|
+
herdr-projects uses `delegate` before an agent has started. With no conversation, the panel
|
|
70
|
+
keeps the explanation visible instead of opening a bare shell; Terminal stays reachable
|
|
71
|
+
when a pane exists. Read-only and unreachable machines cannot run banner actions.
|
|
72
|
+
- **A task's sheet**, from the panel's **…** button, has the same details and actions as
|
|
73
|
+
the Task tab. **Open the chat** closes it and opens the conversation. When the agent has
|
|
74
|
+
no pane, a field sends a reply through herdr-projects (`tell`; on a waiting plan, it sends
|
|
75
|
+
the plan back).
|
|
76
|
+
**Approve** merges finished work or says yes to a plan, after a confirmation; **Start**,
|
|
77
|
+
**Stop**, **Retry**, **Finish** and **Archive** where herdr-projects takes them. **Start** names the agent
|
|
78
|
+
the task starts with by default (its `worker.agent` and where that comes from) and offers the
|
|
79
|
+
other agents installed on its machine: one picked there is for this start only
|
|
80
|
+
(`delegate --worker.agent`). herdr-projects keeps that pick as the task's own setting while
|
|
81
|
+
its run lasts; wherdr puts back what the task had once the run is over (back in To do, or
|
|
82
|
+
done) and before its next Start, so its default, the repo's and your own settings stay as they
|
|
83
|
+
are (`data/start-agents.json` remembers what to put back). A default agent not installed on that
|
|
84
|
+
machine is shown but cannot be picked: Start then waits for an installed one. With every slot of
|
|
85
|
+
the board taken (`board.agents` tasks at work), **Start** says **Queue** and the place the task
|
|
86
|
+
would get (`delegate` queues it). **Start after…** picks tasks to wait for, by key, id or title, on
|
|
87
|
+
every machine the Board reads (another machine's as `machine:KEY-12`): `delegate --after`. A task
|
|
88
|
+
that waits names them, with **Stop waiting** (`after --clear`); one in the queue says its place.
|
|
89
|
+
herdr-projects' refusals (a circle, an unknown task, a machine that does not answer) are shown as
|
|
90
|
+
they are. After an action the sheet
|
|
91
|
+
shows the task's new state, or why it was refused. **Archive** closes the sheet and takes the
|
|
92
|
+
task off the Board, with **Restore** in a toast for a few seconds; **Archived** lists the
|
|
93
|
+
archived tasks, whose sheet is read-only with **Restore**, as in herdr-projects.
|
|
94
|
+
- **Coordinators**, in the same panel: a machine's heading opens its Coordinator, the agent that
|
|
95
|
+
turns what you write into tasks; a repo's heading opens that repo's project coordinator. One
|
|
96
|
+
not started yet takes a first message (`coordinator tell`), which starts it. One that
|
|
97
|
+
herdr-projects could not start (an agent not installed there…) says why, with **Try again**
|
|
98
|
+
(`coordinator restart`) once it is fixed: the message still waiting then goes in.
|
|
99
|
+
- **Autopilot** (herdr-projects 1.2.15 or later): each coordinator has a switch, under the Board's
|
|
100
|
+
bar for the main Coordinator, in each machine and repo heading, and at the top of its panel. It
|
|
101
|
+
shows whether the board wakes that coordinator to work toward its goal, and when next. Turning it
|
|
102
|
+
on asks for the goal (filled in with the saved one, required otherwise) and, optionally, how often
|
|
103
|
+
and how many tasks a day or at once, for this time only (`herdr-projects autopilot on --goal …
|
|
104
|
+
[--machine | --project <repo>]`); stopping asks first (`autopilot off`). The state shown is read
|
|
105
|
+
back from `herdr-projects autopilot --json` after each action; a refusal (no goal, older version)
|
|
106
|
+
is shown as the board says it.
|
|
107
|
+
- **Task identity** stays with the worker on the home list, Board card and conversation header.
|
|
108
|
+
During a review, **Reviewed by** names the reviewer beside its own small logo. The conversation
|
|
109
|
+
explains that it belongs to the worker and the review runs separately; **Open reviewer terminal**
|
|
110
|
+
opens the reviewer's terminal when reachable, or a session switch is offered when it runs in
|
|
111
|
+
another open session. After a worker fallback, the main logo names the current worker and
|
|
112
|
+
**Took over from** names the previous one from the recorded handover.
|
|
113
|
+
- **The agent list** groups the board's spaces under their repo, as Herdr's sidebar does: each
|
|
114
|
+
machine's Coordinator and machine coordinator first, each with its own icon and the Board's name (**Coordinator** with
|
|
115
|
+
the board's icon, **`<machine>` coordinator** with the machine's), then per repo a head row, its project
|
|
116
|
+
coordinator (named after the repo, the wherdr mark on the accent, **Coordinator**, its state; its
|
|
117
|
+
question and one-tap answers when it asks one), a bar under it (fold, the tasks' summary such as `4 TASKS · 1 YOUR TURN ·
|
|
118
|
+
1 LIMIT`, branch and commits behind its upstream, and the repo space's **…** menu, which opens
|
|
119
|
+
its terminal), and its tasks' spaces, indented and folding with the bar (key, title, state,
|
|
120
|
+
progress, time on it, the line the board reports; the Board icon opens the task there). One
|
|
121
|
+
row per task: its reviewer, planner and attempts, each in a tab of the task's space, are part
|
|
122
|
+
of it; in normal mode the row says the stage (**Under review · codex**), and both modes
|
|
123
|
+
open the task panel while a review runs. The counters count tasks, not tabs. A repo
|
|
124
|
+
coordinated from another machine shows **Coordinated from <machine>** above the bar instead
|
|
125
|
+
of a local coordinator. Without either coordinator, the bar is the first row; the repo's plain
|
|
126
|
+
terminal stays accessible through its **…** menu. wherdr reads this from
|
|
127
|
+
the board's files (`~/.herdr-projects/data`: tasks, attempts, reviewers, coordinators, repos)
|
|
128
|
+
and from Herdr's worktree groups, every 15 seconds while the list is shown, never through
|
|
129
|
+
herdr-projects' command line; the branch and behind count come from `git` in the repo's main
|
|
130
|
+
checkout, once a minute, without fetching.
|
|
131
|
+
- **Scheduled** (FR **Programmé**), collapsed in every coordinator panel: its Autopilot
|
|
132
|
+
status, wake frequency, goal and daily limits; board automations for that project
|
|
133
|
+
(including events across all repos), their latest firings and links to created tasks;
|
|
134
|
+
and Claude Code session timers reconstructed from successful transcript tool calls.
|
|
135
|
+
Open the section to read it; refreshing the Board refreshes an open section. It is
|
|
136
|
+
read only. Dates use the coordinator machine's time zone. Session timers disappear
|
|
137
|
+
when deleted, after a one-shot fires, or after seven days; they are lost when the
|
|
138
|
+
Claude Code session closes. An unavailable source is shown explicitly rather than
|
|
139
|
+
presented as an empty schedule.
|
|
140
|
+
- **Coordinator entry points**, named as herdr-projects names them, one name per level on the
|
|
141
|
+
Board, the home list, the conversation header and the menus: the top of the Board offers the
|
|
142
|
+
main **Coordinator** (FR **Coordinateur**), for all repos and machines it can reach. With
|
|
143
|
+
several hosts, its menu lists them by name; unavailable and read-only hosts stay listed with
|
|
144
|
+
their reason. Machine headings offer **`<machine> coordinator`** (FR **Coordinateur ·
|
|
145
|
+
`<machine>`**: the machine as a whole, its repos and folders, its tasks and agents), repo
|
|
146
|
+
headings offer **`<repo> coordinator`** (FR **Coordinateur · `<dépôt>`**: work in that repo). Hover or long-press an entry for its role;
|
|
147
|
+
the conversation header repeats that description.
|
|
148
|
+
- **A machine is one board**, shared by its named sessions: one list, one queue, one card per
|
|
149
|
+
task. A machine whose read fails says why on the Board, and its last tasks stay, marked with
|
|
150
|
+
the time they were read.
|
|
151
|
+
- What wherdr runs, on the task's machine and in its Herdr session (on an SSH machine, its own
|
|
152
|
+
session by name): `herdr-projects list --json`,
|
|
153
|
+
`details <id> --json`, `show <id> --json`, `set`/`unset worker.agent --task <id>` (to put back a pick), `tell <id> <text>`, `approve <id>`, `delegate` (with `--after`), `after <id> --clear`, `stop`, `retry`,
|
|
154
|
+
`archive` and `restore <id>`, `list --json --archived` (Archived), `coordinator tell <text>`,
|
|
155
|
+
`coordinator status --json` and `coordinator restart` (your
|
|
156
|
+
words always after `--`, so they are never read as options), through the plugin's own
|
|
157
|
+
launcher (`bin/run.sh`). Each command also runs herdr-projects' own upkeep, so wherdr calls it
|
|
158
|
+
sparingly: one command at a time per machine, a read every 15 seconds and only while the Board
|
|
159
|
+
is open (a list less than 5 seconds old is reused), and the last list kept when a machine is
|
|
160
|
+
slow or unreachable. Nothing runs where herdr-projects is missing or older than 1.2.1: its first
|
|
161
|
+
run would take over an older install's files.
|
|
162
|
+
- **Agents in user folders**: wherdr runs herdr-projects with your [PATH](installation.md#agent-path), on this
|
|
163
|
+
machine and over SSH, so `claude is not installed here` does not come from a login service's
|
|
164
|
+
short `PATH`.
|
package/docs/command.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# The wherdr command
|
|
2
|
+
|
|
3
|
+
[Documentation](README.md) · [Project](../README.md)
|
|
4
|
+
|
|
5
|
+
### The `wherdr` command
|
|
6
|
+
|
|
7
|
+
An alternative to [the one command](installation.md#the-one-command), from npm or Homebrew: the same app, without
|
|
8
|
+
the Herdr plugin. npm can hold a new release for up to two days (moderation), so these get updates
|
|
9
|
+
later than the installer, which downloads the GitHub release package. The npm package holds the
|
|
10
|
+
built app: nothing is compiled on your machine. Try it with `npx wherdr` (or `bunx wherdr`,
|
|
11
|
+
`pnpm dlx wherdr`); to keep it, install it once:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm install -g wherdr # or: pnpm add -g wherdr, bun add -g wherdr
|
|
15
|
+
wherdr service install # configures automatic startup; prints the address
|
|
16
|
+
wherdr phone # phone state, the app's phone setup page, QR code once it answers
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
| Command | What it does |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| `wherdr` (or `wherdr run`) | Runs in the foreground; Ctrl+C stops it. |
|
|
22
|
+
| `wherdr start` · `stop` · `restart` | Background server, pid and log in `~/wherdr`. `start` says *started* only once the port answers; otherwise it prints the end of the log. With a login service installed, they drive the service. |
|
|
23
|
+
| `wherdr status` | Address, process, service, data folder and log. |
|
|
24
|
+
| `wherdr logs` (`-f` to follow, `-n 100`) | The log, `~/wherdr/wherdr.log`. |
|
|
25
|
+
| `wherdr open` | Opens wherdr in the browser: its tailnet address when published and answering, else `localhost`. |
|
|
26
|
+
| `wherdr phone` | Whether your phone can reach wherdr (Tailscale, `tailscale serve`, the address answering), the `tailscale serve` command to publish it when it is not (wherdr then enables the address by itself), the link to **Settings › Phone**, and the QR code once the address answers. |
|
|
27
|
+
| `wherdr service install` · `uninstall` | Configure automatic startup: a LaunchAgent on macOS (`~/Library/LaunchAgents/dev.wherdr.plist`) starts at login; a `systemd --user` unit on Linux starts at boot with lingering enabled, otherwise at login. The command tries to enable lingering (`loginctl enable-linger`, without sudo; when your system refuses it, the command to run is printed) so it keeps running while you are logged out; without lingering it stops after logout. The service gets your [PATH](installation.md#agent-path). The one command and key **A** of the plugin's panel run it too. |
|
|
28
|
+
| `wherdr doctor` | Checks Node/Bun, Herdr and its socket, the port, the service, the data folder and `APP_URL`. |
|
|
29
|
+
|
|
30
|
+
Options: `--port` (default `7683`), `--host` (default `127.0.0.1`; loopback or this machine's
|
|
31
|
+
tailnet address, anything else is [refused](security.md#network-access) unless `WHERDR_TRUSTED_NETWORKS` names it),
|
|
32
|
+
`--data-dir` (passkeys, push keys and settings; default `~/wherdr/data`, the folder the Herdr
|
|
33
|
+
plugin and the install script use), `--session` (a named Herdr session). Every
|
|
34
|
+
[environment variable](configuration.md#configuration) works too, and so do `KEY=VALUE` lines in
|
|
35
|
+
`~/wherdr/wherdr.env` (for example `APP_URL=…`, read at each start); options win, then the
|
|
36
|
+
environment, then that file. `start` and `service install` remember the port and folders for
|
|
37
|
+
the other commands.
|
|
38
|
+
|
|
39
|
+
**Homebrew:** `brew install afloury/tap/wherdr` installs the same package; the first install also
|
|
40
|
+
brings Homebrew's Node.js (heavier than the Herdr plugin when Node.js 22 is already there). Then:
|
|
41
|
+
|
|
42
|
+
1. `brew services start wherdr`: runs `wherdr run` now and at every login, log in
|
|
43
|
+
`$(brew --prefix)/var/log/wherdr.log` (`wherdr logs` reads it).
|
|
44
|
+
2. `wherdr open`: the setup guide in your browser.
|
|
45
|
+
3. Its Phone step (or `wherdr phone`).
|
|
46
|
+
|
|
47
|
+
On a Homebrew install, `wherdr start`, `stop`, `restart` and `service install` point to
|
|
48
|
+
`brew services` (the installed path changes at each upgrade); `wherdr status` and `wherdr doctor`
|
|
49
|
+
show the Homebrew service. Update: `brew upgrade wherdr && brew services restart wherdr`.
|
|
50
|
+
|
|
51
|
+
The login service records the **absolute path** of the runtime (n, nvm, fnm, Volta or Homebrew
|
|
52
|
+
node) and your [PATH](installation.md#agent-path), since launchd and systemd do not see your shell's. It refuses to point at a
|
|
53
|
+
temporary `npx` / `pnpm dlx` / `bunx` folder: install the package globally first. To update:
|
|
54
|
+
`npm install -g wherdr@latest && wherdr restart` (with `npx`: stop it, then `npx wherdr@latest`).
|
|
55
|
+
|
|
56
|
+
Bun runs wherdr too (WebSockets, push, passkeys and Herdr's socket work); when Node.js 22 is
|
|
57
|
+
also installed, `bunx wherdr` hands the server to Node, the reference runtime. Set
|
|
58
|
+
`WHERDR_RUNTIME=bun` to keep Bun.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Settings and configuration
|
|
2
|
+
|
|
3
|
+
[Documentation](README.md) · [Project](../README.md)
|
|
4
|
+
|
|
5
|
+
- **Themes**: wherdr Titanium (default), herdr.dev and Herdr's built-in themes, or follow your Herdr theme.
|
|
6
|
+
**English and French** interface.
|
|
7
|
+
|
|
8
|
+
## Configuration
|
|
9
|
+
|
|
10
|
+
All settings are environment variables: `KEY=VALUE` lines in `~/wherdr/wherdr.env` for the
|
|
11
|
+
native service (read at each start: `wherdr restart`, or **R** in the panel).
|
|
12
|
+
|
|
13
|
+
| Variable | Default | Meaning |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `PORT` | `7683` | Listening port. |
|
|
16
|
+
| `HOST` | `127.0.0.1` (`npm start`) | Listening address: loopback, or this machine's tailnet address (`tailscale ip`, with Tailscale running). Any other address (`0.0.0.0`, a LAN address) stops wherdr at startup unless `WHERDR_TRUSTED_NETWORKS` covers it. |
|
|
17
|
+
| `WHERDR_TRUSTED_NETWORKS` | *(empty)* | Other private networks wherdr accepts besides this computer and the tailnet, as comma-separated CIDR ranges or addresses (e.g. `10.147.17.0/24` for ZeroTier). `any` accepts every network, with a warning at startup and in the app: not recommended. See [Network access](security.md#network-access). |
|
|
18
|
+
| `HOST_LABEL` | server hostname | Name of this machine in the app (can be renamed in the app). |
|
|
19
|
+
| `APP_URL` | *(empty)* | App address and allowed host; a valid HTTPS URL enables Web Push. HTTP, empty or invalid values disable Web Push with a warning. With Tailscale, leave it empty: wherdr adopts the address `tailscale serve` publishes. |
|
|
20
|
+
| `TAILNET_REFRESH_MS` | `30000` | How often wherdr reads again what `tailscale serve` publishes for its port. |
|
|
21
|
+
| `HERDR_WEB_ALLOWED_HOSTS` | *(empty)* | Additional hostnames or IP addresses allowed to open the app, comma-separated. |
|
|
22
|
+
| `PASSKEY_USER` | `wherdr` | User name stored with the passkeys. |
|
|
23
|
+
| `DATA_DIR` | `./data` | VAPID keys, push subscriptions, passkeys, recent folders, and `settings.json`: the display settings that follow you across devices (theme, machine bar and groups, home list, Board and file browser preferences). Screen-dependent ones (content width, sidebar width, terminal size and rendering), the language, the last tab or filter and drafts stay in each browser. |
|
|
24
|
+
| `HERDR_BIN` | `~/.local/bin/herdr`, else `herdr` in `PATH` | Herdr binary. |
|
|
25
|
+
| `HERDR_WEB_SESSION` | *(default session)* | Named Herdr session to drive. Not `HERDR_SESSION`, which Herdr reads itself. |
|
|
26
|
+
| `HERDR_PROJECTS_DATA_DIR` | `~/.herdr-projects/data` | herdr-projects' data folder, where wherdr reads the `PATH` it recorded ([Agent PATH](installation.md#agent-path)). |
|
|
27
|
+
| `AGENT_KINDS` | all known agents | Agents offered in **New** (only installed ones are shown). |
|
|
28
|
+
| `HERDR_WEB_MACHINES` | `on` | `off` to ignore the SSH machines registered in Herdr. |
|
|
29
|
+
| `HERDR_WEB_SELF_HOSTS` | | Other names / IPs of this machine, comma-separated (profiles pointing to it are ignored). |
|
|
30
|
+
| `HERDR_WEB_REMOTE_SESSION` | | Herdr session to use on every remote machine instead of the profile's. |
|
|
31
|
+
| `HERDR_WEB_HERDR_NOTIFICATIONS` | `on` | `off` to stop relaying `herdr notification show` as push. |
|
|
32
|
+
| `UPLOAD_DIR` | `~/.cache/herdr-web/uploads` | Where photos sent to agents are stored (deleted after 7 days). |
|
|
33
|
+
| `ATTACH_DIR` | `~/.cache/herdr-web/files` | Where other files attached to messages are stored, on the agent's machine (mode 600, deleted after 7 days). |
|
|
34
|
+
| `TZ` | `UTC` | Time zone. |
|
|
35
|
+
|
|
36
|
+
In the app, **Settings** holds display preferences such as theme, typing effect and what the
|
|
37
|
+
home screen shows; these follow you across devices through `settings.json`. Language,
|
|
38
|
+
notifications, terminal text size and renderer remain device-specific. The passkey lock is
|
|
39
|
+
managed under Settings › Security.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Conversation and replies
|
|
2
|
+
|
|
3
|
+
[Documentation](README.md) · [Project](../README.md)
|
|
4
|
+
|
|
5
|
+
- **Conversation view**: the agent's real transcript (Claude Code, Codex and omp), rendered as
|
|
6
|
+
Markdown, with grouped tool calls, images (full-screen viewer with pinch / wheel zoom and pan), timestamps, search and infinite scroll back to the
|
|
7
|
+
first message. Reading a conversation never touches the terminal, so it never resizes a pane.
|
|
8
|
+
A command the agent proposes (shell code block, or inline `! command`) can be copied without
|
|
9
|
+
its prompt, or run in the agent's shell mode (`!`, Claude Code, Codex and omp) after you
|
|
10
|
+
confirm the full command.
|
|
11
|
+
- **Interactive agent screens**: in a conversation, an uncertain menu or panel opens the
|
|
12
|
+
pane's real terminal in a modal window, with arrows, Enter, Escape, Tab, digits and y/n.
|
|
13
|
+
The rest of the app waits behind a scrim (the window fills the screen on a phone); in a
|
|
14
|
+
split, only the cell in use opens it. It closes after the agent's message field returns.
|
|
15
|
+
Close it yourself at any time with its button or a click on the scrim: that releases the
|
|
16
|
+
terminal without pressing Escape, which goes to the agent, and the same interaction stays
|
|
17
|
+
closed until you reopen it. Existing native questions, approvals, menus, waiting screens and
|
|
18
|
+
Claude settings cards keep their controls. The window is a fallback after those
|
|
19
|
+
recognizers, with two explicit exceptions: Codex's two-column `/usage` menu and
|
|
20
|
+
its Agent Command Center. The slash menu still lists and sends commands. On a phone, the window
|
|
21
|
+
temporarily fits the real pane to its width and restores its size on release, using
|
|
22
|
+
the same lease as Terminal view; it does not shrink 120 columns into unreadable text.
|
|
23
|
+
A pane already shown in Terminal keeps its existing live view. Try `/usage` on the
|
|
24
|
+
Codex agent in the browser demo (scripted, no account data).
|
|
25
|
+
In the compact list, native questions keep their preview and one-tap answers.
|
|
26
|
+
Unrecognized blocking screens offer an **Open interactive terminal** button.
|
|
27
|
+
- **Composer**: send messages while the agent works (queued, cancellable: the agent's own
|
|
28
|
+
queue when it takes them, else held by wherdr and sent when the turn ends; never left
|
|
29
|
+
half-typed in its field; a message pulled back out of Claude's queue before it read it, or not seen after an hour, is
|
|
30
|
+
marked “Not sent” with Retry / Cancel, and “Not sent” clears once the message shows in its transcript), attach or paste
|
|
31
|
+
photos and the files the agent can read (Claude Code: PDFs, notebooks, text and code of any
|
|
32
|
+
extension; Codex: notebooks, text and code), run slash commands (`/compact`, `/clear`, `/context`, `/usage`…) and see the output
|
|
33
|
+
of local commands. Stop button while the agent works. When Claude Code suggests a reply
|
|
34
|
+
(grayed-out in the empty field), `Tab` takes it on a computer and **Use**, inside the field on
|
|
35
|
+
its right, on a phone: the field gets the text, to edit or send. A long pasted text (log, output) becomes
|
|
36
|
+
a "Pasted text · N lines" card, sent to the agent as it is and shown the same way in the
|
|
37
|
+
conversation, where it opens in full with Copy; long typed messages fold with Show more.
|
|
38
|
+
The draft (text, quotes, attachments) is kept per agent, across reloads: when Herdr closes a
|
|
39
|
+
pane and opens a new one for the same agent (the same conversation, or the same herdr-projects
|
|
40
|
+
coordinator or task, as after `coordinator restart`), the view moves to the new pane and the
|
|
41
|
+
draft comes along. A pane closed for good keeps it under its banner, with **Copy draft**.
|
|
42
|
+
- **Model and effort pickers** for Claude Code, Codex and omp (omp: its
|
|
43
|
+
"Switch Model" selector, `/switch` or `/model`, and its thinking level, changed with its own
|
|
44
|
+
⇧⇥ cycle). Changes apply **to the current session only**; wherdr never changes your default
|
|
45
|
+
model.
|
|
46
|
+
**Settings › Conversation › Reply style** chooses how an agent's reply offers to be quoted in
|
|
47
|
+
the field, question by question and point by point (a list item or a paragraph that asks
|
|
48
|
+
nothing), so that one message answers them all:
|
|
49
|
+
|
|
50
|
+
| Style | A question | A point |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| **Icon** (default) | A small `↳` after it, in the middle or at the end of the message. | A grey `↳` at its end: on hover on a computer, always there and pale on a phone. |
|
|
53
|
+
| **Tap the text** | No button: the question is underlined, tap or click it. | Click it on a computer. On a phone, tap it, then **↳ Discuss**: a single tap never quotes, so reading, scrolling and selecting text stay as they are. |
|
|
54
|
+
| **List under the message** | A number after it, and the questions listed under the message. | **+ Quote a point** under the message, then the point. Offered when the reply has a list item to quote, or two points or more: not under one paragraph of prose. |
|
|
55
|
+
|
|
56
|
+
Every one of these is a button reachable with the keyboard (`Tab`, then `Enter`), and selecting a
|
|
57
|
+
passage still offers **Reply** on it. A quoted question or point shows `✓`.
|
|
58
|
+
|
|
59
|
+
**One syntax for every reference.** Whatever you reply to, the field gets one line that names it,
|
|
60
|
+
and your answer goes on the lines below:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
↳ Quote message 11:37 ~k3f : I can merge the PR —
|
|
64
|
+
Go ahead.
|
|
65
|
+
↳ Quote point 11:37 ~k3f : Shall I tag the release today? —
|
|
66
|
+
Yes
|
|
67
|
+
↳ Quote decision 11:37 #3 ~k3f : Publish the release notes on the site? —
|
|
68
|
+
No
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
| Line | Written by |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| `↳ Quote message <time> ~<code> : <start of the message> —` | **Reply** under an agent message. |
|
|
74
|
+
| `↳ Quote point <time> ~<code> : <excerpt> —` | `↳` on a question or a point, **Reply** on a selected passage. |
|
|
75
|
+
| `↳ Quote decision <time> #<n> ~<code> : <question> —` | **Yes**, **No** or `↳` on a row of a decision table. |
|
|
76
|
+
| `↳ Quote decisions <time> #<rows> ~<code> : <questions> —` | **OK to all** on a decision table. |
|
|
77
|
+
|
|
78
|
+
- The time is the one shown on the agent's message, so an answer to an earlier message is never
|
|
79
|
+
read as an answer to the last one. The types are the same words in every language.
|
|
80
|
+
- The code after `~` is three characters wherdr derives from the message (and the rank of the
|
|
81
|
+
table, from the second table of a message on). It tells apart two messages of the same minute
|
|
82
|
+
and two tables of one message, whatever the excerpt shows. The field draws it dimmed, like
|
|
83
|
+
the words before the excerpt; the quote of a sent message leaves it out. The rows of **OK to
|
|
84
|
+
all** are the numbers the table really has: `#1-4`, or `#1,4` when rows 2 and 3 do not exist.
|
|
85
|
+
- A reference is a whole line: it starts with `↳` in the first column and ends with ` —` at the
|
|
86
|
+
end of the line, and only there, so an excerpt may hold dashes of its own. The excerpt is plain
|
|
87
|
+
text on one line; a long one is cut with `…` (a message keeps its start, a passage its start
|
|
88
|
+
and its end).
|
|
89
|
+
- Several references fit in one message, each followed by its answer.
|
|
90
|
+
- Anything else is your own text: a `>` at the start of a line, a `↳` line of an unknown type or
|
|
91
|
+
with words after its dash. Text you paste never becomes a reference either: a pasted line that
|
|
92
|
+
reads like one gets a `\` before its `↳`. A long paste, shown as a **Pasted text** card, is
|
|
93
|
+
sent exactly as it was pasted.
|
|
94
|
+
- In the conversation, each reference of a sent message shows as a quote; tap it to see the
|
|
95
|
+
message it names. Messages sent earlier with `> ` lines still show as quotes.
|
|
96
|
+
|
|
97
|
+
**Settings › Conversation › Quoted replies** chooses how the field shows these lines: **Tokens,
|
|
98
|
+
native field** (default) draws each one as a token in the usual field, **Plain text** shows the
|
|
99
|
+
same lines as text, a fallback if the tokens misbehave. The message sent is the same.
|
|
100
|
+
|
|
101
|
+
A **closed question**, one that yes or no answers in full, also gets **Yes** and **No** next to
|
|
102
|
+
its `↳` (at the end of its row in the list style). A tap refers to the question and writes the
|
|
103
|
+
answer under it, in the language of the interface, exactly as Reply and typing would; nothing is sent, so several questions can be
|
|
104
|
+
answered in a row before sending. On a computer a click hands the field the focus, the caret
|
|
105
|
+
right after the answer, so Enter sends it at once; the keyboard stays down on a phone, and a
|
|
106
|
+
button pressed with the keyboard keeps the focus. Tapping the other answer
|
|
107
|
+
replaces the first; words you typed under a quote are never replaced. The rule is cautious, and
|
|
108
|
+
in doubt only Reply is offered: a single sentence that opens like a yes/no question (`Shall I…`,
|
|
109
|
+
`Do you…`, `Is it…`, `Want me to…`, `Est-ce que…`, `Je lance… ?`, `On…`, `Dois-je…`) or ends
|
|
110
|
+
with `, OK?` / `, d'accord ?`, with no alternative (`or`, `ou`), no interrogative word (`which`,
|
|
111
|
+
`how`, `quel`, `comment`…) and no negation.
|
|
112
|
+
|
|
113
|
+
A **decision table**, a Markdown table whose rows are numbered questions as a coordinator writes
|
|
114
|
+
them, gets a panel right under it: **OK to all** refers to the whole table and writes `OK to all`
|
|
115
|
+
under it (a second tap takes it back), and each row has **Yes**, **No** and `↳`, which refer to
|
|
116
|
+
the row by its number and write `Yes` or `No` under it, or nothing for an answer in words; a row
|
|
117
|
+
that asks an open question has `↳` alone. Every answer names the message and the row, even for
|
|
118
|
+
the last message: the agent may write another one before you send. In French: `OK tout`, `Oui`,
|
|
119
|
+
`Non`. Here too everything is composed in the field and you send; on a computer the field takes the focus
|
|
120
|
+
after a click, so Enter sends. A table qualifies when it has a
|
|
121
|
+
number column (a header `#`, `N°`, `No`, `Num`, `ID` or `Q` over short numbers, each once) and a
|
|
122
|
+
question column, known by its header (`Question`, `Decision`, `Choix`…), by cells that all end
|
|
123
|
+
with `?`, or by an advice column next to it (`Avis`, `Recommendation`, `Suggestion`…). Any other
|
|
124
|
+
table is left as it is.
|
|
125
|
+
|
|
126
|
+
Above the field, **N questions unanswered** counts the questions of the agent's last message
|
|
127
|
+
(and the rows of its decision tables) that your draft does not answer yet; tap it to scroll to
|
|
128
|
+
the first one. A question counts once it is quoted, a row once it is answered, quoted or covered
|
|
129
|
+
by **OK to all**; when the message asks one thing only, any words you type answer it. The line
|
|
130
|
+
goes when everything is answered and when you send, and it never shows for earlier messages,
|
|
131
|
+
while the agent is working, or while it waits on a prompt. It hangs from the top edge of the
|
|
132
|
+
field, so nothing moves when it comes or goes.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Development and tests
|
|
2
|
+
|
|
3
|
+
[Documentation](README.md) · [Project](../README.md)
|
|
4
|
+
|
|
5
|
+
### From source
|
|
6
|
+
|
|
7
|
+
For development, or to run a checkout of your own. With Herdr running, Git and Node.js 22 on the same machine:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
git clone https://github.com/afloury/wherdr.git
|
|
11
|
+
cd wherdr
|
|
12
|
+
npm ci
|
|
13
|
+
npm run build
|
|
14
|
+
npm start # listens on 127.0.0.1:7683
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Open `http://localhost:7683` in a browser on that computer: the desktop layout, passkeys and the
|
|
18
|
+
installable app work there, since browsers treat `localhost` as secure. There is no phone access
|
|
19
|
+
and no push notification in this setup; for that, use the [recommended setup](networks.md#recommended-always-on-server--tailscale) (or publish this
|
|
20
|
+
instance with `tailscale serve` as described there and start it with
|
|
21
|
+
`APP_URL=https://server.example.ts.net:7683/ npm start`).
|
|
22
|
+
|
|
23
|
+
Run it as the user who runs Herdr. It uses `$HOME` and `$HOME/.local/bin/herdr`, or `herdr` from
|
|
24
|
+
the `PATH` (Homebrew); set `HERDR_BIN` otherwise. `DATA_DIR` holds passkeys, push data and recent
|
|
25
|
+
folders (default `./data`). `npm start` listens on `127.0.0.1` (`HOST`) and port `7683` (`PORT`).
|
|
26
|
+
The first-passkey bootstrap token is printed in its output. Keep the process running with your
|
|
27
|
+
usual service manager (systemd user unit, launchd, tmux…).
|
|
28
|
+
|
|
29
|
+
With `APP_URL` empty or `http://localhost:7683/`, wherdr starts normally but disables Web Push
|
|
30
|
+
and logs a warning.
|
|
31
|
+
|
|
32
|
+
## Contributing
|
|
33
|
+
|
|
34
|
+
See [CONTRIBUTING.md](../CONTRIBUTING.md), including the [agent test rule](../CONTRIBUTING.md#agent-test-rule)
|
|
35
|
+
and `npm run test:affected -- --base origin/v2 --dry-run`. Changes are listed in [CHANGELOG.md](../CHANGELOG.md).
|
|
36
|
+
|
|
37
|
+
Every commit is public: a leak check (gitleaks plus your own forbidden patterns) covers the files
|
|
38
|
+
and the commits about to be pushed; see [Leak check](../CONTRIBUTING.md#leak-check).
|