Skip to content

fix: resolve 15-second SSH delay with fish shell prompt detection#1631

Merged
arnestrickmann merged 2 commits intogeneralaction:mainfrom
jasperan:fix/1597-fish-shell-prompt-detection
Mar 30, 2026
Merged

fix: resolve 15-second SSH delay with fish shell prompt detection#1631
arnestrickmann merged 2 commits intogeneralaction:mainfrom
jasperan:fix/1597-fish-shell-prompt-detection

Conversation

@jasperan
Copy link
Copy Markdown
Contributor

@jasperan jasperan commented Mar 29, 2026

Summary

Fixes #1597. The previous fix (#1615) addressed a different issue (focus-stealing, #1467) and didn't touch prompt detection.

  • Root cause: waitForShellPrompt tested each PTY data chunk independently against the prompt regex. Fish shell renders its prompt in multiple small writes over SSH (colored segments, escape sequences, prompt character). When > arrived in its own TCP segment without preceding non-whitespace context, the regex failed and fell back to the 15-second timeout.
  • Secondary cause: Fish's cursor save/restore escapes (\e7/\e8) and OSC-ST terminators weren't stripped, leaving non-whitespace bytes after > that broke the \s*$ anchor.

Fix (2 files, 3 changes):

  • Accumulate PTY chunks into a rolling buffer (4KB cap) so prompts split across TCP segments match against the full accumulated output
  • Pass additional strip options (stripOtherEscapes, stripOscSt, stripCarriageReturn) to handle fish's escape sequences
  • Expand stripOtherEscapes regex to cover Fe/Fp/Fs single-byte escapes (was only matching [A-Za-z], now matches all except CSI/OSC openers)

Test plan

  • 7 new test cases: fish prompt, TCP-split prompt, bare > rejection, Fe escapes, OSC-ST
  • All 27 waitForShellPrompt tests pass
  • All 9 stripAnsi tests pass (no regressions)
  • Full suite: 78 files, 782 tests pass
  • Type-check clean, format clean, lint clean on changed files
  • Manual verification: connect to SSH remote with fish shell, confirm no 15s delay

Summary by CodeRabbit

  • Bug Fixes

    • Improved shell prompt detection for fish-style prompts (e.g., "user@host ~>"), including prompts split across multiple terminal/chunked inputs.
    • Expanded removal of noisy terminal escape bytes and OSC terminators to reduce false positives while preserving valid control sequences.
  • Tests

    • Added tests covering split-chunk prompts, escape-sequence noise resilience, and a negative case ensuring a bare "> " alone does not trigger detection.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 29, 2026

@jasperan is attempting to deploy a commit to the General Action Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 621054e8-df78-4fec-98c4-a34fcf49454e

📥 Commits

Reviewing files that changed from the base of the PR and between 10d88f2 and ad446aa.

📒 Files selected for processing (3)
  • src/main/utils/__tests__/waitForShellPrompt.test.ts
  • src/main/utils/waitForShellPrompt.ts
  • src/shared/text/stripAnsi.ts
✅ Files skipped from review due to trivial changes (2)
  • src/main/utils/waitForShellPrompt.ts
  • src/main/utils/tests/waitForShellPrompt.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/shared/text/stripAnsi.ts

📝 Walkthrough

Walkthrough

Appends incoming PTY chunks to a capped rolling buffer, expands escape-stripping to remove OSC/other single-byte escapes and CRs, and runs prompt regexes against the cleaned buffer; adds tests covering fish-style prompts (including prompts split across chunks and noisy escape sequences).

Changes

Cohort / File(s) Summary
Test Coverage
src/main/utils/__tests__/waitForShellPrompt.test.ts
Added tests validating fish-style prompt detection (user@host ~>), prompts split across PTY chunks, delayed > arrivals, handling of cursor save/restore and OSC-ST noise, and rejecting bare > without prior context.
Prompt Detection Logic
src/main/utils/waitForShellPrompt.ts
Now sanitizes each incoming chunk with expanded stripAnsi options (strip other escapes, OSC, CRs), appends to a rolling prompt buffer (trimmed to max), and continues matching the combined cleaned buffer against prompt regexes. No exported signatures changed.
Escape Sequence Stripping
src/shared/text/stripAnsi.ts
When stripOtherEscapes is enabled, broadened final escape removal from /\x1b[A-Za-z]/g to /\x1b[^[\]]/g, removing ESC + any single byte except [ or ] to cover more single-byte ESC sequences while preserving CSI/OSC openers.

Sequence Diagram(s)

sequenceDiagram
  participant RemotePTY as Remote PTY
  participant Buffer as Rolling Buffer
  participant Stripper as stripAnsi
  participant Matcher as Prompt Regex
  participant Caller as waitForShellPrompt caller

  RemotePTY->>Buffer: emit chunk (may be partial)
  Buffer->>Buffer: append & trim (max buffer size)
  Buffer->>Stripper: sanitize(buffer, options)
  Stripper->>Matcher: cleaned text
  alt regex matches prompt
    Matcher->>Caller: finish() — prompt detected
  else no match yet
    Matcher-->>RemotePTY: await further chunks
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through bytes and clear the haze,
Stitching chunks in patient ways,
Fishy prompts no longer hide,
I scrub the noise and find the guide. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing a 15-second SSH delay caused by fish shell prompt detection issues.
Linked Issues check ✅ Passed The pull request directly addresses all coding objectives from issue #1597: buffering PTY chunks, stripping fish-specific escapes, expanding stripAnsi regex, and adding comprehensive test coverage.
Out of Scope Changes check ✅ Passed All changes are scoped to the prompt detection fix: modifications to waitForShellPrompt, stripAnsi, and corresponding tests; no unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/utils/__tests__/waitForShellPrompt.test.ts`:
- Around line 350-363: Test title says "detects prompt when > arrives alone
after accumulated context" but the test emits '$ ' instead of '> '; update the
test so the description matches the emitted token: either rename the it(...)
string to reference '$' (e.g. mention "$ arrives alone") or change the emitted
prompt in the body from pty.emit('$ ') to pty.emit('> '); ensure references to
waitForShellPrompt, createMockPty, and pty.emit are updated accordingly so the
assertion remains valid.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 46b76c10-a1ac-4bfe-9612-8d7cd30c6d1c

📥 Commits

Reviewing files that changed from the base of the PR and between e78b862 and 12549b9.

📒 Files selected for processing (3)
  • src/main/utils/__tests__/waitForShellPrompt.test.ts
  • src/main/utils/waitForShellPrompt.ts
  • src/shared/text/stripAnsi.ts

@arnestrickmann
Copy link
Copy Markdown
Contributor

@jasperan thank you for taking this on again!
Would be amazing if you could resolve the merge conflicts in waitForShellPrompt.ts - happy to merge then!

…neralaction#1597)

Fish shell renders prompts in multiple small writes over SSH, causing
the prompt character (>) to arrive in its own TCP segment without
preceding context. The per-chunk regex matching would fail and fall
back to a 15-second timeout.

Two fixes:
- Accumulate PTY chunks into a rolling buffer (4KB cap) so split
  prompts are matched against the full accumulated output
- Strip Fe escape sequences (\e7/\e8 cursor save/restore) and OSC-ST
  terminators that fish appends after the prompt character, which
  prevented the trailing \s*$ from matching
Rename test from ">" to "$" to match the actual emitted token.
@jasperan jasperan force-pushed the fix/1597-fish-shell-prompt-detection branch from 10d88f2 to ad446aa Compare March 29, 2026 21:25
@jasperan
Copy link
Copy Markdown
Contributor Author

done @arnestrickmann

@arnestrickmann
Copy link
Copy Markdown
Contributor

Thanks!

@arnestrickmann arnestrickmann merged commit 680a5e8 into generalaction:main Mar 30, 2026
3 of 4 checks passed
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.

[bug]: 15-second delay when connecting to SSH remote with fish shell

2 participants