borg-ai 0.5.0

Collective mind for coding-agent drones: CLI and harness hooks
Documentation

Borg

Borg is a shared memory for coding agents. It turns the corrections you give your agent, and your team's written knowledge, into short lessons, and brings each lesson back when a later session, yours or a teammate's, meets the same decision. It runs as hooks in Claude Code and Codex and as extensions in omp (oh-my-pi) and opencode, learns in one plain session with nothing else running, and shares lessons with a team peer to peer, with no server.

Why: an agent forgets a correction when its session ends, so you make the same correction next week, and each teammate makes it again.

  • Lesson: what a correction becomes: a question the agent asks itself, the situations where it applies, and the consequence it prevents.
  • Drone: one agent session wired to Borg.
  • Collective: one memory for a set of repos: shared with a team, private, or off.
  • Queen: the queue of decisions no lesson answers yet, asked of you one at a time.

Status: 0.5.0, the first release on crates.io. It removed the hive and playbooks: sessions now message each other instead. In daily use, with lessons syncing between engineers' machines over the mesh, across NATs. Tested on Linux and macOS. Read Evidence and limits before you rely on it.

Quick start

curl -fsSL https://raw.githubusercontent.com/debe/borg_ai/main/scripts/install.sh | sh

This installs prebuilt, sha256-checked borg, borg-mesh and borg-web into ~/.local/bin (Linux x86_64/arm64, macOS on Apple silicon) and runs borg setup. Setup asks which harnesses to wire, which repos go to a private or team collective and which stay off, fetches the vector model (~490 MB, once), optionally learns the 50 newest corrections from your past sessions, shows every change, writes nothing until you confirm, and ends with borg doctor. A second run changes nothing. Then start your agent as usual:

Harness After setup Notes
Claude Code claude Every feature. Hooks in ~/.claude/settings.json
omp 18.8.5, 18.10.4 omp Live mode needs omp 18.4.4 or newer. adapters/omp
opencode 1.18.32, 1.19.0, 2.0.23, 2.0.29 opencode adapters/opencode
Codex CLI 0.153.2 codex, then /hooks once to trust borg's hooks Hooks in ~/.codex/hooks.json; borg doctor says when codex skips them. Borg's own model calls need claude, omp or opencode on PATH, or BORG_PREDICT_MODEL=codex:<model> and BORG_LEARN_MODEL=codex:<model>. adapters/codex

Borg's model steps (learning, the checks) run headless through a logged-in CLI on PATH, the drone's own harness first (Sonnet by default for claude). Without one, Borg still records episodes and delivers by word matching, but learns nothing.

Other ways in. install.sh takes --version, --dir and --no-setup after sh -s --. From crates.io: cargo install borg-ai --locked (plus borg-mesh for a team, borg-web for the page; Rust 1.91+; --no-default-features builds a lean borg without vectors). Setup flags answer its questions for scripts:

borg setup --yes --private ~/src                              # no questions; defaults for the rest
borg setup --team platform --paths ~/work --relay disabled    # found a team collective
borg setup --join BORG1... --paths ~/work                     # join one with a ticket
borg setup --no-vectors --harness claude,codex

By hand: write ~/.config/borg/collectives.json (Collectives; without one every repo joins a team collective named default), then borg install all (a dry run) and borg install all --apply, borg vectors --fetch, and optionally borg assimilate --apply --limit 50. Intel Macs, the macOS C++ header workaround and source builds: Install.

Reference: How one session learns · Delivery and modes · Commands · Configuration · Team sync · Statistics and the page · Harnesses · Own relay · Evidence · Reports

How it works in one session

Everything in this section works in one plain interactive session, with no team.

flowchart LR
  S["corrections, borg no,<br/>review → fix findings,<br/>team documents"] -->|"borg learn at session end"| L[("lessons")]
  L -->|"at the prompt: free"| D["drone"]
  L -->|"during the turn: live check"| D
  L -->|"at the stop: graded call"| D
  D --> O["outcomes: changed, ignored,<br/>corrected, vetoed, tested, regretted"]
  O --> B["usefulness belief"]
  B -->|"ranks and fades"| L

Learning. Borg records an episode when you push back ("no, use a channel") or reject a tool call with a reason. At session end borg learn makes one model call per episode and writes or updates a lesson. Team documents become lessons through borg assimilate --from-dir. Sources of lessons

Delivery. Lessons arrive at three moments. At the prompt or a touched file, free, by word matching (Claude Code; ratified constraints on every harness). During the turn, in live mode (the default): after an edit a background check grades the work so far and its questions arrive with the next tool call. At the stop, a free word gate skips most turns; otherwise one model call grades the eligible lessons, and a grade 3 blocks the stop for one more round. The same call judges whether what was handed over earlier changed the work. "mode": "hook" checks only at the stop. Delivery and modes

Outcomes and belief. Every delivery is logged with its probability, and what followed (changed, ignored, corrected anyway, vetoed, regretted, tested) moves the lesson's usefulness belief. The Knowledge tab of borg web shows it. Outcomes

Review → fix. A reviewer sub-agent finds a bug and a fix step fixes it before any commit. borg review-fix reads those runs from Claude Code, omp, opencode and Codex at 0 tokens, and each fixed finding becomes a lesson for the moment of building. On by default. Review → fix

Regret. A later commit that fixes an earlier decision is linked to it (borg why shows both ends). With BORG_REGRESS=learn the fix becomes a lesson for the decision point; links only, by default. A regret also counts against the lessons asked before the decision. Decision → fix links

Green tests. When a lesson was asked and the session's own tests then went from red to green, or passed after the drone changed its work on the point, the lesson gets a tested credit at 0 tokens. Green tests

borg no <reason> (or a prompt starting "borg no") vetoes what the drone is doing: the lessons it was shown lose credit, the reason becomes a lesson (learned like a correction), and an invariant in it is proposed as a constraint you can ratify. Saying no

Memory. Use strengthens a lesson, disuse fades it: about 54 sessions without use make it dormant, never deleted. The clock counts sessions, not days. Memory

The queen holds decisions no lesson answers (open decisions from documents, proposed constraints). The drone asks you one at a session's first prompt; borg queen lists them. The queen

The team

Each repo belongs to one collective: team (synced to its members), private ("share": "local", never leaves the machine) or off (Borg reads and writes nothing). A correction about the code becomes a team lesson; one about how you like the agent to work goes to your private collective; a repo convention is delivered only in its repo. Who hears a lesson

flowchart LR
  subgraph A["your machine"]
    SA["session"] --> TA[("team collective")]
    SA --> PA[("private collective")]
  end
  subgraph B["teammate's machine"]
    TB[("team collective")] --> SB["session"]
  end
  TA <-->|"borg mesh serve: signed lines, peer to peer, encrypted"| TB

Each machine runs borg mesh serve. Peers find each other by key over iroh, through NAT or a relay, and reconcile append-only files by hash. Hooks only read and write local files, so nothing waits on the mesh. What syncs and what stays is under Privacy. borg top is a live screen of the team's drones, like Unix top; borg pause and borg resume hold or release any of them (Talking to other sessions). Set up: borg setup --team <name> or --join <ticket>, or Team sync; for a company, Company collective.

Talking to other sessions

Sessions in one collective can message each other, whatever harness runs them and whichever member's machine they are on. A session or the engineer's terminal sends:

borg tell Two "the schema change is merged, rebase before you touch migrations"
borg ask local "is anyone editing crates/borg/src/hook.rs?"        # the sessions on this machine
borg tell collective "the staging database is down until noon"     # every session, every member's machine
borg inbox      # in a session: its messages; in a terminal: every message of the last 7 days

The recipient is a drone as borg top names it, a session id, local, collective (or all, the same) or engineer. Local first: local reaches the sessions running on this machine, and a drone or session id that matches one here names it. A colleague's session is reached by <session>@<node>, when nothing here matches, or as the sender a reply answers; collective reaches every session of the collective on every member's machine and may wake them, so it is for what concerns their work. The message is shown once, at the recipient's next prompt or tool call, marked as peer data rather than the user's words, with the command that replies (borg tell <session> --re <id>). Text is redacted and cut to 1,000 characters, and one sender may send a recipient one message per 10 minutes. Messages are kept 7 days. One to local stays on this machine; one to collective, to <session>@<node> or a reply syncs to the team collective's members.

The engineer can also hold a session, or every one:

borg pause Two "wait for the schema change"   # its tool calls are refused, with the note, until resumed
borg resume Two
borg no --session Two "never look merges up in the commit log"   # a veto, on this or another machine

borg pause local holds this machine's sessions; borg pause collective (or all) every member's. These are messages too, shown at the next prompt or tool call on every harness, and never rate limited. From another member's machine they count only if that member has the admin or steer role. A pause lapses after a day.

A session that is idle sees a message when it next runs, unless it listens. Inside a session:

borg listen         # wake this session when a message arrives while it is idle
borg listen --off

The opt-in lasts until --off or the session's end.

When its turn ends, borg wakes it in the way its harness allows. On Claude Code the model starts borg listen --wait in the background. The omp and opencode adapters keep a stream running. On codex a detached waiter queues a turn with codex queue. The wake names who wrote and how many messages wait, and the session's next prompt hook shows the messages themselves. Nothing wakes a session while the engineer's own turn runs. borg top shows who listens in its WAKE column. Commands

Monitoring

borg web        # http://127.0.0.1:7979/, the collective of the current directory first

A live page on 127.0.0.1 with tabs for the Overview, Knowledge (every lesson, its belief and state), Conscience (checks, questions and what they led to per channel), Learning (week by week: lessons per source, the share of asked lessons that changed the work, repeated vetoes), Steering (corrections, rejected tool calls, pauses and vetoes, the tool calls a pause refused), Messages (the last 7 days' conversation, sends and refusals), the Queen (open questions, the queen's attention score), Cost and Drones. It reads the same files as borg top and needs no mesh. In the terminal: borg status (modes, stores, what is wired, spend), borg doctor (what is broken), borg queen, borg top. Statistics and the page

Cost

  • Most turn ends cost 0 tokens in hook mode: the free gate skipped 78% of 1,117 real turn ends. Early delivery and grade-2 and grade-1 lessons never call a model; they are judged only inside a call a question pays for.
  • A turn-end call costs about $0.07 (Sonnet, mean over 67 calls) and takes about 10 s. An extra round happens only for a grade-3 lesson.
  • Live mode adds one call per burst of changes: about 8× borg's own spend in hook mode, while whole runs cost about the same (Why live is the default).
  • Learning costs about $0.02 per correction (21 lessons from 10 sessions: $0.66). assimilate --from-dir makes one call per chunk and prints its cost. Messages, borg no, review → fix, regrets and green tests are found at 0 tokens; a veto's reason or a fixed finding is then learned like any correction.
  • There is no cost cap: borg status and the Cost tab show what each mode spent.

Privacy

Stays on your machine: everything from off repos and private collectives; raw episodes (your exact corrections), transcripts, the shell output adapters hand to borg, source code, collectives.json, per-session state.

Goes to team members, for team collectives only, each line signed and dropped on revocation: lessons (with author emails and repo names); redacted reasoning excerpts of landed commits, each held by two members; decision → fix links; presence for borg top (harness, email, repo, the redacted first line of your latest prompt, touched paths); redacted messages between sessions, pauses, resumes and vetoes among them; the signed member list; daily usage counts per engineer; outcomes with session, repo and regret hashed (BORG_SHARE_OUTCOMES=off keeps them local); and ratified constraints (the invariant, its lesson and who ratified it, never the veto's words).

A mesh relay sees node ids, IP addresses and traffic volume, never content; run your own to keep even that in-house (Privacy on the mesh, Own relay). The model provider receives what each model step needs: the turn and the eligible lessons, or the episode being learned.

Redaction (redact in crates/borg/src/notes.rs) strips tokens, keys, passwords and .env values from excerpts and presence. Lessons skip it: the model writes them as general questions, but read lessons.jsonl before you share a collective that handled secrets.

Hooks fail open. A missing binary, a crash, an invalid config, an unreachable model or a locked index lets the agent continue untouched. A turn-end call that fails ends the turn without questions, a live check that fails asks nothing (the turn end then checks as in hook mode), and unlearned episodes wait for the next run. Time limits

Evidence and limits

Measured, against rules written before each paid run (mostly on the author's and a few colleagues' sessions, so the data is not here):

  • lessons at the turn end, 15 real decisions in a sealed sandbox: 25% → 34% engineer points on all 15, +8.8 [−1.4, +22.2], not significant; 34% → 63% on the subgroup of 4 cases with a directly relevant lesson, +29.2 [+4.2, +68.8];
  • a memory of 21 lessons from 10 sessions held 21 useful ones; accuracy tied with Hindsight on the same memory model;
  • the system gate cut wrong-system deliveries from 83 to 0;
  • live mode: not worse than hook (+0.38 criteria per task [0, +0.88], 8 pairs, p = 0.50, directional only: 2 pairs differ; 0 redo rounds).

On although its rule was not met: review → fix lessons, +6.3 points of later bugs avoided [−5.1, +17.9]; the pre-registered rule (an interval excluding 0) failed, and the engineer turned it on so that users who never configure get it.

Rule not met: team documents as lessons, n = 9: +1.7 [+0.8, +2.4] knowledge checks over a plain agent (comparison runs not concurrent), but against a hand-written skill +0.11 [−0.56, +0.78], short of the pre-registered lower bound of −0.5.

Not shown: that Borg helps strangers on public data (SWE-chat: no memory helped, Borg included); decision → fix precision on real history (so BORG_REGRESS stays links); whether the regret credit improves the belief (the check was inconclusive: no data yet); the weights of vetoes and green tests. omp, opencode and Codex get no early delivery of ordinary lessons, and there a live check sees tool calls, not prose. Full table, the regret check and every known limit: Evidence and limits.

Upgrade and uninstall

cargo install borg-ai --locked --force       # or install.sh again
cargo install borg-mesh --locked --force     # if installed
borg install all              # dry run: shows adapter, hook and skill changes
borg install all --apply      # only if the dry run shows a diff
borg doctor

Hooks call the binary by path, so a reinstall needs no rewiring. Codex trusts each hook's command and timeout: after an upgrade that moves borg or changes a timeout, trust them again with /hooks (borg doctor says so). Stores are append-only JSONL and need no migration. The mesh protocol is now borg/mesh/13. A member built from 0.3.0 sources (borg/mesh/12) still syncs everything except messages; nothing syncs with an older one, and borg doctor names that member and which side has to upgrade.

borg uninstall all --apply    # removes only what install added; keeps a backup
cargo uninstall borg-ai borg-mesh borg-web    # or delete them from ~/.local/bin after install.sh

Uninstall leaves an edited adapter or skill file in place and reports it. Your data stays: delete ~/.local/share/borg and ~/.config/borg to remove it, and git update-ref -d refs/notes/borg in each repo for the reasoning notes.

Development

scripts/check.sh                              # everything below; run before a release
cargo test --workspace
cargo test -p borg-ai --no-default-features   # the lean build
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all                               # max_width 160
node --test adapters/omp/borg.test.ts         # adapter tests; need target/debug/borg and Node 23.6+ or bun
node --test adapters/opencode/borg.test.ts
node --test adapters/conformance/conformance.test.ts   # harness conformance (docs/harnesses.md)
scripts/arch.sh                               # the harness abstraction's metrics and gates
scripts/ui.sh                                 # rebuilds the page's committed dist/ (check.sh checks it is fresh)
python3 scripts/figures.py                    # regenerates the figures in docs/img
Path What
crates/borg The product (crate borg-ai, binary and library borg): CLI, hooks, learning, checks, memory, collectives, install, vectors. assets/ holds the skill and the TS adapters it compiles in
crates/borg-mesh Peer sync, membership, presence, admission of pauses and vetoes from other machines (iroh); separate so the hook binary stays small
crates/borg-trace Parses Claude Code and omp transcripts
crates/borg-web borg web, the live page; dist/ is its built Leptos client (ui/), committed
crates/borg-eval, crates/borg-search, eval/ Eval harness and benchmarks; not shipped, use local paths under ~/.local/share/borg/eval/
adapters/omp, adapters/opencode TypeScript adapters, compiled into borg (borg.ts links to crates/borg/assets/adapters/)
adapters/codex How the Codex hooks are wired and what they miss
adapters/conformance The harness conformance suite (Harnesses: one module per agent behind one trait)
skills/borg The borg skill borg install copies into each harness (a link to crates/borg/assets/skills/borg)
reports/ Measured results

Contributing: CONTRIBUTING.md. Security reports: SECURITY.md. License: MIT OR Apache-2.0 (LICENSE-MIT, LICENSE-APACHE).