• v0.5.1 488bcaa163

    v0.5.1 (SESSION-ENV)
    All checks were successful
    ci / check (push) Successful in 1m35s
    Stable

    claude agent released this 2026-10-28 11:57:45 +00:00 | 0 commits to main since this release

    v0.5.1 (SESSION-ENV) — the unit waits for the login's session environment

    Why. The user service is wanted by default.target and started at the 2026-10-28 reboot a moment before the X login imported DISPLAY, XAUTHORITY and DBUS_SESSION_BUS_ADDRESS into the user manager (Xsession.d/20dbus_xdg-runtime, then 95dbus_update-activation-env). The shared server ran without them until the launcher's restart; oo-appserver doctor warned. Cinnamon never activates graphical-session.target, so no ordering target can fix it.

    What.

    • oo-appserver.service gets an advisory ExecStartPre gate (ExecStartPre=-python3 -I libexec/appserver_session_env.py): it polls systemctl --user show-environment until DISPLAY or WAYLAND_DISPLAY is present (default 15 s, ceiling 60 s; knob OO_APPSERVER_SESSION_ENV_TIMEOUT_S via a drop-in), then the server is spawned with the imported block. The result is one line in $XDG_RUNTIME_DIR/oo-appserver/session-env. A console or SSH login passes after the bound — the door always opens; the gate can never fail the unit.
    • oo-appserver status shows a session line; doctor names the gate record in its session-keys warning.
    • Tests: tests/test_session_env.py (11 legs) in CI; README updated (Parts, The regular flow step 1, Knobs).

    Evidence. Hermetic experiment on systemd 255: a transient unit whose ExecStartPre waited for a private key imported 2 s after the start — ExecStart printed the imported value (every Exec* gets the manager environment of its own spawn). Independent read-only review in two rounds, all findings folded; CI green.

    Install (fleet law: from the checked-out tag).

    git fetch origin tag v0.5.1 && git checkout v0.5.1 && ./install.sh --target ~/tools/oo-appserver
    

    The running service keeps the old unit until a restart: oo-appserver restart while no client, no loaded thread and the app not attached (or the nightly gated release); afterwards oo-appserver status shows session : already imported · keys DISPLAY,XAUTHORITY,… and doctor has no session-keys warning. The next login shows imported after …s without any restart.

    Downloads
  • v0.5.0 dc343e6469

    v0.5.0 — the nightly gated release
    All checks were successful
    ci / check (push) Successful in 1m32s
    Stable

    claude agent released this 2026-10-28 01:32:35 +00:00 | 2 commits to main since this release

    The owner's word (2026-10-28): a nightly gated oo-appserver release as memory and lock hygiene — and the same gated release before a fallback launch of the ChatGPT app.

    • oo-appserver release --only-if-loaded: a no-op (not-needed) when the shared server holds no thread; never opens a stopped server; when a thread is loaded the usual gate decides (app not attached, no connected client, no busy thread) and restarts. An unreadable loaded list or a hung server (door closed, unit still active) hand over to the normal gate.
    • oo-appserver-release.timer (04:30 plus up to 20 minutes, catches up after a night off) runs oo-appserver-release.service (oneshot, --from nightly-release): a skipped night is not a failure (exit 1 counts as success), a restart that left the door shut exits 5 and shows as a failed unit. Every run leaves a receipt row (kind: heal).
    • Helper: nightly status line (timer, next and last run), doctor info when the timer is not enabled; --dry-run says what the night would do.
    • Tests: eight legs (suite 111); CI verifies all four units.

    Install (from the tag): git fetch origin tag v0.5.0 && git checkout v0.5.0 && ./install.sh --target ~/tools/oo-appserver — installs both release units and enables the timer; the running shared server needs no restart.

    Independent read-only review on 5360298 (1 should-fix, 2 low, 2 nits — folded in 98bc7aa), re-check: "mergeable as is". PR #9, squash commit dc343e6.

    Downloads
  • v0.4.0 5f06c2b0be

    v0.4.0 — `oo-appserver read`, and a release gate that knows ephemeral threads
    All checks were successful
    ci / check (push) Successful in 1m26s
    Stable

    claude agent released this 2026-10-28 00:48:03 +00:00 | 5 commits to main since this release

    The read counterpart of send and the first building block of design C (Z's yes, steer 40, 2026-10-28): the last turns of a thread, read from the shared server without loading it — measured first: thread/read, thread/turns/list and thread/items/list never take the thread store's writer lock, so a read never locks the app out and never needs a heal.

    oo-appserver read <thread-id> [--turns N] [--items] [--full] [--max-chars N] [--timeout S] [--json]
    
    • Status (notLoaded / idle / active), preview, model; the newest N turns (default 3) printed oldest first with their messages; --items every item of each turn (commands, tool calls, web searches as a gist; a reasoning item only as its size, --full adds the raw items), pages followed up to 1000 items and stopped on an empty page or a repeated cursor (items_more); --max-chars clips (2000). An ephemeral thread is read from its metadata alone.
    • --json = one object (the receipt row's fields plus turns[]) — the contract for callers: a backend that got ack-unknown from send looks here before it would ever resend; Luna's "ok" is read from her thread instead of the app. Receipt row kind: read per attempt. Exit 0 read · 1 refused · 2 usage · 4 door-closed (a read does not open the door) · 5 timeout.
    • The heal/release gate reads each loaded thread's state with thread/read: the app's ephemeral threads (new empty chats) answer neither thread/resume nor thread/turns/list — one of them kept oo-appserver release refusing on the station on 2026-10-28. Idle ephemeral threads pass now, active ones still count as busy.
    • README: the read section, the gate text, known gaps (the bundled plugin runs since v0.3.0 through the bridge; both its catalogue and its calls travel over the pipe, a bridge receipt row appears when a tool server's connection ends; six thread tools), the read contract.
    • Tests: tests/test_read.py 23 legs, tests/test_send.py 103 legs (three new gate legs); the fake app-server learns thread/read, thread/items/list with paging, item views, ephemeral ids, stuck-server shapes.

    Install (from the tag): git fetch origin tag v0.4.0 && git checkout v0.4.0 && ./install.sh --target ~/tools/oo-appserver — no unit changes, the running shared server needs no restart.

    Independent read-only review on 2f8bfe5 (2 should-fix, 5 low, 6 nits), delta re-check on 649892b (the paging loop's termination), final confirmation on e5d9fa3: "mergeable as is". PR #7, squash commit 5f06c2b.

    Downloads
  • v0.3.0 95b85b3a17

    v0.3.0 — the app tools bridge
    All checks were successful
    ci / check (push) Successful in 1m10s
    Stable

    claude agent released this 2026-10-27 23:58:33 +00:00 | 6 commits to main since this release

    The bundled Codex app tools (send_message_to_thread, read_thread, create_thread, fork_thread, handoff_thread, …) work in the shared app-server again — the owner's requirement of 2026-10-28, Z's design word (A now, C as the target).

    • oo-appserver-bridge.service + libexec/app_tools_bridge.py: a stable pipe ($XDG_RUNTIME_DIR/oo-appserver-bridge/app-tools.sock, 0600) the shared server gets as CODEX_APP_TOOLS_PIPE_PATH; every connection is forwarded, per connection, to the tools socket of the ChatGPT app running right now (app-owned listener wins, stale files skipped). No running app → the connection is closed at once (no-app), never accepted-and-hung; half-closing clients still get a late answer (120 s window).
    • oo-appserver.service wants the bridge and runs the plugin again (codex_app.enabled=true).
    • Receipts per connection in ~/.local/state/oo-appserver/bridge.jsonl.
    • Helper: oo-appserver tools; status/doctor show the app-tools line and say "restart pending (gated)" while the running process still carries the old unit.
    • Installer installs both units and restarts a changed, running bridge; CI verifies both units and runs the bridge suite (14 legs).
    • README: the bridge section (what the rig and the owner's app taught), the family way oo-appserver send for Mama and Omi, known gaps (the bundled tools need the running app — the family's own tools over the shared server are design C, draft in PR #6).

    Install (from the tag): git fetch origin tag v0.3.0 && git checkout v0.3.0 && ./install.sh --target ~/tools/oo-appserver. The running shared server picks the new unit up only after a gated restart (oo-appserver release or restart while the owner's chats are idle; relaunch ChatGPT from the menu afterwards).

    Independent read-only review on dac3e8a, findings folded in a9b9473 and 42a15c3: "delta clean — mergeable as is". PR #5, squash commit 95b85b3.

    Downloads
  • v0.2.2 f5d10603ff

    claude agent released this 2026-10-27 23:18:22 +00:00 | 7 commits to main since this release

    The second independent read of v0.2.1, folded (PR #4, reviewer: "delta clean", CI green on every commit, suite 100 legs).

    • On the wire means unknown, never refused. Once the turn/start/turn/steer request has been written, every failure before the acknowledgement is ack-unknown (exit 8); replies are parsed defensively, non-object JSON frames are skipped, the verdict is set the moment the acknowledgement arrives.
    • A heal that cannot crash. The lock acquisition is guarded (heal-skipped, lock-unavailable), an unexpected exception still prints a refused receipt and gives the throttle reservation back.
    • The plan is re-derived under the lock: a unit disabled or failed meanwhile is left alone, an app that appeared makes the send held-by-app, a unit someone else is starting is waited for, a station healed meanwhile is recognised (already-healed, door-open-now).
    • thread not found (exactly) is the writer-lock verdict; fragment reassembly survives deadlines; buffered notifications are honoured; doctor names the threads the shared server holds while the app runs in fallback mode and points at oo-appserver release.
    • README: the lock-out as measured on the owner's real app (the locked chat shows "open in another app", release heals in 658 ms, Retry restores the prompt); known gaps — loaded threads keep their memory (backlog: a nightly gated release), and the bundled Codex app tools still need a bridge in the shared server.

    Install from the tag:

    git clone https://oss-oo.io/OSS-OO/oo-appserver.git && cd oo-appserver && git checkout v0.2.2
    ./install.sh --target ~/tools/oo-appserver && oo-appserver doctor
    
    Downloads
  • v0.2.1 e904afa334

    claude agent released this 2026-10-27 22:47:55 +00:00 | 8 commits to main since this release

    The fix release after the second independent read of v0.2.0 (PR #3, reviewed commit by commit, CI green on every commit).

    • Running turns are seen. The server answers thread/resume {excludeTurns: true} with "turns": [], so status.type == "active" is the signal and the running turn's id comes from thread/turns/list by its inProgress status; the heal gate treats active and unreadable loaded threads as busy. Proven live: a headless turn started with --wait 0, a second send steered into it (turn/steer ack 96 ms, ok). v0.2.0 never detected a running turn.
    • Acknowledged lines are never downgraded: a connection lost during the completion wait sets completed: false + wait_error, the receipt stays delivered. A request on the wire without an acknowledgement is ack-unknown (exit 8, delivered: null, throttle kept, do not resend blindly); timeout is reserved for steps before anything was sent.
    • Heal under a lock with re-observation; a unit active for less than 30 s without readyz is waited for (waited), a failed unit is never reset by the sender, the client count is re-read before every restart, the readyz probe bypasses proxies.
    • The thread store's writer lock (measured on rigs: one writer per loaded thread until the holding process ends; thread/unsubscribe does not release it): the server's verdicts (thread-store conflict … active writer, thread not found after a successful resume) are held-by-app; oo-appserver release is a gated restart that frees every lock — while the app is closed, runs its own app-server or an orphaned stdio server exists, never while attached.
    • Throttle as a reservation under a lock (parallel senders pass once, non-deliveries give it back); foreign stdio app-servers and an app appearing mid-send are held-by-app; WebSocket fragmentation reassembled; heal --dry-run acts on nothing.
    • Suite 62 → 92 offline legs; README with the measured facts and the lock-out edge.

    Install from the tag:

    git clone https://oss-oo.io/OSS-OO/oo-appserver.git && cd oo-appserver && git checkout v0.2.1
    ./install.sh --target ~/tools/oo-appserver && oo-appserver doctor
    
    Downloads
  • v0.2.0 b7d1f89311

    claude agent released this 2026-10-27 22:12:24 +00:00 | 9 commits to main since this release

    A line reaches a Codex thread with and without the ChatGPT desktop app — the way ZCode sessions are reached without the ZCode app (the owner's order of 2026-10-27).

    • oo-appserver send <thread> "<line>": observes the station once and takes one path — app closed → headless through the shared server (thread/resume with excludeTurns and a timeout scaled to the rollout size, bounded loading wait, then turn/start, or turn/steer into a still-running headless turn); app attached → turn/start on an idle thread, turn/steer into a running one; app running its own stdio app-server or not attached → refused as held-by-app without any network contact (never a second writer).
    • Heal when safe: a stale (version drift) or closed door is restarted/started before a headless send only while the app is closed, no client holds a connection (re-checked right before the restart) and no loaded thread runs a turn; a hung unit is restarted, a failed one reset first; every heal decision is its own receipt row. oo-appserver heal runs the same decision alone; a disabled unit is honoured.
    • Receipt classes, verb first: delivered-headless, delivered-app-start, delivered-app-steer, held-by-app, heal-skipped, plus refused (incl. reason: unloaded-sub-agent), loading, timeout, door-closed, no-active-turn, dropped. Exit 0 only when delivered (1 refused · 2 usage · 3 held-by-app / no-active-turn · 4 door-closed · 5 timeout · 6 dropped · 7 loading). --json prints exactly one receipt line with a fixed key set — the transport contract for the oo-dispatch appserver backend.
    • Measured defaults (rig with copies of the station's rollouts): the first load of a thread the history does not know costs about 0.02 s/MB (7.6 s warm / 14.1 s cold for 719 MB), later loads under 0.3 s; resume timeout max(10 s, MB × 0.05) capped at 120 s, then up to 60 s of waiting for the thread to appear loaded, then loading — not an error: retry later, never resend, no throttle consumed.
    • Flags --from/--tag, --fyi (the fleet's FYI template), --mode auto|start|steer, --wait, --min-interval (advisory per-thread throttle, marked right after the ack), --no-heal, --dry-run; doctor treats "ChatGPT not running" as the headless path.
    • Shared read-only station observation and a stdlib WebSocket client behind the helper and the sender; 62 offline legs against a fake app-server in CI; README with the decision table, heal rules, resume/loading, receipts, backend contract, known gaps and the Claude-session parity target flag.

    Live-verified twice headless on the station (2026-10-27 22:28 with a heal 0.164 → 0.165, 23:03 over the slim resume), two independent read-only reviews folded (#2), CI green on every commit.

    Install from the tag:

    git clone https://oss-oo.io/OSS-OO/oo-appserver.git && cd oo-appserver && git checkout v0.2.0
    ./install.sh --target ~/tools/oo-appserver && oo-appserver doctor
    
    Downloads
  • v0.1.0 584a499e31

    v0.1.0 — the station's shared Codex app-server
    All checks were successful
    ci / check (push) Successful in 7s
    Stable

    claude agent released this 2026-10-27 16:55:29 +00:00 | 10 commits to main since this release

    The station's shared Codex app-server: the ChatGPT desktop app and the family attach to one writer.

    • user service oo-appserver.service (bundled codex, --listen ws://127.0.0.1:8937, parity environment, bundle version recorded)
    • launcher hook contract for chatgpt-neon: export CODEX_APP_SERVER_WS_URL, restart after an app update or a fresh login, stdio fallback, opt-out OO_APPSERVER=0
    • helper oo-appserver (status, doctor with env-drift and attachment checks, threads, restart, logs)
    • WebSocket clients: appserver_probe.py (read-only) and appserver_turn.py (one turn/start or turn/steer, receipts)
    • README with the regular flow, known gaps and the backend contract for the appserver kiss backend of oo-dispatch

    Proven live on 2026-10-27 (T7): the app attaches without a stdio child; a turn started from outside appears in the open chat; steers land inside running turns, interrupt a running tool step and are read within about two seconds (three steers in one turn, the owner's own in-app steer behaves identically). Independent read-only review folded in (#1); CI green.

    Install from the tag:

    git clone https://oss-oo.io/OSS-OO/oo-appserver.git && cd oo-appserver && git checkout v0.1.0
    ./install.sh --target ~/tools/oo-appserver && oo-appserver doctor
    
    Downloads