Skip to content

feat(terminal): prompt and command marks from shell integration (#614) - #618

Merged
kipavy merged 1 commit into
devfrom
feat/osc133-prompt-marks
Oct 11, 2026
Merged

kipavy merged 1 commit into
devfrom
feat/osc133-prompt-marks

Conversation

@kipavy

@kipavy kipavy commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Closes #614

Problem

Shell integration reports only the working directory (OSC 7). A terminal knows a prompt was drawn, but not where a command's output starts or how the command exited. Jumping between prompts, copying the last output, exit-status marks and output-only decoration (#317) all need that.

Change

Shell hooks (src-tauri/src/shell_integration.rs)

  • bash, zsh and PowerShell now send OSC 133 A (prompt start), C (command start) and D;<exit> (finished), for local shells and for SSH, WSL and container sessions.
  • D and A ride on the existing OSC 7 printf, so a prompt is still one write. C comes from PS0 in bash, preexec_functions in zsh, and a wrapper around PSConsoleHostReadLine in PowerShell.
  • The hook text lived in five copies. It is now built from shared macro_rules! fragments (pwd_fn!, bash_hooks!, zsh_hooks!, zsh_env!, bash_login_chain!, sh_hooks!).
  • Comments that were being sent inside the SSH bootstrap moved to Rust doc comments. The persistent payload is under the 8192-byte cap with the new hooks; it measured 7408 bytes before the comments came out.

Frontend

  • src/components/terminal/commandMarks.ts: a tracker that turns the marks into command regions (prompt line, output start, end line, exit code, start and end time). Positions are xterm markers, so they follow scrollback trimming.
  • useTerminal.ts registers the OSC 133 handler next to the OSC 7 one and exposes getCommandRegions(sessionId).
  • Nothing consumes the regions yet. Sessions that send no marks behave as before.

Deviations from the issue

  • No B (input start). It is the only mark that needs the user's prompt edited, and no planned feature needs it. The tracker records B when the user's own prompt sends it.
  • bash below 4.4 has no PS0, so it sends no C: prompts are tracked, output regions are not.
  • POSIX sh fallback and cmd send no marks.
  • fish gets no hook and relies on its own marks. Not tested.

Open questions from the issue

  • tmux control mode: passes the marks. Checked live on tmux 3.7c with bash and zsh.
  • Reattach: the terminal is reset, so the region list restarts empty. The first command typed at the restored prompt is not tracked, because that prompt's A was never replayed.
  • Duplicate marks: a prompt marked twice on one line counts once; a second C or D for the same command is ignored.
  • Nested shells (ssh, sudo su): the outer command stays open until the outer shell reports again, which is what is happening.

Testing

  • cargo fmt --check and cargo clippy --workspace --all-targets -- -D warnings clean.
  • cargo test --lib shell_integration: 33 pass. New tests run real bash and zsh (zsh is skipped when not installed) and compare the mark sequence.
  • tsc --noEmit clean. 9 new tracker tests; src/hooks suites pass (284 tests).
  • Live debug build in a private headless container: local bash, SSH bash without a multiplexer, SSH bash and zsh through tmux control mode. Regions, exit codes and timings matched the commands run.
  • PowerShell 7.4.6 on Linux, script run standalone, also under Set-StrictMode -Version Latest.

Not covered

  • Windows PowerShell 5.1, WSL and container sessions were not run.
  • bash 3.2 (macOS) takes the no-C path; not run.

Shell integration reported only the working directory, so a terminal knew a
prompt had been drawn but not where a command's output started or how it
exited. The bash, zsh and PowerShell hooks now also send OSC 133 A (prompt
start), C (command start) and D (exit status), for local shells and for SSH,
WSL and container sessions.

Each terminal records them as command regions: prompt line, output start, end
line, exit code and timing, read through getCommandRegions(sessionId). Regions
follow scrollback trimming and are not opened on the alternate screen. Nothing
consumes them yet.

The hooks never edit the prompt, so B (input start) is not sent; it is recorded
when the user's own prompt sends it. bash below 4.4 has no PS0 and sends no C.
The POSIX sh fallback and cmd send no marks. fish relies on its own.

tmux control mode passes the marks through. After a reattach the list restarts
empty, and the first command typed at the restored prompt is not tracked.

The hook text lived in five copies in shell_integration.rs and is now built
from shared fragments. Comments that travelled inside the SSH bootstrap moved
to Rust doc comments, which keeps the payload clear of the 8192-byte cap.

Closes #614
@kipavy
kipavy merged commit b56f6dd into dev Oct 11, 2026
5 checks passed
@kipavy
kipavy deleted the feat/osc133-prompt-marks branch October 11, 2026 14:56
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