Hide a thread from the inbox until a chosen time (later: until an event — review posted, PR merged, CI green),
then bring it back loudly. This plan pressure-tests the idea against how Sidebar v2 actually works
today, proposes a state model, and offers 6 mock options for how snooze could be presented.
The idea is good and fits the product unusually well — better than it fits email, honestly, because
coding-agent threads have machine-checkable wake conditions (PR merged, review posted, CI state) that email never had.
But two things in the current design need to be confronted before building:
Sidebar v2 already has a snooze-adjacent verb: Settle. A third lifecycle verb next to Settle and Archive
is real cognitive load. Snooze must be crisply "not now, come back to me" vs Settle's "done, tuck below." The mocks treat this
distinction as the core design problem, and Option D explores collapsing them.
"Hide until a time passes" is only half a feature — the wake is the feature. Because the active list
sorts by creation order and never reorders on activity (by design), a woken thread silently slots back into its old
position, possibly below the fold. If wake isn't loud, snooze reads as "my thread disappeared and quietly came back somewhere."
Wake behavior gets its own section below.
Also: a fixed 1-day duration is the wrong default for this product. Agent-thread rhythms are
hours (CI run, teammate review, next work session), not days. Presets should skew short. And event-based snooze shouldn't be
treated as distant future — the auto-settle machinery already listens for PR merge/close events, so "until PR merges" is close to free.
Pushback & refinements
01 Truly hiding threads breaks trust
If a snoozed thread is simply gone, the first time someone forgets what they snoozed, the feature reads as data loss.
Every credible snooze implementation (Gmail, Superhuman, Linear triage) keeps a visible, low-pressure home for snoozed items.
We need a "where did it go" answer that's discoverable without being noisy — a collapsed section (Option C) or a badge in the
settled area (Option D). Recommendation: never hide with zero trace.
02 Snooze vs Settle vs Archive needs one-sentence answers
Users already juggle Settle ("done for now, slim row below") and Archive ("remove from sidebar"). The pitch must be:
Settle — "I'm done with this." Stays visible below, no return trip.
Snooze — "Not now. Guaranteed to come back to me." Temporarily out of sight, returns loudly.
Archive — "Out of my sidebar entirely."
If we can't keep those crisp in the UI (distinct icons, distinct locations, distinct return semantics), we should consider
making snooze a mode of settling ("settle until…") rather than a fourth verb — that's Option D.
03 The static sort makes silent wake a real failure mode
sortThreadsForSidebarV2 is intentionally static — creation order, newest on top, activity never reorders.
That's a good calmness property, but it means a thread snoozed for 2 days wakes up buried at its original position.
Wake needs at least: mark-unread + a distinct "Woke" pill. Optionally a stronger exception (float to top on wake) — but that
trades away the calm-sort guarantee. I lean pill + unread first, measure, then decide.
04 Threads aren't email — they can raise their hand while snoozed
A snoozed email stays inert. A snoozed agent thread can finish a run, fail, or hit a pending approval where the
agent is blocked on you. Sleeping through "agent needs approval" is the feature working against the product.
Mirror the existing rule in effectiveSettled (blocked work always stays active):
pending approval, pending input, and failures wake a thread early. A completed run… probably wakes it too
(that's exactly the "something happened" future you described — we get a taste of it in v1 for free).
05 Snooze state must live server-side, not in the client UI store
Read/unread currently lives in the client-local uiStateStore. Snooze can't — it has to survive across devices
(mobile sidebar) and the wake timer has to fire even when no client is open. It belongs next to archivedAt/settledAt
on projection_threads, flowing through the same atom-command path as settle, capability-gated the same way.
06 Event-based snooze is the killer version — don't strand it
"Snooze until PR merges" is more on-brand for a coding agent than any time preset, and the plumbing half-exists:
auto-settle already reacts to changeRequestState (PR merged/closed). The v1 schema should be
snoozedUntilplus a nullable snoozeCondition so time-based is just one kind of condition.
Mocks below show "Until PR merges" as a visible-but-disabled item labeled soon — it advertises the roadmap and
teaches the mental model on day one.
Proposed state model
Snooze is an overlay on the active state, not a fourth destination. A snoozed thread is still "active" in the
data model — it's just suppressed from the top of the inbox until its wake condition fires. This keeps Settle/Archive semantics
untouched and makes un-snoozing trivial (clear the field).
// projection_threads — new columns (alongside archived_at, settled_at)
snoozed_until TEXT // IsoDateTime | null — time-based wake
snooze_condition TEXT // JSON | null — { kind: "pr-merged" | "pr-closed" | "review-posted" | … } (v1.5+)
snoozed_at TEXT // for "snoozed 2d ago" affordances + analytics
Effective visibility becomes: snoozed = snoozed_until > now && !threadRaisedHand,
where raised hand = pending approvals, pending input, or session error — computed in shared logic next to
effectiveSettled so web and mobile agree.
The 6 mocks
All mocks use the real Sidebar v2 visual language: true-black .app-sidebar, 256px width, card rows for active
threads, slim 34px rows below the Settled divider, status pills in the existing colors. Hover the rows — hover
actions are live in these mocks, like the real "Settle" button. Options A–C and E–F are entry-point/placement choices and are
largely combinable; D is a divergent philosophy.
A
One-click hover snooze
clock icon next to Settle · instant default, no menu
A clock button appears on hover beside the existing Settle button. One click snoozes to the smart default
(tomorrow 9:00). No menu, no decisions — undo lives in a toast. Power users get exactly what Settle trained them to do:
hover, click, gone.
Search⌘K
All
t3code
uploadthing
t3codeApproval
Refactor thread projection to support snooze columns
t3/snooze-cols+214−36
Settle
t3codeWorking
Fix sticky PR fallback when remote URL unresolved
t3/pr-fallback#4289
Settle
uploadthing3h
Investigate flaky presigned-URL test on CI
ut/flaky-presign
Settle
Settled · 12
Migrate mobile timer into timeline2d
Bump effect to 3.144d
Hover a row → clock appears left of Settle. Click = snoozed until tomorrow 9:00, toast with Undo.
Snoozed until tomorrow, 9:00Undo
The only feedback — no menu ever opens.
Pros
Zero-decision; matches the Settle hover pattern exactly — instantly learnable
Fastest possible inbox-zero sweep (click, click, click)
Smallest UI surface to build and maintain
Cons
One duration fits nobody; "tomorrow 9:00" is wrong for a 2-hour CI wait
No path to event-based snooze from this entry point
Two adjacent hover icons invite mis-clicks between Snooze and Settle
B
Preset popover (Gmail-style)
hover clock opens a small menu of times + future events
Same hover clock, but clicking opens a compact popover: short-cycle presets first (this product runs in hours, not days),
a date picker escape hatch, and the event-based options visible but marked soon — teaching the roadmap's mental model
from day one.
All
t3code
uploadthing
t3code
Fix sticky PR fallback when remote URL unresolved
t3/pr-fallback#4289
Settle
Snooze until
In 1 hour15:42
This evening18:00
TomorrowThu 9:00
Next weekMon 9:00
Until PR mergesSOON
Until next reviewSOON
Pick date & time…
Click the clock → popover. Presets skew short because agent cycles are hours. Event rows advertise v1.5.
Pros
Right granularity for a coding tool; "in 1 hour" covers the CI-wait case
Natural, already-designed home for event-based options later — no rework
Familiar from Gmail/Superhuman/Slack reminders; zero explanation needed
Cons
Two clicks instead of one for the sweep workflow
A popover inside a 256px sidebar is tight (must overflow the rail gracefully)
Preset list needs real thought — bad presets are worse than none
C
Collapsed "Snoozed" shelf
where threads go — a section between Active and Settled
Not an entry point but the destination: a collapsed one-line divider between the active cards and the Settled list.
Collapsed by default (just a count), expandable to slim rows showing each thread's wake time. This is the direct answer to
concern 01 — snoozed threads are out of the way but never gone.
All
t3code
uploadthing
t3codeWorking
Fix sticky PR fallback when remote URL unresolved
t3/pr-fallback#4289
Settle
Snoozed · 3
Settled · 12
Migrate mobile timer into timeline2d
Bump effect to 3.144d
Collapsed (default): one quiet line. The count is the whole footprint.
All
t3code
uploadthing
t3codeWorking
Fix sticky PR fallback when remote URL unresolved
t3/pr-fallback#4289
Settle
Snoozed · 3
Refactor thread projection for snooze18h
Flaky presigned-URL test on CI2h
Design settings for notification rulesPR
Settled · 12
Migrate mobile timer into timeline2d
Expanded: slim rows with wake-time pills. Hover a row to un-snooze (wake now). The "PR" pill previews an event-based snooze.
Pros
Solves the trust problem completely — snoozed items always findable in one click
Wake times visible at a glance ("what's coming back today?")
Slots cleanly into the existing Active / divider / Settled structure
Cons
A third section in a rail that just simplified to two — visual budget cost
Needs an entry point anyway (pair with A, B, E, or F)
Empty-state handling: the shelf should vanish entirely at count 0
D
Snooze as "Settle until…" — no new verb
divergent philosophy: extend Settle instead of adding Snooze
The contrarian option: don't add a fourth lifecycle verb. Snoozing is settling with a return ticket. The Settle
button grows a chevron; "Settle until…" drops the thread into the existing Settled list with a small clock badge, and at wake
time it un-settles automatically (existing machinery, reason:"timer") and comes back unread with a Woke pill.
uploadthing
Investigate flaky presigned-URL test on CI
ut/flaky-presign
Settle
Settle
Settle until
Tomorrow9:00
Next weekMon
PR mergesSOON
Settled · 13
Flaky presigned-URL test on CI18h
Migrate mobile timer into timeline2d
One verb, one destination. The clock badge in the Settled list is the only trace of the timer.
Pros
Zero new concepts — no fourth state, no new section, no Settle-vs-Snooze confusion
Reuses settle/un-settle machinery and the settled section wholesale; cheapest build
Auto-settle already blurs this line (inactivity settles threads); this just adds intent
Cons
Semantically muddy: "settle" means done; "settle until" means not done — one word, opposite intents
Snoozed threads mix into a 12+-item settled list; wake times don't stand out
Boxes in the event-based future: "settle until next review" reads strangely
E
Command palette + keyboard first
Z on hover/selection · ⌘K "Snooze until…" with natural input
Lean into the palette-first direction the sidebar is already taking (new-thread picker just moved into the palette).
Pressing Z with a thread hovered/selected applies the default snooze; ⌘K → "snooze" opens a
duration picker that accepts natural input ("2h", "monday", "until pr"). Multi-select works for free: select 4 threads, Z, done.
Snooze · Fix sticky PR fallback… 2h
Until
In 2 hourstoday 16:42
TomorrowThu 9:00
Next weekMon 9:00
⌘K flow: type "snooze", pick a thread (or act on the current one), then free-text the duration — "2h", "fri", "next week" all parse.
Z
3 threads snoozed until tomorrowUndo
Keyboard path: hover or multi-select rows, press Z. Superhuman-style sweep.
Pros
Fastest workflow for heavy users; multi-select snooze falls out naturally
Consistent with the sidebar's palette-first trajectory
Natural-language durations beat any preset list for flexibility
Cons
Invisible — without a pointer entry point, most users never discover it
Single-key shortcuts in a list UI need careful focus handling (rename input, search)
NL date parsing is a real (if bounded) engineering cost
F
Context menu only (quiet v1)
a submenu in the existing right-click menu · no new chrome
The minimal-footprint probe: add "Snooze" with a submenu to the existing thread context menu, right under Settle. No hover
buttons, no new sections (snoozed threads get a clock badge wherever they'd otherwise appear via search/palette). Ship it, watch
usage, then invest in A–C chrome only if people actually snooze.
t3codeDone
Preserve draft highlighting during promotion
t3/draft-highlight#4283
Settle thread
Snooze›
Rename thread
Mark unread
Delete
In 1 hour
Tomorrow9:00
Next week
Until PR mergesSOON
Right-click → Snooze › submenu. Sits directly under "Settle thread" so the verbs read as siblings. Multi-select gets "Snooze (N)".
Pros
Cheapest validation of the whole hypothesis; nearly zero visual budget spent
Context menu already handles capability gating and multi-select patterns
Easy to promote to A/B later without throwing anything away
Cons
Low discoverability → risks a false-negative on the whole idea
Still needs a "where did it go" answer (at minimum, palette/search visibility)
Right-click is weak on touch/mobile
Wake behavior — the half that makes or breaks it
Whatever entry point wins, the return trip has fixed requirements. Given the static sort (concern 03), a woken thread
reappears at its original creation-order position — so the wake signal has to carry the weight:
t3codeWorking
Fix sticky PR fallback when remote URL unresolved
t3/pr-fallback#4289
uploadthingWoke
Investigate flaky presigned-URL test on CI
ut/flaky-presign
t3code5d
Design settings for notification rules
t3/notif-rules
A woken thread: unread weight + amber alarm-clock "Woke" pill, in its original sort position. Pill clears on visit, like "Done".
Wake rules (v1)
Timer fires → clear snoozedUntil, mark unread, show amber Woke pill until visited.
Early wake — thread raises its hand: pending approval, pending input, or session error immediately overrides the snooze. The agent blocking on you always outranks your snooze. (Mirrors the blocked-work rule in effectiveSettled.)
Run completes while snoozed: wake early too. This is the v1 taste of event-based snooze — "something happened" already exists as latestTurn.completedAt.
No float-to-top in v1. Keep the calm static sort; the pill + unread does the signaling. If woken threads get lost in practice, revisit with a scoped exception rather than pre-breaking the sort invariant.
Snoozing does not pause the agent. A working thread keeps working; snooze only affects visibility. (Worth stating in the UI the first time someone snoozes a Working thread.)
Recommendation
Combine B + C, with F's context-menu item for parity — and keep the verb "Snooze."
Entry: hover clock button beside Settle opening the preset popover (B); same items mirrored
in the right-click menu (F). Presets: In 1 hour · This evening · Tomorrow 9:00 · Next week · Pick date — with
"Until PR merges / Until next review" visible as soon.
Destination: the collapsed Snoozed shelf (C) between Active and Settled, hidden at count 0,
slim rows with wake-time pills, hover to wake now.
Wake: unread + Woke pill; early wake on approval / input / failure / run-completed; no sort exception in v1.
Later: Z / palette flow (E) once the pointer UX proves out; D is rejected — the "one verb" economy isn't worth
making "settle" mean both done and not done.
Why not A or F alone: A's single fixed duration recreates the "probably a day for now" arbitrariness at the UI
level, and F alone under-exposes the feature enough that we'd learn nothing from shipping it.
Option
Discoverability
Sweep speed
Event-ready
Build cost
Call
A · One-click hover
●●●○
●●●●
●○○○
low
Too rigid alone
B · Preset popover
●●●○
●●●○
●●●●
med
Ship (entry)
C · Snoozed shelf
●●●●
—
●●●●
med
Ship (destination)
D · Settle until…
●●○○
●●●○
●●○○
low
Reject (verb muddle)
E · Palette + Z
●○○○
●●●●
●●●●
med-high
Phase 2
F · Context menu
●●○○
●●○○
●●●○
low
Ship (parity)
Implementation sketch
P1
Server & contracts. Add snoozedUntil / snoozedAt (+ nullable snoozeCondition, unused in P1)
to the thread shell in packages/contracts/src/orchestration.ts; migration on projection_threads; decider/projector
commands snooze / unsnooze alongside settle; wake sweep on a server timer + on the existing PR/turn event paths.
Capability-gate as threadSnooze like threadSettlement.
P2
Shared logic.effectiveSnoozed next to effectiveSettled in
packages/client-runtime/src/state/threadSettled.ts-land: snoozed = future snoozedUntil and no raised hand
(approvals / input / error / fresh completion). One implementation for web + mobile.
P3
Sidebar UI. Hover clock + popover on SidebarV2Row; Snoozed shelf between the active block and the
Settled divider in SidebarV2.tsx (reusing the slim-row component + divider pattern, auto-animate handles the moves);
context-menu items incl. multi-select "Snooze (N)"; Woke pill in the top-status pill priority list (below Approval/Input, above Done);
undo toast.
P4
v1.5 — first event condition. Enable "Until PR merges/closes" by writing snoozeCondition and waking from the
existing changeRequestState handler that auto-settle already uses. Then evaluate review-posted / CI-state conditions.
Open questions for you
Default preset: I'd make the top (Enter-key) preset Tomorrow 9:00 but list In 1 hour first for the CI-wait case. Agree, or should the default be shorter?
Does a completed run wake a snoozed thread? I say yes (argued above), but it does mean "snooze until tomorrow" sometimes returns in 20 minutes — is that delight or betrayal?
Should snoozing a Working thread be allowed silently? Or show a one-time hint that the agent keeps running?
Mobile: ship simultaneously (shelf + long-press menu) or web-first behind the existing Sidebar v2 beta flag?
Snooze count badge: should the collapsed shelf show "next wake in 2h" instead of just a count?