Skip to content

[twarp 07b] Claude Code panel: main-pane host + claude-at-submit trigger#71

Open
timomak wants to merge 3 commits into
masterfrom
twarp-07b-pane-host
Open

[twarp 07b] Claude Code panel: main-pane host + claude-at-submit trigger#71
timomak wants to merge 3 commits into
masterfrom
twarp-07b-pane-host

Conversation

@timomak
Copy link
Copy Markdown
Owner

@timomak timomak commented Jun 2, 2026

Summary

Sub-phase 7b of feature 07 (Claude Code panel). Per the main-pane re-spec (#70, merged), this relocates the Claude Code chat renderer that #69 landed in the left sidebar into a first-class main-content pane, adds the claude-at-submit terminal trigger that opens it, and deletes the #69 sidebar host.

Nothing new is re-introduced from a branch: the crates/claude_code driver and the ported transcript renderer are already on master (via #69). This PR moves the renderer into a pane and wires the entry point.

What changed

New pane type (IPaneType::ClaudeCode), modeled on the simplest existing non-persisted pane (NetworkLogPane/NetworkLogView):

  • app/src/claude_code_view.rs — the [twarp 07b] Claude Code panel: panel shell + ported transcript #69 renderer, repurposed as a BackingView (ClaudeCodeView). The transcript + docked composer are the pane body; the "Claude Code" + cwd header moves to render_header_content. Every render leaf (markdown body, code block, message rows, the synthetic source) is unchanged from [twarp 07b] Claude Code panel: panel shell + ported transcript #69. (File is a git mv of claude_code_panel/mod.rs so history is preserved.)
  • app/src/pane_group/pane/claude_code_pane.rsClaudeCodePane (PaneContent), the thin wrapper around PaneView<ClaudeCodeView>.
  • IPaneType::ClaudeCode enum/Display/render arm + PaneId::from_claude_code_pane_{ctx,view} factories.
  • LeafContents::ClaudeCodenon-persisted (a restored pane can't replay a live claude; twarp keeps no transcript store — session restore is claude --resume, 7h). Handled in is_persisted, restore_pane_leaf, sqlite::save_pane_state, launch_config, vertical_tabs.

Terminal trigger (claude at submit → open the pane), mirroring the existing OpenCodeInWarp/OpenFileInWarp chain exactly:

  • Input::try_execute_command_from_source intercepts a bare top-level claude before the PTY write. Detection is conservative (PRODUCT §3): tokenized with warp_completer::parsers::simple::top_level_command (no hand-rolled shell parsing) — pipelines, &&/; chains, subshells, and full paths are not intercepted; if claude isn't on PATH it's not intercepted (the shell's own error stands, §4); only CommandExecutionSource::User submissions qualify.
  • Emits Event::OpenClaudeCodePane { args, cwd } through input::Eventhandle_input_eventview::Eventhandle_terminal_view_eventpane_group::EventWorkspace::open_claude_code_pane.
  • The intercepted block shows a brief toast ("Opened Claude Code in a pane.") so the command isn't silently swallowed (§1), and the input is cleared.

Sidebar host deleted (the #69 placement the owner rejected): the ToolPanelView::ClaudeCode tab, toolbelt button, LeftPanelAction::ClaudeCode, LeftPanelDisplayedTab::ClaudeCode persistence, the WorkspaceAction::ToggleClaudeCodePanel / CustomAction action, and the ⌘⌥K binding are all removed.

Provisional decisions (flagged for review)

  • Placement: the pane opens as a focused split in the active tab's group via add_pane_with_direction(Direction::Right, …) — exactly what TECH §The pane prescribes and identical to how open_network_log_pane works. PRODUCT §load-bearing-2 marks "new tab vs split vs replace" as open; happy to switch to a genuine new top-level tab if preferred.
  • Inline note: implemented as a toast (the precedent already in try_execute_command_from_source). Can move to an in-block banner if you'd rather it live in the scrollback.
  • Args/cwd: forwarded through the event now (so 7c needn't re-plumb). In 7b the source is synthetic: a claude <prompt> seeds the first synthetic turn; cwd shows in the header.

Testing

  • cargo check -p warp0 errors, 0 warnings.
  • cargo clippy -p warp — clean.
  • cargo fmt --check on all changed files — clean.
  • cargo test -p claude_code19/19 pass (the kept driver crate is unchanged).
  • Conservative detection (§3) delegates to warp_completer's top_level_command, which already has test_top_level_command covering the piped/chained/path cases; the smoke test below exercises the edges manually.

Fork CI ends "cancelled" (no matrix runners), so the gates above are the local presubmit-equivalent.

Smoke test (7b — no live claude session needed)

  1. In a terminal, run claude → a Claude Code pane opens in the main content area and is focused; the terminal block shows a brief "Opened Claude Code in a pane" note and does not run raw claude.
  2. The pane shows the chat layout: a transcript area and a docked composer at the bottom. Type a message and press Enter → it renders as a user turn and a sample assistant reply renders as themed Markdown (heading, list, inline code, a fenced code block, a link) — not plain text.
  3. Run claude fix the bug → the pane opens with "fix the bug" already rendered as the first user turn (synthetic reply follows).
  4. Resize/split the pane; open a second Claude Code pane in another tab — both behave like normal panes; the tab title reads "Claude Code".
  5. Confirm conservative detection runs these raw (no pane): echo hi | claude, echo x && claude, /usr/bin/claude (full path), claudia.
  6. Temporarily remove claude from PATH and run claude → twarp does not intercept (the shell shows command-not-found). Restore claude.
  7. The left sidebar no longer has a Claude Code tab, and ⌘⌥K no longer toggles a chat.

🤖 Generated with Claude Code

timomak and others added 3 commits June 2, 2026 15:51
Relocate the transcript renderer #69 landed in the rejected left sidebar into
a first-class main-content pane (IPaneType::ClaudeCode), add the conservative
`claude`-at-submit terminal trigger that opens it, and delete the #69 sidebar
host. Per the main-pane re-spec (#70).

- ClaudeCodeView (BackingView) is the git-mv'd #69 renderer; transcript + docked
  composer are the pane body, the "Claude Code" + cwd header moves to
  render_header_content. All render leaves + the synthetic source are unchanged.
- ClaudeCodePane (PaneContent) mirrors NetworkLogPane; LeafContents::ClaudeCode
  is non-persisted (no transcript store; resume via `claude --resume`, 7h).
- Trigger mirrors the OpenCodeInWarp chain: Input intercepts a bare top-level
  `claude` (tokenized via warp_completer; pipes/chains/paths/off-PATH run raw),
  emits OpenClaudeCodePane through input::Event -> view::Event -> pane_group
  -> Workspace::open_claude_code_pane. Intercepted block shows a brief toast.
- Sidebar host removed: ToolPanelView::ClaudeCode, toolbelt button,
  LeftPanelDisplayedTab persistence, ToggleClaudeCodePanel action + the cmd-alt-K
  binding.

cargo check/clippy/fmt clean; claude_code 19/19 tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mark #70 merged

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ation

Two fixes found testing #71 on a real build:

1. Alias-aware trigger. Warp expands shell aliases at submit, so a user's
   `alias claude='command claude --flags'` reached the interceptor already
   expanded as `command claude …`; `top_level_command` then read `command`
   (the builtin) and the trigger never fired. `claude_pane_trigger` now peels
   leading env-var assignments and the `command`/`builtin`/`exec` run-a-program
   wrappers to recover the real program token, and forwards only a leading
   positional as the first turn (alias-injected flags are not a prompt).

2. Transcript no longer truncates. The ported `UniformList` clips every row to
   one measured height, so multi-paragraph assistant replies rendered as a
   single line. Render transcript items at their natural height in a
   `ClippedScrollable` column instead (a variable-height virtualized list can
   return later if very large sessions need it, PRODUCT §14).

cargo check/clippy/fmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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