Skip to content

Releases: tezra-io/fermix

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 19 Jul 19:36
Immutable release. Only release title and notes can be modified.
d69d98f

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. /pause hands the machine
    back on demand (the session stays alive and resumable — unlike /stop, which
    tears it down) and /resume continues. Controlled by [fermix_core.computer_use] courtesy (yield default, off) and courtesy_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_codex image backend drives gpt-image-2 over the Codex subscription
    endpoint — billed to the subscription, no OPENAI_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
    /confirm prompt 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), /confirm peek-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 explain annotates 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 :xai atom, XAI_API_KEY, api.x.ai, and grok-* 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 to tezra-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, and fermix doctor/voice status now 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 central CommandHost in their own process group and are
    killed on exit, crash, or daemon shutdown (a new kill_pgid NIF), and cron jobs
    can delegate. Closes the orphaned-subprocess class across git tools, subagents,
    jobs, sandbox env, plugin probes, and realtime.
  • fermix status and fermix doctor now 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 status now
    appends a warning line and doctor's daemon-socket check degrades to a
    warning, both naming the two versions and the fermix restart fix. The
    fermix upgrade managed-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] backend selects the speech-to-text provider — openai, xai, or deepgram
    resolved through a fail-loud registry that lists the valid names on an unknown
    choice (the on-device local backend is reserved for a later phase and says so).
    Each backend has its own optional API-key slot: openai_api_key and
    xai_api_key OVERRIDE 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/stt is 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-class config.toml section (backend, model, per-backend
    openai_api_key/xai_api_key/deepgram_api_key, max_file_mb) with an unknown
    key/backend/max_file_mb failing 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 with fermix 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 shared model to that backend's default so Deepgram
    never inherits the OpenAI-shaped model (SpaceXAI is modelless and sends none).
    fermix doctor gains a transcription row 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 /compact budgets, and the
    fermix doctor context report key off the corrected value; the older gpt-5.5 /
    gpt-5.4 / gpt-5.4-mini windows 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_use for web_search/web_fetch/subagents/memory_recall now 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
    legacy whisper-1) — better accuracy on the same OpenAI endpoint. Set
    [fermix_core.transcription] model to pin a different model.

Fixed

  • Voice calls no longer freeze after a computer-use (or any slow) tool run.
    The realtime SessionServer is 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 ...
Read more

v0.5.8

Choose a tag to compare

@github-actions github-actions released this 13 Jul 03:59
Immutable release. Only release title and notes can be modified.
b98806b

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
    /compact budgets, and the fermix doctor context report now key off the
    corrected value. The older gpt-5.5 / gpt-5.4 / gpt-5.4-mini windows 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

Choose a tag to compare

@github-actions github-actions released this 11 Jul 20:34
Immutable release. Only release title and notes can be modified.
3165611

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 same compux app 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. a gpt-oss pin — 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, set subagent_provider explicitly
    in [fermix_core.routing].
  • fermix stop/restart/upgrade now force-kill a daemon that won't shut down,
    and upgrade verifies the daemon came back on the new version.
    The service
    commands sent a single launchctl kill TERM and 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 a kill -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 default TimeoutStopSec already 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

Choose a tag to compare

@github-actions github-actions released this 11 Jul 00:20
Immutable release. Only release title and notes can be modified.
8b6576c

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), and gpt-5.6-luna (fast,
    affordable) are selectable in the setup wizard and web pane, and gpt-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 a default_model are
    unaffected; the earlier gpt-5.5 / gpt-5.4 / gpt-5.4-mini models remain
    available.
  • max reasoning effort is now available for the GPT-5.6 family on OpenAI and
    Codex.
    max is 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 at xhigh.
    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. max on gpt-5.5 runs as xhigh) 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.3 and the other Grok
    models remain available.

Fixed

  • macOS keychain secrets no longer trigger repeated login-password prompts.
    Secrets were stored with security 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-run fermix setup once 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

Choose a tag to compare

@github-actions github-actions released this 09 Jul 03:57
Immutable release. Only release title and notes can be modified.
06a6921

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, notarized Fermix.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 run tccutil 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, or killall Dock).
  • Upgraded voice configs with any official OpenAI voice no longer crash the
    daemon.
    0.5.4 validated the Realtime voice against only the four curated
    dropdown options (marin/sage/verse/cedar), but earlier Fermix accepted any
    voice — so a config carrying alloy, 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 because secret_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 manual fermix 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 a fermix 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"). TokenManager now (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 still fermix 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

Choose a tag to compare

@github-actions github-actions released this 08 Jul 01:29
Immutable release. Only release title and notes can be modified.
7f1cb0b

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 running python/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's Background (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 at Standard priority;
    the change reconciles onto an already-installed unit on the next fermix setup.
  • fermix restart and fermix upgrade no longer hard-kill the daemon. They
    kicked the service with launchctl's -k (an immediate SIGKILL) 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 graceful SIGTERM plus 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 of security
    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 need node/python on 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 Realtime session.update ([fermix_core.realtime] reasoning_effort,
    default low — 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 existing REALTIME.md is 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

Choose a tag to compare

@github-actions github-actions released this 07 Jul 01:33
Immutable release. Only release title and notes can be modified.
371a1ff

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 one security subprocess 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 compux native 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 :httpc rejected 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/Anthropic sk-…, 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 @keyring secret sequentially — one security/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 setup waits 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

Choose a tag to compare

@github-actions github-actions released this 06 Jul 02:33
Immutable release. Only release title and notes can be modified.
41249c0

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.
    When security returned a secret just after its timeout,
    CommandRunner left 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 a fermix upgrade would
    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). -A lets 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 in fermix setup, or security 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
    @keyring sentinel 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 setup no 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 /setup page
    without an authorized session returns setup authorization required plus a line
    telling you to run fermix 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

Choose a tag to compare

@github-actions github-actions released this 06 Jul 01:19
Immutable release. Only release title and notes can be modified.
4b734c2

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
    @keyring sentinel 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 setup no 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 /setup page
    without an authorized session returns setup authorization required plus a line
    telling you to run fermix 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

Choose a tag to compare

@github-actions github-actions released this 05 Jul 21:54
Immutable release. Only release title and notes can be modified.
c5eca62

What's new in v0.5.0

Added

  • Computer Use is now backed by the standalone compux library. 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 and fermix doctor.

Performance

  • Sandbox path checks no longer recompute their invariant root sets.
    read_path/write_path/working_dir resolve the protected and effective root
    sets once per call instead of ~3×, and content_search/glob_search validate
    their candidates through a single batched Sandbox.read_paths/3 instead of a
    per-file lstat/ls syscall storm. Behavior-preserving: identical allow/deny
    decisions, cond order, 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_write can no longer reach an ext:: RCE — GIT_ALLOW_PROTOCOL
    is pinned so a git pull cannot invoke an external protocol helper.
  • Security: the home page no longer mints a /setup launch token to any
    visitor.
  • Computer use fails closed on host control for detached /background runs,
    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 watch construct, 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.