Skip to content

fix: run Herdr pane payload under bash so non-bash shells work - #594

Merged
agavra merged 1 commit into
agavra:mainfrom
sigma:fix/herdr-wrapper-non-bash-shell
Aug 13, 2026
Merged

agavra merged 1 commit into
agavra:mainfrom
sigma:fix/herdr-wrapper-non-bash-shell

Conversation

@sigma

@sigma sigma commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

herdr pane run injects its command string into the pane's interactive shell, which is not necessarily bash. The completion sentinel was written in bash syntax, so under fish the pane shell fails to parse it and tuicr never starts:

  • $? is not fish's exit-status variable (it is $status), and fish rejects it at parse time
  • tuicr_status=$? is not valid fish; assignment is set tuicr_status ...

Wrap the payload in bash -c '...' so the pane's shell only has to forward a single-quoted argument. Single-quote semantics are identical in bash, zsh and fish, so all three hand bash a byte-identical string.

This also fixes a latent bug on the same line: $quoted_tuicr is built with bash's printf %q, which emits $'...' ANSI-C quoting for awkward paths. That was previously being parsed by the pane's shell, which may have no such syntax; it is now read by bash, which produced it.

bash -c rather than sh -c for that same reason -- $'...' is not POSIX, so dash would choke on it. The payload itself is otherwise POSIX-clean.

Verified on macOS with fish as the pane shell: the pane splits, tuicr runs, the completion token is matched by wait-output, and the wrapper exits with tuicr's own status. Payload output is byte-identical under bash, zsh and fish.

`herdr pane run` injects its command string into the pane's *interactive*
shell, which is not necessarily bash. The completion sentinel was written
in bash syntax, so under fish the pane shell fails to parse it and tuicr
never starts:

  - `$?` is not fish's exit-status variable (it is `$status`), and fish
    rejects it at parse time
  - `tuicr_status=$?` is not valid fish; assignment is `set tuicr_status ...`

Wrap the payload in `bash -c '...'` so the pane's shell only has to forward
a single-quoted argument. Single-quote semantics are identical in bash, zsh
and fish, so all three hand bash a byte-identical string.

This also fixes a latent bug on the same line: $quoted_tuicr is built with
bash's `printf %q`, which emits `$'...'` ANSI-C quoting for awkward paths.
That was previously being parsed by the pane's shell, which may have no such
syntax; it is now read by bash, which produced it.

`bash -c` rather than `sh -c` for that same reason -- `$'...'` is not POSIX,
so dash would choke on it. The payload itself is otherwise POSIX-clean.

Verified on macOS with fish as the pane shell: the pane splits, tuicr runs,
the completion token is matched by `wait-output`, and the wrapper exits with
tuicr's own status. Payload output is byte-identical under bash, zsh and fish.

@agavra agavra left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for the fix :)

@agavra
agavra merged commit b30093d into agavra:main Aug 13, 2026
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.

2 participants