The Problem
My Pi and Herdr customizations had spread. A statusline extension here, a Stream Deck bridge there, three agent personas that lived nowhere, systemd units that existed only on the machine. Four repositories plus untracked files in ~/.pi/agent/:
| Where | What |
|---|---|
jreb-agents |
research + rollout repo for my orchestrator/worker tier design, local-health plane, pi-memctx patches |
jreb-pi-extensions (public) |
9 pi extensions: footer, herdr blocked-state, herdr socket, a five-file Telegram family, roster tools |
jreb-pi-skills |
git skills package: linear-cli, pi-gh, fix-linear-issues |
jreb-herdr / jreb-herdr-web |
a plan document and a firewall script |
| untracked | show-image.ts, three agent personas, settings.json, models.json, systemd units |
None of this could rebuild a machine. The live setup worked, but it was knowledge in my head, not in git. The worst part: only 3 of the 9 extensions in jreb-pi-extensions were actually deployed. The Telegram family β an ask_user_question bridge, run tracking, remote steering β was fully built, documented, and never installed. Sunk cost sitting on a shelf.
The Keep/Nuke Pass
Before writing any plan I had my agent inventory every extension and ask me, one by one, keep or nuke. That pass made the decisions concrete:
| Decision | Items |
|---|---|
| Keep | custom-footer, herdr-blocked-on-question, show-image, the three personas, all three skills, config-as-code |
| Nuke | the entire Telegram family, herdr-agent-list, herdr-agent-live, herdr-socket |
Nuking the Telegram family was the interesting one. It was the newest, most elaborate code in the repo β remote question answering, live run messages, impromptu steering from my phone. And I donβt want it. Telegram is a cloud hop for content that stays inside my LAN otherwise, and the answer to βwould I use this?β had quietly become βnoβ. Writing the delete line for ~170 KB of working, tested code stung a little. Keeping code you donβt use costs more.
One Repo
Everything now lives in jreb-agents:
jreb-agents/
βββ extensions/ custom-footer Β· herdr-blocked-on-question Β· show-image
βββ skills/ linear-cli Β· pi-gh Β· fix-linear-issues
βββ agents/ flash-worker Β· local-worker Β· web-researcher personas
βββ config/ settings.json Β· models.json Β· AGENTS.md Β· systemd units
βββ herdr/ herdr-web firewall Β· fleet research Β· herdr config
βββ scripts/ install.sh + the existing local-health/memory tooling
The nice trick: the repo has a root package.json with a pi.skills manifest, so it installs itself as its own Pi git package:
pi install git:github.com/JohannesBertens/jreb-agents
No more separate skills repo to keep in sync with anything.
The Installer
scripts/install.sh rebuilds the whole stack, idempotently:
- npm packages (pi-subagents, pi-blackhole, pi-memctx, pi-web-access, two @juicesharp tools)
- the self-install above
- extensions + personas symlinked from the checkout (
/reloadpicks up edits β the dev workflow I already had) settings.jsonmerged viajqβ packages unioned, tiering/modelScope blocks canonicalized, volatile keys likelastChangelogVersionpreserved, backup before every write- systemd timer for the local-health availability board
- three local pi-memctx patches re-applied
- memory vault cloned, Herdr integration + web plugin checked
--dry-run prints the plan, --verify runs a nine-section health check. On this machine it prints ALL CHECKS PASSED, and a second run mutates nothing. The extension smoke tests and strict typecheck still run green from the old repoβs dev tooling, which moved along with the code.
Decommission
Then the satisfying part. Each retired repo got a tombstone README (βMoved β jreb-agentsβ, with a table saying what went where), a push, and the GitHub archive flag:
| Repo | Fate |
|---|---|
jreb-pi-extensions |
archived read-only (frozen public source of the kept extensions) |
jreb-pi-skills |
archived β skills serve from jreb-agents now |
jreb-herdr-web |
archived β firewall script + security-audit research moved |
jreb-herdr |
was never a git repo; its plan doc just moved |
The 323-line security audit in jreb-herdr-webβs README β including a standing caveat about the herdr-web plugin binding 0.0.0.0:7936 β got rescued into herdr/herdr-web-research.md before deletion. That document is the reason the firewall script exists; it stays.
What I Learned
- Ask keep/nuke before planning. The consolidation plan was easy to write once every item had an explicit owner decision behind it. The plan just executed the answers.
- Untracked config is a silent dependency.
settings.jsonand three systemd units were load-bearing for months with no backup. Config-as-code with a merge-installer is the fix. - Deployed β shipped. Five of nine extensions in a public repo were never installed anywhere. Code that never gets used should be deleted, not archived-in-place on the main branch.
- Self-installing repos are a neat boundary. One
pi installof the monorepo replaces a separate skills package; the repo is both the source and the package.
Next: a clean-VM drill to prove the installer really works from scratch β the one box left unchecked.