Skip to content

About

Herdr relay for agents running inside a dev container

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Latest commit

 

History

53 Commits

Folders and files

Repository files navigation

herdr-devcontainer-status

A herdr plugin that makes VS Code devcontainers visible to herdr, and lets an agent (Claude Code, OpenCode, etc.) running inside one show up as a normal, tracked herdr agent, the same as one running on the host.

Quick start

herdr plugin install scott-the-programmer/vscode-devcontainers-herdr

That's it for installation. Nothing to configure. Now open a herdr pane in any project that has a .devcontainer/. herdr detects the container's state (running / stopped / none) automatically and reports it back, ready to show in the sidebar once you add the $devcontainer token to a row:

# ~/.config/herdr/config.toml
ui.sidebar.agents.rows = [["state_icon", "workspace", "tab"], ["agent", "$devcontainer"]]

To run an agent inside that container while herdr still tracks the pane, use exec from that same pane:

herdr-devcontainer-status exec claude

This starts claude inside the devcontainer, wired up so herdr sees it exactly like an agent on the host, with the same idle/working/done status.

For the full walkthrough (finding the binary's install path, aliases worth adding, troubleshooting), see USAGE.md.

Why this exists

herdr shows panes and Docker shows containers, but nothing connects the two by default. An agent running inside a devcontainer is invisible to herdr. This plugin fixes that: it reports the container's status and tracks agent sessions running inside it.

What it does

One host binary, three jobs:

subcommand runs on what it does
refresh / hook host detects the pane project's devcontainer state and reports it to herdr
exec [--agent <name>] <cmd> host runs <cmd> inside the container, carrying the pane's herdr identity in so herdr tracks it
bridge / relay host / container the plumbing that lets the container side talk back to herdr's control socket on the host

exec works against any project's devcontainer, not just checkouts of this repo. It pushes a small statically-linked (musl) copy of itself into the target container the first time it's needed, so nothing needs to be installed there ahead of time, and the target project doesn't need a Rust toolchain or any relation to this crate at all.

See .devcontainer/README.md if you want the internals of how the two ends of the relay fit together.

Devsy workspaces

For this project, bin/devco records each worktree's workspace manager, id, and provider under ~/.local/state/revaesor/devco/. The plugin reads these records and shows Docker and SSH workspace states. Add $devsy to a Herdr sidebar row to see the provider summary next to $devcontainer:

ui.sidebar.agents.rows = [["state_icon", "workspace", "tab"], ["agent", "$devcontainer", "$devsy"]]

The plugin also keeps the $devpod token for older sidebar configurations. Press Ctrl+B, then Shift+B to open the current worktree's URL in a new Chrome tab.

To run an agent in a Devsy workspace, set HERDR_DEVSY_PROVIDER before calling exec:

HERDR_PANE_CWD="$PWD" HERDR_DEVSY_PROVIDER=ssh herdr-devcontainer-status exec pi

Use docker or ssh as the provider value. Devsy adds an SSH host alias for each workspace. The plugin uses that host alias to start Pi with a terminal. It also opens a reverse SSH tunnel for Herdr's agent-state relay. The tunnel only lasts for the agent session. It does not expose Herdr's control socket on the network. Configure the Devsy providers before you use them.

Requirements

  • Docker, running
  • The devcontainer CLI: npm i -g @devcontainers/cli
  • Rust, only needed if there's no prebuilt binary for your platform (macOS/Linux, x86_64/arm64), or you're building from a checkout

How installation works

herdr plugin install clones this repo and runs ./build.sh, which downloads the release binary matching that checkout's version for your platform, verifies it against the release's SHA256SUMS, and installs it. If no prebuilt binary covers your platform, or the download fails, it falls back to cargo build (needs Rust). SHA256SUMS is an integrity check, not provenance; releases also carry a build provenance attestation, verifiable out of band with gh attestation verify --repo scott-the-programmer/vscode-devcontainers-herdr <tarball>.

Native Linux Docker

The defaults assume Docker Desktop, which forwards host.docker.internal to the host's loopback. Plain Linux Docker does neither, so point both ends at the docker bridge:

# in the herdr pane, or your shell profile
export HERDR_RELAY_HOST=172.17.0.1    # exec forwards this into the container
export HERDR_BRIDGE_BIND=172.17.0.1   # the host bridge listens here too

Use your own docker bridge address — ip -4 addr show docker0 — which is also what --add-host=host.docker.internal:host-gateway resolves to, if you would rather keep the name and set only HERDR_BRIDGE_BIND.

Set both or neither. Moving only the container end leaves the bridge on loopback, which turns a name-resolution failure into a refused connection, and moving only the host end leaves the container dialling a name that does not resolve. ~/.herdr/relay.log inside the container names which one you have:

relay: host.docker.internal:47100: failed to lookup address information   # no name
relay: 172.17.0.1:47100: Connection refused                               # bridge still on loopback

HERDR_BRIDGE_BIND widens who can reach herdr's control socket, and that socket is not authenticated — on the docker bridge address, every container on that bridge can reach it. That is why it is opt-in and why the default stays on loopback.

Note that none of this affects whether the agent appears in herdr. Pane identity is passed inward as environment at exec time and needs no socket, so a broken relay looks like a working session whose state is screen-detected rather than reported. That is the failure this is easy to miss.

Contributing

The binary always runs on the host. Never build or run it inside the container.

./build.sh --source            # compile to ./bin/herdr-devcontainer-status (what `make build` runs)
herdr plugin link "$(pwd)"     # use this checkout instead of an installed copy

./build.sh with no flags tries a prebuilt download first, same as herdr plugin install. HERDR_PLUGIN_BUILD=prebuilt ./build.sh is useful for debugging just that path.

This repo carries a .devcontainer/ of its own, so it doubles as the test fixture. From a herdr pane here:

make up        # create/start the devcontainer
make status    # what the plugin reports for this pane
make claude    # run Claude in the container, visible in `herdr agent list`
make shell     # shell in, claiming the pane as an agent
make test      # cargo test

make help lists the rest (rebuild, reshell, relay, clean, e2e, …), and .devcontainer/README.md covers the container in depth: credential seeding, the bridge/relay design, and the security tradeoffs of mounting host credentials into a container.

Maintainers cutting a release should see docs/RELEASING.md.

License

MIT

About

Herdr relay for agents running inside a dev container

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages