Releases: adi-family/mono
Release list
ADI v1.4.2
Fixed
- The Windows package is built again. 1.4.1 shipped without one, so no Windows machine could
take that release at all: a diagnostic section written for the macOS front door read a file's
permission bits throughstd::os::unix, which Windows does not have — and although that code
can never run there, it still had to compile there. This is 1.4.1, for Windows.
ADI v1.4.1
Fixed
- The front door can be installed on a Mac again. Since 1.0.0 it could not, on any machine,
and nothing said so. A root daemon is worth no more than the file it runs, so ADI refuses to
point one at a binary an ordinary user could replace — correctly, because with the daemon's
self-watch that is a way to become root without a prompt. But the binary it was naming lived
inside the app bundle, and an app dragged into/Applicationsbelongs to whoever dragged it:
the refusal fired on every install,.adiroute and repair, every time, and it fired before
the password prompt, printing its reason where only a subprocess could see it. Machines whose
front door predated the check kept working and hid it; anyone else got a.adithat resolved
and then hung, with three green ticks in the setup panel above it. The daemon now runs a
root-owned copy ofadi-hivethat the privileged install puts in/Library/Application Support/ADI/, which is exactly what the rule was asking for. One consequence worth knowing:
a copy in root's keeping cannot be refreshed by an auto-update, so after one the front door
goes on proxying with the build it was installed with — the services list says so and offers
Update the front door to this build, and everything else about the update lands as usual. - The repair now reaches the machines it was written for. 1.4.0 taught ADI to notice a front
door that was installed and answering nothing, but it only offered to fix a daemon definition
it recognised — and it recognised them by a filename that daemons installed before 1.0 do not
carry. The one machine the check existed for was therefore the one it skipped. A definition is
ours if it runs a program we install, whatever generation wrote it; one repointed at somebody
else's build is still never rewritten, only started. A dead front door is also now repaired
ahead of a merely stale one, since the repair fixes both on its way past. - A diagnostic report describes the root daemon. It detailed every per-user service and said
nothing about the only one that answers.adi, so an archive from a broken machine looked
exactly like an archive from a working one. It now carries that daemon's definition verbatim,
whether the program it names is present, whether that program is the build the app shipped,
and whether the automatic repair has ever run here.
No build for: windows-x86_64. Those platforms stay on the version they are on.
ADI v1.4.0
Fixed
- A front door that stopped is put back when you open ADI again.
.adinames are answered by
a root daemon, and the only question ever asked about it was whether its file was on disk. So a
machine where the file had been copied but launchd had never loaded it — a password prompt
cancelled halfway through the first install, a background item switched off later — reported
itself perfectly set up while every.adiname resolved and then went nowhere. It does not even
look like a failure: the daemon is also what puts its address ontolo0, and macOS drops packets
to an address no interface owns, so the browser never gets an error page. It just loads forever,
in every browser, and reopening the app fixed nothing because the file was still exactly where it
was supposed to be. Opening ADI now asks the address rather than the file, and offers to put the
daemon back — at most once every few minutes, so a prompt you dismiss does not follow you around,
and never for a front door you repointed at your own build. The services list grows a Repair the
front door button for as long as it is silent,adi-mono dns grant-networkis the same repair
from a terminal, and a diagnostic report now printsfront door answering NOand says which
command fixes it, instead of showing three green gates above a machine that does not work.
ADI v1.3.0
Changed
- The whole product is drawn to one design system now, written down in
design/DESIGN.md
and valued in one file,design/tokens.css. The control panel is dark — there is no theme
toggle any more — and quieter: sidebars and bars recede, the transcript sits on the lightest
surface at 15.5px, tables lost the cards around them, labels lost their capitals, and one
orange per screen marks the one action or live state that matters. Type is Geist, with Geist
Mono only for what a machine wrote or will read — paths, ids, commands, model names. Every
icon is Lucide, at one stroke. The mark is flat: three hexagons in the ink around them, no
gloss, no motion. The same rules reach the front door's error pages, the pages the mesh
gateway serves, the shell every dashboard is generated into, the mesh client, the disk image
and the landing at withadi.dev. Nothing about what the app does changed; a dashboard you
already have picks up the new shell the next time it is listed.
Added
- You can now join another machine's fleet from the control panel. Settings → Fleet has a
Join a fleet panel: paste the invite the other machine minted, press Join, and this machine
dials out and pairs. It then shows the password that pairing minted — once, because neither
machine stores it — and the link to the other machine's panel atapp.<name>.n.adi. Before this
the page could only mint invites, so the machine doing the dialling needed somebody at a
terminal to runadi-mono mesh join; that is precisely the machine most likely to have nobody
who wants one.
Fixed
adi-mono mesh joinprinted the wrong address to open after pairing — the name the other
machine files you under, which resolves nowhere on yours. It now prints the name you file it
under, which is the one that works.
ADI v1.2.1
Fixed
- ADI starts on a Windows machine that has never had a compiler on it. The installer put
everything in place and then Windows refused to run any of it: "the code execution cannot
proceed because libstdc++-6.dll was not found", over an offer to reinstall that could not
help. The released binaries were linked against a GCC runtime library that is not part of
Windows and that nothing installs; they now carry it inside them. Install this version over the
broken one — an ADI that cannot start cannot update itself.
ADI v1.2.0
Added
-
Windows installs like an app now. Download
ADI-Setup-x64.exe, click through it, and what
you get is one entry in the Start menu called ADI. Opening it starts the platform, opens the
control panel, and leaves an icon by the clock you can start, stop and reach ADI from. Before
this, the download was a zip of four.exefiles and four.cmdfiles in one folder, and the
first thing it asked a new person was which of them to run — a question with no good answer,
since all four are the platform and none of them is the app. The four are still there, because
the platform is genuinely four supervised services; they are in abin\folder now, exactly as
they have always been hidden insideADI.appon a Mac. The install goes into your own user
account and needs no administrator,adilands on your PATH, ADI appears in Installed apps, and
uninstalling gives back the.adidomain and leaves%USERPROFILE%\.adi— your projects,
secrets and database — untouched. The one administrator prompt, for the.adidomain, is now
asked during the install where a prompt is expected, instead of arriving unexplained the first
time you opened something. -
The Mac app updates itself, from the app. The window now shows which version you are on and
a button that fetches the next one. This was only ever on the control panel before, and the
control panel isapp.adi— a page reached through a name ADI itself has to resolve. So the one
fault that most needs a new version, a.adiroute that has stopped working, was also the fault
that hid the way to get one: nothing loaded, and the only remaining advice was to download the
disk image again by hand. The button runs the copy of the CLI inside the app bundle and talks to
GitHub over your Mac's own DNS, so it works when nothing of ADI's does. It says what it is doing
— including that ADI closes and reopens itself to finish — and a version that turns out not to
work is still rolled back, exactly as a background update is. -
"Something not working?" makes one file to send. A second button at the foot of the window
collects everything that could explain a fault — the versions, the two permissions, every
service and what its supervisor last did with it, the.adiroute, what is listening, whether
the panel and the front door actually answer, the tail of every log, any crash reports — into a
single archive, and shows it in Finder ready to attach to a message. It reads only; nothing is
started or stopped, so it is safe to press while something is broken. It also tells you in the
window what it already thinks is wrong, which for a stopped service or a missing route is the
whole answer and needs sending to nobody. Secrets, your database and agent transcripts are never
opened, and any credential-looking value in the config it does copy is blanked out first. The
same thing isadi-mono diagnosein a terminal, for a Mac where the app will not open at all. -
…and a second button next to it opens the issue for you. Open an Issue goes straight to
GitHub with the report already written up: which build this is, which macOS, whether each of the
three setup steps is done, what every service is doing, and anything the report flagged — with a
blank space at the top for what actually happened. Those are the details that decide whether a
bug can be looked at, and every one of them used to cost a message asking for it. Drag the
archive into the box and it is a complete report.
ADI v1.1.0
Added
- A Mac installs
bunfor itself. A dashboard is a pair of bun servers, and macOS only ever
assumed bun was there: a Mac that had never installed it by hand still scaffolded a dashboard,
still listed it, still gave it a hostname — and then served a dead host, with nothing on screen
saying why. Starting the stack now fetches the pinned build into~/.bun/bin, checked against
its published SHA-256 before it is ever made executable, exactly as the Linux node installer has
done since 1.0.0. A bun you already have is reported and left exactly as it is — we do not
upgrade one out from under your other projects — and a Mac with no route to GitHub still comes
up, because only dashboards need it.adi-mono bunasks for the step on its own and says in one
line what happened. - A phone pairs by being shown a code. Scanning is the primary pairing action on iPhone and
iPad now: an invite is over nine hundred characters, so a QR code is how it gets onto a phone,
and the text field is the fallback for a camera that is refused, absent, or pointed at nothing.
A machine paired this way is filed under its own name instead of a key-derived
viewer-25f6795fa6.
Fixed
- Opening a dashboard your phone holds no grant for no longer answers "The node refused this
service." Tapping one asks the machine to share it and then opened the page immediately — but
a node's gateway serves from a snapshot it re-reads every few seconds, so the request was judged
against a registry that had never heard of the grant. The phone waits that window out now. It
read as a flake rather than a bug, because iPhone usually won the race and iPad usually lost it.
ADI v1.0.1
Added
-
The chat rail can be narrowed to the conversations you started. A fleet starts most of its
own work — an agent launches a helper, a trigger fires one on an event, a script runs one on a
schedule — so a rail of four hundred conversations mixed the handful a person actually had in
with everything the machine had spawned for itself, and nothing recorded the difference. Every
run now writes down who asked for it at the one moment that is known, the launch: a person,
another agent by name, or automation with nobody watching. The Sessions head gains a filter box
offering All sessions, Only starred and Only started by me — the first two being the
starred-only toggle that was there before, now one option among three. Two cases worth knowing:
a conversation opened before this release is attributed to nobody and deliberately does not
count as yours, because a filter that read every unattributed session as a person's would show
a year of agent-spawned runs under your name; and whatever is on screen stays visible whichever
filter is on, since a filter must never hide the conversation you are reading. -
One run can be launched on a different model, or with its permissions loosened, without
editing the agent. An agent definition is a template and editing it is usually the right way
to change what a run does — the exception is the launch that is deliberately unlike the others:
try this task on the big model, run this one underbypassPermissionsbecause it is a scratch
checkout. Doing that by editing the agent means remembering to edit it back, and forgetting is
how an agent ends up permanently on settings somebody chose for one afternoon. The composer
gains a run-settings panel, andadi-mono agents runtakes--set model=opus,
--set permission_mode=bypassPermissions,--set unattended=true, repeatable.--set <key>=
with nothing after the=unsets what the agent pins for this run, back to the engine's own
default, which is the only way to say "the agent fixes this and this run should not". The
override travels with the launch and is re-applied on every later turn of that conversation, so
a chat cannot answer its second message as a different agent than its first. Settings only: a
run cannot grant itself a tool, a secret or a knowledge base its agent was not given, because
those are the agent's identity rather than its dials. The panel remembers what you set per
agent in this browser, beside the working directory it already kept.
ADI v1.0.0
The first release under a stable version number. Two things are in it: a browser tab can now be
paired with a machine and render its control panel with nothing listening in between, and five
security fixes — one of which closed a path from any web page the operator happened to visit to
code running as root on their machine.
One thing to do after updating. This release replaces the local certificate authority (see
below), so https://app.adi will warn until you trust the new one. On macOS:
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/.adi/mono/hive/tls/ca.pem. The old root is inert from here and worth removing from your trust
store. Plain http:// is unaffected, and the front door logs the instruction on every start
until it is done.
Security
-
A web page you visit can no longer drive this machine's control panel. The panel has no
login: it listens on loopback and treats everything that reaches it as the operator. But.adi
resolves machine-wide, sohttp://app.adi/api/*was an address any page open in the operator's
browser could post to — and because the panel reads JSON out of a body whatever its type claims,
atext/plainPOST was a CORS simple request: no preflight, nothing to consent to, the side
effect just happens. The end of that chain was root,POST /api/fs/writebeing jailed to a
directory that holds thehive.yamlthe root front door re-reads every three seconds and runs.
Every/api/*request is now refused unless itsOriginis absent or names the host it was
sent to. This is not authentication and does not pretend to be — it stops a web page driving the
panel; a process already on this machine can still send whatever it likes. -
The root front door launches nothing at all. The rule that strips service runners from a
hive running as root was applied only to imported hives, leaving the top-level file's own
run:exactly where it was — and the file that got the exemption is the one that needed the
rule, since the root daemon is pointed at a store file that is user-owned by design. Arun:
written there was executing as root within three seconds, no restart needed. The decision moved
to the accessor the supervisor actually calls, which as root now returns nothing and names the
services it dropped. -
A root daemon will not run a program an ordinary user can rewrite. Installing the front door
resolved its program as a sibling of whichever binary was doing the installing, soadi enable
from a repo build was enough to put atarget/releasepath into a root plist — after which a
plaincargo build --releasebecame root within about a minute, with no prompt. Installation
now refuses if that program, or any directory above it, is owned by a non-root user or is
group- or other-writable, and names the component at fault before anything is written. -
The local certificate authority may only vouch for this machine's own names. The CA you are
asked to install as a system trust root was bounded only in path length — nothing constrained
names, so it could sign a certificate forgoogle.com, for a bank, or for your own SSO, and
every browser on the machine would have accepted it. It is now constrained to theadiDNS
subtree,localhostand127.0.0.0/8, which is exactly what the front door serves. Because the
copy in your trust store is not the copy on disk, an existing CA is replaced outright rather
than quietly rebuilt — hence the re-trust above. -
The store is written owner-only. Every file it held landed at whatever the umask said, which
is0644on a stock macOS account. That included this node's long-term mesh identity key, and
the invite nonce and ticket that are together a complete invitation to join. macOS puts every
local account instaff, so a second account on the machine could read all of it, and every
backup and sync carried the same bytes. New files are opened0600and directories0700;
existing ones are repaired as they are read, keeping the owner's own bits so a tool script stays
executable.
Added
-
A browser tab is its own peer, and it pairs by dialling.
mono-mesh-client.withadi.devis a
page that holds its own key, dials the machines it has been paired with, and renders each one's
control panel — no server, no open port, nothing listening behind it. Everything on the screen
came over QUIC from a machine that is not reachable from the internet. Long-lived streams work
both ways, so the panel's live channel, its event streams and its websockets all run through it.
Pair by runningadi-mono mesh inviteon the machine you want to reach and giving the token
to the page. -
Pairing a phone is pointing it at a code. An invite is around a thousand characters, and
getting that onto a phone was the whole friction.adi-mono mesh invitenow draws it as a QR at
a terminal; the Fleet page has a Show pairing QR button that mints one and counts down its
ten minutes; and the browser client has a Scan button that reads one. The code carries the
token rather than a URL, so a phone's own camera app will only offer to copy it — the page says
so, because that failure is silent and looks like a broken code. Redirected output is unchanged,
so scripts that read this command keep working. -
A phone sees what each machine runs, not just its panel. Under every paired machine are the
dashboards that machine is running, read from the node itself. A row your pairing did not grant
says Allow, and the first tap asks the node for it. -
⌘K answers on the page it just took you to. The palette was mounted only inside one shell,
so using it, jumping somewhere, and pressing it again did nothing — it stopped working exactly
where you had started trusting it. Both shells now take their rows from one list, so they cannot
come to disagree about what the app can do, and Pair new device is one of those rows: it
lands on Fleet and raises the QR. -
The chat's right rail says who you are talking to, and where. Chat Analytics counted what a
conversation cost and what went wrong in it, and never named the agent having it — the name was
on the session row you clicked to get here and nowhere on the screen you landed on. Above it
there is now an Agent block of its own: the agent's name and what it is doing right now
(waiting on you, answering, running, awaiting a wake, idle), the backend and model behind it and
the project it is filed under; the conversation's working directory, when it started and
when it last said something; and the settings that explain the behaviour in front of you — its
permission mode, how many tools, knowledge bases and secrets it carries, whether it keeps a
memory, and whether it runs unattended. It appears before the first turn lands, which is when
the counts below it have nothing to show yet. -
Analytics opens with what is running right now. The page led with a fortnight of history,
so it could tell you what this machine had done and nothing about what it was doing. A panel
above the totals now names every run in flight — the agent, the project it is filed under, the
task it was given, how long it has been at it and when it last said something — and the live
sessions of interactive agents beside them, since those keep no run history to appear in.
The times climb while you watch, and when nothing is running the panel says so rather than
vanishing, which reads the same as a page that hasn't loaded. -
An agent is edited on its own page, at
/agents/newand/agents/<name>/edit, rather than
in a form that opened under the list. The page paints filled, survives a refresh, a deep link
and Back, and a rename leaves the URL pointing at what is in the form. Settings in a chat's
Agent panel opens that agent's editor rather than the list you were already past.
Changed
- The
tcp:andctl:grant families are withdrawn from the fleet page and the CLI. Both were
offered as examples and neither was ever enforced: what actually gates the raw-forward path is a
different list entirely, and nothing anywhere consumedctl:. This failed closed, so it was
never exploitable — but an operator who addedtcp:127.0.0.1:22believed they had opened
something and had not, and one who removed it believed they had closed something and had not.
Both beliefs are worth correcting. They still parse and load, so existingfleet.tomlfiles are
unaffected;ctl:is explicitly reserved.
Fixed
-
A Linux node stops taking its whole session down with one runner.
killon procps-ng keeps
only the first digit of a bare negative pid, so stopping one hive runner was aSIGTERM
broadcast to every process the caller owned — control panel, dashboards, DNS and the session
manager itself. Linux pids reach seven figures and a node's all begin with1, so this fired
every time. It read for weeks as "the node keeps losing its linger and dying"; losing the linger
was the aftermath, not the cause. macOS parses the same argument correctly, which is why it only
ever surfaced on Linux. -
A fronted app keeps its own
Authorizationheader. The stored mesh password rode
Authorization, attached whenever the client had sent none — so a page sending its own bearer
token to its own API suppressed the password, drew a challenge from the node, and popped the
browser's native password prompt on an ordinaryfetch. The document itself carried no such
header, so the page always loaded and only its AJAX calls prompted, which looked like a site
asking for a password at random. The password now ridesX-Adi-Authorizationand is stripped at
the gate, so it never reaches the service and the app's own header arrives untouched. A node
from before the split still works. -
**A release will not sh...
ADI v0.3.3
Fixed
- Linux and Windows have builds again — 0.3.2 shipped for macOS alone.
domain,
frontdoor_addrandfrontdoor_labelbecame accessors in an earlier commit and only the
macOS paths were updated with them; the Linux and Windows ones sit behind#[cfg], which a
Mac never compiles, so the tree looked green everywhere except the release builder. 0.3.2's
fleet fix reaches a node with this release.