Skip to content

Releases: awebai/oats

OATS v0.59.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 00:50
de0e956

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.detachKey in tui.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. A tui.json whose open.detachKey is a
    key an action has is now refused: give one of the two another key. See
    Added and Changed (#855).

Added

  • retire on status rows: whether a retire of the home is running,
    cannot be told, failed or was interrupted
    (feature status-retire-state,
    #1247). oats status --json
    instance rows carry retire: {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 an oats retire (self: false). state is running, unknown (liveness cannot be read),
    failed (with the result's kernel code and its one-line message) or
    interrupted (the completion process is gone). since is always an
    instant (the recorded time, else the file's modification time), and
    code and message are strings or absent, never null. Status still takes no
    claim, removes no file and signals no process. retirePending keeps its
    meaning. Remote roster rows relay retire only 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 when oats version --json lists
    status-retire-state: an older kernel never carries it
    (retire).

  • oats session inspect --json reports the agent window's size: { 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 --json advertises session-inspect-size, so
    viewers can discover support before opening a PTY at that size (#1285).

  • oats tui has a leader key, so every action is reached by keys from
    every focus
    (#855). The
    leader is Ctrl+\ (open.detachKey in tui.json), then one plain key:
    k or Space the palette, 1 to 3 the views, Up/Down the
    previous or next instance's terminal, z zoom, w close the terminal,
    X/R/S/D the acts, / filter, o workspaces, ? help, and Esc
    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, or Ctrl+K in
    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 tui lists the open workspace's souls
    (#855). 2, or the leader
    then 2, 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 (or Enter in the detail) shows those instances
    in the Instances view, filtered by that soul; Esc clears the filter.
    The list is the OATS Desktop's, read with oats souls only once the view
    is first shown, and again only when the workspace changes, or with r.
    The palette lists the souls once they are read. tui.json has a new
    action, soul-instances (default i). See
    the TUI page.

  • oats tui spawns an agent on this machine
    (#855). n (or the leader
    then n) opens a picker of the open workspace's souls; N spawns
    another of the selected instance's soul. The preview is the OATS
    Desktop's, read with oats 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. Tab moves between
    Spawn, the name (the instance's --purpose), the parent and the folds;
    Enter on Spawn applies exactly the decision on screen, through the
    shared apply, and a pasted n and Enters 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 with C. One spawn runs at a
    time; spawning on another machine, or with another harness, model or a
    task, stays oats spawn. The palette lists Spawn an agent and Spawn
    another. tui.json has three new actions, spawn (default n),
    spawn-another (N) and spawn-check (C). See
    the TUI page.

  • oats tui splits 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, says Enter 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 then Tab goes to the other group, the leader then m moves the
    shown tab there, and the leader then x closes 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.json has five new actions: split-right
    (default |), split-down (-), and group-next, tab-move and
    group-close, which have no key of their own by default. See
    the TUI page.

  • oats tui opens 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 then Left/Right from 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.json has
    two new actions, tab-previous (default [) and tab-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 under work/ 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 a node_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,
      under after-hooks/, as a worktree's work already was
      (souls-and-instances.md).
  • 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. ...

Read more

OATS v0.58.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 17:09
96b8ba2

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 refused oats session start after 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 spawn itself may pass --max-age on an
    apply bound by --expect-decision, when oats version --json lists
    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-decision now takes --max-age, as
    spawn --preview already did: it reuses member heads this machine observed
    at most that many seconds ago instead of asking each remote again, which
    saves the apply's git ls-remote round (about 0.3–0.45 s). The decision is
    computed from those heads, and one that differs from the confirmed revision
    is still E_DECISION_STALE, with nothing created. --max-age 0 is live, as
    without the flag. The apply's answer is unchanged: it carries no
    observation block. A spawn apply without --expect-decision still 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 --json lists spawn-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=1 set 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 tui runs 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 start refused every directory-mode home with "directory home
    was exchanged; restore the owned root before retrying start", although its
    home and work/ 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 or work/'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

Choose a tag to compare

@github-actions github-actions released this 15 Oct 15:15
fdf474f

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 under detach-on-destroy off, and a late hang-up no longer
    leaves an oatsview-* 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. Enter opens an agent's
    terminal in a panel beside the list; z gives it the whole body. The panel
    needs tmux 3.2 or later. open.detachKey in tui.json keeps its name and
    the keys it accepts, and now means the back key to the list; a key outside
    them is refused when tui.json is read. See Changed
    (#855).

  • pi homes: run oats update to move the @awebai/oats-pi bridge 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 empty STATE.md. See Fixed
    (#1251).

  • To get the new framework skills, pin oats.framework: v1.12.0 in your
    workspace and run oats sync: /oats-host-delivery and /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 spawn child 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 tui opens an agent's terminal in a panel beside the list
    (#855). Enter on 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+\, or open.detachKey in tui.json),
    which gives the focus to the list while the terminal stays open and live.
    From the list, Enter on its row goes back to it, z gives it the whole
    body and c closes it; Enter on 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
    : z replaces 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 -9 of oats tui included; a later run removes what a killed one
    left. open.detachKey keeps its name
    and the keys it accepts, and now means the back key; a key outside them is
    refused when tui.json is 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 keys 1, 2 and 3 are in the help, not beside the names, and
    the footer names them as one hint, 1-3 views; 2 and 3 say 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 off in 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 with set -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 on for 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 reach oats session attach late, 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 end oats before its cleanup, or kill the cleanup's
    tmux call, and leave the oatsview-* session (and a keyed viewer's key
    table) on the agents' tmux server. oats now 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-pi bridge sends the nudge "Read ./STATE.md … then continue
    from STATE.md's Next section". It held the nudge back only while STATE.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.md exists, 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. Run oats update to 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 doctor clean and still
      have two problems nobody had chosen:
      • its Claude homes ran in development channel mode, because
        claudeChannelMode was unset;
      • no host wake broker ran, so every joined team was poll-only, and Codex
        and delivery: session homes were not woken at all.
    • A new skill, /oats-host-delivery, is the one place that teaches both
      choices. /oats-workspace-config now 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's CLAUDE_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 installs aw wake run as a per-user systemd or launchd service, with AW_WAKE_OATS_BIN
        and a PATH that reaches oats, node and tmux; the restart after an aw upgrade; the check (aw wake status --json, and readiness free of wake-daemon-* and
        `join...
Read more

OATS v0.57.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 10:22
011c893

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 remove may 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 one E_BAD_ARGS naming every flag still missing,
    where it got a repository refusal and then E_SPAWN_FAILED on the retry.
    See Changed (#958,
    #964).

  • A retire plan taken before the upgrade is refused once by the 0.57.0
    kernel with E_PLAN_STALE and 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.2 and
    oats.okf: v5.2.0 in your workspace and run oats sync. Instances already
    running keep what they were spawned with. See Provider updates.

  • Pin oats.okf: v5.2.0 and run oats 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 tui stops, starts, restarts and retires an agent
    (#855). With an instance
    selected, X stops it, D retires it, S starts it and R restarts it,
    each after a confirmation that opens with the focus on Cancel: the act
    takes a move (Left/Right or Tab) and a press of Enter, 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 tui does: 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.json changes 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 tui runs 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>/work the 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 --repo given 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's work/ (#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 for work/: 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 their work link would then
      point at a path that is gone, and the receipt's warnings (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's ambiguous and is never stopped, so
      its link is not repointed either. The plan's note for the tree it is
      attached to (an extra tree, or work/) now names it and says that its
      work link would then point at a path that is gone, and the receipt's
      warnings say 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
      --self retirement's receipt does not carry those warnings.
    • oats worktree remove refuses 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 answers E_CHILDREN_RUNNING before Git is
      asked anything: nothing is removed and the record is kept. details is
      {purpose, path, children: [{instance, home, session}]}, session being
      "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's warnings name 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...

Read more

OATS v0.56.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 21:31
bd338ee

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 update now prints this order itself when it
    installs a CLI of another minor.

  • A script that matched E_HARNESS_PACKAGE matches
    E_HARNESS_RESOURCE_MISSING now. A script or capability that read
    E_SPAWN_FAILED from oats spawn as "the spawn failed"
    now gets the
    kernel's own code: match on the exit status or on ok: false instead, and
    read details.unconfirmed for how far a spawn got. See Changed
    (#1047).

  • A tui.json that names the action open-workspace is refused with
    open-workspace is called open now; rename it: rename it to open. See
    Added (#855).

  • To get the new provider versions, pin oats.framework: v1.10.1 and
    oats.okf: v5.1.0 in your workspace and run oats 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 NAME for the server,
    or recreate the server; then restart the affected instances.

Added

  • Feature spawn-kernel-codes (#1047). oats spawn answers the
    kernel's own code; a kernel without the word may answer E_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 none does 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.
  • 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's workspaceKey;
    an empty, missing or malformed value is E_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 runs oats 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 own skills/ (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 (feature soul-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 --json adds souls[0].skills: the skills a spawn of the soul
    copies (not its capabilities' skills), each with its description and
    every file's text, by the rules of oats 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: null with a problem. --skills combines with --instructions,
    refuses --home, and is routed with --server to a host that advertises
    the new feature soul-skills
    (oats inspect,
    #1144).

  • oats tui opens an agent's terminal
    (#855). Enter on an
    instance that runs, on this machine or on a registered one, gives your
    terminal to the agent through oats session attach; Ctrl+\ brings
    oats tui back and the agent keeps running. tui.json's
    open.detachKey changes the key. After the return one line says what
    happened, and Enter on 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 action open-workspace is now open, and a
    tui.json that names open-workspace is refused with
    open-workspace is called open now; rename it.

Changed

  • oats retire --server prints 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 its warnings. It now prints them as a
    local retire does, one WARNING: line each, after the extra-tree lines:
    what a retire left an attached child with, which repository it read from
    Git, where a link at work/ led. The JSON is relayed as it was.

  • More text lines spell what a terminal would act on
    (#1006).
    The note:
    lines of oats retire --plan, oats instance stop --plan,
    oats instance git and oats readiness; the WARNING: lines of
    oats spawn (local and with --server), of the oats session commands
    and of oats 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 spawn answers 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_FAILED is what an error with no kernel code is answered with,
    with details.cause for 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 as E_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 matched E_SPAWN_FAILED to 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.unconfirmed is. The details of each code are what
    they were: a code that carried details keeps ...

Read more

OATS v0.55.1

Choose a tag to compare

@github-actions github-actions released this 14 Oct 13:52
555931e

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.3 in your workspace, then run oats sync. The
    catalog in this release names it. On 1.27.2, readiness reports
    unavailable for every home that the host wake broker serves (Codex,
    delivery: session, joined teams with receive: native) while delivery
    works. Running instances keep the provider they were spawned with. Such an
    instance reads unavailable until it is re-spawned; spawns after the sync
    get 1.27.3. See Provider updates.

Fixed

  • oats recall --show now 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 after aw wake status returns,
    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 published v1.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, then oats 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

Choose a tag to compare

@github-actions github-actions released this 14 Oct 10:09
6e9cf9b

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 --json no longer sees
    E_ROSTER_BUDGET or bounds.skipped: every server is probed, and one
    that does not answer reports its own E_SSH timeout. 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 run oats 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 with E_OWNER on 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 tui runs 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
    use capture --retry-set-aside, or exclude the source through the existing
    ignore list (which also excludes its later turns). capture --health reports
    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_BUDGET and bounds.skipped in oats server roster --json.
    Every group is probed, so no group is reported as not reached any more, and
    bounds is {budgetMs, perTargetTimeoutMs, elapsedMs}. --budget stays,
    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>.insteadOf or pushInsteadOf (a deploy key on an ssh alias,
      for example) failed every okf call with E_OWNER. The frozen-remote
      guard now resolves the binding's repository with 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 a pushurl is 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 while oats 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 published v5.0.5 at 73b85020e52b8584cb15f153a39712f900e69918.
      Compatibility remains OATS 0.29.0 or later.
  • oats.aweb 1.27.2: the /oats-aweb skill'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 and mirrors/oats-aweb take published v1.27.2
    at f82cebe299562b38188f3373fa09a89b50d5f868; 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.0 at 944470be71a96299ae4a1cfb7df0fba94a592899; 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.maintainer and
    oats.engineering-expert change; 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. Pin oats.engineering: v1.10.0 and run oats sync.
      Running instances keep what they were spawned with; new spawns pick
      1.10.0 up after oats 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").

OATS v0.54.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 21:36
201fc63

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, pin oats.framework: v1.10.0
    in your workspace and run oats 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, or details.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 run oats 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. The oats.core briefing, which
    every instance with oats.core reads, 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).

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 tui runs the kernel it
    ships with and is held to the same band.

  • Diagnostic messages, details, provenance and workspace cannot-read values
    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-read fields 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 souls and oats capabilities now 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-saving and 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 status and
      oats instance events <instance>, exist in every kernel oats.core
      admits.
    • A deployment gets it by pinning oats.framework: v1.10.0 and running
      oats sync. Instances already running keep the briefing and the skills
      they were spawned with; new spawns get the new ones.

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, before oats sync.

OATS v0.53.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 16:54
e3de1f0

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 update whose 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,
    before oats 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 update in each deployment that
    launches pi instances.
    It now moves the pi bridge in every pi folder that
    deployment's launch configurations name, and oats doctor warns about each
    one that is behind
    (#991). An oats update run
    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.json are written again at every oats session start and restart, 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 setup was run, run oats setup once more
    after upgrading the CLI, as the same user
    (#1003).
    The capture hooks
    in ~/.claude*/settings.json and the capture watcher's unit still name the
    node that ran the earlier setup, and nothing else rewrites those files:
    no oats update, spawn, start or restart. The run replaces its own hooks
    and unit and adds no second one. oats setup --dry-run first prints the
    node it 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 installed for the watcher's unit has not
    checked that the watcher is enabled
    (#1099). On Linux,
    systemctl --user is-enabled turn-record-capture.service says whether it
    is. Where an earlier oats setup could 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
    --root if 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 recorded aw path 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 of souls.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.launch other than "*" is
    the name of a soul that oats souls lists, 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.launch that 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_UNREADABLE in a second or two, on a network that is fine, needs
    only this upgrade (#1059).

    The refusal names the reason network, or auth, 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 sync
    

    The same prefix works on any oats command that fetches: a spawn, a
    preview, oats souls, oats workspace status. Do not run Git inside
    ~/.cache/oats and do not move a cache entry aside: the old kernel
    rebuilds it and fails the same way. In that state oats souls can also
    print its list without a package's souls, with no error and exit 0
    (#1098); oats souls --json
    names them in problems.

  • 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 run oats 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 the oats command 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 no oats-local.yaml at or above the start, and, when no
      --dir was given, no deployment directly inside ~/Agents to 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 oats found on PATH,
      and only to read (oats status and oats workspace status, then a probe
      of the terminals, and oats server roster for 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.
  • oats soul launch set|remove writes a soul's launch preference
    (#990).
    Until now the only
    way to pin a soul to a launch on a machine was to edit oats-local.yaml
    souls.launch by 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. set names the soul as a spawn does and writes the key that soul
    has, so it cannot write a key that names no soul. remove also 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 of souls.launch that still names no soul. The file is
    rewritten, and every other entry keeps its value and its comments.
    A
    client gates on the feature soul-launch; the answer is soulLaunchApi: 1
    (docs/desktop-cli-api.md). New
    code: E_LAUNCH_PREFERENCE_UNKNOWN, a remove of an entry the file does
    not have. Not in this release: a list verb (oats souls shows each
    soul's launch), and a lock for `oats la...

Read more

OATS v0.52.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 20:53
fb43180

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:

  1. 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 old launchPromptAnswers list.
  2. A host with several launch configurations for one harness marks one
    default: true or names one in souls.launch. Until then, scheduled jobs,
    triggers and agents' own spawns that name no configuration are refused
    (E_LAUNCH_CONFIG_AMBIGUOUS).
  3. Remove launchPromptAnswers from oats-local.yaml: a home entry
    awebDevelopmentChannel: false stops the deployment from loading.

Then upgrade, in this order, with no lifecycle command (a stop or a retire) in
flight on the deployment:

  1. 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.
  2. Upgrade the OATS CLI and the Desktop together. A 0.51.0 Desktop refuses
    a 0.52.0 CLI.
  3. Pin oats.aweb 1.27.0, then run oats sync. It needs OATS 0.52.0: an
    older kernel refuses it with E_CAPABILITY_INCOMPATIBLE. The catalog's
    other versions in this release are oats.okf 5.0.2 and oats.framework 1.9.3.
  4. After upgrading, on every host that runs schedules, run
    oats schedule host install again, from the operator's own shell (not from
    an instance home): an installed timer is not rewritten by upgrading OATS.
    oats schedule host status reports unit-outdated until 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 tui is a
    full-screen, keyboard-only client for people who work in terminals and on
    machines with no display. It ships inside the oats package: there is
    nothing else to install. It is a preview, and this version draws the
    frame only
    : it shows the frame, answers ? (help) and q (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
    reset and report it with the terminal's name and TERM.
    • 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 across Ctrl+Z and fg: 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_COLOR is honoured). After SIGKILL no process can
      restore a terminal: reset is needed (inside tmux, tput rmcup too), 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 TERM unset or
      dumb, it exits 1 with one line on stderr naming E_NO_TERMINAL and
      draws nothing. oats tui --json is refused with E_BAD_ARGS: it is
      interactive, and oats status --json is the machine view.
    • oats pane still refuses, and its message now names oats tui beside
      the Desktop.
    • No JSON answer, configuration key, hook or lock changes, and
      oats version --json lists no new feature: nothing gates on this word.
      See OATS TUI.

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, on E_LIFECYCLE_BUSY) and lifecycle-kernel-codes (a failed stop
    row's stillRunning: [] 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 start or session 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
    default delivery: 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: session or
    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 --preview does 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-ignored tolerance entry (which takes no input), OATS sends no key, the
    start succeeds, and the home records launchPrompts: {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-prompt readiness item does not. A notice in a wording no entry holds
    still ends blocked, 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 records flag-ignored.

  • The flag-ignored words say what was seen, and a spawn's answer carries
    launchPrompts.
    The start's warning reads Claude 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 successful oats spawn --json answer now carries launchPrompts exactly as a start's answer does
    (completed, not-engaged or flag-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...

Read more