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:

  1. npm packages (pi-subagents, pi-blackhole, pi-memctx, pi-web-access, two @juicesharp tools)
  2. the self-install above
  3. extensions + personas symlinked from the checkout (/reload picks up edits β€” the dev workflow I already had)
  4. settings.json merged via jq β€” packages unioned, tiering/modelScope blocks canonicalized, volatile keys like lastChangelogVersion preserved, backup before every write
  5. systemd timer for the local-health availability board
  6. three local pi-memctx patches re-applied
  7. 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.json and 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 install of 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.

Share this post