feat(gojnimer6553): add herdr module - #1060
Conversation
Runs Herdr (herdr.dev) in a Coder workspace, giving it a real pseudo-terminal via a detached tmux session the same way the happy module does for the happy CLI (Herdr has no documented headless/daemon startup mode). Adds an opt-in `plugins` list that installs Herdr plugins non-interactively via `herdr plugin install <spec> --yes`, plus an optional `app_port` to expose a plugin's own local web UI as a Coder app tile, and a `post_start_script` hook so callers can work around plugin-specific gaps (e.g. a plugin's setup wizard assuming infrastructure the workspace doesn't have) without baking plugin-specific logic into the module itself. Validated locally: terraform init/test (14/14 passed), bun test main.test.ts against real Docker containers (10/10 passed), shellcheck clean, prettier/terraform fmt clean. Also validated in production use against the real herdr and herdr-mobile-relay/collie plugin binaries in a Coder workspace template.
Replaces the placeholder glyph with the official mark from https://herdr.dev/_astro/logo.DM81885K_Z1HYzg2.svg.
Rewrites the tmux-usage explanations (README, install script comment, main.tf comment) to stand on their own instead of pointing at the happy module for context. Also fixes a stale README line along the way: tmux installs from the install script, not the start script.
|
/scorecard |
Module Scorecard Check
|
| Presentation & Onboarding | Agent Integration | Credential Hygiene | Restricted-Environment Readiness | Engineering Quality | Overall |
|---|---|---|---|---|---|
| 13 / 25 | 15 / 25 | 20 / 20 | 7 / 20 | 8 / 10 | 63 / 100 |
Drilldown
Presentation & Onboarding — 13 / 25
| Criterion | Max | Score | Notes |
|---|---|---|---|
| Configuration-mode examples | 12 | 6 | README shows multiple examples (basic install, plugin install with app tile, custom workdir, skip install, multiple plugins, expose plugin UI through Coder). However, these are not organized as distinct "modes" with sensible defaults for each major configuration path. The examples are scattered and require piecing together multiple snippets to understand a complete configuration. |
| Coder-context framing | 8 | 7 | README clearly names both Coder and Herdr, explains what Herdr adds (terminal/agent-session manager for coding agents), and shows where Coder fits (workspace integration, app tiles for plugin UIs). Minor deduction: the flow explanation is somewhat buried in the "How it works" section rather than prominently framed upfront. |
| Visual preview | 5 | 0 | No image, GIF, or video in the README. The icon reference in main.tf does not constitute a visual preview of the module in action. |
Agent Integration — 15 / 25
| Criterion | Max | Score | Notes |
|---|---|---|---|
| AI governance | 10 | 0 | No mention of Coder AI Gateway or Agent Firewall. The README discusses Herdr managing coding agents (Claude Code, Codex, OpenCode) but does not document how Coder governs auth, routing, or policy enforcement for these agents. |
| Dashboard entry point | 5 | 5 | Full coder_app support documented with app_port variable. README example shows exposing plugin web UI (mobile-relay port 8375) as an app tile. The app resource includes proper configuration (healthcheck, share, subdomain, open_in). |
| Session continuity | 5 | 5 | Documented support for persistent sessions via tmux. README explicitly states "Herdr detects and drives coding agents in persistent background panes" and explains that the module starts Herdr in a tmux session that "keeps running independent of the coder_script that launched it." The session persists across reconnects. |
| Managed configuration | 5 | 5 | Documented support for managed configuration via session_name (controls HERDR_SESSION), workdir (project directory), plugins (non-interactive plugin installation), and post_start_script (custom setup). README shows examples of configuring these. |
Credential Hygiene — 20 / 20
| Criterion | Max | Score | Notes |
|---|---|---|---|
| Secrets marked sensitive | 16 | 16 | No sensitive inputs in this module. The module does not handle API keys, tokens, or credentials directly. The README's IMPORTANT note explicitly states "This module installs and starts Herdr, but does not authenticate the coding agent(s)" and directs users to authenticate beforehand in the image. The post_start_script example generates a token but does not expose it as a module input. |
| Non-hardcoded auth path | 4 | 4 | Module avoids credential handling entirely by design. Authentication for coding agents is delegated to the workspace image setup (e.g., claude auth login), not managed through the module. This is a valid non-hardcoded path. |
Restricted-Environment Readiness — 7 / 20
| Criterion | Max | Score | Notes |
|---|---|---|---|
| Mirrorable artifact source | 10 | 0 | No variable to override the Herdr download URL. The install script hardcodes `curl -fsSL https://herdr.dev/install.sh |
| Bring-your-own binary | 5 | 5 | Documented via install = false variable. README example shows "Skip installation and use a pre-baked image" with clear usage. The start script checks for the binary and fails with a clear message if not found. |
| Egress transparency | 3 | 0 | No dedicated README section enumerating external endpoints. The install script shows https://herdr.dev/install.sh in code, and plugin installation implies GitHub access, but these are not enumerated in a dedicated network/offline/air-gapped section. Scattered mentions across examples do not meet the rubric requirement. |
| Runs without sudo | 2 | 2 | Install script attempts tmux installation with best-effort sudo detection but explicitly fails with a clear error message when neither root nor passwordless sudo is available: "Add tmux to the workspace image." The core Herdr installation (`curl ... |
Engineering Quality — 8 / 10
| Criterion | Max | Score | Notes |
|---|---|---|---|
| Input quality | 6 | 4 | Most inputs have clear descriptions and sensible defaults. Validation present for share and open_in. However, some descriptions are verbose without clear guidance (e.g., session_name description is long but doesn't clearly state when to use it vs. default). No validation on app_port (should be positive integer), plugins (could validate format), or tmux_session (could prevent shell injection). |
| Test coverage | 4 | 4 | Strong testing story. .tftest.hcl covers business logic (defaults, custom configurations, validation). TypeScript tests in main.test.ts cover end-to-end behavior: install skip, tmux auto-install, session startup, plugin installation (including failure handling), post_start_script execution, and session persistence. Tests use a fake Herdr binary to avoid network dependencies. |
Overall — 63 / 100
Scored against SCORECARD.md with claude-sonnet-4-5. Language-model scores are advisory.
|
Forced a Herdr that crashes a few seconds after launch and ran this script against it: Green workspace, no Herdr. Worth caring about because the module always installs latest, so one bad upstream release fails this way silently. if herdr status 2>/dev/null | grep -q 'status: running'; thenDropping the check entirely is also fine If you do keep it: |
|
Your comment on the variable already has the diagnosis right: herdr isn't in Coder's built-in icon bundle, so One tweak for that PR: the SVG has a solid |
|
@gojnimer6553 I left a few comments but thank you for the contribution it looks good otherwise! |
Description
Adds a
herdrmodule: runs Herdr — a terminal/agent-session manager that detects and drives coding agents (Claude Code, Codex, OpenCode, and others) in persistent background panes — inside a Coder workspace, and optionally installs Herdr plugins non-interactively viaherdr plugin install <spec> --yes.Herdr has no documented headless/daemon startup mode, so this module gives it one via a detached
tmuxsession, so the server keeps running independent of thecoder_scriptthat launched it.Key design points:
plugins(opt-inlist(string), default[]) — each entry is anowner/repospec installed non-interactively on every start. Installing a plugin only registers it; most plugins still need their own one-time interactive setup from a workspace terminal afterwards (documented in the README).app_port(optional) — exposes a plugin's own local web UI as acoder_apptile.post_start_script(optional) — runs after Herdr and all configured plugins are up, so callers can work around plugin-specific gaps (e.g. a plugin's setup wizard assuming infrastructure the workspace doesn't have) without the module itself needing to know about any specific plugin.Type of Change
Module Information
Path:
registry/gojnimer6553/modules/herdrNew version:
v1.0.0Breaking change: [ ] Yes [x] No
Testing & Validation
terraform test: 14/14,bun test main.test.ts: 10/10 against real Docker containers)bun run fmt, shellcheck clean)herdrCLI and a real Herdr plugin (AltanS/collie) in a live Coder workspace templateRelated Issues
None