Is this a reproducible bug?
Current behavior
herdr pane current resolves entirely from the $HERDR_PANE_ID environment variable and never checks that the calling process actually runs in that pane. Since the variable is inherited by every child process, a process forked from a pane but living outside it — a background daemon, a detached job — carries a pane id it does not own. pane current then returns a complete, well-formed record for that unrelated pane (agent, cwd, terminal_title, workspace_id), exit status 0, with nothing indicating the answer describes somebody else.
Overriding the variable has exactly the same effect as inheriting a stale one, so it demonstrates the resolution path:
$ herdr pane current | jq -c '.result.pane | {pane_id, workspace_id, terminal_title_stripped}'
{"pane_id":"w654fdb7cb1a351:p6","workspace_id":"w654fdb7cb1a351","terminal_title_stripped":"Fix herdr config issue"}
$ HERDR_PANE_ID=w5:p1 herdr pane current | jq -c '.result.pane | {pane_id, workspace_id, terminal_title_stripped}'
{"pane_id":"w5:p1","workspace_id":"w5","terminal_title_stripped":"backend-alias-fix"}
Both commands ran in the same shell, which lives in workspace w654fdb7cb1a351. The second reports an unrelated agent in workspace w5.
This also occurs without any override. Scanning /proc/<pid>/environ across live agent processes showed two distinct process trees both carrying HERDR_PANE_ID=w5:p1:
- one descending from that pane's shell (
shell_pid 1568809) — the genuine occupant;
- one rooted at an unrelated parent (
ppid 2411), with children whose cwd is under /tmp/cc-daemon-.../spare — a background agent session that has never run in w5:p1, and which pane current nonetheless identifies as that pane.
herdr pane process-info --pane <id> already returns shell_pid, so the server appears to hold everything required to tell these two cases apart.
Relation to #902: that issue's accepted expected behavior was that --current resolve to the calling shell's pane, "matching $HERDR_PANE_ID and herdr pane current" — taking those two as the ground truth. This report concerns that ground truth being unverified.
Expected behavior
herdr pane current verifies that the caller actually belongs to the pane named by $HERDR_PANE_ID — for instance by checking the caller's pid against the pane's process tree, resolvable server-side via shell_pid — and either reports the true pane or fails, rather than returning another pane's record as the caller's own.
If reflecting the variable unverified is intended, --help should say so. Today it reads only "Show the current pane", and the existence of --pane <ID> for naming a specific pane implies that bare current resolves the caller.
Reproduction
- From a shell inside a herdr pane, run
herdr pane current. It reports that pane, correctly.
- From the same shell, run
HERDR_PANE_ID=<id of a pane in another workspace> herdr pane current.
- Observe a full pane record for the other pane, exit status 0, no warning.
- Without any override: start a long-lived agent process as a background/daemon job from a pane's shell. The daemon and its children inherit that pane's id and keep reporting it, including after the originating pane is gone or while the work runs in a different workspace.
Impact
Agents use $HERDR_PANE_ID — and pane current as the apparently-authoritative version of it — to state their own address when arranging back-channel messaging between panes. When the value was inherited rather than assigned, messages are delivered to an unrelated agent, typically in another workspace. Both send and receive succeed, so neither side observes an error; the messages simply arrive somewhere else. In a multi-agent session this surfaces as an agent receiving instructions meant for a different task.
pane current is the natural place to catch this, but as it stands it confirms the wrong answer instead. We could not use it, and resorted to an external check: walk the caller's ppid chain and confirm it reaches the shell_pid that pane process-info reports for the claimed pane, refusing when it does not.
Environment
- herdr version: 0.7.5
- Update channel: stable
- Operating system: KDE neon User Edition (Ubuntu-based), Linux 7.0.0-28-generic, x86_64
- Terminal: Konsole 26.04.3, also used via Yakuake (which embeds the same Konsole KPart). The herdr server runs detached under systemd; clients attach from Konsole.
- Shell: zsh 5.9.2 interactive; bash 5.2.21 for agent-run commands
- Agents: Claude Code CLI. Some sessions are started as background jobs rather than in a pane, which is the configuration that produces the inherited
$HERDR_PANE_ID described above.
Is this a reproducible bug?
Current behavior
herdr pane currentresolves entirely from the$HERDR_PANE_IDenvironment variable and never checks that the calling process actually runs in that pane. Since the variable is inherited by every child process, a process forked from a pane but living outside it — a background daemon, a detached job — carries a pane id it does not own.pane currentthen returns a complete, well-formed record for that unrelated pane (agent,cwd,terminal_title,workspace_id), exit status 0, with nothing indicating the answer describes somebody else.Overriding the variable has exactly the same effect as inheriting a stale one, so it demonstrates the resolution path:
Both commands ran in the same shell, which lives in workspace
w654fdb7cb1a351. The second reports an unrelated agent in workspacew5.This also occurs without any override. Scanning
/proc/<pid>/environacross live agent processes showed two distinct process trees both carryingHERDR_PANE_ID=w5:p1:shell_pid1568809) — the genuine occupant;ppid2411), with children whose cwd is under/tmp/cc-daemon-.../spare— a background agent session that has never run inw5:p1, and whichpane currentnonetheless identifies as that pane.herdr pane process-info --pane <id>already returnsshell_pid, so the server appears to hold everything required to tell these two cases apart.Relation to #902: that issue's accepted expected behavior was that
--currentresolve to the calling shell's pane, "matching$HERDR_PANE_IDandherdr pane current" — taking those two as the ground truth. This report concerns that ground truth being unverified.Expected behavior
herdr pane currentverifies that the caller actually belongs to the pane named by$HERDR_PANE_ID— for instance by checking the caller's pid against the pane's process tree, resolvable server-side viashell_pid— and either reports the true pane or fails, rather than returning another pane's record as the caller's own.If reflecting the variable unverified is intended,
--helpshould say so. Today it reads only "Show the current pane", and the existence of--pane <ID>for naming a specific pane implies that barecurrentresolves the caller.Reproduction
herdr pane current. It reports that pane, correctly.HERDR_PANE_ID=<id of a pane in another workspace> herdr pane current.Impact
Agents use
$HERDR_PANE_ID— andpane currentas the apparently-authoritative version of it — to state their own address when arranging back-channel messaging between panes. When the value was inherited rather than assigned, messages are delivered to an unrelated agent, typically in another workspace. Both send and receive succeed, so neither side observes an error; the messages simply arrive somewhere else. In a multi-agent session this surfaces as an agent receiving instructions meant for a different task.pane currentis the natural place to catch this, but as it stands it confirms the wrong answer instead. We could not use it, and resorted to an external check: walk the caller's ppid chain and confirm it reaches theshell_pidthatpane process-inforeports for the claimed pane, refusing when it does not.Environment
$HERDR_PANE_IDdescribed above.