Options Paper · portability analysis

herdr vs ainb — what to port, what to skip

Date2026-05-14 Author@stevie Branchfeat/herdr Source repoogulcancelik/herdr@master · v0.5.8 · AGPL-3.0 Draft · for review
01

The framing

herdr is a Rust agent multiplexer — tmux's spiritual successor for AI coding agents. Persistent server + thin client, workspaces / tabs / panes (real PTYs), mouse-native, SSH-attachable, detects 11 agents via process name + screen-text heuristics, exposes a Unix socket API so agents-inside-herdr can spawn siblings and wait for output. 758 stars, AGPL-3.0, updated this week.

ainb is a Rust agent-session orchestrator + analytics TUI. Spawns Claude / Codex inside Docker containers, parses JSONL logs into a SQLite fingerprint cache, surfaces burndown / cost / token rollups across 30 days, manages git worktrees, recovers orphan containers. 89k LOC, 39 panels, 17 CLI subcommands.

They are not competitors. herdr owns the process / window layer. ainb owns the container / analytics layer. You could even run ainb as the root process inside a herdr pane and get both. The interesting question is not "who wins" — it's which herdr ideas does ainb steal without losing its identity, and what does the AGPL license force us to clean-room?

This paper compares the two architectures, surfaces the 15 features herdr has that ainb doesn't, scores 4 candidate ports against the dimensions that actually matter (impact, effort, license safety, fit), and recommends a port order.

02

What they actually are

Architecture at a glance — two products, two layers, almost zero overlap on the data plane.

herdr

terminal multiplexer · pty layer · 400k+ LOC
thin client local · ssh unix socket ~/.config/herdr/*.sock herdr server persistent · headless WORKSPACES · TABS · PANES (BSP layout) pty: claude pty: codex pty: shell pty: pi detect.rs process + screen heuristic hook integrations claude · codex · pi · opencode
LifecyclePTY · server-owned · detach/reattach
State sourceprocess name + screen tail + hook push
APIunix socket · 30+ methods · agents-can-script
PersistenceBSP layout snapshot · scrollback restore
Analyticsnone (intentional)
Authdelegated to each agent CLI

ainb (ainb-tui)

session orchestrator · container layer · 89k LOC
ainb TUI ratatui · 39 panels Docker (bollard) container lifecycle git2 worktrees · diff JSONL parser claude · codex SQLite cache blake3 fingerprint live window watcher · burndown · recovery rate-limit · cost · orphan repair
LifecycleDocker container · per session · isolated
State sourceJSONL polling + live-window file
APIclap CLI + JSON export · no socket
PersistenceJSONL append + SQLite fingerprint cache
Analyticsburndown · cost · token · 30-day rollup
Authkeyring · per-provider (claude / codex / gh)
03

What they do differently

The same axis projected onto each product. Where the two diverge is the answer to "what to port" and "what to leave behind".

Axisherdrainb
What is an "agent"?Anything in a PTY — 11 detectors (claude · codex · pi · droid · amp · opencode · cursor · cline · kimi · copilot · gemini)A Claude Code or Codex Docker session — 2 real providers + 2 stubs (copilot / gemini)
State sourceProcess detection + screen-text heuristic + optional hook push (real-time)JSONL log polling + live-window file polling (~250 ms lag)
Isolation modelNone — host shell processDocker container per session
PersistenceTerminal scrollback + BSP layout snapshot (format v3)JSONL append log + SQLite fingerprint cache
Concurrency modelServer + thin client · detach/reattach · SSH-able · named sessionsSingle-process TUI · background containers
UI primitiveTiled workspaces / tabs / panes · mouse-nativeSession list + detail panels · 39 screens
API surfaceUnix socket · 30+ methods · 3-layer (raw / CLI / agent SKILL)clap CLI + JSON export only · no agent-callable API
AnalyticsNone (intentional — herdr is a window manager)First-class burndown · cost · token · per-project rollup
WorktreeNone — workspace = cwdFirst-class git2 worktree manager · create / delete / branch
Self-updatewebsite/latest.json + in-app update flowbrew tap (no in-app)
LicenseAGPL-3.0 — copyleft, source-copy taintsnon-copyleft (port concepts, never paste)
Surface size~400k+ chars · large flat modules (cli.rs 47k, headless.rs 114k, detect.rs 49k)~89k LOC · 39 components · deep submoduling
04

Evaluation criteria for ports

Six dimensions, weighted. Used to score the four candidate ports in §05. Weights skew toward impact and effort — license safety is low-weight only because every port is concept-port (never source copy), so safety is enforceable at PR review.

Impactuser-visible value to ainb
0.30
Maintenanceongoing ops surface after ship
0.20
Effort (inverse)lower engineer-weeks → higher score
0.20
Robustnesshow solid herdr's pattern is in the wild
0.15
Time to shipdays to first PR landed
0.10
License safetyclean-room reach difficulty
0.05
05

Candidate ports

Four high-signal ports, distilled from the 15-row matrix in §06. Each one re-implements a herdr idea from concept (README / SOCKET_API / INTEGRATIONS) — no GPL source copy.

Port A

Hook-based real-time state forwarding

Install ainb integration install claude writing ~/.claude/hooks/ainb-agent-state.sh. Map UserPromptSubmit→working, PermissionRequest→blocked, Stop→idle. Push to a tiny ainb socket. Eliminates JSONL-poll lag.

Impact5
Maintenance5
Effort↓5
Robustness4
Time→ship5
License5
weighted4.85 / 5
Port B

Notifications + sounds

Toasts + chime when a session flips to blocked or done. herdr ships ui.sound + ui.toast.delivery; ainb has neither. Pairs naturally with Port A — state push triggers the notification.

Impact3
Maintenance5
Effort↓5
Robustness5
Time→ship5
License4
weighted4.35 / 5
Port C

Unix socket API for agents-control-ainb

Newline-delimited JSON over ~/.agents-in-a-box/ainb.sock. Start read-only: session list / get / log-tail / wait done. Mirror herdr's 3 layers — raw / CLI / SKILL.md for agents inside ainb-spawned containers.

Impact5
Maintenance3
Effort↓2
Robustness4
Time→ship2
License3
weighted3.45 / 5
Port D

Heuristic detection for non-Claude agents

Port herdr's Agent enum + per-agent detect_(screen) shape into ainb-tui/src/agent_parsers/heuristic.rs. Plug as a fallback when JSONL is absent (gemini, amp, droid, cursor). Re-implement detectors from README, not source.

Impact3
Maintenance3
Effort↓2
Robustness3
Time→ship2
License4
weighted2.75 / 5
06

Full portability matrix

15 herdr features × ainb status × value × effort × license risk × recommendation. HAVE = ainb has equivalent. PARTIAL = weaker version. MISSING = nothing. Effort: TRIVIAL ≤ 1d · EASY 1–3d · MEDIUM 1–2w · HARD > 2w. Every entry assumes concept port, not source copy.

# herdr feature ainb status Value Effort License Recommendation
01Hook-based real-time state forwardingUserPromptSubmit→working · PermissionRequest→blocked · Stop→idlePARTIALHIGHEASYSAFEDO — Port A · next sprint
02Unix socket API for agents controlling the toolworkspace.list · pane.read · wait agent-statusMISSINGHIGHMEDIUMSAFEDO — Port C · read-only first
03Process+screen heuristic detection for 11 agentspi · droid · amp · opencode · cursor · cline · kimi · gemini · copilotMISSINGMEDIUMMEDIUMCAREDO selectively — gemini + amp first
04Notification sounds + toaststab-aware suppression · OSC deliveryMISSINGMEDIUMEASYSAFEDO — Port B · pairs with hooks
05Live config reloadherdr server reload-config · no restartMISSINGLOW–MEDEASYSAFEMAYBE — only if config edits get common
06Hook-installer command patternainb integration install claude/codex/...MISSINGHIGH UXTRIVIALSAFEDO — ship with Port A
0710 built-in themes + theme configcatppuccin · tokyo-night · dracula · nord · gruvbox · vesperPARTIALLOWEASYSAFEMAYBE — bundle with UX pass
08In-app self-update + manifestwebsite/latest.json + herdr updateMISSINGLOW–MEDEASYSAFEMAYBE — bundle with v1.1.x release
09User-defined prefix-mode command keybindings[[keys.command]] · spawns shell helper or temp paneMISSINGLOW–MEDMEDIUMSAFEDEFER — wait for user signal
10Scrollback persistence + BSP layout snapshotformat v3 · restore terminal stateN/ASKIP — wrong architectural fit
11Tiled workspaces / tabs / panes UIBSP layout · mouse-native splitsN/ASKIP — would require product pivot
12Mouse-native click/drag/right-clickpanes · tabs · workspaces · agents · bordersPARTIALMEDIUMMEDIUMSAFEMAYBE — incremental, not a focus
13SSH thin-client attachherdr --remote workbox · phone-friendlyMISSINGLOWHARDSAFESKIP — ainb is single-process by design
14Kitty graphics protocol in panesimage rendering · 27k LOCMISSINGLOWMEDIUMSAFESKIP — rare use case
15Long-lived event subscription streamevents.subscribe · pushed eventsMISSINGMEDIUMMEDIUMSAFECONSIDER — fold into Port C if scope allows
07

Trade-off radar — 4 candidate ports

Same 6 criteria projected as a hexagon. Larger area = better overall fit. Spikes reveal where each port dominates or fails. Port A (hooks) and Port B (notifications) are the obvious quick wins; Port C is the strategic but expensive one.

impact maint effort↓ robust time→ship license
  • A · hooks (leader · 4.85)
  • B · notifications · 4.35
  • C · socket API · 3.45
  • D · heuristic detection · 2.75
08

Recommended port order

Sequenced by weighted score, with one re-ordering: A and B ship together because the notification is meaningless without the real-time state push. C is the strategic bet — schedule after A+B prove the hook pattern.

1stA · hooks4.85
2ndB · notifications4.35
3rdC · socket API3.45
4thD · heuristic detect2.75
09

Reverse direction — ainb's moats

Useful framing for "where does ainb sit if herdr starts eating our lunch?" These are things herdr does not do — and would have to rebuild from scratch.

Token & cost burndown

Per project · session · day · week · 30-day. herdr does not parse JSONL at all.

moat · high

SQLite fingerprint cache

blake3 + size + mtime keyed bincode blob. Sub-second relaunch on multi-GB log dirs.

moat · high

Docker container lifecycle

Isolated per-session runs · log streaming · env injection. herdr just spawns shell PTYs.

moat · high

Git worktree manager

Create / delete / branch through git2 UI. herdr workspaces are cwd-driven only.

moat · mid

Session recovery / orphan repair

Scan for stale containers + missing worktrees · offer fix. 2.1k LOC component.

moat · mid

Claude live-window watcher

Ingest .claude-live-window.json for rate-limit + Tier1 state in real time.

moat · mid

Skills browser

Read-only Claude Code skill discovery (name · description · author).

moat · low

Provider auth flows

Claude API key / OAuth · keyring storage · per-provider setup UX.

moat · low

Claude Code statusline hook

ainb claudecode statusline plugs the rate-limit window into Claude's statusline.

moat · low
10

Open questions

AGPL clean-room policy — is README citation enough?

Every port re-implements from herdr's README / SOCKET_API.md / INTEGRATIONS.md (documentation, not GPL-encumbered code). Need explicit policy: contributors should not read src/detect.rs line-by-line while writing ainb's equivalent.

@stevie · ship policy note in CONTRIBUTING before Port A merges

Should the ainb socket reach inside containers?

For agents inside ainb-spawned containers to call ainb wait session-done, the Unix socket needs to be volume-mounted into the container. Worth a small spike before Port C lands.

@stevie · 1-day spike before Port C kickoff

Hook vs polling — keep JSONL polling as fallback?

herdr keeps screen heuristics when hooks aren't installed. Mirror this: JSONL polling stays as the fallback path when ainb integration install hasn't run for a session's provider.

@stevie · decide in Port A design doc

Co-existence — should we document running ainb inside herdr?

Architecturally they compose: herdr workspace create --cwd ~/repo then run ainb in the root pane. herdr detects it as unknown but ainb's spawned sessions still work. Doc-only effort; potentially great marketing.

@stevie · README section