posse — the Ranger work-system harness (herdr-native)
posse is the business harness of the Ranger work system: it
knows who your agents are (personas), what environment they run in (env sets),
how they launch (recipes), and what they should work on (beads). It is built
on shared substrates rather than competing with them:
posse the harness (bespoke, this repo)
personas · env sets · recipes · dispatch · cockpit
│
├─ beads work substrate — dependency-aware task graph, agent mail,
│ project memory github.com/steveyegge/beads (bd)
│
├─ herdr presentation & oversight — workspaces, live agent state
│ (working/blocked/idle) herdr.dev
│
└─ agent runtimes — claude code, codex, … (interchangeable labor)
Sessions are herdr workspaces (posse new/attach/kill), work is submitted
through the session's detected agent (posse prompt --wait), and ready work
comes from the repo's beads database (posse ready). The cockpit
(posse cockpit) is a herdr plugin pane: sessions sorted blocked-first, with
the ready queue beneath. See DIRECTION.md for the
architecture and NOTES.md for how it works.
Persona design credits the DISCOVER framework: the Persona Intent Document (ADR 0001) takes its name and its persona · intent · tools · guardrails · metrics binding from that framework's Specify artifact.
The original Ghostty + tmux session manager (bash + Go, launcher TUI, 2×2
grid) lives on the tmux-reference branch, kept working as the reference
implementation.
Requirements
- herdr ≥ 0.8 with its server running
- beads (
bd) for the work graph —
0.49.1 exactly; brew's beads is 1.2.x and does not read
.beads/beads.db at all
- Go ≥ 1.26 to build (
make build); one Go dependency (golang.org/x/term)
Neither substrate ships with posse and neither is optional — posse new
dies on its first call without herdr. INSTALL.md §1 is where to
get both, pins and reasons included.
Quick start
Standing up a new instance from scratch — build, RHQ_HOME, crew,
queue, first dispatch — is INSTALL.md. The short form:
make build # dev build of the working tree → bin/posse-go
make install # clean build of HEAD, then promote → ~/.local/bin/posse
posse init # seed $RHQ_HOME (default ~/.config/rhq) from the
# examples: examples/ beside the binary when there
# is one, else the copy embedded at build time
posse new myproj --dir ~/code/myproj --cmd claude
posse list # live agent state per session
posse prompt myproj "fix the failing test" --wait
make link-plugin # register the cockpit with herdr (runs the installed posse)
Without a checkout the binary installs from the module path — and lands in a
directory your shell does not search:
go install github.com/ranger360ai/posse/cmd/posse@latest
export PATH="$(go env GOPATH)/bin:$PATH" # ← where the line above wrote it
posse init
go install writes to $GOBIN, or to $(go env GOPATH)/bin when GOBIN is
unset — normally ~/go/bin, which is on no default macOS or Linux PATH.
Skip that second line and the very next command is zsh: command not found: posse, with the install itself having exited 0. Put it in your shell's rc
file, not just the current shell. That binary carries the seed tree embedded,
so posse init needs no repo beside it; the module carries no release tag
yet, so @latest resolves to a commit pseudo-version and posse version
reports 0.3.0+dev. make install stays the path for a fleet, because its
build has a commit to name.
posse version prints 0.3.0+<sha>[-dirty] for a build made here, and the
cockpit header shows the same, so "which build is live" is one glance. make build never touches the live binary; only make install does, and that
target is denied to fleet personas in .claude/settings.json — a human
promotes.
Personas share this checkout, so the working tree usually holds somebody's
unfinished edits. make install therefore never builds the working tree: it
checks HEAD out into a throwaway git worktree, builds there, and stamps that
sha — so the promoted binary is always a commit you can name, and never
carries (or fails on) an in-flight edit. Uncommitted paths are listed on
stderr when this happens; commit them and re-run if they belong in the build.
make release does the same build without promoting, and BINDIR=… overrides
the install location. Outside a git repo the build refuses rather than produce
an unidentifiable binary.