Skip to content

Releases: DrOlu/RTerm

RTerm v3.9.2

Choose a tag to compare

@DrOlu DrOlu released this 24 Sep 10:42

RTerm v3.9.2 — AI-Native Terminal App by Hyperspace Technologies

v3.9.2 (2026-09-24)

Fix: the bundled neuralOS engine shipped without its exec bit — every
neuralos_ask/neuralos_graph call in the desktop app died with
engine exited EACCES: (empty stderr).

Root cause chain: curl -o in the release workflow writes files with mode
0644 and the workflow never chmod'd them; electron-builder's extraResources
preserves that mode into the packaged app; and resolveEngine checked only
existence (F_OK), so the un-runnable bundled engine permanently shadowed
perfectly good alternatives (the shared cache, <instancesDir>/engine/needle).

Fixes, layered so this class of bug cannot recur:

  • resolveEngine now checks executability (X_OK), not existence. A
    present-but-unexecutable candidate is skipped (never a hard stop), so a
    broken bundle falls through to the next runnable engine.
  • One-shot chmod recovery: a 0644 engine we own is fixed in place
    (chmod 0755 + re-probe) instead of skipped — covers curl -o, zip/tar
    extraction, and copy flows that drop the exec bit.
  • EACCES at spawn time is named, with the fix in the message
    (engine not executable (path) — restore the exec bit (chmod +x) or set neuralos.engineBin/engineWeights) instead of the cryptic
    engine exited EACCES: with a trailing colon and no stderr.
  • Exhausted-path errors now explain every failure: when no candidate is
    usable, the error lists the found-but-not-executable paths alongside the
    auto-download failure, so operators see why every route was exhausted.
  • Release workflow chmods the downloaded engines on all 4 platforms and
    the verify steps now assert test -x (mac + Linux) so an un-runnable
    engine can never ship again.

Also fixed in the same review (all error-as-data, no thrown exceptions):

  • defaultExec preserved a real EACCES code but reported timeout kills
    (SIGTERM from our own timeout) as a generic exit 1 — now reported as
    killed (SIGTERM) so timeouts are distinguishable from crashes.
  • truncate(undefined) crashed (JSON.stringify(undefined) is
    undefined, not a string) — now renders 'null' honestly.
  • graphProbe threw on a corrupt/non-array needle_menu.json instead of
    answering with an error — every other read path in the plugin already
    reports errors as data; this one now does too.

Spec: 9 new tests (section 12) — 0644-bundle skip, chmod recovery, EACCES
naming, non-EACCES crash shape, real-EACCES code preservation, timeout-kill
honesty, truncate(undefined), corrupt menu, non-array menu. 51 total.

Downloads

Platform File
macOS ARM64 RTerm-3.9.2-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.9.2-x64.exe
Windows x64 (Setup) RTerm.Setup.3.9.2-x64.exe
Linux x64 (AppImage) RTerm-3.9.2-x64.AppImage
Linux x64 (deb) RTerm-3.9.2-x64.deb
Linux x64 (pacman) RTerm-3.9.2-x64.pacman
Linux x64 (rpm) RTerm-3.9.2-x64.rpm
Linux ARM64 (AppImage) RTerm-3.9.2-arm64.AppImage
Linux ARM64 (deb) RTerm-3.9.2-arm64.deb
Linux ARM64 (rpm) RTerm-3.9.2-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng

RTerm v3.9.1

Choose a tag to compare

@DrOlu DrOlu released this 24 Sep 01:58

RTerm v3.9.1 — AI-Native Terminal App by Hyperspace Technologies

v3.9.1 (2026-09-24)

neuralOS is now visible in Settings → Plugins. The plugins tab renders a
fixed set of per-plugin settings panels, and neuralOS had none — the plugin
loaded (its four tools appear under Plugin tools) but had no settings form.
New panel: instances root, python interpreter, engine binary/weights overrides,
auto-provisioning toggle, cache dir, timeout, plus an Enabled switch the
plugin now honors (neuralos.enabled=false registers zero tools). Blank
fields fall back to the bundled engine → shared cache → <instancesDir>/engine.

Also: settings-block enable gate in the neuralos plugin (spec 42 tests).

Downloads

Platform File
macOS ARM64 RTerm-3.9.1-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.9.1-x64.exe
Windows x64 (Setup) RTerm.Setup.3.9.1-x64.exe
Linux x64 (AppImage) RTerm-3.9.1-x64.AppImage
Linux x64 (deb) RTerm-3.9.1-x64.deb
Linux x64 (pacman) RTerm-3.9.1-x64.pacman
Linux x64 (rpm) RTerm-3.9.1-x64.rpm
Linux ARM64 (AppImage) RTerm-3.9.1-arm64.AppImage
Linux ARM64 (deb) RTerm-3.9.1-arm64.deb
Linux ARM64 (rpm) RTerm-3.9.1-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng

RTerm v3.9.0

Choose a tag to compare

@DrOlu DrOlu released this 24 Sep 01:08

RTerm v3.9.0 — AI-Native Terminal App by Hyperspace Technologies

v3.9.0 (2026-09-24)

neuralOS native — on-device data agents as first-class RTerm tools, bundled.

A new official plugin, neuralos, wires the neuralOS instances
(~/neuralos-instances — verified probe menus over real data sources) into
the agent as four tools: neuralos_list_instances, neuralos_ask
(plain-English question -> the 121M on-device engine selects the probe, the
instance bridge executes it, a verified digest comes back), neuralos_graph
(relationship maps, executed directly by probe name), and neuralos_admin
(write probes behind a confirm="yes" interlock). Settings block neuralos
(instancesDir, pythonBin, engineBin/engineWeights, autoDownload); config also
via NEURALOS_* env.

True install-and-nothing-else, on every channel:

  • Desktop: the engine binary + 35 MB needle3.cact weights are
    downloaded at build time and shipped inside every installer (macOS ARM64,
    Windows x64, Linux x64 + ARM64) at <resources>/neuralos/ — a build-time
    verify gate fails the release if the bundle is missing.
  • npm (rterm-backend + neuralos, the same package under both names):
    the plugin auto-provisions ~/.cache/neuralos on first use — one ~36 MB
    fetch from the public Cactus-Compute/needle3 release, then offline
    forever. Publishing is now a first-class release-workflow job (was manual).

Also new: the npm publish pipeline (scripts/publish-npm.mjs +
scripts/npm-package.template.json) assembles the standalone backend into
the published layout (bin/gybackend.cjs + plugins/ + README) and publishes
both names at the repo version, driven by the NPM_TOKEN secret.

Downloads

Platform File
macOS ARM64 RTerm-3.9.0-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.9.0-x64.exe
Windows x64 (Setup) RTerm.Setup.3.9.0-x64.exe
Linux x64 (AppImage) RTerm-3.9.0-x64.AppImage
Linux x64 (deb) RTerm-3.9.0-x64.deb
Linux x64 (pacman) RTerm-3.9.0-x64.pacman
Linux x64 (rpm) RTerm-3.9.0-x64.rpm
Linux ARM64 (AppImage) RTerm-3.9.0-arm64.AppImage
Linux ARM64 (deb) RTerm-3.9.0-arm64.deb
Linux ARM64 (rpm) RTerm-3.9.0-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng

RTerm v3.8.9

Choose a tag to compare

@DrOlu DrOlu released this 18 Sep 19:44

RTerm v3.8.9 — AI-Native Terminal App by Hyperspace Technologies

v3.8.9 (2026-09-18)

Four fixes for the extended-chat freeze family and session durability — all
found by reading the actual code paths, three of them live-observed.

The MemorySaver checkpoint leak — the real extended-chat freeze root cause

LangGraph's MemorySaver keeps every checkpoint of every graph step,
forever
: storage[threadId][ns][checkpoint.id] holds a serialized copy of
the full conversation state per step. A 100-step multi-tool run retains
~100 copies in RAM — unbounded growth, GC thrash, and the "app freezes in
extended chats until force-quit" behavior. The earlier pruning work (v3.8.3)
shrank each blob but never evicted old blobs; the count kept climbing.

SafeMemorySaver now evicts: after each put it keeps only the newest
8 checkpoints per (thread, ns), enforced on all three put paths (normal,
OOM-retry, skip-persist). Insertion order is tracked per (thread, ns) since
MemorySaver exposes no timestamps; untracked ids (from before this process)
are kept rather than risk dropping the resume point. Safe because LangGraph
resumes from the latest checkpoint and parent-chain walking touches only
recent entries.

Interruption marker — force-quit recovery for chat sessions

A force quit mid-run leaves the session's last AI message partial, but
stored looking exactly like a completed turn. After restart the model reads
it as complete and treats the next message as a fresh topic — the
interrupted task is silently abandoned.

Now a run marker (in the history_meta table, survives restart) is set
just before graph.invoke and cleared in the run's finally block. Only a
hard kill skips finally, so a leftover marker means the run was
interrupted; the next run detects it, injects a system notice telling the
model the prior response may be partial (with the interrupted task's input
preview), and offers to continue rather than start from scratch.

Ordering bug caught in review before release: the marker was initially
set before the detection block — every run found its own marker, injected
a false notice, and consumed the real one, so a genuine force-quit left
nothing behind. The feature was inverted. The set now happens after the
restore path has consumed any leftover marker.

Rename race — renames reverted by the run-end save

Renaming a chat session during a running agent task silently reverted when
the task finished: the agent's in-memory session object carried the old
title from run start, and the store's upsert (title = excluded.title)
wrote it back over the rename at run end. ChatHistoryService.saveSession
now treats the stored title as authoritative for an existing session —
the in-memory title only names a brand-new session. Same discipline the
store already applied to created_at, which is why creation dates never
had this bug.

Also

  • Dead code documented: lastCheckpointOffset is written on every run but
    has no reader — the v3.2.5 "recovery can resume from this offset"
    promise was never built. Left in place (harmless) pending a real consumer.
  • GatewayService.resumeTask remains an empty stub.

Tests

  • safeMemorySaverEviction.extreme.spec.ts (6) — retention window, per-thread
    isolation, getTuple resolves newest after eviction, deleteThread, and the
    control: vanilla MemorySaver retains all 50 (the leak), SafeMemorySaver caps.
  • runMarker.extreme.spec.ts (7) — marker survives store close+reopen (the
    force-quit case), per-session isolation, corrupt marker reads as absent,
    consume-once semantics.
  • renameRace.extreme.spec.ts (4) — the exact live race: load → rename
    mid-run → save the stale object → the rename survives.
  • All wired into test:backend-unit-extreme.

Downloads

Platform File
macOS ARM64 RTerm-3.8.9-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.8.9-x64.exe
Windows x64 (Setup) RTerm.Setup.3.8.9-x64.exe
Linux x64 (AppImage) RTerm-3.8.9-x64.AppImage
Linux x64 (deb) RTerm-3.8.9-x64.deb
Linux x64 (pacman) RTerm-3.8.9-x64.pacman
Linux x64 (rpm) RTerm-3.8.9-x64.rpm
Linux ARM64 (AppImage) RTerm-3.8.9-arm64.AppImage
Linux ARM64 (deb) RTerm-3.8.9-arm64.deb
Linux ARM64 (rpm) RTerm-3.8.9-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng

RTerm v3.8.8

Choose a tag to compare

@DrOlu DrOlu released this 18 Sep 12:14

RTerm v3.8.8 — AI-Native Terminal App by Hyperspace Technologies

v3.8.8 (2026-09-18)

New: inbound invoke — mesh peers can now drive RTerm's agent

Found live: the ReactorPro manifest advertised an invoke skill, but
defaultServeSkills had no handler for it — a peer dispatching invoke got
SKILL_NOT_FOUND while the manifest promised "invoke routes a prompt into a
real RTerm agent turn". RTerm could call other agents but couldn't be
usefully called by them.

invoke is now real. A mesh peer sends a prompt; RTerm runs it as a
genuine agent turn — tools, command policy, and the audit ledger all
apply — and the final assistant text goes back over the mesh.

  • New runAgentTask PluginContext hook — one real agent turn, resolve
    with the final answer. Wired on the daemon and desktop; absent in bare
    test harnesses, where invoke returns a clear INVOKE_UNAVAILABLE error
    instead of pretending.
  • Prompt extraction accepts arguments.prompt (the gateway's shape),
    prompt, text, message, or a bare string.
  • conversation_id round-trips — a peer that passes the previous
    reply's conversation_id continues the same agent session.
  • Budget-aware — the agent turn is capped at dispatchTimeout − 10s
    (default 170 s) so the reply reaches the caller before its own mesh
    dispatch timeout fires.

Two live-found details worth recording:

  • say events are deltas, not full text. The first implementation
    captured only the last say event and "PONG" came back as "ONG" — the
    final streamed fragment. The publisher-chaining hook now accumulates
    say deltas in order; the concatenation is the answer.
  • The event publisher is chained, not replacedsay events for the
    mesh-invoke session are captured while everything still passes through to
    the gateway's broadcast unchanged, and the original publisher is restored
    in finally.

Live-verified end to end: a Synapse-convention dispatch of invoke to
RTerm's inbox now returns a real agent answer (previously SKILL_NOT_FOUND),
and RTerm → grip-cli-001 invoke returns a real LLM reply (previously
verified; unchanged).

Spec: 10 new inbound-invoke cases (prompt extraction, conversation
persistence, budget clamping, unavailable-runtime degradation).

Downloads

Platform File
macOS ARM64 RTerm-3.8.8-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.8.8-x64.exe
Windows x64 (Setup) RTerm.Setup.3.8.8-x64.exe
Linux x64 (AppImage) RTerm-3.8.8-x64.AppImage
Linux x64 (deb) RTerm-3.8.8-x64.deb
Linux x64 (pacman) RTerm-3.8.8-x64.pacman
Linux x64 (rpm) RTerm-3.8.8-x64.rpm
Linux ARM64 (AppImage) RTerm-3.8.8-arm64.AppImage
Linux ARM64 (deb) RTerm-3.8.8-arm64.deb
Linux ARM64 (rpm) RTerm-3.8.8-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng

RTerm v3.8.7

Choose a tag to compare

@DrOlu DrOlu released this 18 Sep 10:26

RTerm v3.8.7 — AI-Native Terminal App by Hyperspace Technologies

v3.8.7 (2026-09-18)

Fixed: ReactorPro gateway dropped RTerm from mesh discovery

Three wire-shape bugs in the reactorpro-bridge plugin made RTerm
invisible to ReactorPro gateway discovery — even though every envelope
signature verified correctly.

  1. identity vs id — the manifest advertised identity: where the
    gateway's Manifest struct unmarshals json:"id". The gateway's
    manifestMatches drops a manifest whose ID is empty, so every manifest
    RTerm published was discarded at the filter: signed correctly, silently
    dropped.
  2. Skills as bare strings — the gateway's Skill struct unmarshals
    []{id,name,description} objects; bare strings became empty entries,
    breaking skill_id discovery filters.
  3. Payload nesting — register/discover payloads were wrapped under
    {manifest: {...}}, but the gateway attaches the bare manifest. The
    plugin's reply parser now accepts all three shapes the wire actually
    carries: bare manifest, {agents:[...]}, and the legacy nested form.

Live-verified both directions against the real gateway:

  • RTerm discoverPeers → the gateway answers (reactorpro/bionic-01)
  • The gateway's own Go discovery (TestRtermBridgeReverseDiscover,
    RTERM_BRIDGE_LIVE=1) → lists reactorpro/rterm-01 alongside
    grip-001, agentspan-001, grip-cli-001, omp-cli-001

Spec: 39/39 — 11 new manifest-shape cases pin the gateway's struct
contract (id key, skills as objects, bare-manifest payloads) so this
class of bug is loud instead of silent.

The lesson: a signature verifies bytes, not semantics. The signing
cross-verify passed while discovery was broken — interop contracts need a
test per direction per semantic layer.

Downloads

Platform File
macOS ARM64 RTerm-3.8.7-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.8.7-x64.exe
Windows x64 (Setup) RTerm.Setup.3.8.7-x64.exe
Linux x64 (AppImage) RTerm-3.8.7-x64.AppImage
Linux x64 (deb) RTerm-3.8.7-x64.deb
Linux x64 (pacman) RTerm-3.8.7-x64.pacman
Linux x64 (rpm) RTerm-3.8.7-x64.rpm
Linux ARM64 (AppImage) RTerm-3.8.7-arm64.AppImage
Linux ARM64 (deb) RTerm-3.8.7-arm64.deb
Linux ARM64 (rpm) RTerm-3.8.7-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng

RTerm v3.8.6

Choose a tag to compare

@DrOlu DrOlu released this 18 Sep 00:06

RTerm v3.8.6 — AI-Native Terminal App by Hyperspace Technologies

v3.8.6 (2026-09-18)

ReactorPro Mesh Bridge settings panel (desktop Settings UI)

The reactorpro plugin shipped in 3.8.5 with its backend settings wiring
complete but no Settings panel — configuration was only reachable via
settings:set or by asking the agent. This closes that gap: the desktop
Settings view now shows a ReactorPro Mesh Bridge panel (enabled, NATS
URL, mesh prefix, agent id, display name, identity file, auto-serve),
following the same generic plugin-panel pattern as webIntel / nats /
synapse / numbat / monid. Blank fields are omitted on save so server
defaults apply.

The two fields that deserve warnings carry them in the UI:

  • agent id — PERMANENT once an identity exists. It is hashed into the
    fingerprint; changing it means a new identity peers must re-pin.
  • identity file — minted on first use (0600). Back it up: losing it means
    peers that pinned the old fingerprint will refuse this instance.

Settings round-trip guard

New test pins the v3.1.3 lesson for this block: the reactorpro settings
block must survive save+reload. It shipped with the pickBackendSnapshot
whitelist key, but a future refactor of that list would have silently wiped
it — now that regression is loud instead of silent. Settings migrations
spec: 23/23.

Downloads

Platform File
macOS ARM64 RTerm-3.8.6-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.8.6-x64.exe
Windows x64 (Setup) RTerm.Setup.3.8.6-x64.exe
Linux x64 (AppImage) RTerm-3.8.6-x64.AppImage
Linux x64 (deb) RTerm-3.8.6-x64.deb
Linux x64 (pacman) RTerm-3.8.6-x64.pacman
Linux x64 (rpm) RTerm-3.8.6-x64.rpm
Linux ARM64 (AppImage) RTerm-3.8.6-arm64.AppImage
Linux ARM64 (deb) RTerm-3.8.6-arm64.deb
Linux ARM64 (rpm) RTerm-3.8.6-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng

RTerm v3.8.5

Choose a tag to compare

@DrOlu DrOlu released this 17 Sep 23:23

RTerm v3.8.5 — AI-Native Terminal App by Hyperspace Technologies

v3.8.5 (2026-09-17)

New plugin: reactorpro-bridge — full-duplex ReactorPro mesh citizen

Makes RTerm a first-class verified peer on a ReactorPro mesh. ReactorPro
desktops and edges see RTerm like one of their own — signatures check, the
fingerprint binds, gated invoke included.

  • Discover live mesh peers and their manifests; dispatch signed tasks;
    register with the mesh registry; and — the half that matters — serve
    inbound requests on mesh.agent.{id}.inbox (auto-started), so other agents
    can call RTerm, not just be called by it. Signed heartbeats keep the peer
    alive in the directory.
  • Speaks the ReactorPro wire convention (sig/pub/fp Ed25519, v0.3.0 envelopes)
    over a shared NATS server — the same convention the ReactorPro gateway
    enforces. The signing layer mirrors the gateway's identity.go
    byte-for-byte: length-prefixed field digest over
    v,id,type,ts,from,to,task_id,in_reply_to,fp,[trace],[error] + sha256(payload);
    fingerprint = sha256(agentID + "\n" + raw_pubkey)[:16].
  • 9 tools (reactorpro_health/discover/dispatch/invoke_edge/register/ agents_summary/serve/serve_status/identity), the reactorpro_mesh_event
    trigger, and a reactorpro-mesh-peers panel.
  • Identity is minted once and persisted (0600). The agent id is permanent —
    it is hashed into the fingerprint, so changing it means a new identity peers
    must re-pin. A tampered identity file is rejected on load.
  • Settings: new reactorpro block (url/servers/prefix/agentId/name/
    identityPath/capabilities/auth incl. secretRefs/autoServe/dispatchTimeout),
    with ReactorProSettings + normalizeReactorProSettings + the snapshot
    whitelist key — a settings block missing from that whitelist is silently
    wiped on save (the v3.1.3 lesson, applied up front this time).

Cross-verified against the real Go gateway (rterm_crossverify_test.go):
the plugin's signed envelope passes the gateway's VerifyEnvelope, the
fingerprint binds to the claimed sender, SigningPayload matches
byte-for-byte, and the gateway's own signed envelope verifies under the
plugin's rules. 28/28 spec cases.

Fixture-fidelity fix (found live during that cross-verify)

The cross-verify fixture is now written compact. The gateway's
Envelope.Payload is a json.RawMessage, which captures payload bytes
verbatim from the file — a pretty-printed fixture made the gateway re-hash
different bytes than were signed (whitespace changed the digest) and fail,
even though the real wire exchange was correct all along. The fixture is now
byte-faithful to the wire, with a comment explaining why.

Downloads

Platform File
macOS ARM64 RTerm-3.8.5-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.8.5-x64.exe
Windows x64 (Setup) RTerm.Setup.3.8.5-x64.exe
Linux x64 (AppImage) RTerm-3.8.5-x64.AppImage
Linux x64 (deb) RTerm-3.8.5-x64.deb
Linux x64 (pacman) RTerm-3.8.5-x64.pacman
Linux x64 (rpm) RTerm-3.8.5-x64.rpm
Linux ARM64 (AppImage) RTerm-3.8.5-arm64.AppImage
Linux ARM64 (deb) RTerm-3.8.5-arm64.deb
Linux ARM64 (rpm) RTerm-3.8.5-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng

RTerm v3.8.4

Choose a tag to compare

@DrOlu DrOlu released this 12 Sep 12:43

RTerm v3.8.4 — AI-Native Terminal App by Hyperspace Technologies

v3.8.4 (2026-09-12)

history:search no longer freezes the app

The gateway's history:search called getAllSessions(), which JSON.parses
every message of every session in one synchronous burst
before comparing a
single character. On a 1.6 GB multi-session store that is seconds of blocked
event loop — and because better-sqlite3 is synchronous and runs on the same
thread, the whole UI froze while searching.

Searching is now bounded: searchChatHistoryBounded() reads one session,
searches it, releases it, then yields to the event loop before the next.
Peak memory becomes one session instead of the whole store, and the loop is
blocked for one session at a time instead of all of them.

  • New searchBounded() on the gateway's history bridge; the history:search
    handler prefers it and falls back to getAllSessions() when absent (e.g. the
    desktop app's in-memory bridge), so behaviour stays correct either way.
  • listChatSessions() is now documented as a freeze hazard: it parses every
    message of every session and is only for genuinely whole-store work. Callers
    that need a session list use listChatSessionSummaries() (COUNT only).

Deterministic model errors fail fast (retries were pure latency)

invokeWithRetry retried every non-abort error, so a truncated response or
a code bug burned 4 attempts plus ~13 s of backoff and then failed anyway, with
"Retrying (3/4)…" shown in the UI the whole time.

Only genuinely transient failures retry now: network/socket errors, timeouts,
429, and 5xx. Deterministic errors (4xx, truncation, malformed payloads) fail
fast with the real reason.

The subtle part is that an empty response has two very different causes that
arrive as the same thrown message:

Model stream ended with an empty unusable response (finish_reason=X).
finish_reason Cause Behaviour
error provider-side, often transient retry
length truncated answer, repeats fail fast
content_filter policy block, repeats fail fast

The classifier splits on the finish reason rather than the wording. (An earlier
revision matched the blanket substring "finish_reason=" and killed the
provider-error retry, which a behavioural spec asserts must happen.)

Fixed: "lengthlength" finish reason garble

getRawFinishReason read choice.finish_reason from langchain chunks, whose
streamed value can be a concatenation of every chunk's reason — a streamed
response ending with finish_reason: "length" produced "lengthlength", which
rendered into errors, logs and the UI as "lengthlength, length".

normalizeFinishReason() collapses a value that is exactly a known reason
repeated 2–5 times back to the canonical token. Detection is deliberately
conservative: an unrecognised provider string is returned untouched, so no
canonical value is invented.

Tests

  • historySearchBounded.extreme.spec.ts (7 cases) — loads one session at a
    time, yields to the event loop, preserves ranking/limit/truncated semantics,
    skips a session deleted between summary and load.
  • runtimeRetry.extreme.spec.ts (9 cases) — pins the finish-reason split,
    abort behaviour, transient retries, and deterministic fail-fast.
  • Both wired into test:backend-unit-extreme.

Downloads

Platform File
macOS ARM64 RTerm-3.8.4-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.8.4-x64.exe
Windows x64 (Setup) RTerm.Setup.3.8.4-x64.exe
Linux x64 (AppImage) RTerm-3.8.4-x64.AppImage
Linux x64 (deb) RTerm-3.8.4-x64.deb
Linux x64 (pacman) RTerm-3.8.4-x64.pacman
Linux x64 (rpm) RTerm-3.8.4-x64.rpm
Linux ARM64 (AppImage) RTerm-3.8.4-arm64.AppImage
Linux ARM64 (deb) RTerm-3.8.4-arm64.deb
Linux ARM64 (rpm) RTerm-3.8.4-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng

RTerm v3.8.3

Choose a tag to compare

@DrOlu DrOlu released this 11 Sep 13:53

RTerm v3.8.3 — AI-Native Terminal App by Hyperspace Technologies

v3.8.3 (2026-09-11)

Incremental history save — the real freeze fix

saveChatSession ran DELETE ALL + INSERT ALL on every save, rewriting
the whole session payload. Measured on a 6,102-message / 116.9 MB session, the
old block cost 2.59 s per save, of which 1.50 s was JSON.parse alone
(SQLite I/O was only 0.07 s delete + 0.37 s insert + 0.65 s flush).

Saving is now incremental — only rows that actually moved are written:

  • New loadSessionMessageState() reads raw message_data_json without
    parsing
    (the parse was the expensive half and is unnecessary for an
    equality test).
  • applyChatSessionDelta() upserts only changed rows and deletes only absent
    ones (compaction / rollback), inside one transaction.
  • replaceAllMessages() handles the rare reorder case.

Two silent-staleness bugs fixed on the way in:

  • digestFor was a 200-char prefix fingerprint. A message whose body grows
    past character 200 — exactly what streaming does to the last AI message —
    kept an identical prefix, so the row was skipped and the persisted history
    silently stayed stale. It now fingerprints the full serialized body.
  • replaceAllMessages upserted in place, which collides on the
    (session_id, position) PRIMARY KEY during a reorder (UNIQUE constraint failed). Any chat reorder/branch would have crashed the save. It now clears
    the session's rows and re-inserts inside one transaction.

Two full-session reads removed from hot paths

ChatHistoryService.saveSession called loadChatSession() purely to learn
createdAt, and AgentService_v2.trySaveSessionFromCheckpoint called
loadSession() for a default it never used — each parse discarded immediately.
Both now read a single indexed row via the new getChatSessionMeta() /
getChatSessionCreatedAt(). The checkpoint path still preserves the session
title (a blank default would have renamed sessions to "New Session").

Tests

  • New HistorySqliteStore.delta.extreme.spec.ts (7 cases, wired into
    test:backend-unit-extreme): growth past char 200 reaches disk, no-op saves
    don't duplicate rows, append / remove / reorder / createdAt preservation,
    and emptying a session.
  • AgentSettingProfileService.extreme.spec.ts asserted the literal
    'standard' where the contract is "apply restores the saved value". The
    v3.8.2 default change (standard → smart) broke it; it now captures the saved
    value so it cannot rot again. v3.8.2 shipped with this spec failing.

Downloads

Platform File
macOS ARM64 RTerm-3.8.3-arm64.dmg
Windows x64 (Portable) RTerm.Portable.3.8.3-x64.exe
Windows x64 (Setup) RTerm.Setup.3.8.3-x64.exe
Linux x64 (AppImage) RTerm-3.8.3-x64.AppImage
Linux x64 (deb) RTerm-3.8.3-x64.deb
Linux x64 (pacman) RTerm-3.8.3-x64.pacman
Linux x64 (rpm) RTerm-3.8.3-x64.rpm
Linux ARM64 (AppImage) RTerm-3.8.3-arm64.AppImage
Linux ARM64 (deb) RTerm-3.8.3-arm64.deb
Linux ARM64 (rpm) RTerm-3.8.3-arm64.rpm

Install

macOS: After installing, run xattr -cr /Applications/RTerm.app to remove quarantine.

Linux AppImage: chmod +x RTerm-*.AppImage && ./RTerm-*.AppImage

Linux deb: sudo dpkg -i RTerm-*.deb

Linux rpm: sudo rpm -i RTerm-*.rpm


Contact: rterm@hyperspace.ng