Skip to content

feat: Post-launch polish: launch-at-login toggle + OAuth token caching#57

Merged
hiskudin merged 6 commits into
mainfrom
chore/post-launch-polish
May 26, 2026
Merged

feat: Post-launch polish: launch-at-login toggle + OAuth token caching#57
hiskudin merged 6 commits into
mainfrom
chore/post-launch-polish

Conversation

@hiskudin
Copy link
Copy Markdown
Collaborator

@hiskudin hiskudin commented May 26, 2026

Summary

A bundle of small UX + behavior polish landing after the v1.9.1 launch.

Settings

  • Launch at login toggle (default On). Off unloads + deletes the panel LaunchAgent plist; On rewrites and reloads it. Daemon plist (voice) is intentionally untouched.
  • Quota tracking master toggle (default On). Off disables the /api/oauth/usage poller entirely — hard kill switch for users who don't want keychain access for usage tracking.
  • Poll frequency cycle (1 / 2 / 5 / 10 / 15 / 30 min) — surfaces STACKNUDGE_USAGE_POLL_MIN from config to the UI. Visible-panel cadence stays fixed at 60s.
  • View release notes… action — opens github.com/StackOneHQ/stack-nudge/releases/tag/v<version> for the running bundle, falls back to /releases if version unknown.

Usage tab

  • r keystroke: sync now (immediate probe), with footer hint.
  • p keystroke: pause / resume tracking without leaving the tab. On resume, fires an immediate probe so fresh data appears right away.
  • Richer footer status: distinguishes Tracking off / Syncing… / Never synced / Updated Ns ago instead of just the relative time.
  • Explicit empty state when tracking is off: clears the cached snapshot on toggle-off so the tab doesn't show stale data; renders a dedicated "Quota tracking is off" panel with a pointer back to Settings.

Keychain prompt fix

  • QuotaProbe now caches the OAuth token in memory and only re-reads the keychain on a 401. Claude Code rotates its keychain item periodically (which wipes the trusted-app ACL granted via "Always Allow"); caching means we only hit the keychain — and therefore only risk a prompt — when the current token actually stops working. Cuts prompt frequency to true-expiry cadence instead of rotation cadence.

Test plan

  • Settings: confirm new rows render in the right sections, row count = 21 (or 22 with update banner). Arrow-key navigation lands on each new row correctly.
  • Toggle "Launch at login" off → plist removed from ~/Library/LaunchAgents/. On → plist returns and launchctl list | grep stackonehq shows it loaded. Log out + back in to verify auto-launch behavior matches the toggle.
  • Toggle "Quota tracking" off → Usage tab shows "Quota tracking is off" empty state; footer shows "Tracking off"; r and Sync now hint hidden. On → probe fires within the configured interval; footer shows fresh "Updated Ns ago".
  • Cycle "Poll frequency" → next scheduled tick uses the new interval (no restart needed).
  • "View release notes…" → opens the release page in browser for the running version.
  • Usage tab: press r → footer briefly shows "Syncing…" then "Updated 0s ago". Press p → snapshot clears, footer says "Tracking off", hint flips to "Resume". Press p again → immediate probe fires.
  • Leave panel open for >1h → no keychain password prompts at the Claude Code rotation cadence.

🤖 Generated with Claude Code

hiskudin and others added 6 commits May 26, 2026 10:05
Claude Code rotates its keychain item periodically, which wipes the
trusted-app ACL granted via "Always Allow" — so the next QuotaProbe
poll re-fires the password-entry prompt. Most rotations happen before
the old token actually expires, so caching the token in memory and only
re-reading the keychain on a 401 cuts the prompt frequency to the rate
of true token expiry rather than the rate of rotation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bootstrap already installs a panel LaunchAgent with RunAtLoad=true, so
fresh installs already auto-launch at login. The new toggle surfaces
that behavior so users can opt out without hand-editing launchd
plists.

Off: unload + delete ~/Library/LaunchAgents/com.stackonehq.stack-nudge.plist.
On:  rewrite the plist (if missing) and launchctl load.

The daemon plist (voice) is intentionally untouched — toggling panel
auto-launch shouldn't affect voice playback registration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…notes action

- "Quota tracking" master toggle (default On) gates the /api/oauth/usage
  poller entirely. Off = no keychain access at all, hard kill switch
  for users who don't care about quota.
- "Poll frequency" cycle surfaces STACKNUDGE_USAGE_POLL_MIN from config
  to Settings; options 1/2/5/10/15/30 min. Visible-panel cadence stays
  fixed at 60s.
- "View release notes…" action opens
  github.com/StackOneHQ/stack-nudge/releases/tag/v<version>,
  falling back to /releases if version unknown.

Row layout: +3 rows (master toggle + poll cycle in Usage, release-notes
action in Actions). All downstream switch cases shifted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previously the Usage tab showed whatever snapshot was last fetched,
even after the user disabled polling — looked like fresh data but
was actually frozen. Now: clear the cached snapshot on toggle-off,
and render a dedicated "Quota tracking is off" empty state with a
pointer back to Settings.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Footer status now distinguishes "Tracking off", "Syncing…",
  "Never synced", and "Updated 5s ago" instead of just the relative
  time.
- 'r' in the Usage tab triggers an immediate quota probe (skipped
  when tracking is off). Footer hint "Sync now [r]" advertises it.
- nav.quotaSyncing exposed so the UI can flash "Syncing…" while a
  fetch is in-flight; cleared in the completion handler whether the
  fetch succeeded or failed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
'p' on the Usage tab toggles STACKNUDGE_QUOTA_TRACKING — mirrors the
Settings row but reachable without leaving the tab. On resume, fires
an immediate probe so the user sees fresh data right away instead of
waiting for the next scheduled tick.

Footer hint flips between "Pause [p]" and "Resume [p]" depending on
current state. Toggle logic extracted to PanelNav.toggleQuotaTracking
so the row and the keystroke share one path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@hiskudin hiskudin changed the title Post-launch polish: launch-at-login toggle + OAuth token caching Post-launch polish: launch-at-login, quota tracking controls, keychain prompt fix May 26, 2026
@hiskudin hiskudin changed the title Post-launch polish: launch-at-login, quota tracking controls, keychain prompt fix fix: Post-launch polish: launch-at-login toggle + OAuth token caching May 26, 2026
@hiskudin hiskudin changed the title fix: Post-launch polish: launch-at-login toggle + OAuth token caching feat: Post-launch polish: launch-at-login toggle + OAuth token caching May 26, 2026
@hiskudin hiskudin merged commit 2975466 into main May 26, 2026
4 checks passed
@hiskudin hiskudin deleted the chore/post-launch-polish branch May 26, 2026 09:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant