Repository navigation
Releases: nativelite/atrium
Release list
atrium 0.40.4
Changed
- A codex
cmdmay carry codex's own options. It took--model/-m
and nothing else, so--enable network_proxy,-c model_verbosity=…,
--searchand the rest were refused atfleet upandctl spawn. It now
takes any codex option except the ones that set what codex may do, which
are atrium's: the sandbox and approval flags (with the hidden--yolo
alias),-p/--profile,--remote,--approve-for-me,
--dangerously-bypass-hook-trustand the same settings as-ckeys are
stripped and named (preflight warning, spawnnote), in every spelling
(-sx,-s=x,--sandbox=x, quoted keys).-C/--cdand--add-dir
are refused in favour ofcwd/add_dirs. Config that makes codex start a
program, send the session elsewhere or widen its sandbox (mcp_servers,
notify,hooks,model_providers,otel, network domains, …) is the
fleet file's to set: an agent'sctl spawnis refused it, since codex runs
an MCP server andnotifyoutside its own sandbox (measured under
read-only), and a sandboxed agent could otherwise escape the posture the
human chose (what a codex command may carry).
A respawn or recovery strips a recorded codex command's posture too, and
keeps the--add-diratrium wrote fromadd_dirs.
atrium 0.40.3
Fixed
- Windows: a sandboxed codex pane reaches atrium ctl. codex's Windows
sandbox runs the agent's commands under a restricted token, whose access
check must also pass against the token's restricting SIDs (the logon
session, Everyone, one SID of codex's own); the control pipe granted only the
user and SYSTEM, so everyatrium ctlfrom a codex pane atplan,accept
orautomodewas refused withACCESS_DENIED, and the pane could take a
message but never answer on the bus. The pipe's access list now also names
atrium's own logon SID, which admits that sandbox and no one new: another
user's or another logon session's process is still shut out. The spawn-time
warning that said Windows was not covered is gone; the pane keeps its plain
--sandbox. Measured with codex 0.163.0 (ctl listrun undercodex sandboxinside a live pane, and a claude-lead + codex-dev fleet ataccept
whose codex pane answersctl whoami; two ignored e2e tests keep the proof)
(codex panes). - Windows: the bar names the Store PowerShell. codex runs its commands
throughpwshwhen one is on PATH, and its sandbox cannot start the
Microsoft Store build of it (a packaged app): every command then fails with
Access is deniedbefore it runs, which codex reports as being denied or
unable to connect. A sandboxed codex pane whosepwshresolves into
WindowsAppsnow says so at spawn, with the fix (a non-packaged PowerShell 7
ahead of it, or--mode skip).
Known
- Linux: the e2e test
ctl_who_lists_the_panes_that_edited_a_file_and_a_collision_is_posted_oncefails under WSL Ubuntu on this release and on v0.40.2 alike (pre-existing, tracked in the issue filed with this release). Windows: full gate green. macOS: untested this release.
atrium 0.40.2
Changed
- A sandboxed codex pane can reach atrium ctl, and nothing else new.
codex's sandbox counts a connection to a unix socket as network and has
none, so a codex pane atplan,acceptorautomodecould not run
atrium ctl(Operation not permitted), whatever it was told. With the
control plane on, such a pane now launches under a codex permission
profile,atrium_ctl: codex's own:workspace(:read-onlyforplan)
with the network routed through codex's proxy inlimitedmode, no domain
allowed, and one unix socket allowed, this session'sATRIUM_CTL. Measured
with codex 0.163.0 on macOS:ctl whoamiandctl statuswork from the
pane; another unix socket, HTTPS and raw TCP are refused; writes stay in the
workspace. On by default. It needs codex's experimentalnetwork_proxy
feature, probed once per program per session; a codex without it keeps the
plain--sandboxand the bar says why. Not on Windows, where the endpoint
is a named pipe that codex's allowance doesn't cover; the bar says so there
too (codex panes).
Fixed
- A codex fleet agent with a
promptoreffortlaunches. Both were
passed as claude's--append-system-prompt/--effort, which codex exits
on (unexpected argument), andadd_dirsas one--add-dirwith several
directories, where codex read the second as its prompt. A codex agent now
gets codex's spelling: one--add-dirper directory,-c model_reasoning_effort, and itspromptfolded with atrium's ctl directive
and worktree norms into one-c developer_instructions(a TOML string, so a
prompt that reads liketruestays text). - A codex pane is told about ctl. The directive that teaches an agent
atrium ctland the worktree norms reached claude panes only; a codex pane
in a ctl session or a worktree got neither. It now gets both, in its
developer message.
atrium 0.40.1
Changed
- The generated fleet file shows the
captionsknob. Every built-in
template (atrium fleet init solo|pair|crew) now carries"captions": false, so the opt-in to the model-made caption is a line to flip rather
than a key to know about (fleets).
Fixed
- A codex pane's commands see the pane's environment. From 0.157 an
interactive codex attaches to one per-user background server, forked by
whichever codex starts first anywhere and outliving it, and the agent's
shell commands run as that server's children with its environment. A
codex pane lostATRIUM_CTL/ATRIUM_PANE/ATRIUM_TOKENwhen the server
came from outside atrium (an editor's codex), soatrium ctlfailed; and
when it came from an earlier atrium pane, every codex on the host ran
commands under that pane's capability token. A codex pane now launches with
--no-daemon(not with--remote, nor onqueue/agents, which refuse
it). Whether a codex has the flag is asked of its own--help, once per
program per session; an older one launches as written and the bar says why. - The compile pool holds its size on macOS. The pool counted its free
tokens withFIONREADon its own read/write end of the FIFO, which macOS
answers with 0 however many are buffered. On a Mac the pool always looked
empty, so each refill with no build running put a full pool's worth back on
top of what was there, and the cap stopped capping. It now counts through a
read-only end, which reports the real number.
atrium 0.40.0
Added
- Captions. With the mod, every pane reports what it is doing in a few
words: from each tool call, free (running cargo test,editing filter.rs), and from the model's own streamed text by one smallhaiku
call at most every twenty seconds, when a fleet sayscaptions: true.
The overview shows the caption in place of the transcript's last action; an
unfocused tile draws it dim after the title; the turn's end clears it. - The collision radar. The mod reports the real path of every edit that
ran (report touched=<path>…); the broker keys it by the pane's worktree,
so two worktrees' copies of one file are one file. The first time two live
panes edit it, both wear⚡(tile badge and overview row), the overview
lists the file under the agents, and onecollisiondecision_neededgoes
to the nearest pane above both on theatriumtopic.atrium ctl who <path>(andatrium_who) says which panes edited a file, with when and
whether each is live. - Ask without interrupting.
atrium ctl ask <target> [--timeout S] <question>queues a question that rides the target's inbox; its mod answers
from a fork of the pane's own context ($.model.fork: no tools, the turn
untouched, the transcript never leaving the pane) and reports the reply,
which the waitingaskprints andatrium ctl asked <target> <id>reads
again.Ctrl+A ?on a tile asks the focused pane what it is doing, what it
needs and what blocks it, and opens the reply as an overlay;atrium_ask
does the same from a pane. Subtree-scoped likesend, capped, scrubbed and
never in the audit log. - Fleet key
captions,whoamicarries it; mod version 0.2.0, with the
askcapability.
Changed
- Captions carry less, and the model-made one is opt-in. The caption a
tool call makes named the whole first line of aBashcommand — flags,
KEY=valueassignments, quoted text, paths — inctl status, the overview
and the tile title, for the whole fleet to read. It now names the program
and its subcommand only (running cargo test,running git commit,
running dev.py check): no flags, assignments, quotes, operators or URLs,
no path but the program's own name, three words at most. And the six-word
caption from the model's own streamed text — a second model call the text
leaves the pane for — is now off unless the fleet sayscaptions: true
(it was on unlesscaptions: false); the tool caption is free and always
on. ctl whois subtree-scoped. It was classed read-only likelist, so
any caller, token or none, could list every pane's edited paths. It now
needs a pane token, and a caller sees only the panes in its own tree, as
statusandaskdo; the operator sees every pane.
Fixed
- An ask's slot comes back. A pane holds at most eight unanswered
questions, but an answered ask counted as unanswered again once its reply
expired (ten minutes), and a question the mod had taken but never answered
stayed pending across a respawn: a pane asked eight times over a session
refused every lateraskfor good. An expired reply now takes its ask with
it (askedsays so instead of waiting forever), and a pane's exit or
respawn drops its in-flight questions along with the queued ones. - Collision keys compare paths as the filesystem does. A touch was keyed
relative to the pane's worktree or its cwd, so two panes in unrelated
repos both editingREADME.mdwore⚡and raised acollision; and the
prefix check was spelled-exact, so a mod'sC:/wt/a/src/x.rsunder a
worktree recorded asC:\wt\a(or a\\?\path, or another drive-letter
case) kept its absolute key and two worktrees never collided on Windows. A
pane with no worktree now keys by the absolute path alone, and every path is
compared in one spelling:\as/,\\?\stripped, and a path Windows
wrote lowercased;ctl whofinds a Windows file by any spelling. Areport
whoseaskreply is refused still records its other fields and touches. - Manual splits tile into a grid.
Ctrl+A "/%halved only the focused
pane, so every pane added by hand with one key joined a single1×Nstrip
(five"presses: five full-width slivers), while-n 4andctl spawn --herelaid the same panes out 2×2. A split now re-tiles the whole window
into the balanced near-square grid--herealready uses, with the new pane
where the key pointed:%in the next slot of the focused pane's line,
"in its slot of the next line (not appended bottom-right, as the first
cut of this fix and--heredid). The window keeps the orientation the
first key gave it ("columns,%rows), so a later key reflows the grid
instead of transposing it;ctl spawn --hereputs the worker beside its
caller the same way. Two panes keep the plain split the key names, three
make a line, four a 2×2, six a 2×3. Focus still lands on the new pane. - Install docs name the linker prerequisite.
cargo install atriumon a
machine with a Rust toolchain but no C toolchain ends inlinker `cc` not found(link.exe/gccon Windows) after every crate compiled; the
README's install section now says what to install per platform, why the
ccspelling on a Windows machine means WSL or a stray linker override, and
that a build from a clone needs the sibling nativelite crates beside it.
atrium 0.39.0
The mod release. atrium now carries a Claude Code plugin of function hooks
inside its binary; atrium mod install writes it out once, and every claude
pane atrium spawns loads it for that session only. With the mod in the engine,
three things atrium used to infer from the transcript become certain (a pane's
status, its context fill and cost, the text of its answers), sends and wakes
stop being keystrokes, the control plane becomes typed tools, and a subagent is
a pane the human can see. Nothing changes for a pane that has no mod: the
inference and the pty path stay as they were. Six new ctl verbs carry it.
Install or upgrade with cargo install atrium, then run atrium mod install
once; atrium fleet up says in its preflight whether the mod is installed.
Added
- The mod: a Claude Code plugin in every claude pane.
atrium mod install
writes a plugin of function hooks out of atrium's binary; every claude pane
atrium then spawns loads it (CLAUDE_CODE_PLUGIN_DIRS, withATRIUM_BIN
naming the atrium to call). Inside the engine it reports the pane's status
the moment it changes (working,waiting-approvalwith the tool as the
reason,waiting-prompt,idle,errored,ended), its context fill and
cost, and the text of each answer, over the control channel with the pane's
own token. A reported status wins over the transcript inference for two
minutes;erroreddraws the border red with a!badge and the overview
showsctx 41% $0.12per agent.atrium mod statussays what is installed;
"mod": falseinconfig.jsonor a fleet keeps it out. - New ctl verbs
hello,report,whoami,inbox,answerandwait:
the first four are what the mod speaks and are about the caller only (a
targetis refused);answerreads a pane's last reported answer up the
spawn tree, andwaitpolls for it, for idle, or for exit. - Native delivery. A pane whose mod declared
inboxis never typed into:
ctl sends and bus wakes wait in the queue until the mod collects them and
submits each through the engine's own prompt queue, which starts a turn only
when the session is idle. A task may span lines; a pane without the mod
keeps the pty path. - Typed control-plane tools. With the mod, a claude pane has
atrium_spawn,atrium_send,atrium_status,atrium_list,atrium_kill,
atrium_board_*andatrium_bus_*as tools; each call is oneatrium ctl
run, and an ask for one of them is answered by the mod, never a dialog. - The role section and the file guard. The mod appends an
atrium:role
section to the system prompt fromwhoami(pane, role, parent, mode, item,
owned files, worktree, whether it may spawn) and refuses anEdit,Write
orNotebookEditoutside the item's files, by real path, naming the owner. - The
/atriumpane, the decisions band, andrespawn_at. Inside Claude
Code,/atriumopens a pane with the open decisions (resolve buttons with
hotkeys), the board and the last bus events; a band above the prompt counts
open decisions. Fleet keyrespawn_at: <pct>: a pane whose context fill
crosses it while idle gets one decision posted to its parent on theatrium
topic, never a respawn by itself. - Subagents as visible panes.
atrium_subagentspawns a claude pane beside
the caller, sends it the task, waits for the answer its mod reports, closes
the pane unless kept, and returns the answer; the model's Agent tool is
refused with a pointer to it. Fleet keyssubagents(panes|native|
deny) andsubagents_keep; config keymod;ATRIUM_MODnames the
mod's folder. The fleet preflight states the mod's line and warns when claude
panes would load none.
atrium 0.38.0
A hardening release. Most of the 33 commits reorganize the source for the people
and agents who maintain it, with no change in behavior. The rest fix what a
review of that work and an audit against the rustkb knowledge base turned up.
It is the first release since 0.32.0 that builds on Windows with the Rust version
it declares (1.70), and the local gate now checks that on every push.
Fixed
cargo install atriumworks on Rust 1.70-1.72 on Windows again. Since
0.33.0 the Windows reaper calledusize::div_ceil, which needs Rust 1.73, so
on Windows every release from 0.33.0 to 0.37.2 failed to build on the
rust-versionit declared. The call is replaced by plain ceiling division, anddev.py check
now runscargo +1.70 check --all-targets --locked.atrium ctlrefuses a malformed command instead of sending the wrong
request.- A flag that takes a value (
--role,--identity,--worktree,--mode,
--to,--kind) used to swallow the next flag when its value was missing.
bus pub work --to --decision item=Xaddressed a role named--decision
and sent the escalation as an FYI. A flag is no longer accepted as a value. - An oversized
board claim --ttlcould wrap the lease negative, and a huge
audit <n>asked for a negative tail. Both now report "too large". - Leases are capped at 365 days. The client refuses a longer
--ttl, and the
server clamps any request'sttl_ms, since a raw request is not bound by
the client. - A repeated
--since, or a field named twice (board set k a=1 a=2), is an
error. Before, both copies reached the server and one won silently.
- A flag that takes a value (
atrium reapwaits once per sweep, not once per dead session. Cleaning up
64 dead sessions took 48 s, because each registry got its own 750 ms grace
period. On Windows, where nothing is signalled (the Job Object is the reaper),
it no longer waits at all.- Windows: a dead session's registry file is removed at the next launch.
Any session that ended without a teardown (the window's X, logoff, a crash)
left itsatrium-session-<pid>.pidsin%TEMP%, and only a manual
atrium reapremoved it. - A failed
fleet upremoves the worktrees it made. If the terminal could
not be taken, the roster failed to spawn, or a later member's worktree could
not be made, the worktrees created before the failure stayed on disk. They are
now torn down under the usual rule: removed only if clean and fully merged,
otherwise kept and reported. - Linux: a clean quit no longer reports "pane process group(s) survived
teardown" for plain shell panes. Teardown now reaps each pane's child
(bounded at 250 ms) before checking for survivors. - Unix: atrium never signals a pid above
i32::MAX. The cast to a signed
pid went negative, andkill(-1, sig)signals every process the user owns.
The pids come frompsand from registry files the same user can write. - Windows: the control pipe's access list is built from a correctly aligned
buffer. The token read cast a byte buffer to a pointer-aligned struct, which
is undefined behaviour. It was harmless in practice, but it sits on the path
that restricts the pipe to the current user. A new test checks the result.
Changed
- Library API:
atrium::ctl::build_requestreturns
Result<String, UsageError>instead ofResult<String, String>.
UsageErrorimplementsDisplay(the message alone) and
std::error::Error.atrium ctlprints the same messages as before. - Built on
nativelite-ansi0.4.0 andnativelite-vterm0.5.3, whose
tokenizer no longer allocates per token when feeding pane output. atrium's
own throughput was not re-measured for this release. - The source is split into modules a reader can navigate.
ipc,ctl,
fleet,ctl_serverandfleet_cliare now directories, and the end-to-end
suite has one module per area. Long functions became named steps:run(),
fleet_up,dispatch_ctl,build_requestandspawn_pane_full.main.rs
went from 4,365 lines to 594. No behavior changed. - Stricter lint discipline, enforced by the gate. The gate runs clippy
with-D warningsfor Windows, Linux and macOS. The crate has a[lints]
table, everyunsafeblock states why it is sound (// SAFETY:), and
unwrapis refused outside tests.
Full notes: CHANGELOG.md
atrium 0.37.2
Fixed
fleet uprefused every roster whosecmdis a configured claude alias.
0.37.1 began vetting each agent'scmdat launch with thectl spawnpolicy,
and that policy matched the literal stemclaudewhileis_agent_stemalready
counted an alias fromclaude_aliasesas an agent, so a second account's shim
such asclaude2fell into the "no trust posture is defined for it" refusal
written for aider and gemini. The vet now asksis_claude_stem, the same
test binding and status use, so any stem the operator lists inclaude_aliases
(the config file,ATRIUM_CLAUDE_ALIASES, or the fleet) takes claude's flag
policy and claude's posture. Governed flags are still stripped from an alias
and unlisted ones still refused, exactly as forclaude.
atrium 0.37.1
A patch release: the bus reaches the people it should, and the CLI explains itself.
A bus event wakes the panes it addresses and the topic's subscribers. The bus was pull only: a finished worker's bus pub work status=done sat unseen until the lead happened to run bus feed, and a worker's --to lead was dropped silently by the subtree rule. Seen in a live fleet, where the builder came up, read the feed once, found nothing addressed to it and went idle for good. An event is now typed into every pane subscribed to its topic and every pane it names with --to (a comma list is fine), once each is idle, as one framed line: [atrium bus #68 fyi from teammate "builder" on "work" — not operator input] item=F20 status=done. Who may wake whom: the publisher's own subtree, the panes above it, and any pane that subscribed — never an unrelated pane by name. Wakes are sanitized (no control, bidi or zero-width characters; a body cannot open a second frame), capped apart from ctl send, and coalesced per pane. Roles are unique while a pane lives.
Agents learn it from the CLI. The directive every claude pane receives says to run bus topics, subscribe to what its role must react to, and aim a hand-off with --to. atrium --help, ctl, fleet, config, recover and reap all answer --help/-h from anywhere, in one shape.
The atrium skills (marketplace plugin 0.2.8) subscribe first, address hand-offs with --to, start rosters from atrium fleet init, and describe config.json.
Full details in the CHANGELOG.
atrium 0.37.0
A minor release: preset fleets you call into a repo and configure from there.
atrium fleet init <template> and three built-in reference fleets. solo, pair and crew are compiled into atrium — runnable statements of how a fleet is meant to run: the lead plans and sizes items, delegates one per fresh teammate and reaps it on checkpoint, reviews in fresh sessions, and restarts itself from PLAN.md and the board; builders in their own worktrees. init writes ./atrium.fleet.json from a built-in or from one of your own fleets in the user-global fleet.json (yours wins over a built-in of the same name, and init says so), copied as written; it never overwrites. --agents N scales the builders. atrium fleet ls --templates lists both.
A user-global config.json. What you want in force on this machine for every project, without exporting the same variables into every terminal: claude_aliases (a second account's shim, with the config_dir it runs under, so its panes bind, show status and recover), deny, ctl_allow, trust_allow, build_jobs, memory_mb and fleet_defaults. Precedence: the file, the fleet's key, the ATRIUM_* variable, a flag. The first fleet up or recover on a machine asks once where the file should live and remembers the answer in atrium's own config.path; atrium config init and atrium config path do it by hand and show the result. ATRIUM_CONFIG and ATRIUM_FLEET name each file's full path for anyone who organizes their files their own way.
Fixes carried from 0.36.1. A restarted pane was clipped to the top-left of its tile (its input box missing until a terminal resize); a second account's claude (claude2) ran with none of atrium's launch rules; recovery died on a reaped worktree, blaming the command; a pane painted while its window was hidden showed the startup spinner; an abandoned synchronized update froze a pane for good.
Requires nativelite-agsess 0.2.3. Full details in the CHANGELOG.