Releases: tezra-io/fermix
Release list
v0.6.0
What's new in v0.6.0
Added
- Computer use no longer fights you for the cursor (coexistence). When the
agent is driving the host desktop and you start using the machine, it now yields
the seat instead of stealing the pointer mid-action. Before any disturbing action
(click, drag, scroll, mouse-move, type, key, paste) it checks how long you have
been idle and, if you are active, briefly waits in-turn for a pause, then either
proceeds or holds the action back and tells you so./pausehands the machine
back on demand (the session stays alive and resumable — unlike/stop, which
tears it down) and/resumecontinues. Controlled by[fermix_core.computer_use] courtesy(yielddefault,off) andcourtesy_idle_ms. Idle detection is
macOS-only; where it is unavailable the arbiter proceeds rather than blocking. - Image generation can run on a ChatGPT/Codex subscription (keyless). A new
openai_codeximage backend drivesgpt-image-2over the Codex subscription
endpoint — billed to the subscription, noOPENAI_API_KEY— mirroring how the
Codex chat provider works. Opt-in and connection-gated (never a fallback); a
missing/unentitled token fails loud. Selectable in the CLI wizard and web setup. - One-tap directory-grant approval, and the grant loop is multi-user safe. The
/confirmprompt renders as a tap-to-copy code span, and Telegram/Discord get a
native Approve button that synthesizes the exact confirm through the unchanged
origin-bound, single-use, TTL path. Grants are now strictly operator-only (never
reachable through the guest command allowlist),/confirmpeek-validates before
consuming so a wrong-origin attempt can't burn the owner's token, and a non-owner
button tap is refused before consumption. (Telegram + Discord; Slack deferred.) - Owner-approval directory access, and the sandbox lives where you do. Standard
mode now auto-allows the launch/request working directory (under your real home)
plus the workspace and explicit grants, and open mode is your home minus the
protected credential/OS/state dirs — the mode roots key off your OS home, not
FERMIX_HOME, so "works where I am" is finally true. A new
request_directory_access(path, reason)tool prompts the owner for an
out-of-roots path and, on/confirm, persists the grant and auto-resumes the
original request.fermix sandbox explainannotates each root as (granted) vs
(mode). - Voice notes are heard everywhere, on a pluggable speech-to-text backend (M21).
Milestone 21 makes voice-note transcription real, configurable, and channel-wide
(see the transcription entries below). Also replaces the old Groq backend with a
native SpaceXAI STT backend, and relabels user-facing "xAI" → "SpaceXAI" (display
only — the:xaiatom,XAI_API_KEY,api.x.ai, andgrok-*model ids are
unchanged, so existing configs keep working). - FermixPet is now its own notarized macOS app, and the realtime wire is
versioned. The voice companion moved totezra-io/fermix-macos(SwiftPM source,
notarized universal2 DMG + Homebrew cask). The daemon's realtime socket gained a
versioned hello-first handshake (N/N-1 window) so the pet and daemon can ship
independently, andfermix doctor/voice statusnow flag the OpenAI-Platform-key
requirement (a Codex/OAuth login does not authorize the Realtime API). - Every spawned OS process is group-reaped (subprocess lifecycle). External
commands now run under a centralCommandHostin their own process group and are
killed on exit, crash, or daemon shutdown (a newkill_pgidNIF), and cron jobs
can delegate. Closes the orphaned-subprocess class across git tools, subagents,
jobs, sandbox env, plugin probes, and realtime. fermix statusandfermix doctornow warn when the running daemon's
version differs from the installed binary. A package-manager upgrade
(brew upgrade fermix) swaps the binary on disk while the launchd/systemd
service keeps running the old release until restarted, and nothing surfaced
that skew — right after a brew upgrade, doctor's upgrade check even reported
"on the latest version" while the daemon was stale.fermix statusnow
appends a warning line and doctor's daemon-socket check degrades to a
warning, both naming the two versions and thefermix restartfix. The
fermix upgrademanaged-install refusal also tells you to restart after
running the package-manager command, and the README, wiki, and Homebrew
caveats now document the restart-after-upgrade requirement.- Telegram voice notes are transcribed. Inbound Telegram voice notes, audio
files, audio-MIME documents, and round video notes now parse to a transcribable
audio attachment and are transcribed to text like the other channels — closing
the gap where Telegram (the primary channel) extracted only photos and answered
a voice note with "your message looks empty." Video notes ride their MP4
container straight to the hosted backend (no ffmpeg). - A voice note with a caption transcribes both. When an audio attachment
arrives with a caption, the caption is kept and the transcript is appended under
a[voice note transcript]delimiter, instead of the caption suppressing
transcription entirely. - Transcription is now a backend-pluggable capability.
[fermix_core.transcription] backendselects the speech-to-text provider —openai,xai, ordeepgram—
resolved through a fail-loud registry that lists the valid names on an unknown
choice (the on-devicelocalbackend is reserved for a later phase and says so).
Each backend has its own optional API-key slot:openai_api_keyand
xai_api_keyOVERRIDE the reused chat-provider key (or fall through to it if
unset), while Deepgram (nova-3, batch; no chat provider to reuse) requires its
deepgram_api_key. SpaceXAI's native/v1/sttis modelless (no model to pick)
and requires an API key — the Grok subscription OAuth token does not work for
STT, so paste one when your SpaceXAI provider is on OAuth. Every backend routes
its HTTP round-trip through the shared[:fermix, :provider, :call]telemetry
emitter (purpose: :transcription, no token cost), and a missing key fails loud
rather than degrading silently. - Transcription is now configurable through setup.
[fermix_core.transcription]
is a first-classconfig.tomlsection (backend,model, per-backend
openai_api_key/xai_api_key/deepgram_api_key,max_file_mb) with an unknown
key/backend/max_file_mbfailing config load loudly. The web-setup Transcription
card (moved to right after Channels) shows an API-key field for the selected
backend (all three ride secure-on-save to the OS keyring), plus a per-backend
model dropdown. Set it from the card, or withfermix setup --transcription-backend/--transcription-model/--transcription-api-key(the
generic key flag stores under the currently-selected backend's slot); switching
backend snaps the single sharedmodelto that backend's default so Deepgram
never inherits the OpenAI-shaped model (SpaceXAI is modelless and sends none).
fermix doctorgains atranscriptionrow that reports the active backend and
whether its credential resolves (offline — it never transcribes).
Changed
- GPT-5.6 (Sol, Terra, Luna) context window corrected to 272k (carried
forward from 0.5.8). The catalog listed the 5.6 generation at 372k; the
effective window is 272k on both the Codex (ChatGPT subscription) and OpenAI
direct-API paths. Auto-compaction thresholds, forced/compactbudgets, and the
fermix doctorcontext report key off the corrected value; the oldergpt-5.5/
gpt-5.4/gpt-5.4-miniwindows are unchanged. - Live-voice replies are quieter and shorter. The realtime seed no longer
licenses pre-announcing or narrating tool use ("act and lead with the result; a
slow action stays silent until you have the answer"), and the default length
tightened to one sentence, two at most — the "or multi-step" clause had made
narration the default rather than the exception (computer-use especially). - Built-in tool triggers lead with when to act, not just when not to. The
when_to_useforweb_search/web_fetch/subagents/memory_recallnow opens
with the affirmative trigger (the answer is current/changing, you already have
the URL, the request fans out, it may depend on stored facts) before its routing
exclusions — the documented lever for should-call rate on tool-conservative models. - Time-sensitive facts are grounded before answering from memory. A broad
"Verify, Don't Guess" principle now covers changeable external facts (rates,
figures, standings), not just local machine/repo state — verify with a tool
before answering, however sure the model feels. (Raised the capability-eval
web-research fire rate 32% → 68% with no query changes.) - The agent holds an evidence-backed answer under pushback. A new "Pushback
Gets Diligence, Not Deference" rule: re-check before conceding a challenge,
reconcile an apparent contradiction rather than capitulating, and change the
answer only when evidence changes it — confidence tracks evidence in both
directions, no caving and no digging in. - The default transcription model is now
gpt-4o-mini-transcribe(was the
legacywhisper-1) — better accuracy on the same OpenAI endpoint. Set
[fermix_core.transcription] modelto pin a different model.
Fixed
- Voice calls no longer freeze after a computer-use (or any slow) tool run.
The realtimeSessionServeris now a non-blocking coordinator — tool calls run
off the session loop on a supervised task, so mic audio, interrupts, and stop
keep flowing while a tool runs — and the connection handler owns its socket so
the pet always sees EOF on teardown. (Fixes a four-defect deadlock chain that
wedged ...
v0.5.8
What's new in v0.5.8
Changed
- GPT-5.6 (Sol, Terra, Luna) context window corrected to 272k. The catalog
listed the 5.6 generation at 372k; the effective window is 272k on both the
Codex (ChatGPT subscription) and OpenAI direct-API paths, which still serve
the same window for this generation. Auto-compaction thresholds, forced
/compactbudgets, and thefermix doctorcontext report now key off the
corrected value. The oldergpt-5.5/gpt-5.4/gpt-5.4-miniwindows are
unchanged.
Verifying signatures
Each binary is signed with cosign using GitHub Actions OIDC keyless signing. Verify a download with:
cosign verify-blob \
--certificate fermix_<target>.pem \
--signature fermix_<target>.sig \
--certificate-identity-regexp "https://github.com/tezra-io/fermix/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
fermix_<target>The releases.json artifact lists every binary's URL, sha256, and signature URLs.
v0.5.7
What's new in v0.5.7
Added
fermix doctor's Computer Use check now names the compux sidecar version.
The check reported permission state but never which screen-capture sidecar build
is installed, so there was no one-glance way to confirm it after a bump. The
probed result now appends· sidecar compux v<vsn>, and the not-installed
warning names the target version — sourced from the samecompuxapp version
the daemon resolves the helper by.
Fixed
- Sub-agents now run on your primary provider unless you pin one explicitly.
A sub-agent model set without an explicit provider resolves on the primary
provider, instead of being silently re-routed to whichever provider's catalog
happens to own the model slug. Previously a leftover sub-agent model from a
different provider (e.g. agpt-osspin — an Ollama model — kept after
switching your main provider to Codex) quietly ran delegated workers on that
other provider rather than your main model; if that provider wasn't running,
the spawn failed. The setup page's Sub-agent model picker also no longer
surfaces such a stale cross-provider model as the "current" value on the
primary pane — it shows "Same as main model" and self-heals on the next save.
To run sub-agents on a non-primary provider, setsubagent_providerexplicitly
in[fermix_core.routing]. fermix stop/restart/upgradenow force-kill a daemon that won't shut down,
andupgradeverifies the daemon came back on the new version. The service
commands sent a singlelaunchctl kill TERMand reported success the instant
launchd accepted the signal — not when the process actually died. A daemon whose
orderly shutdown stalled (a draining agent turn, an open Computer Use session, a
hung socket) could survive an "upgrade" silently: the on-disk binary was the new
version while the old BEAM kept running, and every command reported green. Stop
now captures the job pid, waits a bounded grace for that exact process to exit,
escalates to SIGKILL if it stalls, and fails loud (with akill -9/reinstall
hint) only if even that leaves it alive. The post-restart upgrade health check
now asserts the daemon reports the new version (semver compare against
manifest.latest) rather than merely{"status":"ok"}, so a stale daemon
triggers rollback instead of a false green. Linux/systemd was never affected
(its defaultTimeoutStopSecalready guarantees SIGKILL).
Verifying signatures
Each binary is signed with cosign using GitHub Actions OIDC keyless signing. Verify a download with:
cosign verify-blob \
--certificate fermix_<target>.pem \
--signature fermix_<target>.sig \
--certificate-identity-regexp "https://github.com/tezra-io/fermix/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
fermix_<target>The releases.json artifact lists every binary's URL, sha256, and signature URLs.
v0.5.6
What's new in v0.5.6
Added
- GPT-5.6 models (Sol, Terra, Luna) are now in the OpenAI and Codex catalogs.
gpt-5.6-sol(frontier),gpt-5.6-terra(balanced), andgpt-5.6-luna(fast,
affordable) are selectable in the setup wizard and web pane, andgpt-5.6-sol
is now the default model for both the OpenAI (API-key) and Codex (ChatGPT
subscription) providers on a fresh install. All three carry a 372k context
window on both access paths (the Codex path and the direct API report the same
window for this generation). Existing installs that pin adefault_modelare
unaffected; the earliergpt-5.5/gpt-5.4/gpt-5.4-minimodels remain
available. maxreasoning effort is now available for the GPT-5.6 family on OpenAI and
Codex.maxis a gpt-5.6-family capability, so setup offers it only when the
selected model is a 5.6 model; gpt-5.5/gpt-5.4/gpt-5.4-mini top out atxhigh.
Each model carries its effort ceiling in the catalog, and an over-reaching
config or routing override self-heals down to the model's ceiling at route
resolution (e.g.maxon gpt-5.5 runs asxhigh) instead of failing at the
provider.- Grok 4.5 is now in the xAI catalog and is the default Grok model.
grok-4.5(1M context window, accepts reasoning effort) leads the xAI model
list, so a fresh xAI setup defaults to it;grok-4.3and the other Grok
models remain available.
Fixed
- macOS keychain secrets no longer trigger repeated login-password prompts.
Secrets were stored withsecurity add-generic-password -U -A, but the open
ACL (-A) only takes effect when an item is created — on an update it left a
pre-existing item's restrictive ACL in place, so any item first written without
-A(an older Fermix, a manual Keychain entry, or a past "Always Allow") made
the daemon's headless reads prompt for the login keychain password on every
access. Each save now deletes the item before re-adding it, so the open ACL
always applies and the item self-heals; re-runfermix setuponce to rewrite
existing items in a single pass.
Verifying signatures
Each binary is signed with cosign using GitHub Actions OIDC keyless signing. Verify a download with:
cosign verify-blob \
--certificate fermix_<target>.pem \
--signature fermix_<target>.sig \
--certificate-identity-regexp "https://github.com/tezra-io/fermix/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
fermix_<target>The releases.json artifact lists every binary's URL, sha256, and signature URLs.
v0.5.5
What's new in v0.5.5
Fixed
- Computer Use permissions now attribute to one stable, signed "Fermix" app on
macOS. The screen-capture sidecar used to inherit the ad-hoc, per-version
identity of the daemon that launched it, so macOS Screen Recording /
Accessibility grants never persisted — every screenshot re-prompted, and each
upgrade left a new "Fermix" row in System Settings. The sidecar now runs as its
own Developer-ID-signed, notarizedFermix.app(a permanent bundle identity)
that disclaims TCC responsibility from its parent, so a grant sticks across
upgrades and every macOS permission Fermix needs — Screen Recording,
Accessibility, and the voice companion's Microphone — shows as a single
Fermix app with its icon. The setup Plugins page gains a Grant macOS
permissions button that raises the prompts up front (and registers the app in
System Settings) instead of surprising you on the first screenshot.- Upgrading from a pre-release build: if Computer Use reports a missing
permission even though the "Fermix" box looks checked, a stale grant from the
old build is shadowing the signed one — remove the "Fermix" row under System
Settings ▸ Screen Recording (or runtccutil reset ScreenCapture io.tezra.fermix.computer-use) and grant again. First-time installs are
unaffected. - Icon cache: the new row may briefly show a generic icon until macOS
refreshes its icon cache (a relogin, orkillall Dock).
- Upgrading from a pre-release build: if Computer Use reports a missing
- Upgraded voice configs with any official OpenAI voice no longer crash the
daemon. 0.5.4 validated the Realtimevoiceagainst only the four curated
dropdown options (marin/sage/verse/cedar), but earlier Fermix accepted any
voice — so a config carryingalloy,echo, or another official voice raised
during config normalization, which runs on both setup render and daemon
boot/readiness. Validation now accepts the full official OpenAI voice set
(alloy, ash, ballad, coral, echo, sage, shimmer, verse, marin, cedar); the
setup dropdown still lists the recommended voices first. - The setup page reconnects itself after "Apply & restart". Restarting the
daemon from the setup UI briefly stops the web server; the page had relied on
LiveView's default reconnect, which could strand the browser on a terminal
"can't connect" error during the few seconds of downtime — even though the
daemon comes back fine (the setup session survives becausesecret_key_base
is persisted, not regenerated per boot). The "Restarting…" overlay now waits
for the daemon to go down and come back, then reloads, so the page returns on
its own instead of needing a manualfermix setup. - OAuth tokens refresh proactively, and a rotated refresh token is never
reused. The daemon refreshed tokens only lazily — on use, within 10 seconds
of expiry, with no background timer — and refreshed from an in-memory copy of
the refresh token. If that token was rotated out-of-band (by afermix doctor/setup auth probe, or a second daemon on the same account), the daemon
could reuse the now-consumed token, and providers like Codex invalidate the
entire session when a rotated refresh token is reused ("your session has
ended").TokenManagernow (a) schedules a single proactive refresh a few
minutes before expiry — one timer per token, no polling — so an idle daemon
keeps its token warm, and (b) always refreshes from the latest token persisted
on disk, so a rotated token is never reused. Recovery from an already-ended
session is stillfermix auth login.
Verifying signatures
Each binary is signed with cosign using GitHub Actions OIDC keyless signing. Verify a download with:
cosign verify-blob \
--certificate fermix_<target>.pem \
--signature fermix_<target>.sig \
--certificate-identity-regexp "https://github.com/tezra-io/fermix/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
fermix_<target>The releases.json artifact lists every binary's URL, sha256, and signature URLs.
v0.5.4
What's new in v0.5.4
Fixed
- Hung skill and shell commands are fully terminated instead of leaking. A
command that spawned a subprocess (a skill runningpython/node/uv) and
then timed out had only its direct shell child killed — the grandchild was
orphaned to the operating system and kept running, in one case for days at
high CPU. The command runner now signals the whole process group, so every
descendant is reaped with the timeout. - The installed daemon no longer runs at background CPU priority. Its
service definition requested macOS'sBackground(darwinbg) QoS band, which
throttles the daemon and everything it spawns whenever the machine is under
load — so the setup page, keychain reads, and restarts crawled in the
brew-installed daemon while the foreground development process (unthrottled)
stayed fast under the same load. The service now runs atStandardpriority;
the change reconciles onto an already-installed unit on the nextfermix setup. fermix restartandfermix upgradeno longer hard-kill the daemon. They
kicked the service with launchctl's-k(an immediateSIGKILL) and the unit
had no shutdown grace, so a restart could kill the daemon mid-drain and — with
KeepAlive — bounce it in a relaunch loop (the setup page appearing to "keep
reloading"). Restart is now a gracefulSIGTERMplus a shutdown-timeout
headroom, so in-flight work drains first.- A permanently-unreachable MCP server no longer respawns forever. After a
server exhausted its discovery retries and logged "giving up", it was
immediately restarted and tried again — an endless loop that spawned a new
helper process every few seconds. A server that gives up is now quarantined
until the next configuration or plugin change, while a genuine transport blip
still reconnects. - The setup page no longer reads the OS keychain to build its prompts.
Prompt building resolved every stored secret from the keychain on each page
load, though it only needs to know whether each secret is present. It now
tests presence without resolving, removing another batch ofsecurity
subprocesses from the setup path. - A wedged host runtime can no longer hang the setup page. The probe that
runs<runtime> --version(for plugins that neednode/pythonon the host)
had no timeout; a stuck runtime blocked the page render indefinitely. The
probe is now bounded and reaps a stuck process.
Added
- The voice companion's model, voice, and reasoning effort are now selectable
in setup. The web setup Voice pane has dropdowns for the Realtime model
(gpt-realtime-2.1-mini,gpt-realtime-2.1,gpt-realtime-2), the voice
(Marin, Sage, Verse, Cedar), and a new reasoning effort setting
(minimal/low/medium/high/xhigh). Reasoning effort is sent on the
OpenAI Realtimesession.update([fermix_core.realtime] reasoning_effort,
defaultlow— OpenAI's recommended starting point for a voice agent); it was
previously left to the API default. The model/voice/effort option lists have a
single source of truth (FermixCore.Realtime.Config) that both the config
validator and the setup dropdowns read.
Changed
- The realtime voice is now chosen from a dropdown (Marin, Sage, Verse,
Cedar) instead of a free-text field, and the config validates the voice
against that list. - The default live-voice instructions (
REALTIME.md) were rewritten to
OpenAI's realtime prompting guidelines. Labeled sections and tighter rules:
lead with the answer in one or two sentences, no filler openers, and no
trailing "anything else?" / "let me know if you want more" offers; a
truthfulness rule (report only what a tool actually returned, say plainly when
one fails, never present a guess as fact); an explicit act-by-default stance
that still confirms by voice only before irreversible actions; and a rule to
look up current or changeable facts (news, live results, prices, schedules)
with a tool instead of answering from stale training data. Ships as the seeded
default for new setups; an existingREALTIME.mdis left untouched.
Verifying signatures
Each binary is signed with cosign using GitHub Actions OIDC keyless signing. Verify a download with:
cosign verify-blob \
--certificate fermix_<target>.pem \
--signature fermix_<target>.sig \
--certificate-identity-regexp "https://github.com/tezra-io/fermix/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
fermix_<target>The releases.json artifact lists every binary's URL, sha256, and signature URLs.
v0.5.3
What's new in v0.5.3
Fixed
- The setup page no longer reads the OS keychain on every load. Computing
the "restart required" banner reloaded the persisted config with secret
resolution on, spawning onesecuritysubprocess per stored secret on every
page mount (twice per load — LiveView mounts a page twice). On a keychain
that answers slowly this made the setup page take minutes; on 0.4.2's
plaintext config it was instant, which is why the slowdown only appeared
after the keychain move. The comparison now happens at the@keyring
sentinel level — pure, in-memory, zero keychain reads on the web path.
Added
- Computer Use now installs. The
compuxnative helper has its first
published release (v0.3.0): Developer-ID signed and notarized for
Apple-Silicon macOS, plus Linux x86_64. Enabling Computer Use downloads the
helper, verifies its sha256 against the pinned checksum map, and — on macOS
— Gatekeeper accepts it as a notarized Developer ID binary, so the
Accessibility/Screen Recording grants survive upgrades. Also fixes a latent
TLS bug in the helper download (Erlang:httpcrejected GitHub's wildcard
release-asset certificate), which would have failed the install for every
user. Intel-mac and ARM-Linux remain unpublished for now and keep the
honest "not published for this platform" message. - Global log secret redaction. All log output — file and console, crash
reports included — now passes through a redacting formatter that replaces
credential-shaped tokens (OpenAI/Anthropicsk-…, GitHub, Slack, xAI,
Google, Telegram bot tokens, AWS key ids, bearer headers) with
[REDACTED:<vendor>]markers. Defense-in-depth for the 0.5.2 crash-report
leak class: existing redaction was path-specific and could not see what an
unforeseen crash dump carries.
Changed
- Daemon boot resolves keychain secrets in parallel. Boot previously read
each@keyringsecret sequentially — onesecurity/secret-tool
subprocess at a time. A config with 15 stored secrets paid ~0.6s at every
start (measured: 71ms parallel), and a degraded keychain (3s timeout per
read) paid 45 seconds where it now pays ~6. Reads fan out over a bounded
task pool; failure semantics are unchanged (warn loudly, keep the sentinel,
never crash boot). fermix setupwaits up to 60s (was 30s) for the daemon before giving up
on opening the browser. A healthy boot opens the browser the moment the
endpoint answers; the longer window only helps a slow-but-healthy boot
auto-open instead of printing the URL.
Verifying signatures
Each binary is signed with cosign using GitHub Actions OIDC keyless signing. Verify a download with:
cosign verify-blob \
--certificate fermix_<target>.pem \
--signature fermix_<target>.sig \
--certificate-identity-regexp "https://github.com/tezra-io/fermix/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
fermix_<target>The releases.json artifact lists every binary's URL, sha256, and signature URLs.
v0.5.2
What's new in v0.5.2
Fixed
- A slow keychain read can no longer crash the setup page or leak a secret to
the log. Whensecurityreturned a secret just after its timeout,
CommandRunnerleft that output — the raw secret — in the calling process's
mailbox; a GenServer caller (the setup LiveView,BootReport) then crashed on
the unexpected port message and the secret was written into the crash log. The
runner now drains and flushes any late child output on timeout, so it never
reaches the caller. - Honest Computer Use install error. A failed Computer Use install now says
the native helper "hasn't been published for this platform yet" rather than
"…for this Fermix version yet", which wrongly implied afermix upgradewould
help. (The helper's first release is still pending.)
Changed
- macOS keychain secrets are stored with an open access list (
-A). Without
it, each item's ACL is pinned to the exact code signature of the writing
binary; the daemon — an ad-hoc-signed, per-version binary the keychain can't
reliably match — is then treated as an untrusted app and macOS blocks every
read on an authorization prompt the headless service can't answer, so reads
hang and time out (slow boot, slow/failed setup).-Alets the daemon read
headlessly. Trade-off: any process running as the same user can read the item
without a prompt — no weaker than the pre-keychain plaintext-in-config
baseline, and still keychain-stored. The proper long-term fix is Developer-ID
signing the release binary. Existing secrets keep their old ACL until
re-stored (re-enter them infermix setup, orsecurity add-generic-password -U -A …).
Fixed
- The daemon no longer crashes at boot when the login keychain is locked. A
required secret stored under@keyring(e.g.OPENAI_API_KEY) whose keychain
read timed out — common when the login keychain is locked or slow at daemon
launch — raised during config hydration and took down the whole node, leaving
the setup UI (the very surface used to fix it) unreachable. Boot now leaves the
@keyringsentinel in place and logs the failure (the same graceful handling
optional secrets already had) instead of crashing; the secret resolves on the
next boot once the keychain is reachable. fermix setupno longer opens the browser before the endpoint is live. On a
readiness timeout the launcher printed the URL but still opened the browser,
landing on "Safari can't connect to the server". It now opens the browser only
once the endpoint actually answers; on timeout it hands back the URL to open
manually.- The setup 403 page is now actionable. Reaching the token-gated
/setuppage
without an authorized session returnssetup authorization requiredplus a line
telling you to runfermix setup(the only thing that authorizes a browser
session), instead of a bare error.
Verifying signatures
Each binary is signed with cosign using GitHub Actions OIDC keyless signing. Verify a download with:
cosign verify-blob \
--certificate fermix_<target>.pem \
--signature fermix_<target>.sig \
--certificate-identity-regexp "https://github.com/tezra-io/fermix/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
fermix_<target>The releases.json artifact lists every binary's URL, sha256, and signature URLs.
v0.5.1
What's new in v0.5.1
Fixed
- The daemon no longer crashes at boot when the login keychain is locked. A
required secret stored under@keyring(e.g.OPENAI_API_KEY) whose keychain
read timed out — common when the login keychain is locked or slow at daemon
launch — raised during config hydration and took down the whole node, leaving
the setup UI (the very surface used to fix it) unreachable. Boot now leaves the
@keyringsentinel in place and logs the failure (the same graceful handling
optional secrets already had) instead of crashing; the secret resolves on the
next boot once the keychain is reachable. fermix setupno longer opens the browser before the endpoint is live. On a
readiness timeout the launcher printed the URL but still opened the browser,
landing on "Safari can't connect to the server". It now opens the browser only
once the endpoint actually answers; on timeout it hands back the URL to open
manually.- The setup 403 page is now actionable. Reaching the token-gated
/setuppage
without an authorized session returnssetup authorization requiredplus a line
telling you to runfermix setup(the only thing that authorizes a browser
session), instead of a bare error.
Verifying signatures
Each binary is signed with cosign using GitHub Actions OIDC keyless signing. Verify a download with:
cosign verify-blob \
--certificate fermix_<target>.pem \
--signature fermix_<target>.sig \
--certificate-identity-regexp "https://github.com/tezra-io/fermix/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
fermix_<target>The releases.json artifact lists every binary's URL, sha256, and signature URLs.
v0.5.0
What's new in v0.5.0
Added
- Computer Use is now backed by the standalone
compuxlibrary. The native
computer-use sidecar was extracted into a separate signed binary (mechanism in
compux, policy in Fermix). This release wires Fermix to it, ships the compux
v0.2/v0.3 action set, surfaces the screenshot cursor, and gives the Computer
Use setup card its own name and logo. Computer use can also run over realtime
voice now, across one shared untrusted boundary. Still experimental and off by
default. - Emoji-reaction acknowledgements. A pure acknowledgement ("ok", "thanks",
👍) is answered with a message-level emoji reaction instead of a text bubble,
across all reaction-capable channels (Telegram, Discord, WhatsApp, Signal,
Slack). A delivered reaction with no accompanying text ends the turn without a
continuation LLM call, roughly halving ack latency. - Chief-of-staff prompt surgery (safe subset) landed in the operating prompt.
- Plugin auth failures are agent-actionable, and stale OAuth tokens are now
flagged in the provider badge andfermix doctor.
Performance
- Sandbox path checks no longer recompute their invariant root sets.
read_path/write_path/working_dirresolve the protected and effective root
sets once per call instead of ~3×, andcontent_search/glob_searchvalidate
their candidates through a single batchedSandbox.read_paths/3instead of a
per-filelstat/lssyscall storm. Behavior-preserving: identical allow/deny
decisions,condorder, and deny audit traces. - Album image downloads run concurrently. Multi-image attachments (e.g. a
Telegram media group of up to 10 images) are fetched in parallel (bounded)
instead of serially, cutting pre-turn latency from the sum of the downloads
toward the slowest single one. Ordering, all-or-nothing fail-loud, and
temp-file cleanup are preserved.
Fixed
- Security:
git_writecan no longer reach anext::RCE —GIT_ALLOW_PROTOCOL
is pinned so agit pullcannot invoke an external protocol helper. - Security: the home page no longer mints a
/setuplaunch token to any
visitor. - Computer use fails closed on host control for detached
/backgroundruns,
and picks up the compux stop-kill and display-asleep fail-fast paths. - Scheduled deliveries no longer drop on a Finch pool-checkout timeout
(wake-from-sleep pool starvation). - FermixPet stays in its speaking look for the whole spoken reply. The macOS
voice companion previously flipped back to the listening face as soon as the
model finished generating, even though the buffered voice kept playing for
seconds after; it now tracks actual audio playback (face, glow, controls, and
motion), leaving the microphone/turn-taking state machine untouched.
Changed
- Removed the
watchconstruct, parked pending a redesign. - FermixPet mascot animation feels more alive on the existing art — no new
assets or dependencies: eye blinks on the open-eyed states, motion that eases
between states instead of snapping, a smoothed audio-reactive speaking pulse,
and a corrected speaking-face offset. The animation timeline now pauses when
the pet window is hidden to save energy.
Verifying signatures
Each binary is signed with cosign using GitHub Actions OIDC keyless signing. Verify a download with:
cosign verify-blob \
--certificate fermix_<target>.pem \
--signature fermix_<target>.sig \
--certificate-identity-regexp "https://github.com/tezra-io/fermix/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
fermix_<target>The releases.json artifact lists every binary's URL, sha256, and signature URLs.