Repository navigation
Releases: awebai/oats
Release list
OATS v0.59.0
OATS 0.59.0
2026-10-16
Upgrade
-
Install the Desktop first and the CLI second, as
Upgrading says: a 0.58 Desktop refuses a 0.59.0 CLI. The
0.59.0 Desktop accepts OATS CLIs>=0.26.0 <0.60.0. -
The official catalog moves three pins: oats.framework 1.12.0 → 1.12.2,
oats.okf 5.2.0 → 5.2.1 and oats.aweb 1.27.3 → 1.28.0 (see Provider
updates). oats.engineering 1.10.0, oats.cloning 1.0.1, oats.authoring
1.0.3, oats.jira 1.0.1, oats.linear 1.0.1 and oats.apps 1.0.0 are
unchanged. A deployment takes them by changing its pins and running
oats sync. Only new spawns use them. -
With oats.aweb 1.28.0, a host that needs the wake broker (a Codex
home,delivery: session, or a join) installs it once with
oats aweb wake install. Run it from the host's own login session (on
macOS, at the desktop), not over ssh. -
oats tui: the back key is now the leader, pressed twice to go back to
the list.Ctrl+\(open.detachKeyintui.json) pressed once in a
terminal waits for a command key; pressed again it gives the focus to the
list, as one press did up to 0.58.0. Atui.jsonwhoseopen.detachKeyis a
key an action has is now refused: give one of the two another key. See
Added and Changed (#855).
Added
-
retireon status rows: whether a retire of the home is running,
cannot be told, failed or was interrupted (featurestatus-retire-state,
#1247).oats status --json
instance rows carryretire: {state, since, self, code?, message?}while a
retire of the home is running, scheduled or owed, and no such key
otherwise. It is read only from the files beside the home: the self-retire
marker (self: true) with its completion process and its result file, or,
without a marker, the home's claim held by anoats retire(self: false).stateisrunning,unknown(liveness cannot be read),
failed(with the result's kernelcodeand its one-linemessage) or
interrupted(the completion process is gone).sinceis always an
instant (the recorded time, else the file's modification time), and
codeandmessageare strings or absent, nevernull. Status still takes no
claim, removes no file and signals no process.retirePendingkeeps its
meaning. Remote roster rows relayretireonly when the host's row has
it, checked by the same rule, and drop a value that fails it. A client
reads the field only whenoats version --jsonlists
status-retire-state: an older kernel never carries it
(retire). -
oats session inspect --jsonreports the agent window'ssize: { cols, rows }
in cells when present, including through--server. The dimensions come
from the same tmux call as the pane identity and are omitted for absent or
dead terminals.oats version --jsonadvertisessession-inspect-size, so
viewers can discover support before opening a PTY at that size (#1285). -
oats tuihas a leader key, so every action is reached by keys from
every focus (#855). The
leader isCtrl+\(open.detachKeyintui.json), then one plain key:
korSpacethe palette,1to3the views,Up/Downthe
previous or next instance's terminal,zzoom,wclose the terminal,
X/R/S/Dthe acts,/filter,oworkspaces,?help, andEsc
or the leader again the list. In a terminal the leader is still the one
key taken from the agent, now twice to go back to the list. A key that
comes in the same read as the leader cancels it, so a paste never runs a
command. See the TUI page. -
A palette, as the Desktop's ⌘K: the leader then
k, orCtrl+Kin
the list, opens one input over the instances that can be opened (the
most recently opened or shown in the run first), the views, the selected
instance's acts, and workspaces, refresh and help, filtered as you type
with the Desktop's match. Choosing an instance shows its tab, or opens it
in a new one. See the TUI page. -
oats tuilists the open workspace's souls
(#855).2, or the leader
then2, shows the Souls view: one row per soul with its colour, a count
of its instances on this machine, and!for a soul a spawn here would
refuse. The detail beside it says where the soul comes from and where it
works, which harness a spawn would use, its teams, its capabilities and
its instances here.i(orEnterin the detail) shows those instances
in the Instances view, filtered by that soul;Escclears the filter.
The list is the OATS Desktop's, read withoats soulsonly once the view
is first shown, and again only when the workspace changes, or withr.
The palette lists the souls once they are read.tui.jsonhas a new
action,soul-instances(defaulti). See
the TUI page. -
oats tuispawns an agent on this machine
(#855).n(or the leader
thenn) opens a picker of the open workspace's souls;Nspawns
another of the selected instance's soul. The preview is the OATS
Desktop's, read withoats spawn <soul> --preview --json: the name, the
home, where it works, the harness and model and where they were chosen,
the team and the worktree setup, with the launch-prompt policy, the
warnings and the modules folded to one row each.Tabmoves between
Spawn, the name (the instance's--purpose), the parent and the folds;
Enteron Spawn applies exactly the decision on screen, through the
shared apply, and a pastednandEnters never spawn. When the agent
is created and started its terminal opens beside the list; any other
outcome is said in the Desktop's words, with what to do next, and an
outcome that is not known is checked once withC. One spawn runs at a
time; spawning on another machine, or with another harness, model or a
task, staysoats spawn. The palette lists Spawn an agent and Spawn
another.tui.jsonhas three new actions,spawn(defaultn),
spawn-another(N) andspawn-check(C). See
the TUI page. -
oats tuisplits its panel in two groups
(#855). The leader then|
splits it side by side, and the leader then-one above the other (|
and-alone in the Instances view). The open tabs stay in the first
group; the second starts empty, saysEnter on an agent opens it here,
and an agent opened then opens in it. Each group has its own strip and
shown tab, both shown tabs are drawn, and a rule separates them. The
leader thenTabgoes to the other group, the leader thenmmoves the
shown tab there, and the leader thenxcloses an empty group; closing a
group's last tab gives the other the whole panel. Each group needs 40
columns side by side or 8 rows one above the other, and the four tabs
are counted across both.tui.jsonhas five new actions:split-right
(default|),split-down(-), andgroup-next,tab-moveand
group-close, which have no key of their own by default. See
the TUI page. -
oats tuiopens up to four terminals at a time, as tabs
(#855). The panel's top row
is the tab strip: each tab's agent in the order it was opened, the shown
one in reverse while it has the focus and bold otherwise, and•(*in
ASCII) after a hidden tab whose agent wrote since it was last shown. With
one tab the row reads as before.[and]in the Instances view, or
the leader thenLeft/Rightfrom any focus, show the tab before or
after, without wrapping; showing a tab selects its row in the list and
leaves the focus where it was. Opening an instance that has a tab shows
that tab. The palette opens with the second recent instance selected
when the first is the shown tab's, as the Desktop's does.tui.jsonhas
two new actions,tab-previous(default[) andtab-next(]). See
the TUI page.
Changed
-
A retire with a large work tree is about twice as fast
(#1247). On a Linux
laptop (btrfs on dm-crypt), the retire of a home holding about 400 MiB in
37,000 files underwork/took 18–30 s and now takes 10–17 s. Every
recovery copy is still written and verified before the retire hooks run,
and every safety rule is kept.- Cold reads in parallel. A digest reads its files one at a time, and
a tree outside the page cache read at about 40 MB/s: the copy of a
clone just made by a reflink, or anode_modules/not read for a
while. A few worker threads now read the next files ahead of it. No
digest value changes, including those of baselines older kernels wrote,
and no error changes. The verification still reads the copy's own bytes
back. - One read per state. A worktree's untracked and ignored digest and
its bytes are taken from one read of each file, both before the hooks
and after them. - A directory instance's pre-hook copy no longer reads its source a
second time. A file changed before the copy read it still refuses the
retire before any hook runs. A file changed during the copy, after it
was copied, used to refuse the retire. It is now preserved, verified,
underafter-hooks/, as a worktree's work already was
(souls-and-instances.md).
- Cold reads in parallel. A digest reads its files one at a time, and
-
Desktop and TUI: the instance list is in name order
(#1262). The sidebar, the
command palette and the TUI's list order instances by name, each bundle by
its top instance. ...
OATS v0.58.0
OATS 0.58.0
2026-10-15
Upgrade
-
Install the Desktop first and the CLI second, as
Upgrading says: a 0.57 Desktop refuses a 0.58.0 CLI. The
0.58.0 Desktop accepts OATS CLIs>=0.26.0 <0.59.0. -
On a Mac, upgrade the CLI before the next reboot. Up to 0.57.1, every
directory-mode instance refusedoats session startafter a macOS reboot
("directory home was exchanged"). With 0.58.0 those homes start again, with
no edit, including homes spawned before the upgrade. A host that is already
stuck needs only the new CLI. See Fixed
(#1261). -
A client that drives
oats spawnitself may pass--max-ageon an
apply bound by--expect-decision, whenoats version --jsonlists
spawn-apply-max-age. An older kernel refuses the flag (E_BAD_ARGS). See
Added (#1246). -
The official catalog's versions are unchanged in this release:
oats.framework 1.12.0, oats.okf 5.2.0, oats.aweb 1.27.3, oats.engineering
1.10.0, oats.cloning 1.0.1, oats.authoring 1.0.3, oats.jira 1.0.1,
oats.linear 1.0.1 and oats.apps 1.0.0.
Added
oats spawn … --expect-decision <revision> --max-age <seconds>: a
confirmed spawn reuses its preview's observations (feature
spawn-apply-max-age, #1246).
An apply bound by--expect-decisionnow takes--max-age, as
spawn --previewalready did: it reuses member heads this machine observed
at most that many seconds ago instead of asking each remote again, which
saves the apply'sgit ls-remoteround (about 0.3–0.45 s). The decision is
computed from those heads, and one that differs from the confirmed revision
is stillE_DECISION_STALE, with nothing created.--max-age 0is live, as
without the flag. The apply's answer is unchanged: it carries no
observationblock. A spawn apply without--expect-decisionstill refuses
the flag (E_BAD_ARGS), now with a message that says so, and--server
still refuses it. A client passes the flag on an apply only when
oats version --jsonlistsspawn-apply-max-age: an older kernel refuses
it (Apply).
Changed
-
Desktop: a spawn no longer re-reads every member repository at the
press (#1246). With a
kernel that can reuse them, the Desktop's spawn lets the kernel use the
member repositories' heads it observed in the last minute instead of
reading each one again when you press Spawn. If the kernel then works out
a different spawn from what the dialog showed, the spawn is still refused
as before ("Something changed before the spawn went through…") and the
values are read again. -
Desktop: a spawn reaches its terminal sooner
(#1246). Pressing Spawn no
longer runs a second spawn preview when the dialog has been open more than
a minute: the press uses the preview on screen for up to five minutes, and
if anything changed meanwhile the spawn is refused as before ("Something
changed before the spawn went through…") and the values are read again.
Once the spawn is created, the Desktop reads that one workspace at once
instead of waiting for its next full refresh, so the new instance's row and
terminal appear without the extra second or more. -
Spawn preview and apply are about 0.4 s faster on Claude souls whose
capabilities require a Claude plugin
(#1246). The harness-package
check's probe,claude plugin list --json, now runs with
DISABLE_TELEMETRY=1set for its own run, so Claude no longer flushes
telemetry before it exits. The probe's answer, and so the check, is
unchanged; the launch, the install steps and every other probe run as
before (The checks read the pane). -
The Desktop accepts OATS CLIs
>=0.26.0 <0.59.0
(#1261). The compatibility band
admits 0.58; a 0.57 Desktop refuses a 0.58 CLI. No new gate on the band.
oats tuiruns the kernel it ships with and is held to the same band.
Fixed
-
A directory-mode instance starts again after a macOS reboot
(#1261). macOS gives a volume a
new device number each time it is mounted, so after every reboot
oats session startrefused every directory-mode home with "directory home
was exchanged; restore the owned root before retrying start", although its
home andwork/were the same directories. On macOS a start now accepts a
root whose inode matches the one the spawn recorded, and whose birth time
matches too when one was recorded. A spawn now records each root's birth
time; homes spawned earlier, whose baselines hold none, start with no edit.
A real exchange, another directory renamed into the home's orwork/'s
place, is still refused with the same error, and Linux keeps comparing
device and inode. Captured Pi sessions on macOS had the same problem at the
next start after a reboot ("original Pi session directory was replaced");
the same rule now applies to their session directory
(directory— independent execution). -
oats tui: an agent's terminal that ends says why again. On tmux 3.2 to
3.4, a terminal whose viewer ended at once, for example because the agent's
window had just gone, could close with the line that the viewer "ended
without saying why", and without the viewer's error output under it. The
cause: tmux reports a pane as dead a moment before it has the exit status.
The panel now waits for that status, for at most 10 seconds (2.5 seconds
on tmux 3.2), so the line and the viewer's error output show again
(#855; see
oats tui).
OATS v0.57.1
OATS 0.57.1
2026-10-15
Upgrade
-
Either order of Desktop and CLI works: a 0.57.0 Desktop accepts a
0.57.1 CLI, and the other way round. The 0.57.1 Desktop accepts OATS CLIs
>=0.26.0 <0.58.0. -
Upgrade the hosts a Desktop reaches over
--server, too. A routed
attach runs its viewer on the host, so the viewer fixes (it ends with the
agent's window underdetach-on-destroy off, and a late hang-up no longer
leaves anoatsview-*session behind) hold for a remote terminal only once
that host runs 0.57.1. See Fixed
(#1237,
#1243). -
oats tui: the whole-screen open is gone.Enteropens an agent's
terminal in a panel beside the list;zgives it the whole body. The panel
needs tmux 3.2 or later.open.detachKeyintui.jsonkeeps its name and
the keys it accepts, and now means the back key to the list; a key outside
them is refused whentui.jsonis read. See Changed
(#855). -
pi homes: run
oats updateto move the@awebai/oats-pibridge in
your pi folders to this release (by hand: see Upgrading);
the kernel alone doesn't change it. A freshly spawned pi home then no
longer starts by "continuing" from an emptySTATE.md. See Fixed
(#1251). -
To get the new framework skills, pin
oats.framework: v1.12.0in your
workspace and runoats sync:/oats-host-deliveryand/oats-git-setup
in oats.setup 2.7.0. Instances already running keep what they were spawned
with. See Provider updates. -
The official catalog's versions in this release are oats.framework
1.12.0, oats.okf 5.2.0, oats.aweb 1.27.3, oats.engineering 1.10.0,
oats.cloning 1.0.1, oats.authoring 1.0.3, oats.jira 1.0.1, oats.linear 1.0.1
and oats.apps 1.0.0.
Changed
-
A spawn runs in a process session of its own. The
oats spawnchild of
a confirmed spawn now runs in a process session of its own, so a hang-up or
a Ctrl-C in the terminal that started the client does not reach a spawn
while its worktree hooks run. The deadline the confirmed preview implies
still interrupts it, and the kernel rolls it back. -
oats tuiopens an agent's terminal in a panel beside the list
(#855).Enteron an
instance that runs shows its terminal where the detail was, with the list
still on screen and the focus in the terminal: everything you type goes to
the agent but the back key (Ctrl+\, oropen.detachKeyintui.json),
which gives the focus to the list while the terminal stays open and live.
From the list,Enteron its row goes back to it,zgives it the whole
body andccloses it;Enteron another instance opens that one
instead. A terminal whose viewer ends closes with a line that says why,
and is never opened again by itself. The whole-screen open of the
previous version is gone:zreplaces it. The viewer now runs in a tmux
server private to the run (tmux 3.2 or later), ended on every way out, a
kill -9ofoats tuiincluded; a later run removes what a killed one
left.open.detachKeykeeps its name
and the keys it accepts, and now means the back key; a key outside them is
refused whentui.jsonis read, and an older OATS on another machine is
opened like a newer one. See the TUI page. -
The header's second row reads as navigation:
Instances Souls Capabilities, the open view in reverse video and the views not built yet
dim. The keys1,2and3are in the help, not beside the names, and
the footer names them as one hint,1-3 views;2and3say what to
run instead. Every frame is now one
synchronized update (CSI ?2026h…CSI ?2026l).
Fixed
-
Desktop: a team card's warning can be copied. On the Teams board, the
text of a team's warning or blocking problem, with its fix, can be
selected and copied, and a click on that box no longer opens the team's
page. A click anywhere else on the card still opens it, and the card is
still one Tab stop. -
Desktop: a Make default confirmation closes with the team's page. A
confirmation opened on a team's page no longer stays open after Back, Esc,
a tab change or the team going away, and the Teams board updates again
when your instances change. -
Desktop: a failed read shows on an open team page. When the teams on
this computer can't be read, the open team's page says so in its card, in
the board's words, instead of showing facts that may be out of date. -
Desktop: a retired instance's tabs close
(#1237). When a roster read
shows an instance retired, whether the Desktop, the CLI, another agent or
another machine retired it, every tab of that instance closes, in every
split. The next tab becomes active, and the focus moves only if it was in
a closed tab. A remote instance's tabs close only when its server answers
without it, never because the server can't be reached. Stopping an
instance still leaves its tab open, and an instance respawned under the
same name opens a new tab. -
Desktop: a tab no longer shows another instance's terminal
(#1237). With tmux's
detach-on-destroy offin your configuration, retiring an instance moved
its tab to another session, often another tab's agent: the tab kept its
name, and what you typed went to that agent. The tab's terminal now ends
("session ended") when its instance's window goes. Only the Desktop's own
viewer sessions are set this way; your global option and your own
sessions are untouched. -
oats session attach: the viewer ends with the agent's window, even under
detach-on-destroy off
(#1237). When an attached
instance was retired, a tmux configured withset -g detach-on-destroy off
moved the viewer's client to another session, so the terminal went on
showing, and typing into, another agent. The viewer session now sets
detach-on-destroy onfor itself alone, and the viewer ends as it does
under tmux's default. Your own sessions keep your setting. A routed attach
(--server) runs the viewer on the host, so this holds there once the host
runs this release. Remote Desktop terminals use that viewer. -
oats session attach: a late hang-up no longer leaves the viewer session
behind (#1243). A hang-up,
termination or interrupt can reachoats session attachlate, for example
under a wrapping shell or a terminal profile, where it arrives once the
wrapper has died and goes to the whole process group. If it arrived just
after the viewer's client had exited, or while the viewer was still being
prepared, it could endoatsbefore its cleanup, or kill the cleanup's
tmux call, and leave theoatsview-*session (and a keyed viewer's key
table) on the agents' tmux server.oatsnow handles these signals from
before it creates the viewer until its cleanup has finished, and runs its
tmux calls outside its own process group, so the viewer is always removed.
Exit statuses are unchanged. A routed attach (--server) runs the viewer on
the host, so this holds there once the host runs this release. -
pi: a freshly spawned home no longer starts by "continuing" from an empty
STATE.md
(#1251). At session start the
@awebai/oats-pibridge sends the nudge "Read ./STATE.md … then continue
from STATE.md's Next section". It held the nudge back only whileSTATE.md
still held template text that no package writes any more, so every fresh
home got it, ahead of its opening task. A startup now gets the nudge only
when pi kept an earlier session of the home (pi keeps one once it holds a
message) and
STATE.mdexists, whatever a knowledge capability seeded into it. Sessions
of an earlier instance with the same name, at the same path, don't count.
The bridge writes nothing in the home to tell. Runoats updateto move
the bridge in your pi folders to this release (by hand: see
Upgrading); the kernel alone doesn't change it.
Provider updates
- oats.framework 1.11.0: oats.setup 2.6.0. Onboarding now makes a host's two
delivery choices and checks them
(#1224).- Why. A host could finish onboarding with
oats doctorclean and still
have two problems nobody had chosen:- its Claude homes ran in development channel mode, because
claudeChannelModewas unset; - no host wake broker ran, so every joined team was poll-only, and Codex
anddelivery: sessionhomes were not woken at all.
- its Claude homes ran in development channel mode, because
- A new skill,
/oats-host-delivery, is the one place that teaches both
choices./oats-workspace-confignow points to it, instead of holding
the approved-route steps itself:- Choice 1, Claude channel delivery: the approved route (the
managed-settings file,claudeChannelMode: approved, the plugin in the
launch'sCLAUDE_CONFIG_DIR, respawning homes, the banner check) as the
default for unattended hosts. The development fallback is written
explicitly, with its costs stated. Session delivery is the third
option. - Choice 2, the host wake broker: when a host needs it (a joined
team, Codex,delivery: session); how the operator installsaw wake runas a per-user systemd or launchd service, withAW_WAKE_OATS_BIN
and aPATHthat reachesoats,nodeandtmux; the restart after an aw upgrade; the check (aw wake status --json, and readiness free ofwake-daemon-*and
`join...
- Choice 1, Claude channel delivery: the approved route (the
- Why. A host could finish onboarding with
OATS v0.57.0
OATS 0.57.0
2026-10-15
Upgrade
-
Install the Desktop first and the CLI second, as
Upgrading says: a 0.56 Desktop refuses a 0.57.0 CLI. The
0.57.0 Desktop accepts OATS CLIs>=0.26.0 <0.58.0. -
A script that runs
oats worktree removemay now get
E_CHILDREN_RUNNING: the tree is the work of an attached instance whose
session is running or cannot be read. Nothing is removed, and no flag
removes anyway: stop that instance (oats instance stop <instance>) or
retire it, then remove again. A script that attaches a spawn to a tree of
no known instance gets oneE_BAD_ARGSnaming every flag still missing,
where it got a repository refusal and thenE_SPAWN_FAILEDon the retry.
See Changed (#958,
#964). -
A retire plan taken before the upgrade is refused once by the 0.57.0
kernel withE_PLAN_STALEand the fresh plan: the plan's revision now also
binds the instances attached to each tree. Read the fresh plan and retire
with it. See Changed (#964). -
On Linux and Windows the Desktop's palette is Ctrl+Shift+K, and
Ctrl+Shift+P now opens Quick Open, from a focused terminal too. macOS keeps
⌘K and ⌘P. See Changed
(#1217). -
To get the new provider versions, pin
oats.framework: v1.10.2and
oats.okf: v5.2.0in your workspace and runoats sync. Instances already
running keep what they were spawned with. See Provider updates. -
Pin
oats.okf: v5.2.0and runoats sync; only new spawns get the
capability-owned harvest duty. Existing homes keep their copied provider
and instructions, including across session restarts. Deployments whose
task briefings never mentioned harvests now propose eligible knowledge at
finished tasks or PR hand-overs. Souls not ready for that must declare
knowledge: { harvest: off }; consultation and working-memory upkeep
remain. OATS >=0.49.0 is still required. -
The official catalog's versions in this release are oats.framework
1.10.2, oats.okf 5.2.0, oats.aweb 1.27.3, oats.engineering 1.10.0,
oats.cloning 1.0.1, oats.authoring 1.0.3, oats.jira 1.0.1, oats.linear 1.0.1
and oats.apps 1.0.0.
Added
-
oats tuistops, starts, restarts and retires an agent
(#855). With an instance
selected,Xstops it,Dretires it,Sstarts it andRrestarts it,
each after a confirmation that opens with the focus onCancel: the act
takes a move (Left/RightorTab) and a press ofEnter, and pasted
text never acts. The rules and the words are the Desktop's: a stop or a
retire shows the kernel's plan first and applies exactly that plan, on
this machine or on a registered one; a start or a restart uses the launch
recorded for the agent. An act you sent runs to its end whatever
oats tuidoes: closing the confirmation, quitting, a suspend or a signal
never ends it, and when you leave while one runs a line on standard error
says so.tui.jsonchanges the keys (stop,retire,start,
restart). See the TUI page. -
Desktop: each team has its own page, with your instances on it. Click
a card under Workspace › Teams, or press Enter on its name, to open it. The
page shows the team's card at the top (its default, description, who may
join, address, problems and actions), then Your instances on this team:
how many there are, how many run, how many are stopped or need attention,
and on how many machines. Below that, each machine gets a card, with a
table of its instances: the name, the soul, the state, when it was created
and a Terminal button when it can be opened. A click on the name shows the
instance in the roster. The page lists only your instances, the ones on
this computer and on the machines you added to this workspace. Instances
other people run on the team are not listed. Back or Esc returns to the
board, on that team's card.
Changed
-
The Desktop accepts OATS CLIs
>=0.26.0 <0.58.0
(#1211). The compatibility band
admits 0.57; a 0.56 Desktop refuses a 0.57 CLI. No new gate on the band.
oats tuiruns the kernel it ships with and is held to the same band. -
Desktop on Linux and Windows: the palette is Ctrl+Shift+K, and Quick Open
is Ctrl+Shift+P and works from a focused terminal
(#1217). Quick Open was
Ctrl+P, which a focused terminal keeps for the program in it (shell
history), so it did not open from there. Ctrl+Shift+P changes meaning:
it has opened the palette since 0.30.3 and now opens Quick Open; the
palette moves to Ctrl+Shift+K. While the palette is open, Ctrl+Shift+K
moves down its rows and ArrowUp moves up. xterm sends nothing for either
chord, so plain Ctrl+K and Ctrl+P still reach the program. A shortcut you
set yourself is kept; when it is one of these two chords, the shortcuts
editor shows the clash. A Quick Open shortcut you set yourself now works
from a terminal too: if it is a plain Ctrl+letter, such as Ctrl+P, the
program no longer gets that key, so choose a Ctrl+Shift chord. macOS is
unchanged (⌘K, ⌘P). See
Desktop keyboard. -
An attached spawn on an extra tree derives its owner and its repository
(#958).oats spawn <soul> --work attached --work-dir <home>/.work-<purpose>was refused twice: first for the repository
(pass --repo), then, with that given, for the owner (--parent <instance>). For<home>/workthe kernel derived both. An extra tree of
a home is that home's tree too, so the same command now spawns with
neither flag: the owner is the instance in whose home the tree is, the new
instance is its child, and its repository is the repository of the tree
it is attached to (for an extra tree the one Git names for it, which can
be another member repository than the owner's own).--parent <owner>
and--repogiven explicitly still work, so a command that passes both
runs on this kernel and on earlier ones. The tree is an extra tree by the
kernel's own test (a registered linked worktree in a home), never by the
shape of its path. Nothing changes for<home>/work, and no flag, key or
field changes.A tree of no known instance still needs both flags. Its refusal is now
one,E_BAD_ARGS, and names every flag still missing:attached workDir <path> is not a known instance's <home>/work or an extra tree of a known instance's home (<home>/.work-<purpose>), so neither its owner nor its repository is derived — pass both: --parent <instance> (the owning instance) and --repo <repository>. With one of the two given it names
the other. Before, the missing repository was refused first (no repository for a attached instance — pass --repo (the work tree's owner records none)), and the missing owner only on the retry, under the code
E_SPAWN_FAILED. See
attached. -
A tree that goes away says what it leaves its attached instances with
(#964). An instance can be attached to an extra tree of its owner as to
the owner'swork/(#958). Four things change for such a tree:- A retire that re-homes an extra tree repoints its attached children
to the tree's new path, as it does forwork/: only the recorded
children the retire stopped, only once the tree is seen at its new path
with nothing left at the old one, and only a link that is still the one
the retire found. One that cannot be repointed is a warning in the
receipt, with the command to do it by hand. - A retire that removes a tree names the attached children it leaves
without one. A clean extra tree is removed, as before, and so is
work/with--discard-worktree. The plan's note for the tree now
names its attached children and says that theirworklink would then
point at a path that is gone, and the receipt'swarnings(and the
summary) say so afterwards, naming each child, the tree and the link.
Before, the plan and the receipt said nothing of them. - An attached instance the retire does not act on is named too. An
instance that records the owner as its parent under a name that is not
unique is listed under the plan'sambiguousand is never stopped, so
its link is not repointed either. The plan's note for the tree it is
attached to (an extra tree, orwork/) now names it and says that its
worklink would then point at a path that is gone, and the receipt's
warningssay so for each tree that was moved or removed, with the
command to repoint the link by hand where the tree was re-homed. A
--selfretirement's receipt does not carry those warnings. oats worktree removerefuses a tree under a running session. When
an instance attached to the tree has a session that is running, or that
cannot be read, the command answersE_CHILDREN_RUNNINGbefore Git is
asked anything: nothing is removed and the record is kept.detailsis
{purpose, path, children: [{instance, home, session}]},sessionbeing
"running"or"unknown". The message names each instance and the
step: stop it (oats instance stop <instance>) or retire it, then remove
again. The command stops nobody, and no flag removes the tree anyway. An
attached instance whose session is stopped does not refuse: the tree is
removed and the answer'swarningsname the instance and its link.
The new sentences are strings in arrays the plan and the answers already
have (notes,warnings): no key, field or flag is new, and a tree w... - A retire that re-homes an extra tree repoints its attached children
OATS v0.56.0
OATS 0.56.0
2026-10-14
Upgrade
-
Install the Desktop first and the CLI second, as
Upgrading says: a 0.55 Desktop refuses a 0.56.0 CLI. The
0.56.0 Desktop accepts OATS CLIs>=0.26.0 <0.57.0; a CLI of the 0.25 line
is no longer accepted.oats updatenow prints this order itself when it
installs a CLI of another minor. -
A script that matched
E_HARNESS_PACKAGEmatches
E_HARNESS_RESOURCE_MISSINGnow. A script or capability that read
E_SPAWN_FAILEDfromoats spawnas "the spawn failed" now gets the
kernel's own code: match on the exit status or onok: falseinstead, and
readdetails.unconfirmedfor how far a spawn got. See Changed
(#1047). -
A
tui.jsonthat names the actionopen-workspaceis refused with
open-workspace is called open now; rename it: rename it toopen. See
Added (#855). -
To get the new provider versions, pin
oats.framework: v1.10.1and
oats.okf: v5.1.0in your workspace and runoats sync. oats.okf 5.1.0
needs OATS 0.49.0 or later: upgrade the kernel first, then re-spawn your
harvesters for the new hook. Instances already running keep what they were
spawned with. See Provider updates. -
The official catalog's versions in this release are oats.framework
1.10.1, oats.okf 5.1.0, oats.aweb 1.27.3, oats.engineering 1.10.0,
oats.cloning 1.0.1, oats.authoring 1.0.3, oats.jira 1.0.1, oats.linear 1.0.1
and oats.apps 1.0.0. -
A launch now gets exactly its capabilities' declared environment
(#1123). An instance that
relied on an ambient value of a variable one of its capabilities declares
(in the tmux server's or the session's environment, the login shell's, the
Desktop's) and that the capability's hooks do not return now starts without
it. Nothing is required of you. An ambient value set before stays in the
tmux environment until the server or the session is recreated, but no
longer reaches a launch whose capabilities declare it; an instance already
running keeps the environment it started with until it is restarted. To
clear a stale value:tmux -L oats set-environment -t <session> -u NAME
for a session,tmux -L oats set-environment -g -u NAMEfor the server,
or recreate the server; then restart the affected instances.
Added
-
Feature
spawn-kernel-codes(#1047).oats spawnanswers the
kernel's own code; a kernel without the word may answerE_SPAWN_FAILED
where a kernel code was raised. See
spawn errors. -
The Desktop's Install section states what Linux the installers need: glibc 2.34 or later (for example Ubuntu 22.04, Debian 12, RHEL 9 or later), and the Linux installer build fails when any file of the DEB or the AppImage needs a newer glibc, GLIBCXX or CXXABI than that.
-
Desktop: the Start and Restart dialog offers the bare harness
(#1079). The Launch
configuration list has a second entry, "No launch configuration (the harness
as installed)". It runs the harness itself, with no configuration's
executable, arguments or environment, and without the default configuration
the host declares for that harness. The Harness list stays usable with it:
alone it starts the recorded harness bare, and beside a picked harness, that
one. "Preview invocation" shows the same choice. It is what
--launch-config nonedoes on the command line.- For an instance on a server the entry is offered only when the host
is known to read it: a host on OATS 0.49.0 or later, read through an OATS
here that relays the hosts' feature lists. On an older host, pick a
configuration, or use the command line there.
Starting an existing instance has the
whole of it.
- For an instance on a server the entry is offered only when the host
-
oats server roster --workspace-key <key>(feature
roster-workspace-key, repeatable) probes and returns only the groups that
can belong to the given workspaces: a registration recorded for one of
them, a registration whose workspace is not known yet, and a server known
only from saved routes, which is always probed because its workspace is
unknown. A host registered for another workspace is not asked, so a
switched-off host no longer delays the roster of every other workspace's
window. The answer's shape is unchanged; without the flag it is exactly as
before. A key is compared exactly with the registration'sworkspaceKey;
an empty, missing or malformed value isE_BAD_ARGS
(the flag,
#1124). -
Forget… on an instance its server no longer lists. In the Desktop, a
remote instance that is gone from its server now offers Forget… in its
roster row's actions menu and in the context panel. After a confirmation,
the Desktop runsoats server forget <server> --instance <instance>for
that row, which removes only this computer's saved route and nothing on the
server, then reads the roster again. Before, the only remedy was to type
that command
(oats server forget --json,
#1131). -
A soul's own skills on its soul page. In the Desktop, the soul page's
Instructions card has a Skills group between "This soul" and "Instance": each
skill from the soul's ownskills/(not those its capabilities bring), with
its description, expands to its files, and each file reads in place under its
repository path, through the same strict reader as a capability's Contents.
The Desktop asks only a CLI that reports them (featuresoul-skills,
oats inspect --soul <name> --skills), and for a soul on another machine
only when that host reports them too; otherwise the group says this OATS
doesn't report a soul's skills. -
A soul's own skills, before a spawn.
oats inspect --soul <soul> --skills --jsonaddssouls[0].skills: the skills a spawn of the soul
copies (not its capabilities' skills), each with itsdescriptionand
every file's text, by the rules ofoats capabilities show. The whole
field carries at most 1 MiB of text; the files past that are listed with
omitted: true. Nothing is read without the flag. No symbolic link is
followed, and a skill whose files cannot all be listed and read has
files: nullwith a problem.--skillscombines with--instructions,
refuses--home, and is routed with--serverto a host that advertises
the new featuresoul-skills
(oats inspect,
#1144). -
oats tuiopens an agent's terminal
(#855).Enteron an
instance that runs, on this machine or on a registered one, gives your
terminal to the agent throughoats session attach;Ctrl+\brings
oats tuiback and the agent keeps running.tui.json's
open.detachKeychanges the key. After the return one line says what
happened, andEnteron an instance that cannot be opened says why. An
agent on a machine whose OATS is older than 0.51.0 is not opened: it has
no key to leave a viewer. The actionopen-workspaceis nowopen, and a
tui.jsonthat namesopen-workspaceis refused with
open-workspace is called open now; rename it.
Changed
-
oats retire --serverprints the receipt's warnings
(#1006). The routed
retire's text (without--json) printed the recovery and extra-tree lines
of the host's receipt and none of itswarnings. It now prints them as a
local retire does, oneWARNING:line each, after the extra-tree lines:
what a retire left an attached child with, which repository it read from
Git, where a link atwork/led. The JSON is relayed as it was. -
More text lines spell what a terminal would act on
(#1006). Thenote:
lines ofoats retire --plan,oats instance stop --plan,
oats instance gitandoats readiness; theWARNING:lines of
oats spawn(local and with--server), of theoats sessioncommands
and ofoats doctor; and the retire's recovery and extra-tree lines, local
and with--server, spell a control character (an escape, a newline), a
line separator or a bidi override as\u{<hex>}, as the local retire's
warnings have since 0.53.0. A line that holds no such character is printed
as it was. No JSON answer changes. See
Text output. -
oats spawnanswers the kernel's own code (#1047). Apply and
--preview, text and--json: an error with a kernel code is answered
with that code, as the lifecycle commands have done since 0.52.0, and
E_SPAWN_FAILEDis what an error with no kernel code is answered with,
withdetails.causefor one that has a system code or is a defect (its
stack on stderr). Until now the spawn's kernel stage passed a list of
codes and answered every other one asE_SPAWN_FAILED, so a refusal with
a remedy, such as a missing harness package (E_HARNESS_RESOURCE_MISSING)
or a tmux server that cannot be read (E_RUNTIME_ENDPOINT_UNKNOWN),
reached a client as a failure of the spawn mechanism. An operator's script
or a capability that matchedE_SPAWN_FAILEDto mean "the spawn failed"
now sees the specific code: match on the command's exit status, or on
ok: false, to mean "it failed". A code is not a stable signal of how far
a spawn got:details.unconfirmedis. The details of each code are what
they were: a code that carried details keeps ...
OATS v0.55.1
OATS 0.55.1
2026-10-14
A patch release: the oats.aweb 1.27.3 pin, and one fix in the record's recall --show.
Upgrade
-
Either order of Desktop and CLI works: a 0.55.0 Desktop accepts a
0.55.1 CLI, and the other way round. -
Pin
oats.aweb: v1.27.3in your workspace, then runoats sync. The
catalog in this release names it. On 1.27.2, readiness reports
unavailablefor every home that the host wake broker serves (Codex,
delivery: session, joined teams withreceive: native) while delivery
works. Running instances keep the provider they were spawned with. Such an
instance readsunavailableuntil it is re-spawned; spawns after the sync
get 1.27.3. See Provider updates.
Fixed
oats recall --shownow refuses session turns hidden by their author's
tombstone, including claims in another stream. It reports the turn as
tombstoned with exit status 1 and emits no payload. Record-owner authority
resolution and index authority changes remain separate work under
#1125
(#1127).
Provider updates
- oats.aweb 1.27.3: fixes false
wake-status-stale/unavailable
readiness on Codex,delivery: session, and joined-team broker routes
(oats-aweb#116,
provider fix). Broker
timestamps are judged against a clock read afteraw wake statusreturns,
not the readiness phase's start. No skew allowance is added: invalid and
genuinely future timestamps still fail, and inspection ordering and
observation-age warnings remain intact. The catalog, reference workspace,
docs and generated mirror now take publishedv1.27.3.
Both floors remain OATS >=0.52.0 and aw >=1.36.33; this fix needs no new aw
upgrade or service restart. Keep the existing upgrade order: meet the
kernel/aw floors (restart custody services and the wake daemon after an aw
upgrade), update the provider pin, thenoats sync. New compositions take
the fixed provider; existing homes keep their captured module bytes.
Readiness does not prove actual message delivery.
OATS v0.55.0
OATS 0.55.0
2026-10-14
Upgrade
-
Install the Desktop first and the CLI second, as
Upgrading says: a 0.54.0 Desktop refuses a 0.55.0 CLI. -
The first capture after the upgrade takes longer. It reconciles the
existing journals, resets the search index and rebuilds it from them, in
one synchronous pass that can take minutes on a large record; later passes
read only what is new. See Fixed
(#1108). -
A script that reads
oats server roster --jsonno longer sees
E_ROSTER_BUDGETorbounds.skipped: every server is probed, and one
that does not answer reports its ownE_SSHtimeout. See Removed
(#1117). -
The official catalog's versions in this release are oats.framework
1.10.0, oats.okf 5.0.5, oats.aweb 1.27.2 and oats.engineering 1.10.0: see
Provider updates. Pin what your workspace uses, then runoats sync.
Running instances keep what they were spawned with; new spawns get the new
versions, so a standing maintainer gets oats.engineering 1.10.0's lane
rules only by being re-spawned. The same holds for oats.okf 5.0.5: an
instance spawned before the pin keeps its old frozen-remote guard (and
still fails withE_OWNERon a host that rewrites Git URLs) and its old
proposal brief until it is re-spawned.
Changed
- The Desktop accepts OATS CLIs
>=0.25.8 <0.56.0. The compatibility band
admits 0.55. Upgrade the CLI and the Desktop together: a 0.54.0 Desktop
refuses a 0.55.0 CLI. No new gate on the band.oats tuiruns the kernel it
ships with and is held to the same band.
Fixed
-
Capture streams transcript content, stores per-input cursors and journal IDs on
disk, and indexes only new journal bytes in bounded transactions (#1108).
Background input logs share an append-only assumption: an edit to an old
aweb-log line is no longer picked up merely because the log grows. Use
capture --reset-cursors [--source aw|cc|pi|codex]to request reprocessing.
Detected native-transcript prefix changes are set aside before appending, to
preserve v0.53.0 downgrade/re-upgrade compatibility. Restore the prefix and
usecapture --retry-set-aside, or exclude the source through the existing
ignore list (which also excludes its later turns).capture --healthreports
these inputs. This changes capture algorithms; it introduces no service
schedule, record-size policy, or bounded-runner guarantee. Content buffers and
caches are bounded apart from the largest record; sorted path/root metadata
and explicit receipt inventories can still grow with input counts. The first
capture after upgrade reconciles existing journals and rebuilds the index,
with substantial per-input/per-stream synchronous commit cost still unresolved.
Refused aweb entries are counted and consumed; reset source cursors to retry
them. Snapshot and receipt scratch stays on the record-root volume, with
conservative cleanup of proven abandoned allocations under the capture lock. -
Capture health reads current set-aside issues, including direct library calls,
while command snapshots retain their historical run fields. Reading an existing
capture database requires read-only SQLite support (Node 22.12+/23.2+; prefer
22.13+ on 22.x without an experimental flag). Unsupported runtimes, schemas,
WAL databases and unavailable readers fail closed; normal capture's runtime
floor is unchanged. -
A server that can't be reached no longer hides the others. The remote
roster (oats server roster, the Desktop's view of other machines) probes
every registered server at once, each within its own deadline. A server
that is switched off now costs only its own entry, which shows that it
timed out (E_SSH,ssh to <host> timed out: no answer within <n> s), and
the servers registered after it are read as usual. Before, the probes ran
one after another against one 45 s budget. Four registrations on one
offline host could use the budget up, and the servers after them were
never asked (#1117). -
Retry on a remote window reads the servers again. In the Desktop, the
roster's Retry on a window with a deployment on another machine now
reads the servers at once, or waits for the read already running, before it
shows the roster. Before, it showed the last read's result until the next
background read, 10 s later
(#1117).
Removed
E_ROSTER_BUDGETandbounds.skippedinoats server roster --json.
Every group is probed, so no group is reported as not reached any more, and
boundsis{budgetMs, perTargetTimeoutMs, elapsedMs}.--budgetstays,
as the deadline of the whole answer, which caps each probe's--per-target
allowance
(the roster).
Provider updates
- oats.okf 5.0.5 (from 5.0.3; 5.0.4 is included).
- A host's Git URL rewriting no longer breaks Git bases
(oats-okf#76, 5.0.4). A
host whose global or system Git config routes a bound repository through
url.<base>.insteadOforpushInsteadOf(a deploy key on an ssh alias,
for example) failed every okf call withE_OWNER. The frozen-remote
guard now resolves the binding'srepositorywith the host's own
rewrites and compares that with the clone's fetch and push URLs; the
binding stays as written. A rewrite in the clone's own config, a changed
origin or apushurlis still refused, and URLs compare byte for byte. - One harvester at a time (5.0.5). A working instance writes one
proposal per checkpoint, with claims only for the nodes its soul owns,
and spawns one knowledge harvester at a time, none whileoats status
still lists its last one (the flow). Instruction text
only; it reaches instances spawned after the pin. - The official catalog, the reference workspace and the generated mirrors
take publishedv5.0.5at73b85020e52b8584cb15f153a39712f900e69918.
Compatibility remains OATS 0.29.0 or later.
- A host's Git URL rewriting no longer breaks Git bases
- oats.aweb 1.27.2: the
/oats-awebskill's etiquette points to
/oats-token-saving(oats.core 2.6.0, in OATS 0.54.0) for whether to send,
to whom and how long, and keeps how to send
(#1103). Instruction text
only; both floors are unchanged (OATS 0.52.0, aw 1.36.33). The catalog,
the reference workspace andmirrors/oats-awebtake publishedv1.27.2
atf82cebe299562b38188f3373fa09a89b50d5f868; the mirror's tree equals
the tag's. - oats.engineering 1.10.0: maintainers work in lanes
(#1103,
oats-engineering#14).
The official catalog, the reference workspace and the generated mirrors
(mirrors/oats-developer,mirrors/oats-code-review,
mirrors/oats-engineering-expert,mirrors/oats-maintainer) take published
v1.10.0at944470be71a96299ae4a1cfb7df0fba94a592899; each mirror's tree
equals the tag's. Instruction text only: no skill is added or removed, and
the requirement is unchanged (OATS 0.30.0 or later).oats.maintainerand
oats.engineering-expertchange; the other two capabilities only change
version. What changes:- Each maintainer holds a lane. The peers' agreement becomes a written
lane map: what each lane covers, its maintainer and its second reader,
the label a PR shows its lane with, the hold label, and who owns the next
release. A maintainer's state file holds its own lane only; the forge is
the one copy of a PR's state. - Every PR gets one second reader, asked once, at the head the lane's
maintainer approved. This replaces every peer reviewing every PR and
re-binding its verdict at every head. - Intake no longer sweeps on every wake: a full sweep at session start,
after a compaction and at least weekly; on a wake, the event alone. - Peers message each other for five things (a second read, a hold that
must stop work in flight, the release plan, a lane changing hands, a
request that belongs to the peer's lane), and send no notice before or
after a merge or a tag. A hold is a label on the forge, and the merge step
reads it. - The merging maintainer brings a branch up to date itself; the verdicts
carry when the PR's own change is unchanged and CI is green. When the
default branch moved since CI ran, it runs the affected test files on a
trial merge first. - Experts hand over to one maintainer, the one whose lane the work is
in, and leave the branch alone after the hand-over. - To adopt it: peer maintainers rewrite their agreement as a lane map
(/cross-review-peer), create the lane labels and the hold label, and
drop each other's PRs from their state files. A maintainer alone has
nothing to do. Pinoats.engineering: v1.10.0and runoats sync.
Running instances keep what they were spawned with; new spawns pick
1.10.0 up afteroats sync. A standing maintainer gets the new rules
only by being re-spawned, not by a sync or a session restart: hand its
lane over first (/cross-review-peer, "A lane changes hands").
- Each maintainer holds a lane. The peers' agreement becomes a written
OATS v0.54.0
OATS 0.54.0
2026-10-13
Upgrade
-
Nothing is required. Install the Desktop first and the CLI second, as
Upgrading says: a 0.53.0 Desktop refuses a 0.54.0 CLI. -
To get the skill
/oats-token-saving, pinoats.framework: v1.10.0
in your workspace and runoats sync. Instances already running keep the
briefing and the skills they were spawned with; new spawns get the new
ones. See Added and Provider updates. -
A script that reads a refusal about a repository reference (its
message, ordetails.ref,details.url,details.value) now reads a
display form: user information is never in it; a refused value made only
of letters, digits, spaces and._/+-:is shown as written; any other
value that cannot be rebuilt from its parts is replaced whole by a fixed
text. See Changed and Fixed
(#1077). Codes and field
shapes are unchanged, and so is the reference Git itself is given. -
The official catalog's versions in this release are oats.framework
1.10.0, oats.okf 5.0.3, oats.aweb 1.27.1 and oats.engineering 1.9.1: see
Provider updates. Pin what your workspace uses, then runoats sync.
Added
-
oats.core: the skill/oats-token-saving, and three lines of its
briefing (#1103). A message
between instances costs twice: the sender writes it, and the receiver is
woken, reads it with its whole context and often answers. The skill gives
one test before sending, "who will do something different because of this,
and what?", and the rules that follow from it:- to whom: only the instance that will act on it, with no copies and no
sending to every holder of a role; - what not to send: acknowledgements and courtesy, progress and status,
what a shared record already shows, someone else's words passed along, and
the story of how the sender got there. A message that needs a confirmation
says so and gets one line back; - don't ask for what you can read, and never ask for progress reports or
set a helper up to send them; - what a message holds: first what the receiver must do, exact
references, one topic, one message per task boundary. A spec, a brief or a
review's findings is the long message, sent once as a file or a link; - what is never cut: what moves work, what a role owes, and what is owed
on a record (a verdict on the pull request, a decision on its issue, the
evidence of a hand-over, the report of a fault or of one's own mistake).
The skill is provider-neutral: it names no messaging capability, and how to
send stays with that capability's own skill. Theoats.corebriefing, which
every instance withoats.corereads, gains the test in three lines, so it
applies before the skill is loaded. An instance spawned before the release
that carries this keeps its briefing; new spawns get it
(oats.core). - to whom: only the instance that will act on it, with no copies and no
Changed
-
The Desktop accepts OATS CLIs
>=0.25.8 <0.55.0. The compatibility band
admits 0.54. Upgrade the CLI and the Desktop together: a 0.53.0 Desktop
refuses a 0.54.0 CLI. No new gate on the band.oats tuiruns the kernel it
ships with and is held to the same band. -
Diagnostic messages, details, provenance and workspace
cannot-readvalues
now preserve bounded plain refused values, construct displays that omit user
information (including SSH users), or withhold the reference, while the seven
rejected argument fields share the bounded plain rule and Git lines are shown
only for unchanged original operation references
and no literal@in the original line, replacing
#1075's scrubbed-line behavior
(#1077).
Fixed
-
Repository diagnostics no longer copy user information from selected
references (#1077). Messages,
reference-bearing details and provenance, schema problems and workspace
cannot-readfields use a display constructed from recognised host and path
components, with a verbatim exception for original refused values of 1–256
ASCII letters, digits, spaces or._/+-:characters. The same predicate
serves the seven selected rejected arguments; it never trims or decodes an
input. Malformed or mixed values outside that rule are withheld whole,
including harmless text, while known declaration files and key locations
remain available. Raw derived fragments qualify for the plain exception only
through their original selected source, never from a nonplain source. Plain
recognition is not a secret detector: credential-like text within the
permitted alphabet remains visible.
Git's own line is shown only when all original operation references are
proved unchanged by display construction and the original line contains no
@; otherwise the whole line becomes a fixed notice directing the operator
to run the operation by hand. No substring is recovered. This replaces the
quoted-line disclosure behavior shipped for unknown Git failures.
See the diagnostic display contract.
Standalone file/path meanings, command-consumed values and Git's original
transport reference are unchanged.
Explicit pinned-source diagnostics keep a constructed reference and its
validated commit, or withhold the whole source without a plain fallback.
Rejected argument values use the contract's bounded plain-value rule and
neutral withholding notice; valid operational arguments are unchanged. Unknown Git failures quote only
stderr: empty stderr adds no line unless output overflow needs a kernel budget notice. -
Repository and package refusals explain an omitted reference without
exposing it (#1077). The
originating refusal explains withholding or user-information omission once;
existing message slots keep the explanation when forwarding it. HTTP(S)
userinfo refusals keep their specific cause and credential-helper advice,
and package refusals keep their own reason. Admission, codes and field shapes
are unchanged. -
oats soulsandoats capabilitiesnow show every catalog discovery
problem below their text tables, including unreadable locked package
souls. Diagnostics stay on stdout in JSON order, with the kernel's code
and message; partial listings still exit 0
(#1098).
Provider updates
- oats.framework 1.10.0: oats.core 2.6.0. One new skill and three lines
of instruction text in oats.core; no hook, command, schema or provider
contract changes, and the capability floors are unchanged (oats.core
>=0.40.0).- oats.core gains the skill
/oats-token-savingand names it in its
briefing, as the entry under Added says
(#1103). The two commands
the skill tells an instance to read before asking,oats statusand
oats instance events <instance>, exist in every kernel oats.core
admits. - A deployment gets it by pinning
oats.framework: v1.10.0and running
oats sync. Instances already running keep the briefing and the skills
they were spawned with; new spawns get the new ones.
- oats.core gains the skill
Documentation
- Upgrading: the Desktop goes before the CLI
(#1107).
Upgrading OATS on a host now says so, and why: a
Desktop refuses a CLI of a newer minor version, so with the CLI moved
first it lists no instance until it is replaced. The Upgrade section of
the 0.53.0 notes gained that step, and one for a
host that comes from 0.51 or earlier: 0.52.0's steps first, the aw client
among them, beforeoats sync.
OATS v0.53.0
OATS 0.53.0
2026-10-13
Upgrade
Upgrading OATS on a host has the steps that are the same
for every release: the CLI, then oats update in each deployment, then
oats doctor. It also says when a change of Node version leaves something
to do on a host, and what: restart the instances and, where schedules run,
install the host timer again; before that, install the CLI again where it is
installed inside the Node version.
-
Where the Desktop is installed, install Desktop 0.53.0 before the CLI
(#1107). A 0.52.0 Desktop
refuses a 0.53.0 CLI and lists no instance until it is replaced. Desktop
0.53.0 accepts the older CLI in the meantime. This includes an
oats updatewhose plan installs the CLI. -
A host that comes from 0.51 or earlier does 0.52.0's
Upgrade steps first, in their order. One of them is
easy to miss because it is a host tool and not OATS: aw 1.36.33 or later,
beforeoats sync. The sync to this release's catalog locks oats.aweb
1.27.1, which refuses every new spawn below that version. After the sync,
oats readiness --soul <name>shows it as a failed provider check, with
the install that cures it. -
Once the CLI is 0.53.0, run
oats updatein each deployment that
launches pi instances. It now moves the pi bridge in every pi folder that
deployment's launch configurations name, andoats doctorwarns about each
one that is behind
(#991). Anoats updaterun
by 0.52 or earlier moves the bridge of the default pi folder only, so the
one that upgraded the CLI is not enough. -
Claude Code instances on a Homebrew node: a restart rewrites their
waiting hooks, and a respawn makes that last
(#997). A home's hooks in
<home>/.claude/settings.jsonare written again at everyoats session startandrestart, by the copy of oats.core in that home, which a start
does not refresh. A home spawned before the oats.framework that carries
this fix keeps writing the path of the versioned keg, so it is repaired by
a restart after each Node upgrade, and gets the lasting path when it is
respawned. Between a Node upgrade and that restart, such an instance does
not report that it waits on you. A home spawned with the fixed oats.core
gets the lasting path at its first start under this kernel, whichever
kernel spawned it. -
On every host where
oats setupwas run, runoats setuponce more
after upgrading the CLI, as the same user
(#1003). The capture hooks
in~/.claude*/settings.jsonand the capture watcher's unit still name the
nodethat ran the earlier setup, and nothing else rewrites those files:
nooats update, spawn, start or restart. The run replaces its own hooks
and unit and adds no second one.oats setup --dry-runfirst prints the
nodeit would record and changes nothing. The same step follows a change
of Node version wherever the recorded path does not outlast it
(Upgrading).A run that prints
already installedfor the watcher's unit has not
checked that the watcher is enabled
(#1099). On Linux,
systemctl --user is-enabled turn-record-capture.servicesays whether it
is. Where an earlieroats setupcould not enable it, enable it by hand:
systemctl --user enable --now turn-record-capture.service. -
Existing resident custody units: after updating to oats.aweb 1.27.1, run
oats aweb resident create <name>again from the deployment, with the same
--rootif one was used. An existing unit changes only on that rerun; an
OATS upgrade or seat restart alone does not refresh it. OATS 0.53.0 supplies
the kernel-selected Node path; supported older kernels retain the previous
fallback. If the recordedawpath lives inside a Node version that will
be removed, install aw in the new version and rerun before removing the old
one. See the provider's upgrade steps. -
After upgrading, run
oats doctor: it lists each key ofsouls.launch
that matches no soul, with the command that fixes it. Until then a spawn
that would fall through is refused and says the same
(E_LAUNCH_PREFERENCE_UNMATCHED, under Changed below). This reaches
scheduled jobs, triggers and agents' own spawns: before 0.53.0 such a key
was never read.To check before upgrading: every key of
souls.launchother than"*"is
the name of a soul thatoats soulslists, bare for a member's soul and
<package>/<soul>for a package's. For a script, on 0.51.0 or 0.52.0:oats souls --json | node -e 'const r=JSON.parse(require("fs").readFileSync(0,"utf8")).result;const p="oats-local.yaml#/souls/launch/";console.log([...new Set(r.souls.map(s=>s.launch&&s.launch.at).filter(a=>a&&a.startsWith(p)).map(a=>a.slice(p.length).replace(/~1/g,"/").replace(/~0/g,"~")))].sort().join("\n"))'It prints the keys of
souls.launchthat decide some soul's launch. A key
in the file that it does not print, other than"*", names no soul. -
A host on 0.52.0 or earlier that is refused with
E_REMOTE_UNREADABLEin a second or two, on a network that is fine, needs
only this upgrade (#1059).
The refusal names the reasonnetwork, orauth, and neither is the
cause: see Fixed. Installing the CLI goes through npm and not through the
remote cache, so the fault does not block the upgrade, and the first read
by 0.53.0 fetches the commit. To run a command on the old kernel before
that, put three Git variables in front of it, for that command only:GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=fetch.negotiationAlgorithm GIT_CONFIG_VALUE_0=noop oats syncThe same prefix works on any
oatscommand that fetches: a spawn, a
preview,oats souls,oats workspace status. Do not run Git inside
~/.cache/oatsand do not move a cache entry aside: the old kernel
rebuilds it and fails the same way. In that stateoats soulscan also
print its list without a package's souls, with no error and exit 0
(#1098);oats souls --json
names them inproblems. -
The official catalog's versions in this release are oats.framework
1.9.4, oats.okf 5.0.3, oats.aweb 1.27.1 and oats.engineering 1.9.1: see
Provider updates. Pin what your workspace uses, then runoats sync.
Added
-
oats tui(preview) shows a deployment's instances (#855). In 0.52 the
preview drew a frame and read nothing from the kernel. This version shows
a workspace's instances, on this machine and on the other machines
registered on it, and changes nothing. The list
is the roster the Desktop draws, with the same groups, order and states,
from the same code, and it follows the deployment every few seconds. Beside
it is the detail of the selected instance, with what it needs from you./
filters by name, soul and repository. It cannot yet open an agent's
terminal, stop, start, restart, retire or spawn one, show souls or
capabilities, or add, check or remove a machine: its help screen
names theoatscommand for each. It is still a preview: its screens and its configuration
file may change without notice. docs/tui.md has the rest.- Start it in or under a deployment, or name one:
oats tui --dir <path>. With nooats-local.yamlat or above the start, and, when no
--dirwas given, no deployment directly inside~/Agentsto offer, it
prints one line (E_NO_DEPLOYMENT) and exits 1. Started inside an agent's pane it
still reads the deployment it was asked about: it removes the instance's
variables from its own environment first. - It runs the kernel it shipped with, never an
oatsfound onPATH,
and only to read (oats statusandoats workspace status, then a probe
of the terminals, andoats server rosterfor the other machines). A
kernel it cannot accept stops the start with
E_TUI_KERNEL. Start it again after upgrading OATS. - Every key can be changed in
$XDG_CONFIG_HOME/oats/tui.json(else
~/.config/oats/tui.json). A file it cannot honour stops the start, one
line per problem (E_TUI_CONFIG): it resolves no conflict between two
actions and guesses nothing.
- Start it in or under a deployment, or name one:
-
oats soul launch set|removewrites a soul's launch preference
(#990). Until now the only
way to pin a soul to a launch on a machine was to editoats-local.yaml
souls.launchby hand, the edit everyone is told not to make.oats soul launch set <soul>|'*' (--launch-config <name>|none | --harness pi|claude|codex [--model <id>]) oats soul launch remove <soul>|'*'|<exact key>each with
--plan(every check, nothing written),--dir <deployment>and
--json.setnames the soul as a spawn does and writes the key that soul
has, so it cannot write a key that names no soul.removealso takes the
exact text of a key in the file, and that form works when the workspace's
souls cannot be read. Both answer what the next spawn of the soul selects
and every key ofsouls.launchthat still names no soul. The file is
rewritten, and every other entry keeps its value and its comments. A
client gates on the featuresoul-launch; the answer issoulLaunchApi: 1
(docs/desktop-cli-api.md). New
code:E_LAUNCH_PREFERENCE_UNKNOWN, aremoveof an entry the file does
not have. Not in this release: alistverb (oats soulsshows each
soul's launch), and a lock for `oats la...
OATS v0.52.0
OATS 0.52.0
2026-10-12
Upgrade
Steps 1 to 3 each stop a spawn that worked on 0.51, so do them on each host
before upgrading, in this order:
- Establish folder trust first:
oats harness trust --plan, then
oats harness trust. On 0.51 a Claude start on a host without it reported a
launched instance waiting at the trust prompt. On 0.52 every start with the
development-channel flag is observed, so the same start ends as
E_SPAWN_INCOMPLETE,blocked: unexpected prompt, with the pane retained.
That is the loud miss working as designed, and it is new for every home that
was never on the oldlaunchPromptAnswerslist. - A host with several launch configurations for one harness marks one
default: trueor names one insouls.launch. Until then, scheduled jobs,
triggers and agents' own spawns that name no configuration are refused
(E_LAUNCH_CONFIG_AMBIGUOUS). - Remove
launchPromptAnswersfromoats-local.yaml: a home entry
awebDevelopmentChannel: falsestops the deployment from loading.
Then upgrade, in this order, with no lifecycle command (a stop or a retire) in
flight on the deployment:
- Upgrade aw to 1.36.33 or later on every host, then restart every
resident custody service and the host wake daemon. A custody that is
already running keeps its old operations until it is restarted. - Upgrade the OATS CLI and the Desktop together. A 0.51.0 Desktop refuses
a 0.52.0 CLI. - Pin oats.aweb 1.27.0, then run
oats sync. It needs OATS 0.52.0: an
older kernel refuses it withE_CAPABILITY_INCOMPATIBLE. The catalog's
other versions in this release are oats.okf 5.0.2 and oats.framework 1.9.3. - After upgrading, on every host that runs schedules, run
oats schedule host installagain, from the operator's own shell (not from
an instance home): an installed timer is not rewritten by upgrading OATS.
oats schedule host statusreportsunit-outdateduntil you do.
A host or launch configuration that opts out of Claude Code's telemetry
(DISABLE_TELEMETRY, DO_NOT_TRACK or
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC) gets no channel delivery on the
default delivery: channel, and every start now says so: see Changed.
Added
oats tui(preview): a terminal client (#855).oats tuiis a
full-screen, keyboard-only client for people who work in terminals and on
machines with no display. It ships inside theoatspackage: there is
nothing else to install. It is a preview, and this version draws the
frame only: it shows the frame, answers?(help) andq(quit), and
reads nothing from the kernel yet. The views arrive in later releases, and
while it is a preview its screens may change without notice. It leaves
preview when the readers it shares with the Desktop are in their shared
home, a person has used it for a working day and both maintainers agree.
So far it has been run in tmux only: not in a terminal emulator
without tmux, and not over ssh. If it leaves your terminal wrong, run
resetand report it with the terminal's name andTERM.- What it does to your terminal is a closed list, restored on every way
out a process can handle (quit, an internal error, SIGINT, SIGTERM,
SIGHUP, SIGQUIT) and acrossCtrl+Zandfg: raw mode, the alternate
screen, the cursor hidden, autowrap off and bracketed paste on. It
switches on no mouse or focus reporting and no keyboard protocol, writes
no title, clipboard sequence or bell, and uses only your terminal's own
sixteen colours (NO_COLORis honoured). After SIGKILL no process can
restore a terminal:resetis needed (inside tmux,tput rmcuptoo), and
nothing is left in tmux. - Text it did not write never reaches the terminal raw. The screen
draws only the TUI's own words and text that passed the display filter it
shares with the Desktop, so a name or a message cannot write a control
sequence. - Without a terminal on stdin and stdout, or with
TERMunset or
dumb, it exits 1 with one line on stderr namingE_NO_TERMINALand
draws nothing.oats tui --jsonis refused withE_BAD_ARGS: it is
interactive, andoats status --jsonis the machine view. oats panestill refuses, and its message now namesoats tuibeside
the Desktop.- No JSON answer, configuration key, hook or lock changes, and
oats version --jsonlists no new feature: nothing gates on this word.
See OATS TUI.
- What it does to your terminal is a closed list, restored on every way
Changed
-
The Desktop accepts OATS CLIs
>=0.25.8 <0.53.0. The compatibility band
admits 0.52. Upgrade the CLI and the Desktop together: a 0.51.0 Desktop
refuses a 0.52.0 CLI. No new gate on the band. The Desktop reads two of this
release's features where the answering kernel names them, and makes the
weaker claim for a kernel that does not:lifecycle-claim-stop(who holds
the claim, onE_LIFECYCLE_BUSY) andlifecycle-kernel-codes(a failed stop
row'sstillRunning: []says the harness exited). -
OATS confirms Claude's development-channel prompt on every start that
launches Claude with the development-channel flag
(#886). When a spawn,
oats session startorsession restart(by hand or by an agent) starts
Claude with--dangerously-load-development-channels plugin:aweb-channel@awebai-marketplace, the launcher confirms Claude's
confirmation once, with one Enter, in the pane it created. Launching with the
flag is the decision. There is no consent setting and no list of homes:
every Claude home the messaging provider starts in development mode (the
defaultdelivery: channel,claudeChannelMode: development) is covered,
existing homes included at their next start. This reverses the rule that no
existing home is enabled automatically. To keep the prompt for a person, stop
launching with the flag:settings.oats.aweb.delivery: sessionor
settings.oats.aweb.claudeChannelMode: approved, then respawn the home. Each
start that engages it says so in its warnings (launch-config preview, the
spawn's warnings,session start|restart).spawn --previewdoes not yet:
the argv comes from the provider's spawn hook, which a preview does not run (a
kernel follow-up runs preview-aware launch hooks there).
See the development-channel confirmation. -
Accounts where Claude Code offers no channels, on the default
delivery: channel: every start now says the instance gets no channel
delivery. Claude Code disables channels when telemetry is opted out (DISABLE_TELEMETRY,DO_NOT_TRACK,CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC): a host or launch configuration that sets any of
them is affected the same way, and oats.aweb's readiness warning names the
three variables that do it. For such an account Claude 2.1.296 ignores
--dangerously-load-development-channels, shows no confirmation, and starts
the session with the notice--dangerously-load-development-channels ignored (plugin:aweb-channel@awebai-marketplace) Channels are not currently available. Before 0.52 that start reported launched and said nothing, and mail
and chat never woke the instance. Now, when that notice block equals the new
flag-ignoredtolerance entry (which takes no input), OATS sends no key, the
start succeeds, and the home recordslaunchPrompts: {status: "flag-ignored", reason: "channels-unavailable", signatureId, startId, at}. The start's
warnings replace the statement that OATS confirms the prompt with one that
says what was seen and the causes to check, in order (next entry). It says so
at every start until the cause is removed or delivery changes. The provider's readiness reports it; the kernel's
launch-promptreadiness item does not. A notice in a wording no entry holds
still endsblocked, like any unknown screen. Known limit, on a first spawn: a fresh Claude configuration can show
another notice (auto mode becoming the default) and keep this one behind
1 more notice hidden. OATS cannot see it, so that spawn ends
E_SPAWN_INCOMPLETE,blocked: unexpected prompt, with the session running in
the retained pane. The error and the readiness remedy then say Claude may have
ignored the flag: look at the pane and, if the session is running, restart the
instance; the restart sees the notice and recordsflag-ignored. -
The flag-ignored words say what was seen, and a spawn's answer carries
launchPrompts. The start's warning readsClaude reported that channels are not currently available and ignored the development-channel flag, so this instance gets no channel delivery: mail and chat will not wake it. Check first for a telemetry opt-out in the launch environment (DISABLE_TELEMETRY, DO_NOT_TRACK or CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: Claude Code disables channels when one is set), then whether this Claude account offers channels; otherwise change the messaging provider's delivery (its readiness warning says where the setting is). See docs/configuration.md#the-development-channel-confirmation.The hidden-notice hint in the
error and the readiness remedy names the same causes in the same order. Neither
states that the account lacks channels, since a telemetry opt-out is the
other cause, and neither names a provider setting. A successfuloats spawn --jsonanswer now carrieslaunchPromptsexactly as a start's answer does
(completed,not-engagedorflag-ignored), so a client learns a
spawn's outcome from the answer, as it does a start's. -
The match no longer depends on the Claude binary, platform or pane size.
The executable-hash pin, the platform gate and the 110×35 geometry pin are
removed; the launcher never resizes a pane. The screen, with box-drawing rows
dropped and whitespace collapsed (nothin...