Skip to content

feat(desktop): add clear terminal option to right-click context menu#308

Merged
Kitenite merged 2 commits intomainfrom
outstanding-swordtail-9ac6b3
Dec 10, 2025
Merged

feat(desktop): add clear terminal option to right-click context menu#308
Kitenite merged 2 commits intomainfrom
outstanding-swordtail-9ac6b3

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Dec 10, 2025

Summary

  • Add "Clear Terminal" option to the terminal right-click context menu
  • Uses the Eraser icon and displays the ⌘K keyboard shortcut
  • Mirrors the existing CMD+K functionality for clearing terminal

Test plan

  • Right-click on a terminal pane
  • Verify "Clear Terminal" option appears below "Split Vertically"
  • Click "Clear Terminal" and verify terminal is cleared
  • Verify CMD+K still works as before

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a "Clear Terminal" action to the terminal context menu with keyboard shortcut (⌘K), enabling users to quickly clear terminal content directly from the UI.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 10, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
website Ready Ready Preview Comment Dec 10, 2025 9:41am

@Kitenite Kitenite force-pushed the outstanding-swordtail-9ac6b3 branch from dcebabb to dc4b33a Compare December 10, 2025 09:34
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 10, 2025

Warning

Rate limit exceeded

@Kitenite has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 23 minutes and 41 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between b260b97 and 7fe5f10.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (4 hunks)

Walkthrough

This pull request introduces a terminal clear feature by establishing a Zustand-backed callback system. A new store manages pane-to-callback mappings, the Terminal component registers its clear handler, TabPane retrieves and invokes callbacks, and a "Clear Terminal" context menu item with ⌘K shortcut is added to the UI.

Changes

Cohort / File(s) Summary
New Terminal Callbacks Store
apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts
New Zustand store managing a Map of pane IDs to clear callbacks. Exports TerminalCallbacksState interface and useTerminalCallbacksStore with methods to register, unregister, and retrieve callbacks.
Terminal Component Clear Integration
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
Adds store refs to access callback registration/unregistration, implements handleClear to perform xterm clear and scrollback operations, registers callback on mount, and unregisters on cleanup.
Context Menu and Pane Handler
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabContentContextMenu.tsx, apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
TabContentContextMenu adds onClearTerminal prop and displays new "Clear Terminal" menu item with Eraser icon and ⌘K shortcut. TabPane retrieves the callback from store and wires it to onClearTerminal. Replaces "Close Pane" label with "Close Terminal".

Sequence Diagram

sequenceDiagram
    participant User
    participant ContextMenu as TabContentContextMenu
    participant TabPane as TabPane
    participant Store as TerminalCallbacksStore
    participant Terminal as Terminal Component

    User->>ContextMenu: Click "Clear Terminal"
    ContextMenu->>TabPane: onClearTerminal()
    TabPane->>Store: getClearCallback(paneId)
    Store-->>TabPane: callback: () => void
    TabPane->>callback: invoke()
    callback->>Terminal: handleClear()
    Terminal->>Terminal: xterm.clear()
    Terminal->>Terminal: xterm.clearScrollback()
    Terminal-->>User: Terminal cleared
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Store implementation: Verify immutable state updates in registerClearCallback and unregisterClearCallback (Map cloning pattern).
  • Callback lifecycle: Confirm proper registration in Terminal's useEffect mount and unregistration in cleanup phase.
  • Props wiring: Validate onClearTerminal callback flow from TabPane through TabContentContextMenu and correct destructuring.
  • UI integration: Ensure ContextMenuShortcut display (⌘K) and Eraser icon import are correctly positioned in the menu.

Possibly related PRs

Poem

🐰 A terminal cleared with a whispered command,
No scrollback clutter left upon the land!
The rabbit hops through callbacks neat and clean,
Where Eraser icons brighten up the scene—
⌘K brings order to the digital sand! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately describes the main change: adding a clear terminal option to the right-click context menu, which is the primary focus of the changeset.
Description check ✅ Passed The PR description is mostly complete with a clear summary and test plan, though it deviates from the repository template by omitting several structured sections like Related Issues, Type of Change, and Screenshots.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Add "Clear Terminal" as a context menu option accessible via right-click,
mirroring the existing CMD+K keyboard shortcut functionality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Dec 10, 2025

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (1)

85-90: Consider updating refs consistently with the established pattern.

While these refs work correctly (Zustand store methods are stable), the pattern is inconsistent with other refs in this file. Lines 74-83 show that mutation refs are both initialized and updated:

const createOrAttachRef = useRef(createOrAttachMutation.mutate);
// ...
createOrAttachRef.current = createOrAttachMutation.mutate;

For consistency, consider adding updates for these refs as well, even though it's not strictly necessary.

 const registerClearCallbackRef = useRef(
   useTerminalCallbacksStore.getState().registerClearCallback,
 );
 const unregisterClearCallbackRef = useRef(
   useTerminalCallbacksStore.getState().unregisterClearCallback,
 );
+registerClearCallbackRef.current = useTerminalCallbacksStore.getState().registerClearCallback;
+unregisterClearCallbackRef.current = useTerminalCallbacksStore.getState().unregisterClearCallback;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d1f47d and b260b97.

📒 Files selected for processing (4)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabContentContextMenu.tsx (5 hunks)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx (3 hunks)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (4 hunks)
  • apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabContentContextMenu.tsx
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabContentContextMenu.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Maintain type safety and avoid using any unless absolutely necessary in TypeScript code

Files:

  • apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabContentContextMenu.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules in renderer process or shared code - only in src/main/

Files:

  • apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabContentContextMenu.tsx
**/components/**/[A-Z]*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Use one folder per component with structure ComponentName/ComponentName.tsx + index.ts barrel export

Files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabContentContextMenu.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Applies to apps/desktop/src/main/lib/terminal-*.ts : Use node-pty for terminal session management in the desktop app

Applied to files:

  • apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Applies to apps/desktop/src/main/lib/*{workspace,worktree}-*.ts : Use git worktree-based workspace management in the desktop app through workspace-manager.ts and worktree-manager.ts

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
🧬 Code graph analysis (3)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx (1)
apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts (1)
  • useTerminalCallbacksStore (10-34)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (2)
apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts (1)
  • useTerminalCallbacksStore (10-34)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts (1)
  • setupKeyboardHandler (181-244)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabContentContextMenu.tsx (1)
packages/ui/src/components/context-menu.tsx (2)
  • ContextMenuItem (244-244)
  • ContextMenuShortcut (249-249)
🔇 Additional comments (5)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx (1)

114-117: Implementation looks clean.

The callback retrieval and optional chaining correctly handle the case where a callback might not be registered yet.

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (1)

308-311: Callback lifecycle management is correct.

The handleClear function is properly defined within the effect scope, registered with the store after initialization, and unregistered during cleanup. The integration with the existing keyboard handler maintains backward compatibility with ⌘K.

Also applies to: 319-319, 323-323, 351-351

apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabContentContextMenu.tsx (2)

54-58: Clear Terminal menu item implementation is correct.

The Eraser icon, ⌘K shortcut display, and positioning before the separator align well with the PR objectives and maintain consistency with the existing keyboard shortcut functionality.


84-84: Label change improves clarity.

Changing "Close Pane" to "Close Terminal" makes the context menu more terminal-specific and intuitive for users.

apps/desktop/src/renderer/stores/tabs/terminal-callbacks.ts (1)

1-34: Well-designed Zustand store following best practices.

The implementation correctly:

  • Uses Map for efficient paneId-to-callback lookups
  • Maintains immutability by cloning the Map on updates
  • Returns undefined for missing callbacks, allowing safe optional chaining in consumers
  • Follows the pattern established by the existing pane-refs store

This aligns with the coding guideline to prefer Zustand for state management.

@Kitenite Kitenite merged commit 890b929 into main Dec 10, 2025
4 checks passed
@Kitenite Kitenite deleted the outstanding-swordtail-9ac6b3 branch December 11, 2025 03:06
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