Skip to content

fix(herdr): repair the plugin install and the agent working directory - #25

Merged
pratikbin merged 3 commits into
mainfrom
fix/cli-flag-order
Aug 26, 2026
Merged

fix(herdr): repair the plugin install and the agent working directory#25
pratikbin merged 3 commits into
mainfrom
fix/cli-flag-order

Conversation

@pratikbin

Copy link
Copy Markdown
Contributor

Two blocking bugs found by driving the plugin interactively for the first time. Both were invisible, so they looked like dead keybindings.

1. Every GitHub install was broken

build.sh baked its build-time directory into the generated run.sh. A GitHub install runs build.sh inside Herdr's temporary checkout, then moves the plugin to its final home and deletes that directory.

run.sh points at: ~/.config/herdr/plugins/.tmp-install-<pid>-<ms>/checkout/.../src/main.ts
that directory:   deleted by Herdr after the move

Every action died with error: Module not found. Recovered from herdr plugin log list:

plugin-log-1  11:58:53  apply  exit=1  error: Module not found ".../.tmp-install-26487-.../src/main.ts"
plugin-log-2  11:58:54  info   exit=1  (same)
plugin-log-3  11:59:41  apply  exit=1  (same)

run.sh now resolves its own directory. Only the bun and createos paths stay baked, since the move does not affect them.

Check: build in one directory, move it, run run.sh from the new place. Before the fix it printed Module not found.

2. The agent never landed in the uploaded repository

The createos CLI parses flags with urfave/cli, which stops at the first positional argument. Every flag after the sandbox name is discarded with no error.

launch() passed process start <box> --pty --cwd /workspace, so --cwd was dropped and the agent started in /root. It could not see the worktree the plugin had just uploaded — which is the entire point of the plugin.

Confirmed with /proc/<pid>/cwd inside the sandbox:

before:  claude cwd=/root
after:   claude cwd=/workspace

Three more calls carried the same order:

call what was dropped effect
sync() --local, --remote, --mode, --exclude, --yes the sync pane fell back to an interactive prompt
boxExec() --stream agent installs never streamed their output
sandbox rm --yes confirmation not skipped

Fixed CLI-side in NodeOps-app/createos-cli#81, but this ordering also works on already-released CLI versions, so the plugin does not have to wait for a release.

Interactive test behind these findings

Real keystrokes through Herdr 0.8.2, not scripted CLI calls. All five supported agents were installed, attached, and reached a live PTY, each stopping at its own login screen:

agent start PTY stops at
claude-code 20 s pass login method picker
codex 19 s pass ChatGPT sign-in picker
opencode 16 s pass /connect prompt
pi 25 s pass /login prompt
cursor 12 s pass "Press any key to log in"

Pressing Enter on Claude Code's theme picker advanced the screen, which proves input reaches the agent. A .env tracked by Git was correctly kept out of the upload.

Full report, including the findings not fixed here: docs/herdr-plugin-interactive-test-2026-08-26.md.

Known, not fixed here

  • No action result ever reaches the screen. Herdr records plugin stdout, stderr, and exit codes — herdr plugin log list has them — but shows nothing in the UI. This is what hid both bugs above. delete's "invoke twice to confirm" gives no prompt, and info shows nothing at all. The plugin never calls herdr notification show, which exists and works.
  • delete leaves the pane open, still labelled with the destroyed sandbox.
  • The PTY size is hardcoded to 40x120 and never follows the pane.
  • dsh is not a supported agent, although this repo ships packages/dsh-createos.

Checks

bun test (4 pass), oxlint (0 warnings, 0 errors), oxfmt --check (clean), plus the live end-to-end run above.

build.sh baked its own build-time directory into the generated run.sh.
A GitHub install runs build.sh inside Herdr's temporary checkout, then
moves the plugin to its final home and deletes that directory, so
run.sh pointed at nothing and every action died:

  error: Module not found
  ".../plugins/.tmp-install-<pid>-<ms>/checkout/.../src/main.ts"

Every install through 'createos sandbox setup herdr' was broken this
way. The failure was invisible, because Herdr never puts plugin output
on screen, so it looked like the keybindings did nothing.

run.sh now resolves its own directory. Only the bun and createos paths
stay baked, because the move does not affect them.

Check: build in one directory, move it, run run.sh from the new place.
The createos CLI parses flags with urfave/cli, which stops at the
first positional argument. Every flag written after the sandbox name
is discarded with no error.

launch() passed 'process start <box> --pty --cwd /workspace', so the
agent started in /root and could not see the uploaded worktree. That
is the whole point of the plugin. Confirmed with /proc/<pid>/cwd:

  before:  claude cwd=/root
  after:   claude cwd=/workspace

Three more calls carried the same order:

  sync()     --local/--remote/--mode/--exclude were dropped, so the
             sync pane fell back to an interactive prompt
  boxExec()  --stream was dropped, so installs never streamed
  rm         --yes was dropped

Fixed CLI-side in createos-cli#81, but this order also works on
already-released CLI versions, so the plugin does not have to wait
for a release.
@pratikbin
pratikbin merged commit 5d48e02 into main Aug 26, 2026
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