-
v0.5.1 (SESSION-ENV)
StableAll checks were successfulci / check (push) Successful in 1m35sreleased this
2026-10-28 11:57:45 +00:00 | 0 commits to main since this releasev0.5.1 (SESSION-ENV) — the unit waits for the login's session environment
Why. The user service is wanted by
default.targetand started at the 2026-10-28 reboot a moment before the X login importedDISPLAY,XAUTHORITYandDBUS_SESSION_BUS_ADDRESSinto the user manager (Xsession.d/20dbus_xdg-runtime, then95dbus_update-activation-env). The shared server ran without them until the launcher's restart;oo-appserver doctorwarned. Cinnamon never activatesgraphical-session.target, so no ordering target can fix it.What.
oo-appserver.servicegets an advisory ExecStartPre gate (ExecStartPre=-python3 -I libexec/appserver_session_env.py): it pollssystemctl --user show-environmentuntilDISPLAYorWAYLAND_DISPLAYis present (default 15 s, ceiling 60 s; knobOO_APPSERVER_SESSION_ENV_TIMEOUT_Svia 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 statusshows asessionline;doctornames 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-appserverThe running service keeps the old unit until a restart:
oo-appserver restartwhile no client, no loaded thread and the app not attached (or the nightly gated release); afterwardsoo-appserver statusshowssession : already imported · keys DISPLAY,XAUTHORITY,…anddoctorhas no session-keys warning. The next login showsimported after …swithout any restart.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v0.5.0 — the nightly gated release
StableAll checks were successfulci / check (push) Successful in 1m32sreleased this
2026-10-28 01:32:35 +00:00 | 2 commits to main since this releaseThe owner's word (2026-10-28): a nightly gated
oo-appserver releaseas 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) runsoo-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:
nightlystatus line (timer, next and last run), doctor info when the timer is not enabled;--dry-runsays 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 in98bc7aa), re-check: "mergeable as is". PR #9, squash commitdc343e6.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v0.4.0 — `oo-appserver read`, and a release gate that knows ephemeral threads
StableAll checks were successfulci / check (push) Successful in 1m26sreleased this
2026-10-28 00:48:03 +00:00 | 5 commits to main since this releaseThe read counterpart of
sendand 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/listandthread/items/listnever 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;--itemsevery item of each turn (commands, tool calls, web searches as a gist; areasoningitem only as its size,--fulladds the raw items), pages followed up to 1000 items and stopped on an empty page or a repeated cursor (items_more);--max-charsclips (2000). An ephemeral thread is read from its metadata alone. --json= one object (the receipt row's fields plusturns[]) — the contract for callers: a backend that gotack-unknownfromsendlooks here before it would ever resend; Luna's "ok" is read from her thread instead of the app. Receipt rowkind: readper 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 neitherthread/resumenorthread/turns/list— one of them keptoo-appserver releaserefusing 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.py23 legs,tests/test_send.py103 legs (three new gate legs); the fake app-server learnsthread/read,thread/items/listwith 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 on649892b(the paging loop's termination), final confirmation one5d9fa3: "mergeable as is". PR #7, squash commit5f06c2b.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Status (
-
v0.3.0 — the app tools bridge
StableAll checks were successfulci / check (push) Successful in 1m10sreleased this
2026-10-27 23:58:33 +00:00 | 6 commits to main since this releaseThe 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 asCODEX_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.servicewants 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/doctorshow 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 sendfor 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 releaseorrestartwhile the owner's chats are idle; relaunch ChatGPT from the menu afterwards).Independent read-only review on
dac3e8a, findings folded ina9b9473and42a15c3: "delta clean — mergeable as is". PR #5, squash commit95b85b3.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v0.2.2 — the on-the-wire guard, a heal that cannot crash, the plan re-derived under the lock
StableAll checks were successfulci / check (push) Successful in 1m4sreleased this
2026-10-27 23:18:22 +00:00 | 7 commits to main since this releaseThe 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/steerrequest has been written, every failure before the acknowledgement isack-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 arefusedreceipt 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;doctornames the threads the shared server holds while the app runs in fallback mode and points atoo-appserver release.- README: the lock-out as measured on the owner's real app (the locked chat shows "open in another app",
releaseheals in 658 ms, Retry restores the prompt); known gaps — loaded threads keep their memory (backlog: a nightly gatedrelease), 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 doctorDownloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- On the wire means unknown, never refused. Once the
-
v0.2.1 — running turns seen, acknowledged lines never downgraded, heal under a lock, foreign writers refused
StableAll checks were successfulci / check (push) Successful in 1m0sreleased this
2026-10-27 22:47:55 +00:00 | 8 commits to main since this releaseThe 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": [], sostatus.type == "active"is the signal and the running turn's id comes fromthread/turns/listby itsinProgressstatus; 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/steerack 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 isack-unknown(exit 8,delivered: null, throttle kept, do not resend blindly);timeoutis reserved for steps before anything was sent. - Heal under a lock with re-observation; a unit active for less than 30 s without
readyzis 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/unsubscribedoes not release it): the server's verdicts (thread-store conflict … active writer,thread not foundafter a successful resume) areheld-by-app;oo-appserver releaseis 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-runacts 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 doctorDownloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Running turns are seen. The server answers
-
v0.2.0 — `send`: one entry, the path chooses itself, headless when the app is closed
StableAll checks were successfulci / check (push) Successful in 43sreleased this
2026-10-27 22:12:24 +00:00 | 9 commits to main since this releaseA 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/resumewithexcludeTurnsand a timeout scaled to the rollout size, bounded loading wait, thenturn/start, orturn/steerinto a still-running headless turn); app attached →turn/starton an idle thread,turn/steerinto a running one; app running its own stdio app-server or not attached → refused asheld-by-appwithout 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 healruns 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, plusrefused(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).--jsonprints exactly one receipt line with a fixed key set — the transport contract for the oo-dispatchappserverbackend. - 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, thenloading— 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;doctortreats "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 doctorDownloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v0.1.0 — the station's shared Codex app-server
StableAll checks were successfulci / check (push) Successful in 7sreleased this
2026-10-27 16:55:29 +00:00 | 10 commits to main since this releaseThe 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: exportCODEX_APP_SERVER_WS_URL, restart after an app update or a fresh login, stdio fallback, opt-outOO_APPSERVER=0 - helper
oo-appserver(status, doctor with env-drift and attachment checks, threads, restart, logs) - WebSocket clients:
appserver_probe.py(read-only) andappserver_turn.py(oneturn/startorturn/steer, receipts) - README with the regular flow, known gaps and the backend contract for the
appserverkiss 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 doctorDownloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- user service