Releases: odiumuniverse/beadle
Release list
v0.5.1
beadle v0.5.1
Why a patch. Nothing a script branches on moves in this release: no exit code, no document
shape, no home. It is a dependency bump, one containment check made correct, a README that says
what the last release actually does, and a release manifest that can finally be verified the way
the release page tells you to verify it.
verger v0.1.4
The embedded plugin manager is verger v0.1.4. Two things come with it.
Recoverable writes stop paying for a barrier they do not need. A delivered artifact, a rendered
document, a staged copy — losing one of those is the same as the file never having been written,
because the next run writes it again and the reader cannot tell the two states apart. They now go
through the cheap writer and the run pays one directory barrier at the end. What is not
re-derivable — a receipt, the lock, the spec, a secret, a consent — keeps both barriers, and the
classification lives next to the writers where the decision is made.
A host that refuses to uninstall is an answer, not a crash. The removal re-reads what the host
still lists before it deletes the receipt, so a plugin that survived its own uninstall fails the
cell instead of being reported as removed, and it leaves at exit 6 rather than at the code that
means beadle itself broke.
Containment counts whole path components
fsutil.Under answered with a string prefix, which is a question nobody asked: with a home of
/Users/bob it called /Users/bobby/x inside it, and with a vault root of /x/vw-a it called
/x/vw-ab a child. The answer mattered — a containment check that is too generous reads files and
prunes directories belonging to a neighbour of the root, and the neighbour's name is exactly what
the shorter prefix cannot see. It compares whole path components now, on both sides cleaned, so a
root spelled with a trailing separator compares the same as its canonical spelling.
The release manifest describes the download
checksums.txt was written from outside dist, so every line carried a dist/ prefix and
shasum -a 256 -c checksums.txt failed with FAILED open or read for anyone who ran it beside the
assets they had just downloaded — a browser and gh release download put the files there as bare
names. The sums are written from inside dist now, so the manifest names what the release page
actually hands you.
The README catches up
The second machine (clone the vault, beadle init there, enable the agents that machine has),
--json on every command that has a machine-readable form and exit 2 on the ones that do not, the
.gitignore init writes at the vault root, and what eject leaves behind.
v0.5.0
beadle v0.5.0
Why a minor and not a patch. The tree is at v0.4.2, and this release changes what a script
observes, not only what a person sees: three exit codes move (2, 5, 7), one new
machine-readable document appears, the plugin home moves into the vault, and the agent ids in
documents become the short canonical ones. A patch would claim compatibility that three of the
seven sections below deliberately break. In 0.x, the minor is the breaking slot, so v0.5.0
is the smallest honest name.
Plugins are managed by verger now
beadle plugins install, remove, list, eject, pin, pins and canon are the same
plugin manager verger is, running inside beadle. The packages, the versions and the per-agent
cells you see are the ones verger keeps; beadle no longer keeps a second opinion about them.
eject moves the plugin home out of the vault to ~/.verger and keeps the packages where they
are, so a plugin home that has to live outside the vault can.
beadle init absorbs a ~/.verger left behind by an older standalone install into the vault,
so the two stops being two homes.
The farm is still here, and it is still beadle's
This is the part most likely to be misread, so it is said plainly: the farm is not removed.
A plugin installed into any host with file-based plugins is still scanned, parked in the vault
and presented to the other hosts — install it in one agent and it reaches the others. Skills,
subagents and commands are delivered through the farm; MCP servers go through the MCP kind;
hooks wait for your approval. The farm is what feeds bundles, and what beadle hooks approve
refers to.
What has changed is that the farm is not what beadle plugins talks to. Plugins are
installed and removed through the plugin manager; the farm is the cross-host delivery surface,
and it is not reachable through beadle plugins.
A farm recorded by an older build is taken over, not hidden. If the state on disk still
points at a farm, beadle doctor names the directory and the command that moves it, before you
sync. beadle sync then backs the farm up, moves what it owns to the plugin manager, and
prints one line per move with the backup path. A second sync has nothing left to say.
What the embedded plugin manager gained in this release
beadle carries verger inside the binary, so a verger release reaches you through the same
commands you already use. This release moves to verger v0.1.2, and these are the changes a
person can notice.
Removing a native plugin can now fail honestly
Some agents manage their own plugins, and an agent that was asked to remove one can decline. That
used to end the run as a generic failure, which reads as "beadle broke" — the one thing a script
cannot act on.
It now leaves as exit 6, and the message names the agent and what it would not do:
claude did not remove acme/tool
So a removal that half-succeeded says so, and you know which agent to go and look at, instead of
being told the tool failed.
verger.toml keeps your comments
verger.toml is a file people edit by hand, and every write used to rewrite it from scratch, so a
comment you had written to remember why something was there came back stripped. It is now edited
in place: your comments, blank lines and the spacing around your keys survive, and a key beadle
removes takes its own leading comments with it rather than leaving them orphaned above whatever
moved up.
Two things that were already true and are now simply here
These are worth knowing in the same place, but neither arrived with this bump — they were already
in the plugin manager beadle was carrying, and listing them as new would be wrong.
- One skills folder several agents read.
~/.agents/skillsis read by gemini, agy, pi and
omp. A skill placed there is available to all four, which is the point of a shared folder;
beadle still keeps each host's own copy where that host owns its own skills directory. --excepton the plugin commands.beadle plugins installandbeadle plugins removeboth
take--except, so you can leave a host out of a run rather than enumerating the others with
--hosts. (verger's ownremoveis the one surface that does not expose it.)
One home, one watcher
beadle and verger share a home: the plugin home is <vault>/verger, not a second directory
that has to be kept in step.
They also share a single watcher. The lock is taken once, by the command that owns it, so
there is exactly one watcher and one writer no matter which tool you started. Starting a
second one is refused rather than allowed to race.
Your vault travels between macOS and Linux
A vault is a directory you can put in git or your own sync, and both machines can share the
canon. Three things had to be true for that, and now are:
- The cache of scanned skill trees is keyed by place, not by path. A key that read
/Users/you/...meant nothing on a Linux box, the whole cache missed, and every sync wrote a
second machine's home directory beside the first. - A hook module's delivery record travels. That record is the only proof beadle has that a
file it is about to overwrite is its own. Keyed by a path from another machine, beadle called
its own file a stranger's — and a stranger's file is never updated and never removed, so the
module was orphaned on the second machine instead of updated. - An adoption's two paths travel. An adoption is a standing instruction ("this slot held
somebody else's copy, and here it is"), so a path from another machine is not a fact that went
stale — it is an instruction that is wrong. On the second machineunadoptnow restores into
that machine's own slot, pointing at that machine's own copy.
A path outside your home has no portable name and keeps its absolute spelling on purpose. If
such a record cannot be honoured on the machine reading it, unadopt refuses, says which link
is missing, writes nothing into the slot, and keeps the record for you to look at.
Existing vaults are upgraded as they are read. Nothing has to be run to convert them, and
beadle doctor names anything it had to leave alone.
What travels is the vault. What stays behind is machine-local: receipts, journals, consent records
and anything else that describes this machine's history. The next machine rebuilds what it can
from the parts that do travel.
sync is idempotent
Running beadle sync twice leaves the vault byte-identical, and the second run says nothing.
This is checked in the same form the release gate uses it — a real sequence, hashes taken
around a repeated sync — rather than in a shape chosen to pass.
A vault written by an older beadle is migrated in place: what that build kept on disk and this
build keeps somewhere else is moved, the copy of anything removed is left in
<vault>/state/backups/<timestamp>/, and the run prints one line per move. Nothing is deleted
before the copy is taken, and a file that is not what this build would write is copied and named
rather than deleted.
beadle migrate is the on-demand form for the stored schemas: the upgrade already happens on
every read, and migrate persists it and reports what changed. On a current vault it writes
nothing at all. The moves that change what your agents see — the farm take-over above, the
agent-id renames, the plugin ledger rekey — belong to sync rather than migrate, on purpose.
Exit codes are the same table verger uses
One code means one thing across both tools:
| code | meaning |
|---|---|
| 0 | the run did what it said |
| 1 | unexpected — an error with no more specific class |
| 2 | usage — a wrong flag, argument or command; nothing was written |
| 3 | a destructive conflict a human must settle |
| 4 | a refusal by a policy rule |
| 5 | consent — a package needs approval before it runs |
| 6 | host unavailable — the host cannot be reached, has no schema, or was asked and did not do it; the rest still ran |
| 7 | written by a newer tool — do not rewrite, report it |
Three of these are new to beadle, and all of them used to be something else:
-
6 is wider than it was, and it is the same code verger now uses. It used to mean only "that
agent is not installed here". It now also means the agent was asked, answered, and did not do
what it was asked - so a removal the host refused leaves as 6 instead of the 1 that reads as
"beadle broke". Both tools read the class from the type rather than from the message, so a
rewording cannot change it. -
A question nobody answered is 5, not 1. When beadle asked you something it could not put
to you and then declined for you, the run used to report an unexpected error. Your next move
was always the same — answer it, or pass-y— so it now has a code that says so. -
A vault or config from a newer beadle is 7. Refuse to rewrite it and say which version
wrote it. Previously this could surface as a usage error about a vault that was perfectly
fine.
--json everywhere, or a refusal
Every command either answers --json with one document or refuses. There is no third case
where a command takes the flag and prints a table anyway.
A command with no machine-readable form now exits 2 and says so, naming the commands that
do have one:
$ beadle guide --json
error: `beadle guide` has no machine-readable form; drop --json, or use one of: …
Documents are told apart by schema.name, never by their fields — a document grows fields
within a version, so a field you read today is not the whole document. Switch on
schema.name.
What may break a script
In rough order of how likely it is to surprise you:
--jsonon a command that has no document is now exit 2, where it used to print a
human table and exit 0. If a script passed--jsoneverywhere and ignored the output shape,
it will now see a failure.- A declined question is exit 5, not 1. A scri...
v0.4.2
v0.4.1
v0.4.0
v0.3.2
v0.3.1
v0.3.0
v0.2.0
What's Changed
- build(deps): bump the actions group across 1 directory with 2 updates by @dependabot[bot] in #1
New Contributors
- @dependabot[bot] made their first contribution in #1
Full Changelog: v0.1.0...v0.2.0
v0.1.0
Full Changelog: https://github.com/odiumuniverse/beadle/commits/v0.1.0