Skip to content

feat: clear scrollback history on clear commands#306

Merged
Kitenite merged 3 commits intomainfrom
brief-alligator-e569b2
Dec 10, 2025
Merged

feat: clear scrollback history on clear commands#306
Kitenite merged 3 commits intomainfrom
brief-alligator-e569b2

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Dec 10, 2025

Summary by CodeRabbit

  • New Features

    • Added a clear-scrollback action accessible from the terminal UI to reset both visible and stored scrollback.
  • Improvements

    • Detects terminal clear escape sequences to ensure proper clearing behavior.
    • Terminal history is written/read using explicit UTF-8 encoding.
  • Tests

    • Added test coverage verifying clear behavior, history reinitialization, and handling of clear sequences.

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

- Add clearScrollback method to TerminalManager that clears in-memory
  scrollback and reinitializes history file
- Add clearScrollback tRPC endpoint for renderer to call
- Detect clear scrollback escape sequences (ESC[3J, ESC c) in PTY output
  to automatically clear stored buffers when shell clear command is used
- Update Terminal component to call clearScrollback on Cmd+K
- Use explicit UTF-8 encoding for terminal history read/write

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@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:03am

@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 1 minutes and 0 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 1d400e1 and 591acb3.

📒 Files selected for processing (1)
  • apps/desktop/src/main/lib/terminal-escape-filter.ts (2 hunks)

Walkthrough

Adds a terminal scrollback-clear feature end-to-end: detects clear-scrollback escape sequences, enforces UTF-8 for history IO, exposes a TRPC mutation, extends TerminalManager with clear/reinitialize logic, and wires the renderer UI to invoke the mutation.

Changes

Cohort / File(s) Summary
TRPC Terminal Endpoint
apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
Adds clearScrollback(input: { tabId: string }) TRPC mutation that delegates to TerminalManager.clearScrollback.
Escape Sequence Detection
apps/desktop/src/main/lib/terminal-escape-filter.ts
Adds CLEAR_SCROLLBACK_PATTERN and containsClearScrollbackSequence(data: string): boolean to detect ESC[3J and ESC c clear-scrollback sequences.
Terminal History UTF-8 Encoding
apps/desktop/src/main/lib/terminal-history.ts
Makes file read/write and Buffer conversions explicitly use UTF-8 encoding when initializing, appending, and reading scrollback.
Terminal Manager Clear Handling
apps/desktop/src/main/lib/terminal-manager.ts
Imports containsClearScrollbackSequence; detects clear sequences during data events; adds public clearScrollback(tabId: string) and private reinitializeHistory(session) to reset in-memory scrollback, reset escape filter, and recreate history writer.
Terminal UI Integration
apps/desktop/src/renderer/.../Terminal/Terminal.tsx
Adds trpc.terminal.clearScrollback mutation and ref; wires onClear handler to clear the xterm display and call the mutation with the current tabId.
Tests
apps/desktop/src/main/lib/terminal-manager.test.ts
Adds tests for TerminalManager.clearScrollback (clearing scrollback, history reinitialization, handling missing sessions, responding to clear sequences). Note: the new test suite appears duplicated within the file.
Minor comment cleanup
apps/desktop/src/renderer/.../Terminal/helpers.ts
Removes several non-functional comments; no behavioral changes.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as Terminal UI
    participant TRPC as TRPC Router
    participant Manager as TerminalManager
    participant Filter as EscapeFilter
    participant History as HistoryWriter

    User->>UI: Press clear shortcut (e.g., Cmd+K)
    UI->>UI: Clear xterm buffer (local)
    UI->>TRPC: clearScrollback({ tabId })
    TRPC->>Manager: clearScrollback({ tabId })

    rect rgb(200,220,255)
    Note over Manager: Clear in-memory state & reset filter
    Manager->>Manager: session.scrollback = []
    Manager->>Filter: reset/reinitialize filter state
    end

    rect rgb(200,220,255)
    Note over Manager,History: Reinitialize persistent history
    Manager->>History: close writer (async)
    Manager->>History: recreate & initialize writer (truncate)
    end

    TRPC-->>UI: Success

    Note over Manager,Filter: On incoming PTY data containing ESC[3J or ESC c
    Manager->>Filter: containsClearScrollbackSequence(data)?
    alt detected
        Manager->>Manager: clear session.scrollback
        Manager->>History: reinitializeHistory(session) (async)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review TerminalManager.reinitializeHistory for race conditions and proper file/handle cleanup.
  • Verify containsClearScrollbackSequence is performant and invoked at correct point in data flow.
  • Inspect tests for the duplicated clearScrollback suite and ensure no accidental duplication or false positives.
  • Confirm TRPC mutation error handling and renderer ref lifecycle (unmounts) are robust.

Possibly related PRs

Poem

🐰 I hopped through bytes and ESC-filled night,
Cleared the scroll, made the session bright.
UTF-8 stitched each memory seam,
A cleaner terminal, carrot-powered dream. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete and does not follow the template structure; it lacks key sections like Description, Type of Change, Testing, and Related Issues. Add a proper Description section explaining the changes, specify Type of Change, document testing steps, link related issues (#302), and fill out other template sections.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: clearing scrollback history when clear commands are executed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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.

@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! 🎉

@Kitenite Kitenite changed the title brief alligator e569b2 feat: clear scrollback history on clear commands Dec 10, 2025
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: 1

🧹 Nitpick comments (2)
apps/desktop/src/main/lib/terminal-history.ts (1)

116-123: Minor inconsistency in encoding string format.

Line 118 uses "utf8" while line 123 uses "utf-8". Both are functionally equivalent in Node.js, but for consistency with the rest of this file (which uses "utf8"), consider using the same format.

 			const metaPath = getMetadataPath(this.workspaceId, this.tabId);
-			const metaContent = await fs.readFile(metaPath, "utf-8");
+			const metaContent = await fs.readFile(metaPath, "utf8");
apps/desktop/src/main/lib/terminal-manager.ts (1)

229-236: Consider adding minimal error logging for history reinitialization failures.

The silent .catch(() => {}) suppresses all errors from reinitializeHistory. While history errors are non-critical, a console warning could help diagnose issues if scrollback clearing stops working.

 			// Reinitialize history file asynchronously (truncate to empty)
-			this.reinitializeHistory(session).catch(() => {});
+			this.reinitializeHistory(session).catch((err) => {
+				console.warn(`Failed to reinitialize history for ${session.tabId}:`, err);
+			});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac34c59 and a046cde.

📒 Files selected for processing (5)
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts (1 hunks)
  • apps/desktop/src/main/lib/terminal-escape-filter.ts (2 hunks)
  • apps/desktop/src/main/lib/terminal-history.ts (3 hunks)
  • apps/desktop/src/main/lib/terminal-manager.ts (3 hunks)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
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/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/main/lib/terminal-history.ts
  • apps/desktop/src/main/lib/terminal-manager.ts
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/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/main/lib/terminal-history.ts
  • apps/desktop/src/main/lib/terminal-manager.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • apps/desktop/src/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/main/lib/terminal-history.ts
  • apps/desktop/src/main/lib/terminal-manager.ts
apps/desktop/src/main/lib/terminal-*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use node-pty for terminal session management in the desktop app

Files:

  • apps/desktop/src/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/main/lib/terminal-history.ts
  • apps/desktop/src/main/lib/terminal-manager.ts
apps/desktop/src/lib/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules like node:fs, node:path, node:os in src/lib/electron-router-dom.ts or similar shared code

Files:

  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
**/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/Terminal/Terminal.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/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
🧠 Learnings (1)
📚 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/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/main/lib/terminal-history.ts
  • apps/desktop/src/main/lib/terminal-manager.ts
🧬 Code graph analysis (2)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (1)
apps/website/src/trpc/server.tsx (1)
  • trpc (26-30)
apps/desktop/src/main/lib/terminal-manager.ts (2)
apps/desktop/src/main/lib/terminal-escape-filter.ts (2)
  • containsClearScrollbackSequence (272-274)
  • TerminalEscapeFilter (115-247)
apps/desktop/src/main/lib/terminal-history.ts (1)
  • HistoryWriter (30-105)
🪛 ast-grep (0.40.0)
apps/desktop/src/main/lib/terminal-escape-filter.ts

[warning] 17-17: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${ESC}\\[3J|${ESC}c, "g")
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (7)
apps/desktop/src/main/lib/terminal-escape-filter.ts (1)

17-18: Static analysis false positive - no ReDoS risk.

The static analysis warning about ReDoS is a false positive. ESC is a compile-time constant ("\x1b"), not user input, and the pattern has no nested quantifiers or catastrophic backtracking potential.

apps/desktop/src/lib/trpc/routers/terminal/terminal.ts (1)

148-160: LGTM!

The new clearScrollback mutation follows the established patterns in this router, with proper input validation and async handling. The documentation clearly describes its purpose.

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

71-82: LGTM!

The integration follows the established ref-based mutation pattern used throughout this component. The fire-and-forget approach for clearScrollback is consistent with other non-critical mutations like write.


306-311: LGTM!

The clear flow correctly prioritizes immediate UI feedback by clearing xterm first, then asynchronously clearing the persisted scrollback. This provides a responsive UX while maintaining backend consistency.

apps/desktop/src/main/lib/terminal-manager.ts (3)

6-9: LGTM!

The import correctly brings in both the containsClearScrollbackSequence function for detection and TerminalEscapeFilter class for filtering.


372-393: LGTM!

The clearScrollback method correctly clears in-memory state, resets the escape filter, and awaits history reinitialization. The await here (vs fire-and-forget in the data handler) is appropriate since this is an explicit user action where completion confirmation matters.


395-407: LGTM!

The helper correctly sequences the close-create-init operations and properly handles the case where historyWriter may not exist.

Comment thread apps/desktop/src/main/lib/terminal-escape-filter.ts
Add tests for clearScrollback functionality:
- Clear in-memory scrollback
- Reinitialize history file on clear
- Handle non-existent session gracefully
- Clear scrollback on shell ED3 sequence

Remove comments that restate what the code already expresses.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Using test() with a global regex causes stateful lastIndex behavior
leading to sporadic false negatives on consecutive calls.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@Kitenite Kitenite merged commit daee6b4 into main Dec 10, 2025
7 checks passed
@Kitenite Kitenite deleted the brief-alligator-e569b2 branch December 10, 2025 09:05
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/main/lib/terminal-manager.test.ts (1)

764-841: Optional: split multi‑assert tests to better follow “one assert per test” guideline

In this new block, several tests contain multiple expect calls (e.g., checking both scrollback and wasRecovered, or result + console.warn call, or two scrollback content checks). If you want to adhere more strictly to the “one assert per test” guidance, consider splitting these into smaller tests per behavior (e.g., one test for scrollback contents, another for wasRecovered, etc.). This is optional, but would bring the new tests closer to the documented style without changing coverage. As per coding guidelines, tests should ideally have one assert per test.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a046cde and 1d400e1.

📒 Files selected for processing (4)
  • apps/desktop/src/main/lib/terminal-manager.test.ts (1 hunks)
  • apps/desktop/src/main/lib/terminal-manager.ts (3 hunks)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx (2 hunks)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/desktop/src/main/lib/terminal-manager.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
🧰 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/main/lib/terminal-manager.test.ts
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/main/lib/terminal-manager.test.ts
apps/desktop/**/*.test.{ts,tsx,js,jsx}

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

apps/desktop/**/*.test.{ts,tsx,js,jsx}: Tests should have one assert per test
Tests should be readable
Tests should be fast
Tests should be independent
Tests should be repeatable

Files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
apps/desktop/src/main/lib/terminal-*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use node-pty for terminal session management in the desktop app

Files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
🧠 Learnings (5)
📚 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/main/lib/terminal-manager.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be repeatable

Applied to files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be independent

Applied to files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be readable

Applied to files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should have one assert per test

Applied to files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (1)
apps/desktop/src/main/lib/terminal-manager.test.ts (1)

737-842: Clear scrollback behavior is well-covered and tests look deterministic

The new clearScrollback suite exercises all the key scenarios (in‑memory scrollback reset, history reinit across process exit/cleanup, non‑existent sessions, and ED3 clear‑sequence handling) using the real history implementation and the existing mockPty wiring. Tab/workspace IDs are isolated and there are no added timing hacks, so these tests should remain repeatable and independent. Based on learnings, this aligns well with the “readable / independent / repeatable” test guidelines.

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