GET api.eliasstravik.com /projects/herdr-chat 200 OK

herdr-chat

project · 200 OK · application/json

A live structured chat view for agents running inside Herdr.

0★ Stars
0⑂ Forks
TSTypeScript
View on GitHub ↗
README.md

Herdr Chat is a local chat overlay for Codex and Claude Code sessions running inside Herdr. It turns the bound JSONL transcript into a readable conversation while the original agent keeps running in its source pane.

The overlay renders messages, Markdown, code, thinking, tool activity, diffs, plans, todos, usage, approximate cost, images, and Claude subagents. Its composer sends text through Herdr's session-bound agent API, with file, command, and skill completion.

Requirements

  • Apple Silicon Mac. Intel macOS and Linux are not supported by the pinned renderer yet.
  • Node.js 22 or newer.
  • Herdr 0.8.2 or newer.
  • A local Ghostty or kitty window with Kitty graphics support.
  • A Herdr integration for each agent you use.

Enable the graphics API in ~/.config/herdr/config.toml:

[experimental]
kitty_graphics = true

Reload a running server after changing it:

herdr server reload-config

Install the agent integrations, then restart any running agent sessions so they begin reporting session identity:

herdr integration install codex
herdr integration install claude

Install

Review the repository and manifest, then install it from GitHub:

herdr plugin install eliasstravik/herdr-chat

Herdr runs the three manifest build steps: npm ci, npm run build, and the pinned terminal-browser installer. The installer supports darwin-arm64 only, verifies the archive against scripts/terminal-browser.lock, and does not run terminal-browser's setup command.

For local development, build and link the checkout instead:

npm ci
npm run build
npm run install:terminal-browser
herdr plugin link "$PWD"

Open and close

Focus a Herdr pane running Codex or Claude Code, then invoke:

herdr plugin action invoke herdr-chat.open

The same action is a toggle. Invoke it from the source pane or the open overlay to close the overlay. Invoke it from a different agent pane to move the overlay binding to that pane.

Plugins cannot ship user keybindings. To bind the recommended prefix+c, add this to ~/.config/herdr/config.toml:

[[keys.command]]
key = "prefix+c"
type = "plugin_action"
command = "herdr-chat.open"

Controls

Control Result
Enter Send the composer text
Shift+Enter Insert a newline
Ctrl+X Interrupt the bound agent
Esc Leave the composer, then close the overlay when the draft is empty
/ Focus the composer
Ctrl+S Stash the draft in local browser storage
? Show the shortcut panel
PgUp, PgDn, wheel Scroll the conversation
@path Search workspace files and insert a path
/command Complete Codex built-ins or Claude commands and skills
Paste or drop an image Save it under plugin state and insert its path
Claude mode button Send Shift+Tab to cycle permission or plan mode
Open raw terminal Close the overlay and reveal the source pane

Codex /model and /approvals, plus Claude /rewind, send the command and return to the raw terminal for the agent's interactive picker. Claude /model <name> can remain in chat. The selected text from the source pane appears as an optional context chip.

You can override the seven displayed shortcuts by creating keybindings.json in the directory printed by herdr plugin config-dir herdr-chat:

{
  "send": "Enter",
  "newline": "Shift+Enter",
  "interrupt": "Ctrl+X",
  "quit": "Esc",
  "focusComposer": "/",
  "stash": "Ctrl+S",
  "shortcuts": "?"
}

Values use combinations such as Ctrl+X, Shift+Enter, Alt+K, or Cmd+K.

Session detection

Herdr's Codex or Claude integration reports the focused pane's agent type and session identity. Herdr Chat binds that identity to the pane before it reads or sends anything.

  • Codex UUID sessions resolve to one rollout-…-<uuid>.jsonl below $CODEX_HOME/sessions (normally ~/.codex/sessions).
  • Claude UUID sessions resolve to one <uuid>.jsonl below $CLAUDE_CONFIG_DIR/projects (normally ~/.claude/projects). Claude subagents resolve only below that session's subagents directory.
  • An integration may report an explicit transcript path. Its real path must still be a regular file below the corresponding agent root.

No match, more than one match, a path outside the root, or a changed pane identity fails closed with a text screen or disabled input. A new session in the same pane reloads the conversation. The transcript is tailed read-only; prompts and key presses go through Herdr's agent APIs and are rechecked against the binding immediately before sending.

Limits

  • v1 is local-terminal only. It does not render through mosh, mobile, or a standalone web view.
  • Approval prompts and AskUserQuestion cards are read-only. Use Open raw terminal to answer them.
  • Unknown transcript records are retained as optional raw cards and never become actions.
  • Uploaded images are limited to PNG, JPEG, GIF, or WebP files up to 10 MB. Claude can read the inserted path; Codex may ignore an image path in an existing session.
  • Initial transcript loading is capped at the newest 32 MB; refreshes read at most 4 MB and individual JSONL records at most 1 MB.
  • Cost is an estimate derived from transcript token totals and bundled list-price assumptions. It is not billing data.
  • Links are displayed and copyable, but the overlay does not open them.

Security model

Herdr plugins are executable code and run as your user. Review the manifest and scripts before installing this or any third-party plugin.

Herdr Chat starts one HTTP server on a random 127.0.0.1 port for each overlay. Requests must carry the exact loopback Host, and control routes require a random per-launch session token. A one-use bootstrap token is passed in the terminal-browser URL, which means it is briefly visible in the renderer process argv and initial query string. The session token used by the EventSource stream also appears in that loopback request's query string because the EventSource API cannot set a custom header. Other control requests put it in a header. Both tokens die with the overlay and are never written intentionally, but local process inspection or renderer diagnostics may expose them while it runs.

The bridge has no shell-execution endpoint. It caps request bodies, restricts uploads to a private plugin-state directory, validates transcript and subagent paths by real path, and serves static files only from the built web root. Transcript content is untrusted display data: Markdown HTML is escaped, control characters are stripped, and unknown records remain inert. The vendored renderer is version-pinned and checksum-verified during install.

Development

npm run check
npm test
npm run test:page
npm audit --audit-level=high

The integration suite starts isolated headless Herdr servers with temporary home, config, and state directories. It never starts or resumes a real coding agent and never touches the user's Herdr plugin registry.