Repository navigation
cmux-next: New Tab suggestions are an omnibar popover - #19750
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Typing in the New Tab field showed its rows inline, pushing the page down,
and "reddit" showed nothing. The rows now float in a popover anchored under
the composer on a solid theme surface. They complete addresses from visited
pages and top sites, match open tabs and workspaces, and end with "Search the
web for …" and "Ask <agent>". The top row is highlighted and taken by
Return. Blank browser tabs ("about:blank workspace-N") are never offered.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…tters
The blank-page filter ran on the host context, which also feeds a split
page's Open Tabs list, so a fresh browser tab could not be moved into the
pane. Filter only the popover's rows. Two-letter words ("go", "no") stay
prompts instead of completing to google.com or notion.so.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gallery178 states changed: agent-pane.new-tab/typed-tab-match, agent-pane.new-tab/typed-prompt, gallery.visual-media-board/all-previews, agent-pane.new-tab/typed-address, pages.settings/general-group-3, ... · 8 new states · 45 broken states · 93 play checks failed Diff page and renders (the run's 172 more on the diff page. Live preview (follows this branch; start it with
Play checks failed (0 px anchor movement, 0 layout shift, no frame over 33 ms unless the entry gives a reason):
487 nondeterministic states differed from a second render of the same head (a clock or fixture leak) and are not counted as changes. |
…-omnibar-popover # Conflicts: # webviews/src/agent-session/acpmux/newtab/NewTabScreen.gallery.ts # webviews/src/agent-session/acpmux/newtab/NewTabScreen.tsx
…Ghostty (#19758) * test: Opacity in Ghostty mode repaints live and leaves Ghostty Red: with Material "Ghostty" (unset), moving Settings > Window Background > Opacity through the page's preview does not repaint the window, and a write leaves Material on Ghostty. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: Opacity leaves Material Ghostty and repaints the window live With Material "Ghostty" (unset), the Opacity slider's preview never reached the window: TerminalThemeSetting followed only the loaded settings for the window background. It now follows the applied (previewed) background, so every slider step repaints the window. Writing Opacity while Material is unset now also names the material Ghostty's background-blur gives (none, frosted, glass or clear glass), and removing either key removes the other, back to Ghostty. The rule lives in WindowBackgroundSetting.linkedEdits and runs in SettingsController.setSetting and preview, so the page, the palette and the socket's settings.set agree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: add the Ghostty blur hook to SettingsController Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: Opacity reset keeps a chosen Material; slider reloads coalesce Red: resetting Opacity drops a Material the user chose, the flip reads the window's resolved blur rather than Ghostty's own, and every slider step reloads the Ghostty config. GhosttyRuntime now records the config files' raw background-opacity and background-blur (configBackgroundOpacity/Blur), which nothing reads yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: Opacity reset keeps a chosen Material; coalesce slider reloads Resetting Opacity now removes Material only when it is the one the flip wrote (the material the config files' own background-blur gives); a material the user chose stays. The flip and this check read Ghostty's raw blur, which GhosttyConfigBackground records on every load of the user's config, instead of the window's resolved blur. A window background step that keeps the window translucent (or opaque) and its material repaints the chrome from the theme at once (ThemeBridge.repaintBackground) and reloads the Ghostty config 60 ms after the last step (DemandTimer). Crossing opaque/translucent or changing the material reloads at once, so the terminals follow. The raw values move from GhosttyRuntime statics to GhosttyConfigBackground (GhosttyRuntime's type was over the god-type budget), so the tests set that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: build the app services before the stand-in Ghostty values AppServices may load the machine's Ghostty config, which records its own raw background values over the test's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) * test: Show more lines reads a git scope's file whole and expands between hunks (cx-ncc.85, red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Agent pane: Show more lines in the changes view's git scopes (cx-ncc.85) A git scope's file is read again as it comes into view, with every unchanged line (git.diff paths + context_lines). With both versions known, Pierre's hunk separators expand. A read whose changes differ from the shown diff (the file changed since) is not used, nor is one for a rename. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: Show more lines ignores a read that does not start at the first line (cx-ncc.85, red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Agent pane: Show more lines uses only a read from the file's first line (cx-ncc.85) Review fix: a host that ignores or caps context_lines answers with the hunk's own context; rebuilt from that, the file was too short and Pierre indexed past it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…t a silent cursor (#19773) * test: a terminal whose host link the daemon gave up on is never a silent cursor The daemon pushes no tab change when a terminal's host link is lost, given up or back, and the app ignores terminal_state, so such a terminal keeps a connected view with no label: the last screen, often a lone block cursor, and keys that go nowhere. Red until the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a terminal whose shell the daemon cannot reach says so The daemon now pushes a terminal's tabs when its host link is lost, given up or back, and the app labels a live terminal whose shell it cannot reach (reconnecting, link lost, owned by another build) instead of leaving a silent last screen. It re-attaches once the shell is reachable again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: push a resync reconnect's loss; the organization banner wins Review follow-ups: a reconnect started by a resync that then fails moves the terminal to reconnecting, which clients now hear about at once, and a link an administrator turned off keeps its own label over a stall. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…19775) #19725 calls Mux::landed_agent_session from conversation_tabs_wire, which builds everywhere, but agent_transfer (where it lives) is #[cfg(unix)], so feat-cmux-next's cargo check (x86_64-pc-windows-gnu) fails with E0599. Off unix no chat lands through agent-transfer, so the check is false there. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… (cx-wab7m) (#19783) * test: right-click hides the mic, right-click its row shows it, across a relaunch (cx-wab7m, red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Agent pane: hideable chrome; right-click a composer control to Hide it, its row to Show it (cx-wab7m) ui/HideableChrome: a piece of optional chrome (id, Hide/Show labels, icon, persisted shown/setShown) hides from its own right-click and comes back from its area's right-click. ContextMenu items take an icon, and a menu inside another wins the right-click. The composer's dictation mic and context ring use it in the agent composer and the New Tab page: Hide Dictation Button / Hide Context Usage on the control, Show ... on the button row. The choice stays the agentPane.showDictation / showContextUsage setting, written by the host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a popup's right-click keeps its own menu; New Tab offers Show only for what it draws (cx-wab7m, red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Agent pane: the button row's Show keeps out of popups and offers only what it draws (cx-wab7m) ContextMenu targets="own" opens only for right-clicks on the host's own DOM, so the project chooser's search field (a popup React events pass up from) keeps its own menu. The New Tab row offers Show for the mic only; that page draws no context ring. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…-10-12) (#19788) * test(next): Chrome tab keys select sidebar items from any focus (Leo 2026-10-12) Every Chrome-standard tab key (Ctrl-Tab, Cmd-Shift-] / [, Cmd-Opt-arrows, Ctrl-PageDown / Up, Cmd-1…9) from a terminal, the New Tab field and an agent composer, in one-tab and two-tab panes, compared with the sidebar action from the same start. Leo's two Karabiner paths also go in transition by transition with their timing through the new DEBUG `debug.key` `sequence`, which posts CGEvent-built key events to the app's event queue. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(next): debug.key sequence schedules its steps with DemandTimer check-concurrency bans asyncAfter; each step's timer posts its queued event. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(next): Chrome tab keys select sidebar items from every focus (Leo 2026-10-12) Leo's Karabiner sends Cmd-Shift-] / [ and Ctrl-Tab, as Chrome, ChatGPT and Claude use them. Here they ran Previous / Next, which steps the focused pane's tabs when it has two or more, and in a terminal Ctrl-Tab and Ctrl-PageDown / Up went to Ghostty's next_tab (the pane's tabs). Cmd-Opt arrows focused panes. Now Ctrl-Tab / Ctrl-Shift-Tab, Cmd-Shift-] / [, Cmd-Opt-Right / Left, Ctrl-PageDown / Up (and Ctrl-Cmd-] / [) select the next / previous sidebar item, and Cmd-1…8 / Cmd-9 the nth / last item. These Chrome tab keys sit after the Ghostty config's keybinds and claims in the binding table, so a terminal, a Ghostty keybind (super+[ included), a page and the agent composer never take them; only cmux.json entries change them. - Next / Previous Sidebar Item show Cmd-Shift-] / [ as their keys. - Next / Previous Tab or Workspace keep no default key (palette only). - Focus Pane Left / Right move to Ctrl-Cmd-H / L. - Home's Cmd-Shift-[ / ] conversation keys go: Home is a sidebar item. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): regenerate action exports for the Chrome tab keys scripts/measure/export-action-surfaces.sh on the fleet at the fix commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(next): chrome-tab-keys e2e reads older builds' sidebar selection and focus Builds before the selection and focus readouts (Leo's DEV d0364e0) mark the selected row and name no focus; the script falls back to those. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): regenerate action exports after the base merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… ring around open menus (#19749) * test: the New Tab field keeps its caret across updates and a click into it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the New Tab field takes the keyboard once, not on every update The page's focus effect depended on the input-ready callback, which the App makes anew on each render, so every update and a click into the focused field focused and selected it again: the caret blink restarted and the text under the caret was selected. It runs once per input token now (and on Cmd-L). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the default New Tab is the composer and five recent chats, with a real send button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: an open menu draws no focus ring around itself Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a calm default New Tab with a real Send button, and no focus ring around open menus The default New Tab is the composer and the five newest chats as quiet rows, with All Chats for the rest; the action row, Recently Closed and the All chats table leave the default (the other templates keep theirs). Send is the composer's arrow-up disc, off while the field is empty. An open menu, list or popover takes focus so its keys work; the global keyboard rings no longer draw a square around it, and the focus-ring lint refuses a universal ring that would. Monaco's find fields draw no ring of their own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: lists that take Tab focus keep their ring; only open menus and popovers drop it Review: the Cloud machine list and the History list are themselves the focus target, so leaving [role=listbox] out of the ring hid their keyboard focus. Drops the classic page's unused tools and onRunAction props. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the New Tab's recent chats are one-line rows The list variant set height 30px, but the card's 84px min-height won, so every row drew three lines tall (fleet capture of the calm default; Threads and Console had it too). The calm-default gallery play now refuses a row taller than one line: 84px before, 30px after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the New Tab page has no tools row, so no Integrate a harness button in it The base's #19755 test rendered the tools row the calm default removes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) * test: the pane's git diff reads pass paths and context_lines to the session host (cx-ncc.85, red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: the pane's git diff reads pass paths and context_lines to the session host (cx-ncc.85) Show more lines asks for one file's patch with enough unchanged lines to hold the whole file. The App decodes paths (relative, inside the repository) and context_lines (0 to 1,000,000) and refuses anything else rather than dropping it, which would be another read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: import the pane module testably for its request decoder (cx-ncc.85) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ws (#19774) * test: closed.list marks a tab that reopens as nothing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: closed.list marks a tab that reopens as nothing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: Recently Closed leaves out New Tab pages and names the rest Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: leave New Tab pages out of Recently Closed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: History and untitled chats keep about:blank out of Recently Closed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep about:blank and New Tab pages out of History and Tab Search Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: closed chat fixtures carry no folder, as the daemon records them Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: name the closed-tabs helper's lifetime Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 5b12bae - regenerated cmux-tui/crates/cmux-app-host/generated/cmux-app.d.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38219624487 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com>
* test: themed menu rows draw the theme accent and run once The workspace, tab and pane menus (#19754) highlight rows in the system accent. Adds the failing behavior test for cmux-drawn rows: a highlighted row draws the theme accent in a non-default theme scope, and Return or a click runs the item's action exactly once. The API it calls is a no-op stub here; the Palette accentFill/onAccent tokens it reads are real. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: workspace, tab and pane menus highlight in the theme accent NSMenu draws its highlight in the system accent whatever the theme. NSMenu.themeRows(in:) swaps a menu's rows (and its submenus') for ThemedMenuRowView, which draws the highlight in Palette.accentFill with Palette.onAccent ink, in the scope of the view that was right-clicked. Items keep titles, key equivalents, states and submenus; their action goes through ThemedMenuDispatch, which validates via the original target and runs once per opening whether it arrives from AppKit's Return, a click on the row, or Return delivered to the row. Applied to the three menus #19754 trimmed: the sidebar workspace and tab menus and the strip's tab and pane menus. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: Return on a themed submenu row reaches AppKit Review of #19784 (cx-3pcgz): the row took Return whenever it was highlighted, so Return on More or Move to Group was swallowed instead of opening the submenu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: themed menu rows run after tracking and redraw on arrows Review of #19784 (cx-3pcgz): - A click or Return on a row closes the menu and runs the action once the tracking loop has ended (RunLoop default mode), as a native row does. The selector form of RunLoop.perform keeps it Swift 6.0 safe. - Each themed menu gets a delegate relay that redraws the rows losing and taking the highlight on menu(_:willHighlight:) and forwards to the menu's previous delegate (a choices submenu's coordinator). - The row takes Return only for an enabled item with an action and no submenu; otherwise AppKit gets it. - The row view is no accessibility element, so VoiceOver uses the native menu item. - A release with no press on the row also runs it once the pointer has moved since the menu opened (right-drag-release). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…19776) * test: backdrop art is iconic paintings in four collections (cx-t2x.7) The picker groups bundled art into Dark Art, Museum Icons, Calm and Doré, labels each "Title — Artist", ships every image at 1600x1000, and keeps every id an earlier cmux.json saved choosing art. Fails on the current set: two collections, title-only labels, mixed image sizes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: thumbnails for every work, a bundled dark starter set, verified downloads (cx-t2x.7) Leo's list grew to about 170 works, so the full images no longer all fit the app-size budget: every work ships a 480 px thumbnail, a starter set of dark works ships its full 1600x1000 image, and the rest download once into the backgrounds folder, kept only when the bytes match the manifest hash. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: iconic public-domain paintings as backdrop art (cx-t2x.7) Replaces the figure-drawing sketches and Met paintings with 169 well-known public-domain works from Leo's list (cmuxterm-hq#1906): Goya, Doré, Friedrich, Van Gogh, Bosch, Klimt, Munch and more, in four picker collections (Dark Art, Museum Icons, Calm, Doré), labelled "Title — Artist". - art/manifest.json is the source of truth: Commons source and license, copyright dates, framing, tone, measured range and SHA-256 per work. Gate: artist dead 70+ years and first published before 1931. - Every image is 1600x1000 AVIF framed for a terminal backdrop (subject to one side, dark side for text) at <=150 KB. The app ships 480 px thumbnails of all works plus a 16-work dark starter set (~2 MB, down from 4.4 MB); the rest download once from files.cmux.com by hash (cmux-art-publish.yml) and are kept only when the bytes match. - Each work sets its own default tint, and the legibility floor uses its measured darkest and lightest colors instead of assuming black-to-white. - Ids saved by earlier builds map to a stand-in work. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: starter-set test reads metadata on the main actor; format the gallery fixture (cx-t2x.7) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate settings schema and MDM exports for the new art set (cx-t2x.7) Generated by scripts/measure/export-settings-artifacts.sh on the fleet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: keep non-art backdrop strings, all locales and true brightness extremes (cx-t2x.7) Red on the current generator: it deletes backdrop.desktop/system strings, writes art strings in 9 of the catalog's 21 locales, and measures the brightest pixel from a 160x100 downscale, which loses a small moon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep wallpaper strings, ship art strings in all 21 locales, measure true brightness extremes (cx-t2x.7) - The generator no longer deletes backdrop.desktop/system strings; restored them from base with their 21 translations. - Art titles, collections, label and "Public domain" now carry every locale the catalog does (bs, da, it, km, nb, pl, pt-BR, ru, th, tr, uk, vi added). - darkest/lightest are the full-size extremes, so the legibility floor holds over moons and flames a 160x100 downscale averaged away. - Merged the stacked JSDoc on the settings backdrops type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate settings page strings after the base merge (cx-t2x.7) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate settings schema and MDM exports after the base merge (cx-t2x.7) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate settings page strings from the refreshed schema (cx-t2x.7) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ectory (cx-zld.1) (#19799) * test: the header's Terminal inherits the chat's folder only when splits inherit (cx-zld.1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * CmuxNext: the header's Terminal honors split-inherit-working-directory (cx-zld.1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a chat of another machine keeps its folder for the header's Terminal (cx-zld.1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * CmuxNext: a chat of another machine keeps its folder for the header's Terminal (cx-zld.1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * CmuxNext: keep AgentTabStore's length while wiring the header's local check (cx-zld.1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ding silently (cx-lyqio.7) (#19800) * test: New Worktree hands back the host's folder question (cx-lyqio.7) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: type New Worktree's folder question, no behavior yet (cx-lyqio.7) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * webviews: New Worktree shows the host's folder question instead of ending silently (cx-lyqio.7) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#19757) * test(next): rapid workspace create/close stress e2e (cx-7cit9) 30 Cmd-N at key-repeat speed with interleaved Cmd-Shift-W, some landing on a workspace still being created; then the sidebar must match the daemon, the new names must be consecutive, New Tab must suggest only live tabs and workspaces, and no refusal HUD or toast may appear. DEBUG readouts for it: debug.toast reports the refusal HUD's history and debug.new_tab state the New Tab page's suggestions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(next): rapid workspace e2e skips workspaces the sidebar never shows (cx-7cit9) Home is in the daemon's list-workspaces but has no sidebar row; the count and order checks compare only the workspaces shown at the start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(next): queue workspace creates and closes per window (cx-7cit9) Cmd-N at key-repeat speed started every create at once, so the daemon numbered workspaces in arrival order with gaps, and a Cmd-Shift-W pressed before a new workspace was mirrored closed the one the window still showed. Each window's creates and closes now run one at a time, in the order they were pressed (WorkspaceLanes). The workspace key is fixed at the press, so a close pressed while a create waits or is in flight takes exactly that workspace: one not started never runs, one in flight closes once the daemon made it. The create body moves from WindowManager to WorkspaceSpawner (the god-type budget). Not-found refusals are quiet for keyboard and menu runs, so a gone target is a no-op instead of a "no workspace <uuid>" notice; the socket still answers not_found. The New Tab omnibar lists only terminal and browser tabs, not every New Tab page as "about:blank". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(next): rapid workspace e2e checks press order under any placement (cx-7cit9) New workspaces go to the top by default, so the sidebar is not in the daemon's order; the new rows must instead be in press order. Home stays a live workspace for the New Tab check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(next): capture the spawn command, not the shadowed spawn (cx-7cit9) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: 20 Cmd-N with closes in between keep every workspace in press order (cx-7cit9) Real daemon and launch window: 20 named presses inside a second with Close Workspace pressed after presses 5, 6, 12 and 18. Every workspace not closed must be in the window's sidebar in press order, each close must take exactly one, and no press may fail or show a notice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…x-t2x.8) (#19802) * ci: publish art thumbnails and a public manifest to files.cmux.com (cx-t2x.8) cmux.com/art and the in-app Browse page read the collection from cmux-art/manifest.json: art/manifest.json plus each work's image and thumbnail URL. Thumbnails upload write-once by their own SHA-256. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: check ids before reading thumbnails; verify a served thumbnail (cx-t2x.8) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…kql5h) (#19797) Real Chromium, both New Tab screens rendered the way the agent pane renders them: a host update hands the screen new callbacks. Types "hello world 123" a key at a time with a page render before each, as the bead's keys came. Red on #19749's parent (both screens keep only "3"), green on base. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…cx-rppd.4) (#19722) * test: bring a VM's edits, commit and chat back to the Mac Two boundary tests of cmux link sync pull against the fake fs-v1 socket link_sync.rs already uses: an edit, a delete, a new file and a commit made on the machine come back (the branch fast-forwards, git status matches the machine's) while its hooks, config, ignored output and new .env files stay there; and a file changed on both sides is a conflict that changes nothing here, as is a branch both sides moved. A Linux journey, the reverse of cloud_move_journey.rs, with real processes: a Cloud-VM-shaped daemon whose chat runs in ~/work/app with history, a running turn and a queued prompt, and a local daemon. An edit and a commit made on the VM come back with link sync pull, then link agent move takes the chat back under the Mac's web guard, where its queued prompt runs once. A chat that approves everything is refused with transfer.policy and stays open on the VM. The journeys share their machine helpers in tests/journey_support. cmux link sync pull does not exist yet, so these fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux link sync pull: bring a pushed folder back by a three-way merge cmux link sync pull --socket LINK_SOCKET LOCAL REMOTE merges what a push left on a Cloud machine back into the local folder, against the push manifest as the base. Per file: the machine's still as pushed keeps the local one, the local still as pushed takes the machine's (written, or deleted), both changed alike settles, both changed differently is a conflict. New machine files come back unless the working copy ignores them, they are untracked .env files, or they are not regular files. Any conflict changes nothing and answers {"ok":false,"error_code":"sync_conflict","conflicts":[paths]}. Otherwise the machine's files are first staged in a folder of the pull, the local files are checked again, and each moves into place by rename, through no symlink, with 0644, 0755, 0600 or 0700 permissions. The git leg takes the same three-way rule for HEAD and for what is staged. The push now records the branch, HEAD and a digest of git ls-files --stage in its manifest. When the local branch is still at the pushed commit, it fast-forwards to the machine's; a switched branch, a rewritten history or both sides moving is a conflict. The machine's objects (loose objects and pack data, never its pack indexes) go into a quarantine repository whose object store borrows the local one; git fetches only what the new commit and staged tree need from it with transfer.fsckObjects, and the branch moves by update-ref compare and swap. The machine's hooks, config, info and refs files never come back. The manifest then records the merged state, so a second pull finds nothing new. Unix only, like the rest of the link module. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: make the machine's hooks folder before writing a hook there The push sends no .git/hooks folder, so the pull test made none to write its machine hook into and stopped before the pull ran. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux link sync pull: clippy fixes; journeys bind install-host tabs (cx-k21v) A registry: tab of a store takes its session only from agent-session-start since cx-k21v, so the journeys' stand-in for a client's chat tab records an install host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the bring back journey starts its approve-all chat under an approving profile Only the person's app may switch a chat to approve-all (cx-1l61), so the journey starts that chat under a fake-approve harness profile instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a malicious machine can't plant a hook, climb out, half-apply or lie about the base The fake fs-v1 machine can now plant hostile listing entries. A pull must not bring back .GIT, git~1 or a nested repository, must refuse listed names that climb (x/../.git/hooks/..., ../escaped.txt), must leave the files, branch and index unchanged when it fails partway, and must use the copy of the push record this Mac kept, refusing a missing or different one. The names helpers are stubs with today's rules; their unit tests cover git's HFS and NTFS .git spellings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at f93b4f7 - cargo fmt in cmux-tui Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38208995763 * test: compare names, not paths, for a repository folder under another spelling On a Mac's case-insensitive disk .GIT exists wherever .git does, so the test looks for the planted names in the folder's listing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux link sync pull: treat the machine as hostile - A listed name must be one plain component, or the listing is refused (sync_unsafe_name). No path that reads as .git under git's HFS and NTFS rules (.GIT, git~1, .git., ignorable code points) comes back, nor any folder below the top holding one (a nested repository). - The base is this Mac's own copy of the push record, kept in its state folder by local folder and machine folder; a missing copy is sync_no_base and a machine record that differs is sync_base_mismatch. - All or nothing: files are staged and the machine's commits fetched first; then files move into place through folder handles (openat, renameat, unlinkat, mkdirat with O_NOFOLLOW), each replaced or deleted file moved aside, and the branch (compare-and-swap) and index move last after this Mac's branch and index are checked again. Any failure puts back the files, and the branch if the index can't follow. - A file's revision is read before and after its content, which streams to disk; pack and object files stream with a 4 GiB cap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 47ca161 - cargo fmt in cmux-tui Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38209935609 * cmux link sync pull: fmt and clippy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a hostile machine's repository shapes, hooks, fd load, races and endless answers Red first for the re-review of the pull: a planted bare-repository shape (HEAD, objects, refs, config), the working copy's hooksPath folder, 300 new folders under ulimit -n 128, a file edited after the plan, and answer lines, ids and listings that never end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 98b2197 - cargo fmt in cmux-tui Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38215666535 * fix: a pull never brings back a planted repository, hook folder or endless answer - A folder that is a repository on either side (a .git, HEAD or commondir) is fenced off: nothing in it comes back or is deleted. A top with a repository's shape keeps out its repository names. - The folder core.hooksPath names (and .husky above .husky/_) is fenced. - The transaction keeps folders by path, so it holds no handle per file. - A file is moved aside, then checked against the plan; one edited after the plan goes back and the pull answers sync_conflict. Files are placed and put back with a hard link, never over a file made meanwhile. - Roll back reports what it could not put back and keeps the staging folder (also on panic). - Answer lines, answers for other requests and listing pages are capped. - The staged tree is rebuilt from the machine's entries in a new index, not taken from its cached trees. The .cmux-sync filter ignores case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at c40e787 - cargo fmt in cmux-tui Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38216347988 * test: the hooks fence ignores case, and the git leg refuses hooks and repositories Red first for the second re-review: core.hooksPath spelled .GitHooks, and a machine commit or staged change that adds a hook or a bare repository's shape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: case-blind hook fence, and the git leg refuses hooks and repositories - The hooks and fenced-folder checks compare names as a Mac's disk does (case and HFS-ignorable code points ignored). - A machine commit or staged tree that adds or changes a path in a hooks folder, a .git under any spelling, or a HEAD or commondir in a subfolder is a conflict (.git/HEAD or .git/index). - A repository here in a folder the push sent is fenced even when the machine no longer lists it. - Roll back removes a placed file only if it is still the one placed. - The staging folder has a name of its own and is never reused. - All listings together are capped at 2,000,000 entries. - core.hooksPath with ~/ or through a symlinked prefix is resolved. - ENOTSUP and EOPNOTSUPP are one value on Linux (clippy there). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(next): PR autofix at 19e2f4c - cargo fmt in cmux-tui Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38220021551 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com>
* test: the New Tab field keeps its caret across updates and a click into it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the New Tab field takes the keyboard once, not on every update The page's focus effect depended on the input-ready callback, which the App makes anew on each render, so every update and a click into the focused field focused and selected it again: the caret blink restarted and the text under the caret was selected. It runs once per input token now (and on Cmd-L). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the default New Tab is the composer and five recent chats, with a real send button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: an open menu draws no focus ring around itself Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: a calm default New Tab with a real Send button, and no focus ring around open menus The default New Tab is the composer and the five newest chats as quiet rows, with All Chats for the rest; the action row, Recently Closed and the All chats table leave the default (the other templates keep theirs). Send is the composer's arrow-up disc, off while the field is empty. An open menu, list or popover takes focus so its keys work; the global keyboard rings no longer draw a square around it, and the focus-ring lint refuses a universal ring that would. Monaco's find fields draw no ring of their own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: lists that take Tab focus keep their ring; only open menus and popovers drop it Review: the Cloud machine list and the History list are themselves the focus target, so leaving [role=listbox] out of the ring hid their keyboard focus. Drops the classic page's unused tools and onRunAction props. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: the New Tab's recent chats are one-line rows The list variant set height 30px, but the card's 84px min-height won, so every row drew three lines tall (fleet capture of the calm default; Threads and Console had it too). The calm-default gallery play now refuses a row taller than one line: 84px before, 30px after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the New Tab page has no tools row, so no Integrate a harness button in it The base's #19755 test rendered the tools row the calm default removes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: New Tab scrolls in one place and fades at its edges Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: New Tab scrolls in one place and fades at its edges Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a short New Tab keeps two rows of list, and the page never fades Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep two rows of New Tab list, fade only the list Review: in a short pane the list collapsed to nothing behind the hidden page overflow, the page's fade dimmed the composer's model menu (it opens inside the page), and the list's fades covered its first and last rows. The list now keeps two rows and the page scrolls below that; only the list fades, over end padding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The gallery's play checks caught the hand-placed popover: All chats rows painted over it (their mask makes a stacking context) and, in Chromium, it grew .nt-screen's scroll so the page shifted. The rows now sit in the shared ui/Popover (portaled to the popup layer, as wide as the composer box, focus left in the field), mounted only while there are rows. The New Tab jsdom tests that type gain the DOM globals Base UI and Floating UI read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Found 1 test failure on Blacksmith runners: Failure
|
|
Unclear: CI failed on
Not re-run automatically: Written by |
|
Agents: |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>






Typing in the New Tab field ("Ask anything or type a URL") had three problems:
Leo asked for a real omnibar. Bead: cx-gl7dv, taken over from op-next-motion.
What changed
about:page are left out of the popover's rows. A split page's Open Tabs list still lists them, so a blank tab can be moved.This widens cx-e2aa's rule (rows only for addresses and other tabs, 2026-10-09). Workspaces, Search and Ask now also get rows, as Leo asked on 2026-10-12.
Verification
webviews/test/new-tab-omnibar.test.tsx, run withbun test webviews/test/new-tab-omnibar.test.tsx:.nt-popover, and a prompt had no Ask row.new-tab-no-agent,new-tab-send-button,new-tab-default-agent) andui-rulespass.bun run checkpasses, including the layers, type-scale, format and lint checks.typed-redditshows "reddit" typed over the page.typed-tab-matchandtyped-addressnotes are updated.newTab.row.searchFor("Search the web for {text}"), with all 21 locales. Non-English values are marked needs_review.generated/strings.jsonwas regenerated (gen-strings.mjs --check agentPanepasses). The Ask and Switch-to-workspace rows reuse existing keys.Changelog
Showcase
Open the live gallery
🤖 Generated with Claude Code