Repository navigation
cmux NEXT: view a Claude Code or Codex session without taking it over - #21921
Conversation
session/new with _meta.acpmux.adopt.watch finds the conversation as adopt does but starts no harness: acpmux reads the transcript into history and follows what the other app appends, writing nothing to it. The chat refuses prompts (watch.read_only) and its summary carries watching: family, until _acpmux/watch_take_over ends the watch; that refuses with adopt.live while the original still runs unless ifLive forks or opens it, and the next prompt resumes the conversation as for any idle chat. The read position is saved, so a watch survives a daemon restart. Web connections cannot take over. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The composer is off while acpmux shows a Claude Code or Codex chat another app runs; Take Over asks acpmux to run it, and a chat still live elsewhere asks whether to fork or open it anyway. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ux-watch-session # Conflicts: # cmux-tui/crates/acpmux/src/hub/lifecycle.rs
…view One opener for every entrypoint (ChatsOpenCoordinator.watch): the All chats row menu's View Only (chats.watch), the agentChat.view action, and `cmux agent view <chat>`, which takes an index key, a transcript path or a bare session id. 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 |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Gallery before/after for
States
Pick other states with a Not verified: macOS jobs did not run: compile and app tests were skipped on CI passes on Written by web and size checks: green
Tour of |
|
Agents: |
|
Bead |
This comment has been minimized.
This comment has been minimized.
|
Visual preview of b246cef: in the maintainers' private review feed. |
…e allows Take Over Review fixes for the watch PR: - child_for refuses a watched chat, so the pane's warm-up, a mode or model pick, or a fork never resumes the original conversation before Take Over. - The pane transport allows _acpmux/watch_take_over (it was default-denied). - The open watched turn is kept in the session meta: a daemon restart goes on with it instead of marking it failed, and Take Over settles it. - A Claude turn ends on its text line, not the thinking line before it. - A cut file is followed from its end (no duplicated history); a line over 4 MiB is skipped instead of stalling the watch; answer pieces read as paragraphs; a purged or closed chat's meta is not written back. - adopt.watch with ifLive fork is refused; Take Over's live choice shows only on its chat. - cli.rs keeps mod app unix-only. - CmuxNextApp does not grow: ChatOpenSubject moves to CmuxNextAgentPane and the refusal to RefusalStrings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nder 1000 lines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
A review subagent read Blocking
Medium Low
Also fixed after the first CI run:
|
Leo 2026-10-19: viewing is an extra option, never a gate. The View Only banner offers Continue in New Chat, which forks a Claude Code session into a new chat, and for Codex (which cannot be forked while another app runs it) New Chat Here in its folder. An adopt with ifLive fork no longer returns the chat that already adopts or views the conversation. New test: a new chat in the viewed chat's folder runs, and a fork is its own chat while the view goes on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Open on a Claude Code or Codex chat another app runs shows it View Only (Debug toggle agent.openOutsideChatsViewOnly, default on); other harnesses open as before. The composer stays on: sending takes the chat over first, and while the other app still runs it the pane asks how and keeps the message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A profile is named freely (fakecodex, claude-work, a subrouter account), so the open route must not read the family off the profile's name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_acpmux/chat_open's adopt plan says the chat's family (claude, codex, opencode); the open route watches a Claude Code or Codex chat by that, so a profile named claude-work or a subrouter account still opens View Only. A daemon without the field falls back to the profile's name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…watch-session # Conflicts: # webviews/src/agent-session/acpmux/generated/strings.json
…eo/acpmux-watch-reply-takes-over # Conflicts: # Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/AgentPaneTunables.swift
- regenerated plans/cmux-next/action-surfaces.json - regenerated plans/cmux-next/actions.md - regenerated schemas/defaults/cmux-next.json - vp fmt webviews/src/agent-session/acpmux/replyHref.ts - vp fmt webviews/src/pages/markdown/links.ts - vp fmt webviews/test/markdown-cmux-app-links.test.ts Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39208471588
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (claude-opus review subagent): BLOCK at f776fe7 I read the diff against Blocking
Checked and right
Not this PR's reds
Should fix (not blocking, carried over)
Once item 1 is wrapped and |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
# Conflicts: # cmux-tui/crates/acpmux/src/server/change_kind.rs
|
Review (claude-opus review subagent): SHIP at 397c459 I read the changes since my BLOCK at f776fe7: c40a7f2, and the base merges 09a8c2d and 397c459. I also read the whole PR against its merge base 76f7e42. I built nothing locally. The blocker is fixed
The merges are right
Still open (not blocking, carried over)
CI at this head when I posted77 passed, 0 failed, 19 pending. |
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (claude-opus review subagent): SHIP at 951b84b The only commit since my SHIP at 397c459 is the base merge 951b84b (second parent 80f4317). I compared it against base and built nothing locally. The merge only brings in base
CI at this head when I postedNo failed checks: 69 passed, 2 neutral, 50 skipped, 7 still running or queued. The ones not finished are Still open (not blocking, carried over)
|
…t as the Swift host does (base red) The macOS host's AcpmuxPaneMethods lists two pane methods policy.json lacks: - _acpmux/attachment (#20411): requests, knownParams [sessionId, id] - _acpmux/watch_take_over (#21921): requests, sessionScoped, knownParams [sessionId, ifLive] so tests/swift.rs (the_requests_are_the_macos_hosts, the_known_params_are_the_macos_hosts) fail on feat-cmux-next and are skipped in scripts/ci/cmux-tui-base-red.tsv (cx-c0wvp). Add both to policy.json as Swift has them and drop the two skips. The typescript.rs skip stays, with its reason brought up to date. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15df4-118f-7020-8a15-dbb7b04d4092&host=cosmic-gray
…t as the Swift host does (base red) (#23447) The macOS host's AcpmuxPaneMethods lists two pane methods policy.json lacks: - _acpmux/attachment (#20411): requests, knownParams [sessionId, id] - _acpmux/watch_take_over (#21921): requests, sessionScoped, knownParams [sessionId, ifLive] so tests/swift.rs (the_requests_are_the_macos_hosts, the_known_params_are_the_macos_hosts) fail on feat-cmux-next and are skipped in scripts/ci/cmux-tui-base-red.tsv (cx-c0wvp). Add both to policy.json as Swift has them and drop the two skips. The typescript.rs skip stays, with its reason brought up to date. Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15df4-118f-7020-8a15-dbb7b04d4092&host=cosmic-gray Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Shipped in:
|
Leo wants to see a Claude Code or Codex session open in cmux NEXT next to the app that runs it, to compare the UI and move over gradually, without cmux taking the session away. This adds a View Only open: cmux NEXT shows the chat and follows the app as it writes, and it never resumes, writes to or locks the original. Take Over is a separate, explicit step. Viewing never blocks starting a session: new chats, harness picks and folders work as before, and the viewer always offers a new chat of its own.
Behavior
session/newwithadopt.watch: true(Claude Code or Codex) looks up the transcript the way adoption does:~/.claude/projects/**/<id>.jsonl, or a Codexrollout-…-<id>.jsonl. It does not start the harness. The chat replays the transcript into acpmux history, then reads only new complete lines every 400 ms and shows each prompt and answer as it lands. It stores the file and the byte offset (SessionMeta.watching), so a daemon restart picks up where it stopped. A transcript that is replaced or truncated is read again from the start.--resume,session/loador lock. A prompt is refused withwatch.read_only, and web origins cannot use_acpmux/watch_take_over(watch.origin_refused)._acpmux/watch_take_overends the watch. The next prompt resumes the conversation as an ordinary adopted chat. If the transcript was written in the last few minutes, Take Over first answers with the sameadopt.livedetails an adopt does. The page then asks whether to fork the chat (Claude Code only) or open it anyway.claude --resume <id> --fork-session), so the original is only read. For Codex, which cannot be forked while another app runs it, New Chat Here starts a Codex chat in the same folder. The viewed chat stays as it is. An adopt withifLive: forknow always makes a new chat; before, it could return the chat that already adopted or viewed the conversation. This only adds a button and changes no existing flow, so it has no Debug toggle.watching: "claude" | "codex". The pane shows "Viewing Claude Code session" with a Take Over button, and the composer is off with "Take over this session to send messages".chats.watch), the palette's View Chat Only (agentChat.view) andcmux agent view <chat>all callChatsOpenCoordinator.watch. That coordinator is the Open Chat path withadopt.watchset.<chat>is an index key (claude-code:<id>,codex:<id>), a transcript path, or a bare session id; a bare id is Claude Code's when its transcript is under~/.claude/projects, otherwise Codex's.cmux agent view show|ensure|…keep their sidebar-view meaning.Supporting changes:
hub/lifecycle.rswas at the 1000-line limit. Its route check moves toroute_switch.rs::check_new_route.cli.rsis at 993 lines. The positional chat foragent viewlives incli/agent_view.rs.server/requests.rsstays under the line limit: adopt and Take Over share oneIfLive::parse.ChatOpenSubjectmoved toCmuxNextAgentPane, and the View Chat Only refusal moved toRefusalStrings.feat-cmux-nextat59d0076. The base this branch started from failed to compilecmux-sdk'shome_conversation_livetest, and that is fixed upstream.Validation
Hosted CI only; nothing was built on a Mac.
tests/hub_integration/watch.rs:initializeorsession/loadis recorded;viewing_a_chat_never_blocks_starting_a_new_one).test_filter=watch: 39204810572, in progress.cli/agent_view.rs: key, path and bare-id mapping, and sidebar view verbs are left alone. Focused runtest_filter=agent_view: 39204813047, in progress.AgentChatViewTests: View Only sendswatch: truein the adopt handshake, and an ordinary open sends none.chats.watchdecodes, and the action takes only Claude Code or Codex keys. These run in this PR's cmux-next checks.watch-banner.test.tsx: the banner names the app and offers Take Over plus Continue in New Chat (Claude Code) or New Chat Here (Codex);all-chats-view-only.test.tsx: the row menu offers View Only, off for chats acpmux cannot watch, and it calls back with the row's key.tsc --noEmitis clean.plans/cmux-next/action-surfaces.json) are left to the autofix bot, which regenerates them on a Mac runner.Not verified: a live run against a real Claude Code or Codex session in a built app, and the side-by-side capture against the Claude app. That needs a dogfood build (
dev-buildlabel) on a machine with those apps signed in.Limits
Changelog
cmux agent view): the chat follows the app that runs it without taking it over, until Take Over.Context: manaflow-ai/cmuxterm-hq#2503. Related: #21253 (read-only observe of an acpmux session, which complements this one).
No capture: View Only needs a Claude Code or Codex transcript written outside cmux, and a capture slot has none. The banner and the All chats menu row are webview UI, covered by
watch-banner.test.tsxandall-chats-view-only.test.tsx.🤖 Generated with Claude Code
Agent session: cosmic-gray