fix: wait for a pane's shell to be ready before sending its command - #11
Open
19Naveen wants to merge 1 commit into
Open
fix: wait for a pane's shell to be ready before sending its command#1119Naveen wants to merge 1 commit into
19Naveen wants to merge 1 commit into
Conversation
A pane that was just created has a shell which has not started its line editor yet. `herdr pane run` sent immediately after `workspace create`, `tab create` or `pane split` is echoed to the PTY and then discarded during shell startup, so the configured `command` silently never runs, or arrives truncated (`claude --continue` landing as `p`). This is reliably reproducible with a heavyweight interactive shell (Oh My Zsh + powerlevel10k + a fastfetch banner) and is invisible in `--dry-run`, because the planned argv is correct — only the timing is wrong. The same `pane run` succeeds once the pane is about a second old. Poll the pane with `pane read` and wait for its output to stop changing before sending. Output stability alone is not sufficient: powerlevel10k's instant prompt paints very early, so the pane looks settled while the real line editor still does not exist. A minimum floor is enforced on top of the settle check, and both bounds are overridable: HERDR_SPREADER_READY_FLOOR_MS (default 1500) HERDR_SPREADER_READY_TIMEOUT_MS (default 10000, 0 disables) `CliBackend::with_ready_settings` exposes the same knobs in-process. The fake-herdr integration tests use it to disable waiting, so they keep asserting the exact argv sequence and stay fast.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Commands configured with
command:silently never run. The layout is builtcorrectly — tabs, splits and ratios are all right — but the panes just sit at
an idle prompt.
--dry-runshows nothing wrong, because the planned argv is correct:Running the same file for real leaves both panes at a bare prompt —
nvimnever opens,
npm run devnever starts.Cause
CliBackend::runcallsherdr pane runimmediately after the pane iscreated. A shell that has just spawned has not started its line editor yet,
so the command text is echoed to the PTY and then discarded during shell
startup. Reading the pane's scrollback afterwards shows the command sitting
above the shell's own startup banner, with an empty prompt underneath —
the text arrived before there was a line editor to receive it.
The same
pane runagainst the same pane succeeds once the pane is about asecond old, which is what makes this a startup race rather than a quoting or
argv bug.
Reliably reproducible with a heavier interactive shell — Oh My Zsh +
powerlevel10k + a startup banner tool (e.g.
fastfetch) is enough to lose therace every time. A minimal
.zshrc/.bashrcstarts fast enough to usuallywin it, which is likely why this hasn't surfaced before.
Fix
Wait for the pane to settle before sending: poll
herdr pane readuntil itsoutput stops changing.
Output stability alone is not sufficient on its own — some prompt frameworks
(powerlevel10k's instant prompt is one) paint an early prompt before the
real line editor exists, so a pane can look settled while still not being
ready to receive input. A minimum floor is enforced on top of the stability
check to cover that case.
Both bounds are overridable, for slower machines or for minimal shells that
need no wait at all:
HERDR_SPREADER_READY_FLOOR_MS1500HERDR_SPREADER_READY_TIMEOUT_MS100000disablesCliBackend::with_ready_settings(floor, timeout)exposes the same knobsin-process.
Tests
parse_msunit tests cover absent, empty, whitespace, invalid, negative andvalid values, including
0..with_ready_settings(Duration::ZERO, Duration::ZERO), so they still assert the exact argv sequence and areunaffected by polling. They also stay fast — without the opt-out they would
spend the full timeout per
pane run.cargo fmt,cargo clippy --all-targets -- -D warningsandcargo test(118 tests) all pass.
Verified
Against herdr 0.7.5 on Linux, applying a multi-tab layout with several panes
each running a different
command:. Before this fix, every pane's commandwas silently swallowed. After, every pane's command started correctly and
panes with no
commandwere left untouched.Note
Happy to adjust the shape of this — e.g. a per-pane
wait_for_shell:YAMLkey, or a
--ready-floor-msflag instead of environment variables — if you'dprefer the knobs surfaced somewhere else.