Release Notes

What's new in NevoFlux — versions, downloads, and changes.

  1. v0.3.16

    Latest

    The headline of this release is another agent at the wheel — pair an AI agent such as Muse with your browser, decide exactly how far it may reach, watch every tab it touches, and hand it whole tasks that run in the sidebar like your own. Around it: a model that runs entirely on your machine, clicks that land once and on the thing you meant, every reply showing what it cost, and a headless agent that speaks A2A and the OpenAI and Anthropic APIs.

    🤝 Another agent at the wheel

    • /pair-agent shows a pairing block to paste into an agent; you approve it at nevoflux.app/device and it reaches this browser over the encrypted relay as an MCP server. There is no plaintext mode, and agent pairings live in a file of their own — kept apart from phones, so a downgraded daemon cannot mistake an agent for a phone and hand it device control
    • It sees sixteen browser tools and nothing else — snapshot, read, screenshot, tabs, navigate, click, fill, type, keys, scroll, wait, upload. Anything off that list is answered unknown_tool
    • Tiers are a ceiling, not a question. Every pairing starts read-only; browser-auto adds clicking, typing and switching tabs; full-auto adds uploads. A call above the tier is refused on the spot and nobody is asked, and the tier is checked again after an approval wait, so lowering it mid-approval wins. Only you raise it — with /agent-tier or in the new Muse section of nevoflux://settings
    • It works in its own tabs. New tabs open in the background of a normal window, never a private one, private tabs are left out of the lists it receives, and every tab an agent opened or touched carries a badge on its favicon. Navigation is http, https or about:blank only, and a tab id from before a restart answers tab_closed instead of landing on one of yours
    • Site rules now apply to an agent's clicks and typing. They were judged without knowing which tab was the target, so they were never applied at all
    • A status bar for each paired agent, with pause, resume and unpair. Pausing survives a restart and a paused agent is never redialled; unpairing cancels its open questions and forgets its tabs. /devices lists everything that can reach this machine — phones and agents, with their live state — and /unpair revokes one
    • An approval outcome the sidebar cannot show reaches you as a system notification, and it tells the truth: lower the tier while the agent is approving and you read "approved — stopped: the agent's tier was lowered", not "approved"

    📋 Handing it a whole task

    • An agent can give NevoFlux a task instead of driving it click by click (nevoflux_task_start, wait, approve, cancel). It runs as an ordinary sidebar turn in a session of its own — "Muse is working on this task", with Stop, its approvals and View session — and history marks such sessions running, waiting or finished
    • The agent gets the reply back with one screenshot of the result: the Canvas it generated, else the tab it opened, else the tab it last acted on. The browser used to give up on the Canvas after about 100 ms and send no picture; it now waits for the tab to appear and draw
    • One task per pairing at a time, at most twenty an hour, and a task can continue the agent's own earlier session — "now make the buttons blue"
    • Ten actions always ask, at any tier — scheduling, running a schedule, starting a loop, switching a pack or a model, setting a goal, replacing the system prompt, sharing the screen. Only you answer them, unless you switch on "Let Muse approve sensitive actions"; either end can answer the rest, the first answer wins, and an unanswered one is denied after thirty minutes. task_wait used to return instantly on an approval only the desktop could answer, so the agent polled for half an hour
    • A delegated task cannot write NevoFlux's own settings or pairings — config, skills, packs, the pairing file, the database — including through .., symlinks and Windows' case-insensitive paths. Said plainly: shell commands are not covered, so at full-auto this does not hold
    • The holes it closed on the way: a delegated turn picked up your active tab, so your current page went into the agent's task and the result screenshot was aimed at it; its subagents ran ungated, so at full-auto they could do all ten must-ask actions without asking; and a session whose origin could not be read was treated as yours. It is treated as delegated and read-only now

    📱 One phone, the whole machine

    • /pair-device pairs a phone with a QR code in the sidebar, and the pairing is kept and redialled at every start. The QR carries only the link — you type the code, so it never lands in browser history — and the instructions say to install the app first, because on an iPhone the home-screen app and Safari keep separate storage
    • The phone sees every session on the machine and opens any of them with its earlier messages replayed — newest first within a byte budget, since 512 retained frames had reached 175 MB. Moving between conversations reuses the channel rather than renegotiating a peer connection that can take minutes, and while nothing is open on the phone no chat data is sent at all
    • A conversation that sometimes opened empty is re-sent; a mistyped pairing code that gave a green badge and an empty list forever is normalized, and after eight seconds of unreadable traffic the phone asks for the code again; HarmonyOS no longer loops on "install first"; and a phone that has dropped off stops counting as connected after two minutes instead of thirteen to sixteen

    💻 A model on your own machine

    • Settings › On-device runs the agent on a local model. NevoFlux probes the hardware, recommends a model and a backend, and shows everything it will download — engine and model separately, with the hosts they come from — before fetching anything. It offers the cheaper backend where one exists: CUDA is about ten times the size of Vulkan
    • The engine is a pinned build of llama.cpp's llama-server, CUDA → Vulkan → CPU (Metal on macOS), each archive pinned by size and SHA-256 and fetched from mirrors before upstream. The models are Qwen3 in Q4_K_M: 8B by default (5.0 GB), with 4B and 1.7B for smaller machines, and a memory estimate disables any that will not fit
    • 8B, because 4B was not good enough. In the experiment that chose it, 4B reached 0.35–0.51 on picking the right tool in every configuration tried, and 8B 0.78 overall and 0.89–1.00 on browser and agent tasks. The code had defaulted to 4B anyway
    • Nothing leaves while it is on. Every model call passes one egress guard. Summaries and memory move to the local engine; goals without a programmatic check pause rather than ask a cloud evaluator; loops are skipped, due schedules recorded as missed, and switching to a cloud model is refused. Until the engine is up, requests go to a closed local port so they fail here instead of reaching the cloud, and the engine itself starts with an empty environment so nothing can hand it a network route of its own
    • A local turn starts with a short prompt of about 7 KB instead of tens of thousands of tokens, and with one tool, tool_search, rather than about sixty schemas — the rest load when the model asks. Keeping a page reader permanently loaded dropped browser-mode accuracy from 0.90 to 0.20
    • The install is atomic, verified and re-hashed before every launch; the engine proves one generation before reporting ready, chat never waits behind background memory work, and the engine unloads after five idle minutes. A badge in the sidebar says what on-device means and what it does not: pages, search and MCP tools still use the network

    🎯 Clicks that land once, on the right thing

    • A click used to be tried up to three ways, falling through whenever no effect showed within 500 ms — so ticking a checkbox could untick it again. Each click is now sent once, and a click or fill that may already have run is never re-sent: the agent is told it may have happened and takes a fresh look
    • No clicking through a cover. A covered target is refused with the name of what covers it; the third method used to click the cover deliberately. The click lands on the target's own point, a target clipped inside a scroll box is scrolled into view first, and an overlay on the top page cannot take a click meant for an iframe
    • An element id names one node for the life of the page. Snapshots used to renumber on every call and write attributes into the page that shadow roots and iframes never cleared. Now nothing is written into the page, and acting on an id is refused when the node is gone or is no longer what the snapshot showed — a recycled list row that now reads "Parma" instead of "Paris" included
    • Accessibility roles come from Gecko itself. A hand-written table had been reading links as "dialog" and buttons as "row"; one evaluation's snapshots carried 1464 unlabelled lines, and after the change 165
    • Snapshots now include shadow-DOM controls (they were all dropped), same-origin iframe controls, every option of a select as something to click, ✓/☐ on checkboxes instead of a val="on" that only looked like state, and the visible text no element already names. Password and file values are left out. At 125% display scaling the top of every list had been discarded as covered, which is how the agent picked a decoy contact
    • CSS-selector tools are now a fallback the model loads on purpose. On the regression set every final run passed 21 of 21, and the scripted workarounds the agent reached for fell from 120 a run to 26

    📊 What every reply cost

    • Each reply carries input and output tokens and generation speed on its toolbar — tool-only replies too — and hovering shows calls, context size, first-token and total time and the model, subagents included. It is saved with the message; when the provider reports nothing, an estimate that counts CJK properly fills in and says so
    • Usage that providers did report had been thrown away: Qwen and DeepSeek send it on a final chunk with no choices, which both parsers skipped, and the Anthropic path ignored it too
    • All Anthropic-wire traffic now uses prompt caching, and the prompt is kept byte-stable from turn to turn — skills in a fixed order, tool schemas left alone, old tool results shortened together once they pass 64 KB rather than one per step. On the regression set uncached input fell from 179k tokens a trial to 4.9k, a 98% cache hit rate, with every task passing
    • A context overflow shortens the oldest tool results and retries once instead of failing the turn, and a tool result too large to keep is saved to disk where the model can still read it

    🔌 A2A, and the APIs you already call

    • A headless NevoFlux joins Agent2Agent networks in both directions. It serves an agent card and both the 0.3 and 1.0 wire formats with streaming; a task keeps running when its caller leaves and can be re-subscribed; files come back inline up to 256 KiB and as a link beyond. The official SDK found three wire mismatches unit tests had missed, all fixed
    • The other way round, a remote A2A agent is configured like an MCP server and its skills become tools
    • The headless daemon also answers POST /v1/responses and POST /v1/messages, so the official OpenAI and Anthropic clients drive it by changing only the base URL
    • Headless tasks report usage per turn, accept follow-up turns in the same session, and each get a session of their own. A cancelled task now reports canceled rather than failed, so clients that match every status value need the new one
    • Sessions are logged as events and can be exported (session export) and replayed without an API key

    🧱 What a Canvas may do

    • Generated canvases may call a short list of SDK methods and nothing else; settings, pairing and accounts are permanently out of reach, and six more commands that handed out a bearer token or reached other sessions' data were added to that list. Each nevoflux:// page is held to the bridge messages it needs, and web pages and canvas frames get none
    • Pack dashboards declare the daemon commands they send, the install preview lists them, and a panel that declares nothing reaches nothing. Install had never saved the pack manifest, so every pack panel had been judged as a generated canvas and its declarations did nothing
    • A panel acts only on tabs it opened and gets the verdict the model would get for the same action on the same site. Pack site rules apply strictest-first, a pack's tool policy can deny or ask but never allow, a pack's replacement system prompt no longer leaks into later conversations, and the install checklist leaves unticked anything that cannot be undone
    • Tool calls made by ACP providers had bypassed the gate and the log entirely — one session showed 14 tool results and 0 logged calls. Every call now passes the same ordered pipeline

    🧪 Jev, off by default

    • Settings › Jev connects TypeSafe's Jev, a small model that decides which tools, skills and context the agent sees and grades large tool results, with your own key, billed by TypeSafe. It is off, and it says what it will send before it sends anything; banking, payment, medical, mail, government and intranet sites only ever share their domain and title
    • We measured it before shipping it and it did not pay: on DeepSeek, cost rose 95% with no gain in score, because a per-task tool set breaks prompt caching. So choosing tools is off even when Jev is on, and Jev stays an experiment you can opt into rather than a default

    🛠️ Fixes

    • "Speak replies" was silent whenever MOSS fell back to Kokoro — the common case, since most machines do not have MOSS — and a MOSS "not installed" answer was remembered even after its weights had downloaded
    • After any dropped connection the sidebar stuck on a daemon error until the browser restarted; bursts of requests threw the stream out of step ("Message too large: 1919951483 bytes"); and an interrupted reconnect left the connection permanently dead
    • The sidebar logged every redraw, and the agent bar redrew every second; a streamed Canvas could reopen truncated; and the Muse settings switch went stale after five quiet minutes
    View on GitHub →
  2. v0.3.15

    The headline of this release is a conversation — you talk to it, it talks back, all of it on your own machine, and for the first time that includes Chinese. Behind the voice: remote control that reaches a phone anywhere rather than one on the same WiFi, any OpenAI-compatible endpoint as a provider, and a browser that can finally say what a page did on the network and in its console.

    🎙️ It listens

    • tts_transcribe had been registered for months and answered "not configured" — the tool's own description said as much. SenseVoice now actually transcribes, on the CPU, at 39× realtime in a release build
    • Long recordings are cut at pauses, not on a stopwatch. A single pass decides the language once for the whole recording and holds activations that grow about 6 MB per second of audio: 305 s of speech cost 2011 MB at 5.9× realtime and lost every word outside the winning language. Segmented at speech pauses it costs 528 MB at 14.6×, peak memory stops growing with the length of the recording, and all four languages survive — which is what puts a five-hour recording back within reach
    • Each span keeps 200 ms of padding rather than the usual 30: at 30 ms the first syllable came back with the wrong initial consonant
    • Whisper for the languages SenseVoice cannot do. SenseVoice chooses among five languages and returns the nearest of them for a sixth, so a German recording came back as a confident, wrong transcript rather than an error. Whisper is enabled by default now with base — 585 MB resident at 2.5× realtime, against small at 1.90 GB and 0.9× and large-v3-turbo at 4.77 GB and 0.3×, and on the clip they were compared on the first two produced the same transcript
    • Two silent faults in the reference implementation this is a port of: it has no language detection, and omitting the language token does not make Whisper guess — it makes it emit one character seventy times; and its repetition guard was dead code (NaN > 2.4 is false), so silence came back as a fabricated sentence
    • A recording where every span fails now returns the error. It used to return an empty transcript, which is exactly what a genuinely silent recording returns
    • The audio-event tag SenseVoice emits (Speech, BGM, Applause, Laughter) is reported rather than discarded — a microphone left open hears music and colleagues, and a transcript of either must not be submitted as though you had said it

    🗣️ Chinese has a voice at all

    • Kokoro's g2p refuses its own Chinese voices, so until now a Chinese speaker did not get a worse voice — they got silence. MOSS-TTS-Nano is the engine that fixes it: five ONNX graphs, 717 MB, 48 kHz stereo, twenty languages, measured at 0.647× of realtime against a 0.85 budget
    • Its SentencePiece tokenizer is implemented here and verified against the two worked examples upstream ships — Chinese and English, 20 and 69 tokens, both reproduced exactly. That check is the only one that catches a wrong merge rule; every structural test passes just as happily with the wrong algorithm
    • Which engine speaks is measured, never chosen by language. MOSS when it is installed and fast enough on this machine, Kokoro otherwise — and every fallback carries its reason to the sidebar and the settings page, because "fell back to Kokoro" is a different voice for an English speaker and no voice at all for a Chinese one
    • The verdict is now the median of the last five real syntheses: a single 2.07× sample taken while transcription was running had been deciding everything, against 0.87× for the same work a minute later. And it has a way out — once "too slow" was stored the engine never ran, so it never measured, so the verdict never changed, and the only escape was editing config.toml by hand. Re-measure in Settings clears it, and the panel shows the samples the number came from
    • Kokoro gains a speak-chinese tier of its own — Kokoro v1.1-zh, its vocabulary and 103 voices. It supersedes the English tier rather than extending it: the v1.1-zh bank carries English voices too, and keeping both is 375 MB of duplication
    • Settings no longer asserts "English only"; it reads the voices that are actually loaded. That line exists to explain why you are hearing English, and on a machine now speaking Chinese it was pointing the investigation the wrong way
    • A grouped voice picker built from the daemon's answer rather than a table in the page — which voices exist depends on which engine will speak, and offering MOSS's eighteen while Kokoro is running lets you pick a voice that silently does nothing

    🎧 Talking to the sidebar

    • The microphone button now runs the whole chain. What you say becomes an ordinary user message on the current session — same history, same tools, no special case anywhere in the daemon
    • The audio path lives in the browser, because both ends of it are there. Voice detection runs in a Worker and capture frames reach it over a transferred port: through the main thread that measured 56 ms of extra latency at 97% duty cycle, which is exactly the condition interrupting has to work under, since the agent talking is the agent streaming tokens into the page. Capture keeps a 400 ms pre-roll, because by the time speech is detected the first consonant is already gone
    • You hear the first sentence before the last one exists. The reply is split sentence by sentence as it streams and synthesized as each one completes, on a tap that can fail without touching the text answer. Playback holds a small buffer first, so the gaps between sentences become one wait at the start instead of a stutter between every pair; a one-sentence answer is released by a timeout, and an interrupt throws the buffer away
    • Hearing replies without opening the microphone. Spoken answers used to ride on voice input, so wanting to talk to it meant it talked back, and wanting it to talk back meant an open microphone. "Speak replies" is its own switch now, off by default, beside "Use GPU when it helps" — on by default, and not a command: speech measures both backends and keeps whichever is faster here, which for these models is often the CPU
    • From the second answer onwards a listening session went silent with no error anywhere, because sequence numbers restart with every turn and the player was still waiting on the previous one's cursor. It claims the turn the daemon started now
    • A voice view: a waveform in place of the message bubbles while you are talking. It is a rendering switch and nothing else — replies are still generated, still saved, still searchable. The voice bar also has somewhere to stop it, reachable from the keyboard, and reports each gap it hears — how long, before which sentence, how many this turn — instead of leaving "it stutters" as the whole diagnosis
    • The microphone is granted at startup for the sidebar's own origin, so starting voice does not cost two gestures every session. It never overrides an explicit refusal
    • The models download from Settings, in tiers: 240 MB before anything can be heard, 120 MB more for spoken replies, 717 MB for MOSS — separately, because making the first wait on the last means nobody talks to it until all of it has arrived. Sizes and digests are pinned, mirrors come before upstream, a partial reads "Paused at 40 MB" with a Resume button rather than a percentage, cancelling keeps what has already arrived, and a failure keeps the daemon's own message naming every source it tried

    📡 Remote control that reaches a phone anywhere

    • The direct path only ever worked on a LAN, which for a feature whose whole point is a phone that is somewhere else is the feature not existing. The head now learns its public address from a STUN server over the very socket the connection will use — a NAT maps per source port, so an address learned on another one describes a pinhole nobody is listening behind
    • And a relay for the last fifth. Every allocation this had ever sent was answered 400 Bad Request: the transport attribute the standard makes mandatory was never sent, so a relayed path could not be obtained at all and a phone on a carrier NAT had no route whatsoever. Traffic is now wrapped four bytes at a time instead of in a whole STUN message per packet, and each channel-bind answer is matched to the request that asked for it rather than to whichever of three in-flight binds a hash map happened to yield
    • Pictures and files travel on the peer connection instead of the relay, which bills per message. The head advertises the chunk size it will serve and the portal plans its offsets on that, and nothing is ever answered with less than was asked for — a 77 KB screenshot used to arrive a quarter complete, because offsets stepping 256 KiB were answered with 64 KiB and nobody went back for the holes. Video that still takes the relay costs 171 requests for an 89 MB file instead of 466
    • Screen sharing: the agent can put a live screen on that connection, refusing when there is no direct connection rather than spinning up an encoder with nowhere to send its output, and the consent prompt says what is being recorded and who will see it instead of asking you to approve the words "Perform action: screen_record"
    • A long run of reported success while delivering nothing, all of it now fixed: a data channel declining an oversized write reported that as a success value; ranges routed onto a connection that was still negotiating; the portal never reading the flag that marks a frame as unsequenced, so every range was dropped as already delivered while both ends logged success; a repeated offer tearing down the connection it was already forming; every offer replayed to a reconnecting portal and answered thousands of times for negotiations this end had long forgotten; a socket bound to 0.0.0.0 while the offer advertised a real interface, so the connection reported itself established and the handshake timed out; and a Windows connection-reset error, routine while probing candidates, treated as the end of the connection
    • A session gives up gracefully now — after five unanswered offers, or four connections this network refused — and says so once, rather than re-offering every five seconds for as long as it lives. Nothing is lost by it: the relay was carrying everything throughout
    • The relay keeps its own contract. A channel belongs to the first account that opens it and answers any other with 403; a leaked channel id used to be enough to take one of the two places on it and put a working head off the air. Two heads on one channel no longer feed each other their own output — that ran at machine speed for hours, 9.5 million relayed messages in an afternoon against a daily allowance of a hundred thousand, with nobody touching anything
    • A reconnect is earned by lasting rather than by opening. A server that accepts a socket and drops it in the same breath used to reset the backoff every time: two connections a second for as long as the page stayed open, about a hundred thousand in a working day, which is precisely the allowance that then ran out. The phone pings every 30 s so a carrier NAT does not quietly drop an idle socket, and waits at least a minute before redialling once the relay has said nobody is there
    • A reply that points a player at media the store never minted is repaired against what the turn actually produced, or dropped with its alt text kept — the portal used to draw the player, ask for the range, take a 404 eleven times, then keep asking forever. And a failed request to the account service now says whether the name did not resolve, the handshake was refused, or the connection timed out, instead of "error sending request"

    🧩 Bring your own provider

    • Any OpenAI-compatible endpoint can be a provider now: add, edit and delete them in Settings, or drive them from the config commands. They get stable ids and appear in the provider list beside the built-ins
    • The chat path did not know about them. A turn on a custom provider failed with Invalid provider: custom:<id> while the settings page listed and activated it perfectly happily — five call sites parsed the provider id themselves instead of going through the one lookup that understands them
    • The API-key lookup named 7 of the 18 built-in providers, and the other eleven silently fell through to an environment variable. An empty stored key now counts as absent rather than being handed to the client
    • On OpenAI's Responses API the request body carried role twice and was rejected with 400 invalid_json. Bodies are normalized on that path now; custom providers, which take the chat-completions path, were never affected

    🔍 What the page actually did

    • Network capture. The agent can record what a page requests — off by default, started by name, and now spanning turns rather than one, because debugging a page means clicking around it yourself and the turn ends before you get there. Forgetting it is the risk that creates, so there is a thirty-minute cap that discards the buffer, an explicit stop, and a notification when recording starts and when it stops itself
    • It keeps far more and returns far less: 2000 records or 4 MB held, 100 returned at a time. A live session on GitHub captured 532 requests against a 200-record buffer; 332 were evicted, what came back looked complete, and the model — reading a bare dropped:332 — told the user that "concurrent requests were sampled and merged". Truncation now says outright that the log is incomplete and that the evicted records cannot be recovered
    • Results filter by resource type, and the summary counts by type as well as by status, so "what did this page call" stops being answered with a hundred JavaScript files from a CDN. Request headers are collected at last — Authorization and Cookie were not redacted, they were never read — and the byte counts are named request_bytes / response_bytes, since as request_size they were reported to you as body sizes
    • An empty result says which empty it is: capture is off, this tab has nothing, or the recording is live on another tab
    • Console messages are read from the same store DevTools reads, so everything logged before anyone asked is already there, nothing is lost to a page's own security policy, and internal pages work too. Every browsing context in the tab is walked, so a page that reports its errors from a cross-origin frame no longer reads as clean, and uncaught JavaScript errors come along with the console.* calls
    • Their severity was wrong in the first cut, and it made healthy pages look broken: the level lives in a flags field, not in an attribute that does not exist, so a GitHub page with nothing wrong with it reported 248 errors — every one of them a Referrer Policy warning — and filtering by level changed nothing
    View on GitHub →
  3. v0.3.14

    The headline of this release is speech — the agent reads a passage aloud on your own machine, and you hear it while the rest is still being made — plus media that reaches the phone as a picture or a film instead of a wall of base64, and a headless agent that serves your own Python tools over MCP.

    🗣️ It speaks, locally

    • tts_synthesize_local was registered everywhere and returned "not configured" no matter what you configured — the inference had never been written. There is now a real Kokoro-82M engine behind it: 54 voices, 24 kHz, running on your own machine with no API key
    • Put the model and voice files in ~/.cache/nevoflux/models/, or point [tts.kokoro] model_path and voices_path at them, and ask for a passage to be read
    • You hear it while it is still being made — long text is cut on sentence boundaries only, never mid-phrase, and each part is offered as it lands, so a player is there about a second in rather than after the whole reading exists. On the portal those parts play as one reading, in the place the first one appeared
    • Faster than realtime with nothing configured by hand: the fp32 weights are now preferred over int8 (int8 only pays off on a CPU with VNNI, which most desktops lack) and inference is no longer pinned to one core — 0.67× → 3.41× realtime. The cost is resident memory, roughly 310 MB against 92 MB; [tts.kokoro] threads and model_path let you choose the other way on purpose
    • A passage no longer has to be cut up by the caller: the old 510-character limit was a token window measured in characters, and text split across calls came back as several recordings rather than one reading
    • English only. Chinese voices are refused with a reason rather than read through an English G2P, because gibberish is worse than an error

    🖼️ Media by reference, not as bytes in the prose

    • A screenshot used to reach the phone written into the assistant's own prose as a data URL — bytes the model never had and could only invent, which no browser would decode. The head now writes ![alt](nevo-asset:<id>) and the bytes travel over their own channel
    • Screenshots are diverted into the session's asset store before the model sees them: it still receives the picture as a vision block, so it can describe what it is looking at — it simply no longer has a transcript to retype. Invented image bytes are stripped at the boundary as defense in depth
    • The portal pulls the ranges it wants instead of being pushed at, and a Service Worker stands in as an origin that answers them, so the browser's own stack does start time, buffering, seeking and decoding — which is what makes an ordinary recording play on an iPhone at all
    • "Play the file at /tmp/a.mp4" now has an answer: a film already on this machine is adopted where it lies rather than copied, so a two-hour file costs no memory and no second copy
    • Watching a 158 MB film pulled 425 MB over the wire and took fourteen minutes to get through nine and a half of video. Keeping the last sixty-four ranges and asking for four at a time fixed both halves of that
    • The portal now says what it cannot play — an HEVC recording used to read sixty-eight megabytes off the wire and sit blank — and says when the bytes never arrive instead of showing nothing

    🔌 MCP: your own tools, and an admin API

    • MCP is served over rmcp rather than hand-rolled JSON-RPC, and a tool call on that path actually executes
    • Custom tools from Python scripts: a script declares them with describe() and implements each as a function; the file stem becomes a namespace, so jira.py exporting search is offered as jira__search and can never collide with the built-in browser_* names. One broken script is skipped with a reason instead of taking the others down
    • A token-protected admin API (PUT/DELETE/GET /admin/scripts) on its own --admin-addr, so it can be bound to a private interface while the task surface faces outward. It mounts only when NEVOFLUX_ADMIN_TOKEN is set, PUT reports what the script actually produced, a single script reloads without re-scanning everything, and tools/list_changed tells connected clients when the offer changed
    • Profiles over the same API: PUT /admin/profiles/<name> swaps a base profile by rename without restarting the browser, so a cloud deployment can refresh a login without rebuilding the image. Export is off unless NEVOFLUX_PROFILE_EXPORT=1 — it ships saved passwords, which the admin token alone is not the right bar for
    • NEVOFLUX_BRAIN_ENABLED overrides the read-only config file in both directions, and in session mode the shared browser now launches at startup — an MCP client whose whole interaction is tool calls no longer gets "no browser registered" until some task happens to run first

    🐍 Code Mode: Monty v0.0.19

    • The Python interpreter behind Code Mode jumps from v0.0.7 to v0.0.19: class, with, filter(), and native re and datetime all work now. The last two matter most for /loop, which had been reaching them through python3 — dropped whenever shell is off, which is exactly the unattended run that cannot report the failure
    • An invented function name raises NameError instead of returning an error dict the script then treats as data
    • Decorators are rejected rather than silently dropped, and orchestrate has a usable runaway backstop again

    🔗 Remote control follow-ups

    • /remote-control opens the approval page with the code already filled in, words the prompt from a live check of whether the browser is signed in, and keeps polling through transport errors instead of throwing away a sign-in in progress
    • A half-open relay socket is noticed now: a ping every 30s, give up after 90s of silence. And a channel that failed to dial for a while — a lid closed over lunch — is no longer retired for good; it keeps dialling and comes back instead of staying dead until the daemon restarts
    • On a wide screen the portal's conversation gets a proper column instead of stretching a message across the glass; with a mouse, copy and edit sit under a message on hover, and right-click goes back to the browser
    • ACP: orchestrate runs on that path instead of being advertised and then answering "unknown tool", bash is no longer offered where there is no shell to run it, and a stuck tool call can no longer hang the whole turn

    🐛 Fixes & platform

    • Canvas exports no longer fail silently — no file, no error, not even a record in about:downloads. An export now checks whether a download actually started and writes the file from the parent if it did not, reporting where it saved; "Export as PDF" no longer lands on a blank tab; and error toasts stay until dismissed
    • A broken video render no longer passes as a finished one: ffmpeg's exit status was never checked, so a truncated MP4 reached you as a completed job. Its output is drained now (a full pipe could block a render forever), a failure carries what ffmpeg actually complained about, and both outcomes raise a notification with the path the file landed at
    • A caller's timeout_ms for browser actions is honoured instead of a hardcoded 30 seconds, and a missing ONNX Runtime no longer deadlocks startup
    View on GitHub →
  4. v0.3.13

    The headline of this release is remote control — pair NevoFlux with the Portal and drive it from another device — plus a headless Docker image published with every release and finer control over how much the agent does on its own.

    🔗 Remote control

    • Type /remote-control in the sidebar to open a channel: sign in to nevoflux.app with a device code, and you get a portal.nevoflux.app/connect/… link and a pairing code
    • Open that link on your phone, enter the code, and you are in the same conversation — the portal receives the whole turn rather than just the text: streaming replies, thinking, tool events, artifacts and plan proposals
    • Answer from either end: permission gates and the agent's own questions now render on the phone and can be answered there, and a dialog answered on one device closes on the other instead of leaving buttons that decide nothing
    • The phone's stop button is the local stop — the same interrupt the sidebar uses, not a second mechanism that could disagree with it
    • Compose with @ and # from the phone: mention a soul, pick a tab, and ask what skills, souls and tabs the session actually has
    • The portal shows the session's mode and execution tier and can change neither, so you can see what the remote head is allowed to do
    • Notifications the agent raises reach the phone too, instead of only becoming a toast in the sidebar
    • Frames are end-to-end encrypted (Argon2id key derivation, AES-256-GCM): the relay carries ciphertext, and the pairing code is what opens it
    • The channel is tied to the session you opened it from — keep that window open, closing it ends the channel

    🐳 Headless image on Docker Hub

    • docker pull nevoflux/agent — the headless agent is now published on Docker Hub, tagged per release, so running it no longer starts with building it
    • Give it work over a small HTTP API (POST /tasks, then poll or follow SSE), or drive it as an OpenAI-compatible, MCP or ACP endpoint — they all reduce to the same task runner
    • Isolation is the container: one disposable container per task for untrusted work, or a long-lived service for trusted flows, with per-task caps on shell, filesystem, upload, domains, wall-clock and tokens
    • Watch a run live in any web browser over noVNC, and scrape Prometheus /metrics
    • Fixed-script mode runs a deterministic Python pipeline instead of the agent loop — the same browser tools, but no LLM calls and no API key
    • Session mode reuses one browser across a sequence of tasks, so a login carries from one to the next

    🛡️ Agent execution tiers

    • Agent execution in Settings is now four cumulative tiers: read-only (browse freely, confirm every change) → browser auto (+ run clicks and typing on its own) → + local read (+ read local files) → full auto (no confirmations)
    • A tier chip in the sidebar toolbar shows the current session's tier and follows whichever session you're in
    • Upgrading stays safe: the old Auto-execute setting never actually took effect, so it migrates to the strictest tier rather than silently granting full permissions

    🧹 /clear empties the sidebar

    • Clearing a session now empties the panel with it — including a plan panel or permission dialog left standing, whose buttons no longer decide anything
    • The sidebar also stays in the conversation with a quiet "Session cleared" line, instead of dropping you back to the welcome screen while the session is in fact still open

    🐛 Fixes & platform

    • Canvas sharing and Canvas tools work again — seven canvas.* calls (share, import, share list/extend/delete, tool invoke and list) were reaching the bridge mislabelled as event subscriptions, so artifact sharing had been dead since April and a Canvas app calling a whitelisted tool waited forever
    • Sidebar default is now three options — Remember last state (the new default), Auto-open and Manual only — enforced per window, so your choice holds at startup and through the session-restore burst instead of being overridden
    • Sturdier Linux CI: the AppImage build retries its tarball download and no longer fails on an unrelated apt mirror
    View on GitHub →
  5. v0.3.12

    The headline of this release is Space Souls — give each Space its own AI persona with an avatar that follows you — plus support for the Antigravity provider and agent reliability fixes.

    🪄 Space Souls

    • Give each Space its own soul: a named AI persona you bind per Space and edit in a dedicated editor — you can even have AI draft one for you
    • Summon a soul with an @-mention or a chip in chat, and see its avatar in the sidebar header and floating on the page, following whichever Space you're in

    🔌 Antigravity provider

    • Added the Antigravity provider, with a Terms-of-Service warning before you turn it on
    • The FAQ now covers the Antigravity ACP adapter install steps

    🐛 Fixes & platform

    • The agent now pierces closed shadow roots, so pages like LinkedIn's new app shell are readable again
    • The Loop Jobs panel backfills existing jobs, and event toasts auto-dismiss (and can be closed)
    • Sturdier builds: retry the Firefox l10n clone/fetch with backoff, rebuilt the chat-sidebar WASM, and pinned the arm64 toolchain to a Visual Studio instance with ARM64 + ATL
    View on GitHub →
  6. v0.3.11

    This release lets NevoFlux run tasks on a schedule and chase goals on its own, tracked from a new Jobs panel, with richer loop controls, OS notifications when the agent needs you, and a shortcut to toggle the sidebar.

    📅 Scheduled jobs & goals

    • New schedule and goal skills: ask the agent to run a task at a set time or on a repeating schedule, or to keep working toward a goal until it's verified done
    • A background scheduler runs these jobs even while you browse, with a jobs badge on the floating avatar that shows running, needs-you and done states
    • OS notifications now fire when the agent needs your attention and the window isn't focused, so reminders reach you even when NevoFlux is in the background

    🔁 Loop Jobs panel

    • A new Loop Jobs panel (in the maximized sidebar) lists running and completed loops, each with per-iteration details and the final result
    • Loop cards always offer a "View details" toggle and a pass/fail verify chip, plus a proposal card with an "Evolve now" button to refine what the loop does
    • Four starter loop templates and a new /loop verify option to gate each iteration

    🧭 Space- and folder-aware tabs

    • When the agent lists tabs it now respects your active scope and reports each tab's folder and Space, so it acts on the right tabs in Zen-style workspaces
    • Fixes so pinned-tab groups and the top window resolve correctly

    ⌨️ Shortcut & under the hood

    • Ctrl+Shift+A toggles the agent sidebar
    • The agent can run JavaScript inside a Canvas artifact (canvas_eval) to check its own work
    • Resynced the browser patches with upstream Zen changes
    View on GitHub →
  7. v0.3.10

    This release brings a floating agent avatar you can drag anywhere, a sidebar that follows each site's Zen Boost, a headless agent you can run in Docker, and code-signed Windows builds.

    👤 Floating agent avatar

    • A draggable avatar you can drop anywhere on the page, with a click menu to restore, maximize or close it
    • Status bubbles show when the agent is done or needs you, and minimizing now collapses the sidebar into the avatar (replacing the old sidebar-rail minimize)
    • Theme-aware bubble and menu colors, viewport-clamped positioning, and a NevoFlux logo fallback when no identity avatar is set

    🎨 Sidebar follows the website's appearance (Zen Boosts)

    • The agent sidebar now honors Zen's Boosts: restyle a site with a Boost and the sidebar follows its per-site look — invert, contrast, font, zoom and tint
    • Powered by a new pure theme-color engine with dark-palette accent indirection
    • The right sidebar gap now matches the left, with readable text across light and dark themes

    📝 Sidebar markdown upgrade

    • Switched the sidebar renderer to pulldown-cmark with table support, and split boot code out of init.js for a cleaner, CSP-safe startup

    🐳 Headless agent — run it in Docker

    • The agent now ships as a headless service you can run in a container: the new nevoflux/agent image (with a docker-compose.yml) spawns a fresh headless browser per task and serves a task HTTP API — no desktop UI required
    • Drive it your way — submit tasks over a small REST API (POST /tasks, then poll or stream results via SSE), or talk to it through an OpenAI-compatible /v1/chat/completions endpoint, MCP or ACP
    • Isolation-first: run one disposable container per task for untrusted work, or a long-lived service for trusted flows, with per-task policy caps (shell / filesystem / upload, domain allowlist, wall-clock and token budgets)
    • Watch a run live in your browser over noVNC, scrape Prometheus /metrics, and reuse one browser across a sequence of tasks with session mode
    • The image pulls prebuilt multi-arch (amd64 / arm64) releases — no local compile — and comes with the GBrain knowledge base enabled

    🔧 Post-update maintenance

    • Bundled cross-platform cleanup scripts run after each update, plus a replace/keep dialog when bundled skills change so your own edits aren't overwritten
    • Successful Pack installs are now reported to the website's install count

    🔐 Signed Windows builds & fixes

    • Code-signed Windows installer and portable zip for x64 and arm64 (Authenticode SHA-256, RFC3161 timestamped)
    • Extension menu-bar injection now probes both browser-menubar filenames, and agent state resets cleanly on daemon disconnect
    • skill-creator's record & replay now compiles recordings into run_flow packages
    View on GitHub →
  8. v0.3.9

    A small stability release that makes the knowledge base work reliably in installed builds and keeps slow agent tools from timing out.

    🧠 Reliable knowledge base in every build

    • The agent's ONNX Runtime — the engine behind the knowledge base's embeddings introduced in 0.3.7 — is now bundled in every release for Windows, Linux and macOS (including universal builds) and refreshed when the in-app agent updates, so semantic search works in installed builds, not just in development

    🐛 Fixes

    • Raised the Claude agent's MCP tool-call timeout to 5 minutes (above the knowledge base's own 120-second limit), so a slow tool returns its real result or error instead of being cut off early by a timeout that looked like success
    View on GitHub →
  9. v0.3.8

    The headline of this release is Record & Replay — show NevoFlux a workflow in the browser once and turn it into a reusable skill — plus one-click Pack installs straight from a link.

    🎬 Record & Replay

    • Demonstrate a task instead of describing it: a passive recorder watches your real in-page actions and navigation (it never blocks you) while the agent writes an ordered, lossless trace
    • Agent-orchestrated with new start_recording / stop_recording tools — the agent arms the recorder on the active tab, you perform the workflow, then it stops and reads the recording
    • The skill-creator turns that demonstration into a reusable skill: values you confirm become placeholders, secrets are never baked in, and durable role + name selectors are carried over so the skill relocates elements live and survives page changes
    • Browser use scope for now (in-page interactions plus navigation), with a new Record & Replay guide for skill authors

    📦 One-click Pack install from a link

    • Open a Pack install link and get an inspect → preview → confirm → install flow right in the browser, with live progress — no trip through Settings
    • GitHub-only sources, with install / update / reinstall decided for you

    🐛 Fixes & platform

    • Windows: the agent no longer hangs on Ctrl+C shutdown
    • Fixed the Linux AppImage launcher name and taskbar icon (zen → nevoflux)
    • Skills: list fields such as allowed_tools now accept either a single value or a list
    View on GitHub →
  10. v0.3.7

    A big platform release: NevoFlux catches up to Zen Browser on Firefox 151, bringing Boosts and Space Routing, alongside Canvas and knowledge-base improvements.

    ⬆️ Synced with upstream Zen Browser (Firefox 151)

    • Jumped from Firefox 149 to 151, picking up the latest upstream Zen features and fixes
    • Boosts — restyle any website to your taste: adjust element size and text case, tweak color contrast, brightness and saturation, invert, or drop in your own CSS — then save and reuse them per site
    • Space Routing — send matching sites to the Space you choose, so links open where they belong
    • Plus upstream tab, workspace, split-view and window-sync fixes and polish

    🧠 Knowledge base (Brain)

    • Upgraded the embedding engine to fastembed 5 (ONNX Runtime 1.24.2) with dynamic loading, for faster and more accurate semantic search across your saved pages

    🎨 Canvas

    • Export an artifact's full HTML content to PNG, not just the visible viewport
    • Large artifacts now persist reliably — the content store cap went from 500 KB to 50 MB, so files over 1 MB save without being dropped

    🐛 Fixes & stability

    • More reliable Pack install: progress now streams (no more 30-second bridge timeout) and a watchdog keeps the dialog from hanging if the stream stops
    • Sidebar shows an optimistic "Start Setup" that reconciles with the authoritative status
    • Softened harsh white-out flash transitions in the video skill's templates, with a new linter rule to catch them
    • Steadier Windows native builds
    View on GitHub →
  11. v0.3.6

    A focused release that adds Packs management, with Windows build and stability fixes.

    📦 Packs

    • New Packs management section in Settings
    • Install Packs directly from GitHub sources, with an inspect → preview → confirm flow
    • A pack development reference guide for authors

    🐛 Fixes

    • Restored missing chrome resource URLs after the workspaces → spaces sync
    • More reliable pack-install dialog — its auto-close timer now tracks the correct modal

    🛠️ Build & platform

    • Re-enabled WebRTC on native Windows builds
    • Steadier Windows builds: capped native compile parallelism to avoid clang out-of-memory, de-hung the mozmake setup in CI, and trimmed cruft from the source tarball
    View on GitHub →
  12. v0.3.5

    🧠 Knowledge Base (Brain)

    • A built-in personal knowledge base (your "second brain") powered by GBrain, an AI-agent memory system that synthesizes cited answers across your saved pages and auto-builds a knowledge graph — not just keyword search
    • New nevoflux://brain browse page and install wizard, save-to-knowledge-base from any page, shareable .nbrain packs (create, manage, import), and a gbrain runtime with status and restart/update controls
    • Five /brain skills work together:
      • brain — the hub: entry point and shared conventions that route to the four skills below
      • brain-capture — save and ingest notes, web pages, PDFs, Office and ebooks, video subtitles and images, with optional web enrichment
      • brain-recall — look up saved pages, recall facts, see what is notable or recent, and follow links and backlinks
      • brain-think — synthesize: multi-hop cited answers, who-knows-about routing, trends, concept maps and prediction calibration
      • brain-care — health and recovery: diagnostics, sync, find contradictions and orphans, and restore deletes or earlier versions

    🔁 Iterative tasks (/loop skill)

    • Run a prompt or skill on a loop, with sticky loop cards and per-iteration progress
    • A /loop slash command and a DOM watcher for state-triggered iterations

    🎬 AI video generation (/video skill)

    • Generate videos on the Canvas with a new render pipeline (nevoflux://render): deterministic frame capture, progress cards and cancellation
    • A library of HTML templates and components — captions, lower-thirds, transitions, data charts and 3D reveals — plus TTS and Three.js workflows
    • A composition linter that catches issues before rendering

    🤖 Stronger browser automation

    • Rich-text and contentEditable editing (paste and fillRichText), file uploads, element probing and stable CSS selectors
    • Shadow DOM editor support and smarter tab activation and navigation

    🎨 Canvas sharing and tools

    • Share and import canvases (nevoflux://import) with redesigned dialogs and one-click copy
    • Pin artifacts to My Canvas, and manage custom Canvas Tools from settings

    🧩 Platform

    • An EventBus with notification toasts and tab-discard recovery; the NevoFlux Agent is now a built-in system add-on enabled on first launch

    ⬆️ Synced with upstream Zen Browser (Firefox 147)

    • Brings Zen features and fixes: workspaces, split view, live folders, essentials, window sync, drag-and-drop improvements, macOS native popovers, and session backup and restore
    View on GitHub →
  13. v0.3.2

    A maintenance release focused on extension distribution and Windows upgrades.

    🔌 Extension distribution

    • The bundled NevoFlux Agent extension now auto-syncs on startup, with its version injected into the manifest automatically
    • More reliable XPI syncing

    📦 Installer and build

    • Windows upgrades now clear the old extension cache
    • Fixes for Windows build paths
    View on GitHub →
  14. v0.1.3

    🎨 Canvas exports

    • Export artifacts to PNG, PDF, DOCX, SVG, Markdown, XLSX and ZIP
    • New slides artifact type with a PowerPoint-style preview and PPTX export
    • An export split-button with a format dropdown

    💬 Sidebar

    • AskUser prompts are now shown as question-and-answer cards
    • Fixed code-block copy in markdown and sidebar resize after collapse

    ⚙️ Settings

    • New OpenClaw extended configuration form
    • AI settings split into separate LLM Providers and Agents sections

    📖 Docs

    • Updated README and architecture, and added an FAQ covering the sidebar shortcut, settings and Claude Code setup
    View on GitHub →
  15. v0.1.2

    🤖 AI agent and browser automation

    • New nevoflux browser API and engine that lets AI drive the browser
    • Browser Use tools: tab management, mouse and keyboard control, cookies and storage, network capture and interception, JavaScript execution, frames, dialogs and downloads
    • Element picker, page lock, scrolling, wait-for-stable, and automatic page snapshots
    • Privacy-filtering kernel, in-browser WASM agent runtime, and a Manifest V3 extension

    💬 Sidebar chat

    • AI chat sidebar with a first-launch onboarding wizard and a connection status bar
    • Message attachments, recent history, and sidebar-to-tab mode switching

    🎨 Canvas micro-apps

    • Generate multi-file mini-apps bundled in the browser with esbuild-wasm
    • A virtual file system with persistence, and React, Vue and Svelte support

    ⚙️ Settings and branding

    • LLM provider configuration, including a custom base URL
    • NevoFlux branding, welcome screen, and menu integration

    🛠️ Builds

    • Cross-platform builds for Windows, macOS (universal) and Linux (x64 and arm64), with code signing
    View on GitHub →