Repository navigation
Conversation
The Snooze menu offers five fixed choices. Users who often snooze for the same span, like three days or until Friday morning, have to go through Custom… every time. Users can now save two kinds of presets, which appear after the built-in choices in every Snooze menu: - A delay in minutes, hours, or days, counted from when you snooze. A day is 24 hours, the same as Custom… durations. - A weekday at a local time. It resolves to the next such day after today, never today itself, like the built-in "Next week". Presets are device-local, like the time format. Web and desktop keep them in client settings (Settings → General). Mobile keeps them in device preferences (Settings → Thread behavior). Shared logic in client-runtime resolves, labels, and validates them, so every surface agrees: row and bulk menus, desktop context menus, the chat header menu, and mobile row menus. Any choice that lands on the same instant as an earlier one now collapses into it. This general rule replaces the Sunday "Tomorrow"/"Next week" special case. Settings refuse rules that always duplicate a built-in or saved preset. Unconfigured users see exactly the menu they had before. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… them Presets were device-local: a web client setting plus a mobile preference with its own editor. Setting "In 3 days" on desktop did nothing on your phone, and mobile needed a second editor for the same list. Presets are now a shared server setting, next to "Snooze limited threads": - Web and desktop edit them in Settings → General. The row is server-scoped, so the scope picker, mixed-value indicator, and Restore defaults all work as they do for sibling rows. - Clients write them to every shared-settings target, like the other thread preferences. - Every client reads the presets of the thread's environment. Mobile shows them in its row menus but has no editor, matching how it treats other shared preferences such as the writing style. Its device-local mirror and editor are gone. - Each client still resolves a rule in its own time zone. A rule like "Friday at 9:00" is wall-clock, so storing it on the server changes nothing about when it fires. - A new `snoozePresets` capability keeps writes and mismatch checks away from older servers, which would silently drop the key. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The amount field clamped to 1–999. Typing 0 left 0 on screen while the form held 1, so pressing Enter validated "In 1 hour" and said it was already a built-in choice. The field no longer clamps, matching Custom…, and validation explains out-of-range amounts. Found during web verification by Codex GPT-6.1-Sol. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 of 2 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Snooze menu has five fixed choices. If you often snooze for the same span, like three days or until Friday morning, you have to go through Custom… every time.
Change
You can now save your own snooze presets. They appear in every Snooze menu after the built-in choices. A preset is one of two kinds:
Add presets in Settings → General → Snooze presets on web or desktop. They're saved on the environment, so the mobile app offers them in its menus too. If you never add one, the menu is exactly what it was. Custom… stays for one-off times.
Where to start: read
resolveSnoozePresetsinpackages/client-runtime/src/state/threadSettled.tsand its tests insnoozePresets.test.tsnext to it. The rest of the diff stores the list, wires that one function into each surface, and adds the settings row.Semantics
{ weekday: 1, time: "09:00" }.America/Los_Angeles.Duplicates
parseSnoozePresetDraftrefuses rules that always duplicate a built-in or saved choice (In 60 minutes, Monday 9:00 AM, In 72 hours when In 3 days is saved). It also caps the list at 8 to keep menus scannable.Storage: a shared server setting
Presets live in the environment's
settings.json, next to Snooze limited threads, and are inSHARED_SERVER_SETTING_KEYS. I chose this over a device-local client setting for three reasons:How it plays out:
snoozePresetscapability makes the row read-only there and keeps shared writes and mismatch checks away from them.ForwardCompatibleArray, so a preset kind added later never breaks an older build's settings.t3_environment_preferences_updateMCP tool is unchanged. It covers a curated set that excludes sibling thread settings like Snooze limited threads, and agents already snooze to absolute times.Surfaces
On mobile, the thread-list environment projection carries each environment's list. The array keeps its identity until the presets change, so memoized rows don't re-render on unrelated settings broadcasts.
Scope and approval
This is focused configuration of an established capability:
A tracking proposal is drafted and awaiting Matt's review before it's published. I'll link it here once it is.
Verification
settingscovers server decoding, round trips, and dropping unreadable entries.snoozePresets,threadSnoozed,customSnooze, andsharedSettingscover ordering, the time column, collapsing, DST, validation, and the capability filter.serverSettingscovers persisting and broadcasting, and a removal replacing the list rather than merging by index.Sidebar.snooze,threadActionMenu.logic,SettingsPanels.restore, andsettingsSearch.threadListV2covers re-resolving a saved preset at tap time.thread-list-environmentscovers per-environment lists that stay stable across unrelated broadcasts.TZ=Asia/Kolkata,Australia/Sydney, andUTC. The host is AWST, which has no DST, so the Los Angeles DST cases really exercise the stub.tsc --noEmitpasses forpackages/contracts,packages/client-runtime,apps/server,apps/web, andapps/mobile.In the apps
Codex GPT-6.1-Sol (xhigh) ran these checks against an isolated dev server with neutral fixture data. One real branch name is blurred in the images.
iOS and Android:
settings.jsonremoves it from the menu without a restart. Restoring it brings it back.Web:
That pass found one bug: the amount field silently corrected 0 to 1, so Enter validated a different preset than the one on screen. It's fixed in 2cae485.
Web screenshots are still pending. The in-app browser host dropped after the first pass, and that pass's captures show personal data, so they aren't posted. The bulk menu, reload persistence, and 24-hour format checks are still to do.
Observed, but not caused by this PR:
4d, and the built-in "In 1 hour" shows2h. The mobile label clock is rounded down to the minute while the label rounds up. That's unchanged by this PR; I'll handle it separately.maindoes the same.Made with Claude Opus 5.5 in the Claude Code harness (xhigh reasoning effort), acting on Matt's behalf. Verification is delegated to Codex GPT-6.1-Sol (xhigh).
🤖 Generated with Claude Code