hey watch --notify: the engine under the Omarchy bar plugin, in place of hey omarchy - #243
Conversation
There was a problem hiding this comment.
Pull request overview
Replaces the unreleased Omarchy poller with generic, event-driven notifications and improves long-running cable authentication.
Changes:
- Adds
hey watch --notifywith tests and documentation. - Refreshes cable credentials on every reconnect.
- Migrates Omarchy setup to configure the external bar plugin and removes legacy polling code.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
.surface |
Adds the watch --notify surface. |
README.md |
Documents notifications and the Omarchy plugin. |
docs/omarchy.md |
Describes the watch-driven plugin architecture. |
skills/hey/SKILL.md |
Adds agent guidance for --notify. |
internal/cable/cable.go |
Refreshes credentials per cable dial. |
internal/cable/cable_test.go |
Tests refreshed reconnect headers. |
internal/cmd/accounts_test.go |
Removes obsolete Omarchy command coverage. |
internal/cmd/local_config_trust.go |
Removes the deleted command’s exemption. |
internal/cmd/omarchy.go |
Configures and migrates the bar plugin. |
internal/cmd/omarchy_notify.go |
Removes poll-based notification state. |
internal/cmd/omarchy_notify_test.go |
Removes obsolete poll-notification tests. |
internal/cmd/omarchy_test.go |
Tests plugin configuration and migration. |
internal/cmd/root.go |
Removes the hey omarchy command group. |
internal/cmd/watch.go |
Integrates desktop notification batching. |
internal/cmd/watch_notify.go |
Implements desktop notification behavior. |
internal/cmd/watch_notify_test.go |
Tests notification filtering and delivery. |
tests/smoke/helpers_test.go |
Isolates smoke-test state storage. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a7699345b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d5b291e322
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
monorkin
left a comment
There was a problem hiding this comment.
Great fixes!
Can we replace the --notify with a --run-async? It looks like it just shells out and the run commands are exactly for that.
Then we could make the box filter generic.
|
🤖 @monorkin — you were right, and zooming out made it clearer why.
My defence was about the first row; your question was about the second. So 881aa9e splits them rather than sugaring one over the other:
Docs ( |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 30dfcab431
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Stanko asked on #243 whether --notify could just be --run-async. It couldn't, and the reason it couldn't is the tell: the flag bundled two things. What counts as new mail — unseen, not muted, active_at later than the watch's record of the thread or than its start on HEY's clock, remembered across every box so a move-in isn't new — is HEY's semantics and state across events, and belongs in the CLI, decided once and Go-tested. notify-send, the app-name, -p/-r, the Omarchy glyph and exec hints, `Sender — Subject`, one toast per read and the Imbox-only scope are presentation, a desktop's business, and belonged in the plugin that already owns rendering and settings. So the CLI grows a generic, scriptable notion of new mail and loses the desktop: every added and updated line carries "new": true|false, --events new selects the true ones (a union with added, updated and deleted), a --run-* script sees HEY_NEW=1, and `hey watch --box imbox --events new --exit-on-first` is "block until new mail". The tracker always runs — one cheap serverNow GET at startup, one map — so the line shape is stable, and a read is classified before it is recorded, as before. --notify, --notify-box, desktopNotifier and notifiedBoxes are gone; neither flag was released, so .surface-breaking needs no entry. The Omarchy plugin toasts from the new lines itself (basecamp/omarchy-hey-plugin#3). Docs follow: docs/omarchy.md's "hey watch --notify" becomes "New mail is a watch event" and "The plugin toasts", the decision record tightens to "Generic commands; the face presents", README and the skill lead with --events new, and `hey setup omarchy --notify` says it turns on the plugin's toasts rather than running hey watch --notify.
…new-mail cutoff Two Codex threads on #243. A catch-up read that failed transiently left the box queued for a retry and returned nil, so ready was announced with a box still behind it — a reader then took the gap for a clean picture. catchUp now announces ready only once every box is read (readyOnceCaughtUp); a retry that reads the last box owed announces it (retryUnread), and a drop in between cancels the debt, since the reconnect's catch-up announces its own. A 409 skipped a box ahead without the new-mail record learning anything about the gap, so a thread that arrived in it and was later moved or labelled while still unseen measured its gap activity against the watch's start and read as new. skippedTo moves that box's cutoff up to the cursor it skipped to — HEY's last_posting_activity_at for the box, which bounds every thread in it — and the cutoff is the box's alone, so another box's mail is unaffected. A gap thread moved to another box may still read as new once; the resync line is the reader's cue to re-read either way.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a5183a5ede
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Stanko asked on #243 whether --notify could just be --run-async. It couldn't, and the reason it couldn't is the tell: the flag bundled two things. What counts as new mail — unseen, not muted, active_at later than the watch's record of the thread or than its start on HEY's clock, remembered across every box so a move-in isn't new — is HEY's semantics and state across events, and belongs in the CLI, decided once and Go-tested. notify-send, the app-name, -p/-r, the Omarchy glyph and exec hints, `Sender — Subject`, one toast per read and the Imbox-only scope are presentation, a desktop's business, and belonged in the plugin that already owns rendering and settings. So the CLI grows a generic, scriptable notion of new mail and loses the desktop: every added and updated line carries "new": true|false, --events new selects the true ones (a union with added, updated and deleted), a --run-* script sees HEY_NEW=1, and `hey watch --box imbox --events new --exit-on-first` is "block until new mail". The tracker always runs — one cheap serverNow GET at startup, one map — so the line shape is stable, and a read is classified before it is recorded, as before. --notify, --notify-box, desktopNotifier and notifiedBoxes are gone; neither flag was released, so .surface-breaking needs no entry. The Omarchy plugin toasts from the new lines itself (basecamp/omarchy-hey-plugin#3). Docs follow: docs/omarchy.md's "hey watch --notify" becomes "New mail is a watch event" and "The plugin toasts", the decision record tightens to "Generic commands; the face presents", README and the skill lead with --events new, and `hey setup omarchy --notify` says it turns on the plugin's toasts rather than running hey watch --notify.
…new-mail cutoff Two Codex threads on #243. A catch-up read that failed transiently left the box queued for a retry and returned nil, so ready was announced with a box still behind it — a reader then took the gap for a clean picture. catchUp now announces ready only once every box is read (readyOnceCaughtUp); a retry that reads the last box owed announces it (retryUnread), and a drop in between cancels the debt, since the reconnect's catch-up announces its own. A 409 skipped a box ahead without the new-mail record learning anything about the gap, so a thread that arrived in it and was later moved or labelled while still unseen measured its gap activity against the watch's start and read as new. skippedTo moves that box's cutoff up to the cursor it skipped to — HEY's last_posting_activity_at for the box, which bounds every thread in it — and the cutoff is the box's alone, so another box's mail is unaffected. A gap thread moved to another box may still read as new once; the resync line is the reader's cue to re-read either way.
…threads too; HEY_NEW=0 Sol's advisory on #243. The floor a 409 skip-ahead sets (newMail.skippedTo) now applies to every thread in that box, known or not: a reply the watch missed inside the gap and then a move while still unseen measured its gap activity against an older record and read as new. Activity at or before the floor — the cursor the box skipped to, its last posting activity — is never new there; mail after it is, on a known thread or a new one. resync joins the watchable events. It is reported by default, scripts run for it and --exit-on-first counts it, and --events can leave it out — --events new does, so `--events new --exit-on-first` never exits on a 409 and a notify-send one-liner never toasts on one. The plugin asks for it by name. Scripts see HEY_NEW=0 as well as HEY_NEW=1, on top of the inherited-variable strip, so a test for new mail never reads a parent's value.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 83faa7dd80
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… of hey omarchy The 37signals.hey bar plugin needed two things from hey-cli: the Imbox, and to know when it changed. `hey omarchy bar-status` and its planned successor `hey omarchy poll` answered both with one ten-minute poll that also diffed a fingerprint file to toast new mail — a toast could land ten minutes after the mail, the TUI had to nudge the plugin over IPC after its own mutations, and an Omarchy-named command that sounded watch-like sat on the CLI surface. `hey box imbox --json` is the read and `hey watch` is the wake-up: it catches up from its cursor on reconnect and skips ahead on a 409, so the bar is live and self-healing, and the cable reports the TUI's own mutations back within a second. `hey watch --notify` is the notifier — a generic flag on a generic command: notify-send under the app-name HEY so notification silencing applies, at most one toast per batch of changes, replaced rather than stacked, with Omarchy's glyph and focus-the-TUI hints when Omarchy is on PATH. What counts as new is an unseen, unmuted posting that was added, or updated with an active_at later than the watch last recorded (or than its start) — active_at moves on new mail only, so seen flips, mutes and moves never toast. No state file: a box's first read is its catch-up from the server's cursor (the box's last activity, not this moment) and is recorded but never toasted, and what the notifier remembers lives and dies with the watch. The cable now authorizes every dial with the credentials of the moment. actioncable-go reuses the header it was given on each reconnect, so a watch that outlived its access token came back with a stale one and exited with an auth error; a Transport wrapper refreshes the Authorization or Cookie header from the auth manager per dial, which the TUI's live updates get too. The `hey omarchy` group goes, never released: bar-status, the poll state and its lock, the config-degraded signalling only the poll reported, the account-scope and local-config exemptions, and the smoke state dir's reason. `hey setup omarchy` keeps configuring the plugin's notify key and removing the legacy hey-unread module; turning toasts on is now just setting the key.
…ay ready/disconnected/resync The notifier measured a thread's activity against its start only when it had no record, and it recorded only what --events let through and only after a box's first read, which it dropped whole. Three holes: mail that arrived while the watch was starting up was thrown away with the backlog; with --events updated an arrival was never recorded, so its later seen flip read as new; and a first read that ended in a 409 left the next arrival to be dropped as backlog. Now every posting the watch reads is recorded, in every box and whatever --events reports, and a toast needs activity later than the record — or later than the watch's start for a thread without one, which is what keeps a first read's backlog quiet without touching what arrived since. --notify covered every watched box, so the plugin, which watches all of them to see a thread leave the Imbox, would have toasted The Feed and Paper Trail too while the docs promised the Imbox. It toasts the Imbox unless --notify-box names another watched box; a name that isn't watched is a usage error, since that toast would never come. The watch now says so itself when its state changes: "ready" once the cursors are set and the subscription is live, and again after each reconnect's catch-up, so a reader that reads its own state on that line has no gap to reason about; "disconnected" when the cable drops; "resync" when a box changed more than the feed can list and the watch skipped ahead, which used to reach stderr only and left a watcher stale. A resync is a change — scripts run for it and --exit-on-first counts it; ready and disconnected go to stdout alone, since a script runs per change and neither is one. Their box is omitted, so the event's box is a pointer now and the environment leaves the box variables out. Rebased onto main, which meanwhile refreshed the cable credentials per dial itself (WithHeaderFunc); the transport wrapper here is gone in its favour.
…eave the plugin's notify alone A drop and the reconnect that followed it reached the loop through two channels, so a reconnect that completed while a slow catch-up held the loop could be announced ready and then, from the other channel, disconnected — a reader following the watch's own news would sit offline until the next reconnect. The cable's callbacks now queue every transition in order behind one wake-up, and the loop drains the queue in that order: a drop is announced, a reconnect catches up and is announced ready. The cutoff between backlog and new mail was the workstation's clock, compared with the server's active_at: a clock behind the server toasts backlog, a clock ahead sits on new mail. The watch now reads HEY's own clock off the Date header of one cheap, uncached request before the cursors are taken, and falls back to the local clock only when the server's can't be read. hey setup omarchy --remove deleted the bar plugin's notify key. The key is the plugin's: the panel and `omarchy bar set` write it as readily as setup does, so removal cannot tell a preference it wrote from one it didn't. --remove leaves it and says so; --no-notify is the explicit off switch.
Stanko asked on #243 whether --notify could just be --run-async. It couldn't, and the reason it couldn't is the tell: the flag bundled two things. What counts as new mail — unseen, not muted, active_at later than the watch's record of the thread or than its start on HEY's clock, remembered across every box so a move-in isn't new — is HEY's semantics and state across events, and belongs in the CLI, decided once and Go-tested. notify-send, the app-name, -p/-r, the Omarchy glyph and exec hints, `Sender — Subject`, one toast per read and the Imbox-only scope are presentation, a desktop's business, and belonged in the plugin that already owns rendering and settings. So the CLI grows a generic, scriptable notion of new mail and loses the desktop: every added and updated line carries "new": true|false, --events new selects the true ones (a union with added, updated and deleted), a --run-* script sees HEY_NEW=1, and `hey watch --box imbox --events new --exit-on-first` is "block until new mail". The tracker always runs — one cheap serverNow GET at startup, one map — so the line shape is stable, and a read is classified before it is recorded, as before. --notify, --notify-box, desktopNotifier and notifiedBoxes are gone; neither flag was released, so .surface-breaking needs no entry. The Omarchy plugin toasts from the new lines itself (basecamp/omarchy-hey-plugin#3). Docs follow: docs/omarchy.md's "hey watch --notify" becomes "New mail is a watch event" and "The plugin toasts", the decision record tightens to "Generic commands; the face presents", README and the skill lead with --events new, and `hey setup omarchy --notify` says it turns on the plugin's toasts rather than running hey watch --notify.
…new-mail cutoff Two Codex threads on #243. A catch-up read that failed transiently left the box queued for a retry and returned nil, so ready was announced with a box still behind it — a reader then took the gap for a clean picture. catchUp now announces ready only once every box is read (readyOnceCaughtUp); a retry that reads the last box owed announces it (retryUnread), and a drop in between cancels the debt, since the reconnect's catch-up announces its own. A 409 skipped a box ahead without the new-mail record learning anything about the gap, so a thread that arrived in it and was later moved or labelled while still unseen measured its gap activity against the watch's start and read as new. skippedTo moves that box's cutoff up to the cursor it skipped to — HEY's last_posting_activity_at for the box, which bounds every thread in it — and the cutoff is the box's alone, so another box's mail is unaffected. A gap thread moved to another box may still read as new once; the resync line is the reader's cue to re-read either way.
The box a catch-up left behind may be the one that rings next, and its read clears it: announce the owed ready there too, rather than waiting for the retry that may be two minutes off. TestWatchDoorbellReadPaysTheReadyACatchUpOwed.
…iables Two Codex threads on a5183a5. A drop queued while a catch-up was reading — noteConnection appended it, listen hadn't drained it — let ready go out with the subscription already down; readyOnceCaughtUp now looks at the queue and withholds it, so the drain says disconnected and the reconnect's catch-up says its own ready. And scriptCommand built its environment on os.Environ, so a watch started by another watch's script handed HEY_NEW=1 or a thread id to events that never set them; the event's variables are stripped from the inherited environment first.
…threads too; HEY_NEW=0 Sol's advisory on #243. The floor a 409 skip-ahead sets (newMail.skippedTo) now applies to every thread in that box, known or not: a reply the watch missed inside the gap and then a move while still unseen measured its gap activity against an older record and read as new. Activity at or before the floor — the cursor the box skipped to, its last posting activity — is never new there; mail after it is, on a known thread or a new one. resync joins the watchable events. It is reported by default, scripts run for it and --exit-on-first counts it, and --events can leave it out — --events new does, so `--events new --exit-on-first` never exits on a 409 and a notify-send one-liner never toasts on one. The plugin asks for it by name. Scripts see HEY_NEW=0 as well as HEY_NEW=1, on top of the inherited-variable strip, so a test for new mail never reads a parent's value.
… no ready on the way out Three Codex threads on 83faa7d. The server bakes a box's last posting activity into its cursor, so mail that landed between the watch reading HEY's clock and reading the box list sat behind the cursor and was never read: noLaterThan moves such a cursor back to the start, and the catch-up reads it as new. followConnection took the whole transition queue at once, so a drop queued behind a reconnect was invisible to dropQueued while the reconnect caught up; it now takes one transition at a time. And readyOnceCaughtUp no longer pays a ready to a watch that --exit-on-first has already finished or an interrupt has cut short.
Sol's finding. serverNow returned the Date header as it stood when the server answered, so mail that landed while the request was in flight — its updated_at no later than Date — made a box cursor no later than the start, which noLaterThan left where it was, and the mail sat behind the initial cursor for good. An SDK retry could widen that window by seconds. The Date is now translated back to the request's start by the monotonic elapsed time, so a slow or retried request only moves the start earlier; the fallback is the local clock at the start for the same reason. Two tests: a delayed response puts the start at least the delay before Date, and the whole window end to end — a posting landing during the clock request, the box's cursor moved back to the start, the catch-up reading it, new: true.
|
Sol's clock-window finding, fixed in eabf979: Tests: Also noted: the 409 cross-box case is the documented residual, and the skip-ahead test's "moved" posting stays in its box — my recap overstated it. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eabf9791df
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex on eabf979: started was nanosecond-precise while every cursor and active_at is milliseconds, the feed answers what is strictly later than its cursor, and isNew asks for strictly later than the start — so mail in the start's own millisecond was neither read nor new. cutoffBefore truncates the start to the millisecond and steps one back, on both the server's clock and the local fallback.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b1e1dba664
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…as it is classified Two Codex threads on b1e1dba. --box used to pick the boxes the watch read, so activity in the others was never recorded and an unseen reply in The Feed followed by a move into the Imbox read as new under the documented `--box imbox --events new`. Every box is followed now and --box picks the boxes whose changes are reported; a --box that names nothing is still not found. And a read's postings were classified against the pre-read record and recorded afterwards as a batch, so a posting carried twice by one read could be new twice; classify records each posting as soon as it is decided.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c2bb571b6a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…tops with its last reported box Two Codex threads on c2bb571. A drop could be queued between readyOnceCaughtUp looking at the queue and announcing: the look and the announcement are now one critical section with noteConnection's queueing, so a drop lands before the look and withholds the ready, or after the ready is out, in the order things happened. And since every box is followed but only the --box ones reported, stopWatching gives up when the last reported box is gone rather than when the last box is: a watch following the rest for the record alone would sit there for good, reporting nothing.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c68f04174
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex on 8c68f04: a 409 on a box the server no longer lists drops the box, and when another reported box remains that path returned nil — so readBox still reported a resync for a box that is gone, inviting a re-read of nothing and ending --exit-on-first on it. skipAhead now says whether it moved the cursor, and a resync is reported only when it did.
Supersedes #236.
What
basecamp/omarchy-hey-plugin(Jason, Rob) shells out toheyfor the Imbox; #236 gave ithey omarchy poll, a ten-minute poll that also diffed a fingerprint file to toast new mail. Stanko asked why nothey watch; the sharper objection is that an Omarchy-named, watch-like subcommand sullied the CLI surface — and a poll is ten minutes stale by construction (the TUI→IPC nudge in #236 covered only the TUI's own mutations). So, with generic commands only:hey box imbox --jsonis the read,hey watchis the wake-up. The plugin runs onehey watchper shell (it becomes aservice-kind plugin), re-reads the Imbox per batch of events, andhey watchalready catches up from its cursor on reconnect and skips ahead on a 409 — live and self-healing, no IPC nudge: the cable reports the TUI's own mutations back within a second. The watch covers every box because a move out of the Imbox is written in the target box's feed, never the Imbox's.hey watchsays what state it is in. Three new lines beside the thread changes:readyonce every box is caught up and the subscription is live (again after each reconnect's catch-up; a read that failed is retried andreadywaits for it) — a reader that reads its own state on that line has no startup gap to reason about;disconnectedwhen the cable drops;resyncwhen a box changed more than the feed can list and the watch skipped ahead (this used to reach stderr only). A resync is a change (scripts run,--exit-on-firstcounts it); ready and disconnected are stdout-only and carry nobox.added/updatedline carries"new": true|false, and--events newselects the true ones — a union withadded,updated,deleted(newalone = new mail only;added,new= arrivals plus new activity on known threads).--run-*scripts seeHEY_NEW=1;hey watch --box imbox --events new --exit-on-firstis "block until new mail". New = an unseen, unmuted posting whoseactive_atis later than the watch last recorded for it, or later than the watch's start — on HEY's clock (serverNow) — for a thread without a record;active_atmoves on new mail only, so seen flips, mutes and moves are never new, a box's first read carries its backlog quietly, mail that arrived during startup is new, and a box that skipped ahead on a 409 gets its own cutoff at the cursor it skipped to. The tracker records every posting the watch reads, in every box and whatever--eventsreports. No state file. (An earlier cut of this PR sent the toast itself ashey watch --notify; Stanko's review — why not--run-async? — showed that flag bundled HEY semantics with a desktop's presentation. The semantics stayed here; the toast moved to the plugin, and nothing desktop-shaped is left inwatch*.go.)hey omarchygroup is gone (never released: v0.1.1 predates all of it andbar-statuswas hidden):bar-status, Omarchy: hey omarchy poll, the engine under the 37signals.hey bar plugin #236'spoll, the poll state and flock, the config-degraded signalling only the poll reported, the account-scope and local-config exemptions.hey setup omarchykeeps Omarchy: hey omarchy poll, the engine under the 37signals.hey bar plugin #236's plugin-entry configuration and legacyhey-unreadremoval; turning toasts on is now just setting the key.Main refreshed the cable credentials per dial itself meanwhile (
WithHeaderFunc, 45b0263); this branch is rebased on it and the transport wrapper it carried is gone.Docs:
docs/omarchy.md("The bar plugin", "New mail is a watch event", "The plugin toasts", a Generic commands; the face presents decision, follow-ups), README, the skill.Companion: basecamp/omarchy-hey-plugin#3 (service kind, watch-first with the read on
ready, debounced re-read, backoff restart, auth exit waits for the probe, and the toast: Imboxnewlines debounced into oneomarchy-notification-send --app-name HEY … -p [-r <id>]).Release note
Unchanged from #236: do not release 0.2.0 until the plugin repo is public and its PR is merge-approved.
Heads-up, not this PR's:
make check-surface-compatfails onmaintoday because.surface-breakinglistshey screener list --count, which v0.1.1 never had (the script calls that entry stale). Dropping that line fixes it.Verified
make build && make test && make lint;.surfaceremoves nothing released (--notify/--notify-boxexisted only on this branch). Live:hey watch --box imbox --events newagainst production connects, reads HEY's clock, printsready, and exits clean on--timeout; an earlier cut reported ahey seenfrom another process within ~1 s, and the reconnect/token-refresh matrix passed on it. Plugin:./tests/run(23 node + 41 QML) andomarchy plugin validategreen.Not yet done live on the final cut: a plugin toast for mail from an external mailbox, a second one replacing it,
hey seen→new:false, and SUPER+CTRL+comma silencing it.