Changelog

v0.4.22

Features

  • Claude Opus 5 is here, and it is the new default. Anthropic's most intelligent model is available across Foxl Agent, Foxl Code, and Foxl Notes from day one. It matches or beats Fable 5 on agentic coding and professional knowledge work at half the price, so it takes over as the default everywhere Opus 4.8 used to be - same $5/$25 rate, materially stronger results, no action needed on your side. 1M context, 128K output, all five reasoning effort levels, and reasoning is now on by default: Opus 5 decides for itself how long to think on each turn. Every earlier model stays available in the picker.
  • Model pickers show the current generation, not the archive. Superseded models (Opus 4.7 and 4.6, Sonnet 4.6, GPT-5.4 and older, Gemini 2.0) are now hidden by default across all four model pickers - chat, Settings, Foxl Notes, and Foxl Code. Nothing was removed: "Show older model versions" in Settings > Model & provider brings them all back, and every picker has the same one-tap row at the bottom of its list. A model you have selected or favorited is never hidden, and searching still finds everything, so typing "4.6" turns up Sonnet 4.6 with the setting off. Foxl Notes and Foxl Code settings carry the same switch, so wherever a list is shortened you can widen it on the spot.
  • Foxl Code: your starred models stop disappearing. Foxl Code and Foxl Agent share one favorites list, but stored them in two different formats, so opening Agent chat once silently unstarred every model you had favorited in Code. New Foxl Code chats also started on Sonnet 4.6 while the send path assumed Sonnet 5; both now agree on Sonnet 5.
  • Gemini CLI actually works now. Replies came back empty every time: Foxl read the CLI's stream in a format it has never emitted, so every line of the answer was discarded. Errors were worse than silent - a quota or sign-in failure was indistinguishable from success, so you got an empty reply with no explanation. Both are fixed, the current Gemini 3 models are selectable, and signing in with gemini is now detected (Foxl only looked for an API key, so a signed-in CLI still showed as not configured).
  • Fixes to model identity that were quietly costing you. Picking the short "Claude Code Sonnet" option ran Sonnet 4.6 long after Sonnet 5 shipped. Six other model IDs resolved to nothing internally, which made Foxl treat a 1M-context model as 256K - compacting your conversation about five times earlier than needed - and record its cost as zero. GPT models over a ChatGPT subscription were assumed to hold 1M tokens when the service actually serves 272K, so long sessions failed upstream instead of compacting in time. A GPT-5.3 option that OpenAI does not serve at all has been removed.
  • Settings: a Refresh button next to Save Provider Settings. After running claude /login or codex login outside the app, Foxl kept showing the old "not configured" state until you restarted it. Refresh re-reads provider credentials and model lists on the spot.
  • Chat: starter prompts on mobile actually work now. The tappable "try asking something like" rows under the mobile greeting had never been able to show anything; they do now, and your last greeting and prompts are remembered so they appear instantly on a cold start instead of a few seconds later. The desktop empty state is unchanged (greeting and composer, no prompt list). The composer no longer repeats the question already asked above it.
  • Sidebar: switching product closes the mobile drawer, like every other destination in it, so you land on the screen you tapped instead of dismissing a panel first. The product switcher is also reachable by keyboard and screen reader for the first time.
  • Foxl Code: AgentCore compute is now actually billed. A task costs two things - the model tokens and the machine it runs on - and the machine half was never charged on relay-routed tasks, because finalize treated the two as alternatives and kept only the larger. Both are now recorded, and a task's reported cost is the real total. Pre-flight cost estimates also no longer price a model at zero just because it was missing from an internal table.
  • Foxl Code: budget settings that actually do something. The Budget section had four knobs, and two of them did nothing: an "Account-wide budget cap" that promised to reject new tasks (nothing enforced it) and a "Hard cap fraction" the server ignored. Both are gone, along with the per-task multiplier, leaving one number - max spend per task - which the relay really does enforce. The daily spend cap also could not be saved at its own default value; its limit now matches the server's.
  • Foxl Code: Runtimes shows real live spend. The spend bar read $0.000 for the entire time a task was running, because that figure is only written when the task finishes. It now shows the running total the relay is metering. The fake mini-terminal preview, which could never display agent output, is gone.
  • Foxl Notes: an AI summary can no longer land on the wrong note. If you clicked a different note while a summary was still being written, the finished summary replaced THAT note's contents and renamed it. The summary now always goes to the note it was started for, and it no longer overwrites whatever you happen to be reading.
  • Foxl Notes: import a recording you already have. Drag a wav, mp3, m4a, or mp4 onto Notes - or use File > Import Recording... - and it becomes a new note with a full transcript, speaker labels, and the same AI summary, title, and export you get from a live recording. It runs through the exact same transcription path as recording, so an imported note behaves like any other note; the audio is kept too, so clicking a line still plays that moment.
  • Foxl Code: one chat, like Foxl Agent. Sending the first message no longer jumps you to a separate task screen with what looked like a copy of your conversation. You stay in the same chat, the reply keeps streaming, and the new task appears in the left sidebar. Picking a task from the sidebar swaps that task's thread in place and reveals its status, plan, PR link, and live terminal above the same chat; picking nothing puts you back on a fresh chat. The composer no longer jumps from the middle of the screen to the bottom either - it is the same composer, so a half-typed message and its attachments survive your first send. The old "Clear chat" link is now "Reset session" in the task menu, next to Retry and Cancel.
  • Chat: a marker when the model changes mid-conversation. Switching the model in the middle of a chat now drops a subtle "Switched to <model>" divider into the transcript, so the record shows which model answered which turns. It only appears on an actual change (consecutive same-model turns add nothing) and is saved with the conversation on app.foxl.ai and mobile, so it survives a reload or a second device. (On the desktop app the marker shows for the session; the divider is not yet persisted to the local chat database.)

v0.4.21

Features

  • Foxl Code: the loop closes itself. A batch of loop-engineering capabilities so a task drives from prompt to verified PR with less hand-holding:
  • PR reviewer (maker-checker). When a coding agent opens a pull request, an independent reviewer agent fetches the diff, grades it against the original task, and posts a real GitHub review (approve or request changes with a structured assessment). On "request changes" the coding agent is automatically resumed with the feedback, up to two rounds.
  • CI-aware self-heal. Foxl now ingests GitHub check/workflow results: a task shows a CI status chip, and a red run feeds the failing check back to the agent to fix instead of sitting silently.
  • Verify gate. After a coding agent finishes, its repo's own test suite runs; a red suite blocks the PR and marks the task failed rather than "ready for review".
  • Scheduled tasks. Set a task to run on a cadence (every N hours or a daily UTC time on chosen weekdays), from Settings or by asking the agent. Scheduled runs respect the same budget and beta gates as manual ones.
  • Per-repo memory + custom instructions. Tasks start warm with a short brief distilled from prior work on the repo, plus account-level custom instructions and per-user MCP connectors.
  • Cross-device chat history. Foxl Code chat threads are mirrored server-side, so a task's conversation is there when you reopen it on another device.
  • Push notifications when a task is ready for review, merged, or fails.
  • Foxl Code: more coding agents. Codex (default model GPT-5.6 Sol), Kiro, and OpenCode backends are enabled alongside Claude Code, and mid-run steering (read the agent's screen, send input, resume) now routes to each backend's own runtime instead of only Claude Code's.

Fixes

  • Notes: transcript sentences no longer land out of order. With system audio + mic captured together (two transcription pipelines) or across the periodic socket rotation, a late-arriving sentence could be appended to the bottom of the live transcript - and stay there in the saved note - instead of slotting in where it was actually said. Segments are now kept in absolute audio order as they stream in, the transcript view sorts defensively, and previously saved notes are repaired on load (fixes copy, summaries, and send-to-notes built from those notes too).

v0.4.20

Features

  • Foxl Code: per-task conversations. Every task now has its own chat thread alongside the live terminal (Conversation | Terminal toggle in the task header, next to the status). The home composer starts a task and drops you into its thread; follow-ups there steer the same coding agent instead of starting a new one. Clear chat now clears only the thread you are in, and the autonomous heartbeat's updates get their own activity feed on the Tasks home page.
  • Foxl Code: one chat UI everywhere. The Tasks home and a task thread now render the exact same chat surface (the glass-composer, rich reasoning + tool-call timeline). Previously the two used different code and looked unrelated. Each task also has its own address (/code-tasks/:id, like the Agent's /chat/:id); /code-tasks is the "new chat" home.
  • Foxl Code: the "Tasks" title is New Chat. Clicking the Tasks title in the Code header (from anywhere, including inside a task) returns to the empty composer home and starts a fresh chat, mirroring the Agent header.
  • One Settings for all three products (desktop). Opening Settings from Notes or Code now lands in the same two-pane Settings view the Agent product uses, drilled to that product's section - instead of each product showing its own standalone settings page. Every setting is reachable from every product, and the mobile sheet already worked this way.

Fixes

  • Code Settings opens again. After viewing any task, clicking Settings in the Code sidebar footer kept showing the task instead of Settings: the task-selection sync replayed the remembered task over the fresh settings route on every remount. The sync now only drives task routes, and the desktop Settings entry renders the unified Settings directly.
  • Code Settings coding-agent cards read properly. Inside the shared Settings column the coding-assistant picker used a 3-column grid meant for the wide standalone shell, so each card squeezed to ~200px and every label wrapped one word per line. The cards are now full-width rows, and product settings (Notes/Code) get a wider column than the plain preferences list.
  • Code "New task" button works from anywhere. The in-shell New task button did nothing while a task detail page was open (only the Tasks page listened for its event); it now clears the selection and opens the composer from any Code page.
  • One language setting for the whole app. The Code sidebar could show Korean labels while the rest of the app was English: its nav labels were missing from the shared locale files, and Notes kept its own UI-language picker in its own store. The language picker in Settings > General is now the single source of truth - it drives Agent, Notes (including the HUD window and AI output language), and Code together, and the Code nav labels are translated in all 10 locales.
  • Foxl Code task view polish. A spawned task's prompt now shows as a proper user message bubble (it used to render as a washed-out grey box); the task header is a single tidy row; and a stray vertical scrollbar that appeared even on short pages is gone.
  • Foxl Code: "Tasks" title now actually leaves a task. Clicking Tasks while viewing a task changed the address bar but left the task on screen; it now returns to the composer home.
  • iOS: the top and bottom safe-area strips match the app. In dark mode the strips around the clock and home indicator showed pure black against the app's slightly-grey background (and could even show the opposite colour when the phone's system appearance differed); they now paint the same colour as the app in both themes.

Marketing

  • The Foxl Code landing hero is now a live recording. foxl.ai/code plays a real screen capture of app.foxl.ai/code (typing a task, browsing the Task Plan) in a browser frame - retina-crisp, autoplaying muted loop with a play/pause control, a scroll scale-up entrance, and a poster fallback that respects reduced-motion preferences.

v0.4.19

Features

  • The mobile terminal has a reconnect button. Next to the new-tab chip, the refresh chip does what the desktop terminal's refresh does: tears the session's connection down and reconnects, re-hydrating the scrollback.

Design

  • Glass everywhere it floats. The chat's scroll-to-bottom arrow is now a frosted glass chip like the header buttons, and the mobile terminal's bottom bar matches: quick keys and arrows as translucent glass pills on the dark surface, and the command box restyled as a frosted glass card with the same specular rim and lift as the message bar.

Fixes

  • Spawning a terminal from the web app no longer shows two tabs. Starting a terminal on app.foxl.ai created one real session but two tabs (both looking selected): the desktop's "terminal appeared" push and the spawn request's own response both added the same session. The session list now merges by id, so one session is always one tab.
  • Rolled back native iOS glass. v0.4.18's native Liquid Glass darkened the top and bottom of the app on real devices and the glass never showed: an iOS app is fullscreen, so unlike a transparent macOS window there is nothing behind the web view for glass to sample - making the web view transparent only exposed the app's black container. The header chips and message bar are back on the proven CSS glass everywhere.
  • The mobile terminal now covers the whole screen. It slid in under the header (sidebar/title/menu chips stayed visible) because the animated app shell turns position: fixed into shell-relative positioning; the terminal page now renders outside the shell, so it truly covers everything, header included.

v0.4.18

Fixes

  • Desktop terminals appear the moment the app opens. On web and iOS the terminal list was fetched once at launch - before the desktop connection was up - so it came back empty and only a terminal opened *after* that point would show. The list now re-syncs as soon as the desktop comes online and on every app resume, so terminals already open on the desktop are there immediately.

Design

  • Real Liquid Glass on iOS 26+. The header chips and the message bar now render actual system glass - native UIGlassEffect views tracked behind the web content via our new @foxl/capacitor-liquid-glass plugin (the electron-liquid-glass architecture, adapted to Capacitor) - instead of a CSS imitation. Older iOS, Android, and the web keep the CSS glass.
  • Cmd+T shows and hides the terminal. One shortcut flips the chat's terminal view open and closed, from anywhere in the app (desktop menu accelerator + in-page shortcut on the web).
  • The mobile terminal is a full page now, not a bottom split. Tapping the terminal in the message bar pushes a full-screen terminal in from the right (the iOS navigation push), so the PTY and its command input get the whole screen instead of fighting the chat composer, quick keys, and keyboard in one cramped stack. Swipe right from the left edge - or tap the round back chip - to return to the chat. Desktop keeps the bottom panel.
  • Mobile header, reworked. The three round header buttons grew to a full 44px touch size, and search + new chat merged into one menu button: tap it and an iOS-style menu drops out of the corner (with the springy water-drop spread) holding Find in this chat, Search conversations, and New chat.
  • Mobile sheets match the shell's roundness. The Settings sheet and the model selector sheet now use the same 28px corners as the main screen card when the sidebar drawer is open, so all lifted surfaces read as one family.

v0.4.17

Features

  • GPT-5.6 Luna joins the free tier. Free accounts can now chat with GPT-5.6 Luna (the fast, light GPT-5.6 tier) alongside Haiku 4.5, Sonnet 4.6, and Sonnet 5. Sol and Terra remain Pro+.
  • Locked models sink to the bottom of the model picker. Models your plan can't use no longer sit greyed-out between usable ones - they collect in a "Requires upgrade" group at the end of the list.

Fixes

  • Stop responds instantly on mobile. Two bugs stacked up: the web app's tunnel routing dropped the abort signal, so tapping Stop cancelled nothing - the reply kept streaming until the desktop finished; and on iOS the tap itself could be swallowed when it coincided with the keyboard dismissing. Stop now aborts on touch-down (with a haptic tick) and the abort reaches the stream and the desktop agent immediately.
  • A failed reply now always answers back. Credits exhausted, a model not on your plan, permission or rate-limit errors used to vanish - no toast, no banner, no bubble. Every failed turn now ends with a clear in-conversation reply (a calm red-tinted message that persists in history) explaining what happened and what to do next, on desktop, web, and mobile alike.
  • Tool activity chips stopped swapping identities for good. The tool name now rides the authoritative SDK event (not a lookup that could miss), and every pairing path - live stream, tunnel, and mid-stream reconnect replay - refuses to attach a result to a different tool's chip. Shell commands no longer render as "file read" or "web search".
  • Model and provider names no longer clip in Settings on phones. Wide pickers (Notes AI model, translate model/language, save format) drop to their own full-width row on small screens instead of squeezing into an ellipsis next to the label.

Design

  • Selects match the app's roundness. Dropdown triggers, menus, and rows across Settings now use the same softly-rounded corners as the chat model selector (rounded-lg triggers, rounded-xl menus) instead of the sharper stock corners.

v0.4.16

Fixes

  • CRITICAL: replies work again on mobile and app.foxl.ai without the desktop connected. Since v0.4.13, chats on the relay-only path rode a relay-internal conversationId field (for chat-complete push deep links) that the relay forwarded verbatim to the model provider. Bedrock rejects unknown fields ("Extra inputs are not permitted"), so every model returned an empty reply with no message bubble. The relay now strips relay-internal metadata before any upstream forward, with a regression test that sends exactly what the apps send.
  • Tool activity chips no longer mislabel each other's work. When results arrived for interleaved tools (for example a web fetch and a shell command running in the same turn), a result that missed its id match was stapled onto whichever chip was last running - showing "Web search completed" over a python command, duplicated across rows. Results now carry the tool name and only ever pair with a chip of the same tool.
  • Mobile header buttons line up with the message bar. The phone header's glass chips sat on a slightly narrower margin (px-3) than the composer strip (px-4), so the top row looked subtly off against the message bar. Both now share the same horizontal edge.
  • Workspace is friendlier to touch. File and folder rows get taller tap targets on touch devices, the mobile back button is a proper 36px target, Save grows to a touch-sized button, and the editor uses 16px text on phones so iOS no longer zooms in when you tap it.
  • Every recent blog post has its own cover. Four posts (v0.4.10, v0.4.12, v0.4.15, and the AirPods deep-dive) shared the v0.4.7 sessions thumbnail; each now has a cover drawn from its own story.

v0.4.15

Fixes

  • Skills, Channels, and custom tools (MCP) are reachable again. When Integrations moved from the sidebar into Settings, its five-tab bar (Integrations / Skills / Channels / System / Custom) was left behind in the old page header - so Skills, Channels, and the System/Custom tool pages (including custom MCP servers) silently disappeared from the UI. Settings > Integrations now carries all five tabs inside the section as a segmented control, on desktop and mobile.
  • The Integrations section scrolls on mobile. The Settings sheet expects each section to own its scrolling; Integrations didn't, so the section was frozen at the top on phones. The new hub owns its scroll container.
  • Integrations dropped its gradient hero for a quiet prompt strip. The rotating full-color gradient carousel is gone; in its place a single flat row shows one featured integration with a real example prompt and a "Try in chat" button - tap the row to see the next example. Less visual noise, zero idle animation cost (the carousel was a steady compositor load on phones), and the page now reads like the rest of Settings.
  • Usage scrolls (and loads fast) on the phone. The Usage section didn't own its scrolling inside the Settings sheet, so it was frozen at the top on mobile - fixed. Its dashboard also caches to durable storage now, so reopening the app paints the last numbers instantly and refreshes in the background instead of holding a spinner through a full tunnel round trip. The headline metric scales down on small screens instead of overflowing.
  • Workspace opens instantly on the phone. The file tree now persists to durable storage: relaunching the app paints the last known tree immediately and refreshes in the background, instead of spending seconds on a spinner while the tree crosses the tunnel. (Demo data shown while the desktop is disconnected is never persisted.)
  • Your name no longer gets stuck as "..." in the sidebar. Opening the app after being away could leave the account footer showing "..." even though you were signed in: the profile lookup sent the expired session token, got rejected, and never retried - on the web a manual refresh papered over it, but the app has no refresh gesture. The lookup now refreshes the token first, re-runs automatically when a refresh happens or the app returns to the foreground, and keeps showing the cached name instead of blanking to "..." while it revalidates.
  • The Skills page dropped its gradient hero too. Same treatment as Integrations: the rotating gradient carousel is replaced by a flat prompt strip (tap to see the next example) - no ambient animation left anywhere in Settings.
  • Usage Breakdown folds on the phone. The per-model chart in Account is collapsed behind its headline total on mobile - tap to expand. The number you check stays visible; the dozen bar rows no longer push everything else off screen.
  • A tall message bar no longer covers the conversation. The chat's bottom scroll room was sized for the short one-line composer, so a multi-line draft or an attachment card sat on top of the last messages with no way to scroll them clear. The scroll area now tracks the composer's real height - as the bar grows, the conversation gains exactly that much extra room, and if you're reading the bottom it stays pinned above the bar.
  • Attachment chips show their remove button on the phone. The X to remove a pasted-text block, image, or document from the message bar only appeared on hover - a concept touch screens don't have, so on mobile there was no visible way to remove an attachment. On touch devices the X is now always visible as a quiet gray chip (and slightly larger for the finger); desktop keeps the hover reveal, now in the same quiet gray instead of alarm red - removing a draft attachment is routine, not destructive.

v0.4.14

Features

  • Share from the iPhone app. Every chat reply now has a share button that opens the iOS share sheet (Messages, Mail, AirDrop, Notes...), and Notes exports (.md / .docx) go through the share sheet too - previously the browser-style download simply vanished on iOS, so exporting from the phone didn't work at all.
  • The app icon shows an unread badge. When replies finish while you're away, the home-screen icon carries a count that matches the in-app unread state and clears as you read. Chat-finished pushes also set the badge, and opening the app sweeps its delivered notifications out of Notification Center instead of letting them pile up.
  • Home-screen quick actions. Long-press the Foxl icon for New Chat and New Recording - New Recording jumps straight into Notes and starts recording.
  • foxl:// links now navigate the iPhone app. Links like foxl://chat/{id} (the sidebar's "Copy link") and foxl://chat/new open the right conversation on the phone instead of just launching the app; they work from a cold start too.
  • The status bar matches the app theme on iPhone. Switching Foxl between light and dark now flips the clock/battery icons to stay legible, instead of leaving them at whatever the system default was.
  • Unread tracking works on the phone. A reply that finishes in a background conversation now marks it unread (sidebar dot + icon badge) on the mobile app, matching desktop behavior.
  • Cmd+1 / Cmd+2 / Cmd+3 switch between Foxl Agent, Notes, and Code. The product switcher now has first-class keyboard shortcuts on desktop, listed in the View menu so they're discoverable like any native app.
  • "New Recording" in the menu-bar tray. Right under New Chat: starts a Notes recording immediately and brings up only the floating meeting panel - the main window stays wherever it was, so you can capture a meeting without switching context.
  • The floating meeting panel opens instantly. It used to build its window from scratch on every open (and closing destroyed it), which took visible seconds. The panel is now pre-warmed hidden at startup and hides instead of closing, so opening it - from the tray, from Notes, or automatically when a recording starts - is immediate.
  • Bottom sheets on the phone now swipe down to close. The model picker and the Settings modal follow your finger 1:1 on a downward drag and dismiss past the threshold (or on a quick flick), springing back otherwise - the standard iOS sheet gesture the grab handle always implied. Scrolling inside a sheet still works: the drag only takes over when the content is at its top. Both sheets also float with a slim gutter on each side instead of running edge-to-edge. (Follow-up during staging: the gesture now attaches at the document level so the portal-mounted model sheet actually receives it, and a dismissed sheet slides straight off instead of replaying its exit animation from the top - the brief "bounce back up" glitch.)
  • Key actions on the phone now give haptic feedback. Opening the sidebar, starting a new chat, opening Settings, sending a message, and picking a model or reasoning effort each give a light native tick (a firmer one for send). Phone app only - web and desktop are unchanged.
  • Notes recordings keep going in the background on iPhone. Starting a recording and switching apps (or locking the screen) no longer kills it. iOS suspends web-view microphone capture the moment an app leaves the foreground, so the iPhone app now records through a native audio engine instead - paired with the audio background mode, the capture and live transcription continue with the system's recording indicator showing. Phone calls interrupt and resume cleanly, and switching to or from AirPods mid-recording re-anchors the capture instead of going silent.

v0.4.13

Features

  • Mobile notifications now have per-category controls. Settings > Notifications on the phone splits into individual toggles - chat replies, scheduled tasks, product updates, and promotions & tips - like a proper app, instead of one on/off. Each toggle is stored on the relay (the thing that actually sends the push), so a change takes effect immediately across your devices. Promotions are off by default and only ever sent to people who turn them on.
  • "Open Settings" jumps straight to the system notification screen. When iOS or Android has notifications turned off for Foxl, the settings screen now has a button that opens the OS app-settings page directly - the standard way to re-enable them, since no in-app toggle can grant the system permission itself. A "System notification settings" row is always available too.

Fixes

  • Chat-finished notifications now actually arrive on the phone. The chat-complete push was only wired into the desktop tunnel path, so a reply sent straight from the phone (or app.foxl.ai) finished silently with no notification when the app was backgrounded. The relay now fires the push on the mobile chat path too, and keeps the reply generating to completion in the background even after the app is backgrounded or locked. The iOS app also declares the remote-notification background mode so the system can wake it to deliver.

Features

  • See which chats are still answering, right in the sidebar. Every conversation with a reply in progress now shows a small right-aligned spinner next to its name - whether that chat is open in front of you or generating in the background. Replies already keep running when you switch to another chat; now the sidebar makes that visible so you know at a glance what's still working. On desktop the spinner steps aside for the delete button on hover (same slot, no layout jump); on mobile it stays put.
  • The phone has its own notification settings. Settings > Notifications on mobile is no longer the desktop's notification page: it now shows the phone's push controls - whether iOS has allowed notifications for Foxl (with a one-tap request, or a pointer to system Settings if previously denied), and per-kind toggles for chat-reply and scheduled-task pushes. The toggles are stored on the relay, which is what actually sends the push, so turning one off takes effect immediately for every registered device. Desktop notification settings are unchanged and stay on the desktop.

Fixes

  • Notes recordings now capture the meeting's audio, not just your mic. Recording with headphones or AirPods produced an empty or one-sided transcript: the other participants' voices played inside your headphones and never reached the microphone, and system-audio capture only ran when live translation was armed. Every recording on desktop now captures system audio (the sound this Mac is playing) and mixes it with your microphone - both in the transcript and in the saved audio file. A new toggle in Settings > Recording turns the capture off. This needs macOS's "System Audio Recording Only" permission, which macOS never prompts for on its own - it just hands over a working-looking but silent capture - so Foxl now proves the capture end-to-end instead of trusting it: a new onboarding step and a test button in Settings > Recording play a short inaudible tone and verify it comes back through the capture, with a one-click "Open Settings" jump straight to the right privacy pane when it doesn't. The same self-test runs at the start of every recording; if the capture is dead, a standing warning appears in Settings until it's fixed. On macOS older than 14.2, where the system can't provide loopback audio at all, it tells you up front that the recording is microphone-only.
  • A background chat's tool activity no longer bleeds into the chat you're reading. When a reply that uses tools kept running in one conversation and you opened another, the first chat's "running tool" chips and status could appear at the bottom of the new chat - pure display bleed, nothing was actually shared. Tool status is now tracked per conversation on every path (desktop stream, WebSocket events, relay web), and a background turn can no longer paint its bubbles or tool chips into whichever chat is on screen.
  • A single ~ no longer strikes through your text. Chat and Notes render Markdown, and a lone tilde used as a range ("rank 0~7, rank 8~15") was being paired with the next tilde and struck through everything between them - so a perfectly normal sentence showed up with a line through it. Strikethrough now requires the standard double tilde (~~like this~~); single tildes are left as plain text.
  • The keyboard animation no longer reflows the app every frame. Docking the composer on the rising keyboard animated the shell's height, and height is a layout property - every frame of the 250ms transition forced a full relayout of the app, which stayed visibly choppy no matter how much paint work was removed. The composer now rides the keyboard on a compositor-only transform and the real layout change commits exactly once, at the moment the keyboard settles - the standard technique for smooth keyboard docking in embedded web views.

v0.4.11

Fixes

  • The keyboard animation is smooth on mobile. While the app shrank to dock the composer on the rising keyboard, every animation frame re-rendered the glass surfaces' backdrop blur - the most expensive per-frame job in the iOS web view, and the source of the stuttery keyboard feel. During the 250ms docking transition the glass now switches to a near-opaque matte and the frost returns the moment it settles; the swap is imperceptible, the dropped frames are gone.
  • Sidebar text no longer peeks out while the keyboard opens. The reveal drawer sits at full screen height behind the app shell, so when the shell shrank for the keyboard, drawer rows ("For You") showed through the strip between the shell and the keyboard. The closed drawer is now fully hidden, with the hide delayed past the close animation so it never vanishes mid-slide.
  • Glass looks closer to native iOS material on phones. Touch devices with backdrop-filter support now get a more translucent tint with stronger blur and saturation on the header buttons and composer - nearer the real iOS 26 material in the native app - while desktop keeps its subtler treatment.
  • The content panel border is back to its v0.4.1 weight. The recent full-opacity border on the desktop inset shell read too heavy; restored the original softer hairline.

v0.4.10

Features

  • Get a notification when your chat finishes on mobile. Send a message from the phone, switch apps or lock the screen, and Foxl now delivers a system push when the response is ready - tapping it opens that conversation. The push only fires when the app actually stopped watching the stream mid-turn; foreground chats never notify.
  • The product switcher is now three tabs. The sidebar's "Foxl Agent" dropdown is replaced by a segmented Agent / Notes / Code control on both desktop and mobile - one tap to switch, and the active product is always visible.
  • Swipe to manage chats on mobile. Conversation rows in the mobile sidebar now swipe left to reveal Rename and Delete, replacing the long-press menu. The drag tracks your finger and settles with a spring; tapping an open row closes it. Desktop keeps the right-click menu and hover actions.
  • Settings is a native mobile sheet, and all three products now share it. On the phone, Settings slides up as a glass sheet over the app (the sidebar stays put beneath it, iOS-style) with a single round back button - no title bar, no divider - and sections push in from the right and pop back like a native settings app. Your Account, Integrations, Mobile/Web, and Usage all moved inside it, and Foxl Notes and Foxl Code settings are sections here too, so everything lives in one place. Tapping your avatar on mobile opens Settings straight to Account. Each section loads on demand, so the sheet opens instantly. Desktop keeps its familiar two-pane Settings page unchanged.

Fixes

  • A dead desktop connection no longer causes a burst of repeated Gateway Timeouts. When the desktop's tunnel socket died silently (sleep/wake, network switch - no close event ever arrives), the relay kept writing every request into the dead socket for up to two minutes: each one waited its full 10 seconds and failed with a 504 while the dashboard still showed green. A live desktop always answers within 8 seconds, so the relay now treats one full request timeout as proof the socket is dead: it closes it and flips the desktop offline immediately. The desktop redials within about a second, so the next request goes through instead of joining the timeout storm.
  • The chat composer now rides the keyboard smoothly on mobile. Tapping the input used to stutter as the composer rose: the layout transition ran on a different curve than the iOS keyboard, and every animation frame fired scroll events that re-rendered the chat mid-animation. The shell now animates on the keyboard's own timing curve and scroll-state updates pause until the keyboard settles, then reconcile once.
  • Mobile chat is redesigned to mobile norms. The empty state drops the centered logo for a large left-aligned greeting, and suggestions become quiet full-width rows instead of centered pill buttons. Message text is 15px with relaxed line height (was 14px), the input is 16px (which also stops iOS from zooming the page on focus), sidebar rows grow to 40px touch targets with 14px labels, composer buttons grow to 36px, the disclaimer line under the composer is hidden on phones, and tap-highlight flashes are gone.
  • The mobile chat header follows the round-button pattern. The hamburger and the header actions are now round soft-filled buttons (like the Claude and ChatGPT apps), the header grows to a comfortable 48px, and the two search buttons collapse into one on phones - the conversation search palette covers both finding a chat and finding within it.
  • The message composer floats on a soft shadow. On desktop and mobile the input card now carries a subtle diffuse elevation that deepens slightly while typing, instead of sitting flat on the page. The border is thinner and the edge definition comes from a tight shadow fade hugging the card.
  • Free users with fresh monthly credits can chat again. One oversized agent turn could overdraw the internal balance by more than a month's grant; that debt silently carried across months, so every later request failed with "Credits exhausted" while the Account page still showed 10 credits available. Monthly free credits are use-it-or-lose-it, so the refill now also clears any carried overdraft, and affected accounts were reset.
  • Chat errors are visible again. A regression dead-wired the persistent error banner, so a failed send (out of credits, plan-gated model, relay errors) produced no feedback at all - the reply just never came. The banner is rewired: credits/plan issues show the amber upgrade prompt, other errors show the alert with the real message.
  • The chat header is now translucent glass. Content scrolls beneath a blurred, semi-transparent header (same treatment as the foxl.ai site), and tapping the Foxl logo in the sidebar returns home (new chat / Notes / Code tasks) on desktop and mobile.
  • Scrolling the chat while touching a message bubble works again. A containment rule applied to every scrollable element stopped touch gestures from reaching the transcript when they started on a nested scroller (code panes, text blocks); containment is now scoped to the top-level scrollers.
  • A request that lands exactly on a dead connection recovers by itself. The relay heals a silently-dead desktop link the moment one request times out, but that first probe request still surfaced as a Gateway Timeout in the app. Read requests now retry once after the desktop's ~1s redial, so the healing is invisible instead of an error flash.
  • Fixed an accessibility violation when the sidebar opened over a focused chat input on mobile (focus retained under aria-hidden). The composer no longer steals focus on phones - the keyboard appears when you tap the input, not when the app decides.
  • Vertical scrolling no longer freezes intermittently on mobile. A legacy iOS scrolling hint forced the chat list onto a deprecated scroll path where streaming content could stall it until the next touch; removed.
  • Dropdowns inside the mobile Settings sheet open again. Selects, popovers, and menus were rendering behind the sheet (a stacking-order regression), so tapping the language picker or any Settings dropdown did nothing. They now layer above the sheet.
  • The chat follows a long answer as it streams again. When a single reply or thinking block grew tall, the view stopped scrolling with it - you had to keep tapping "scroll to bottom." Auto-scroll now tracks the content as it grows (not just when a new message arrives), and still hands control back the moment you scroll up, exactly like before. This restores the v0.3.x stick-to-bottom behavior.
  • The message bar has a crisp, defined edge again. The glass composer's border was washed out by the blur and nearly black in dark mode; it now has a clear hairline (like Codex), a soft gray card in dark mode instead of near-black, and a symmetric shadow that lifts the top and bottom edges evenly instead of pooling at the bottom. Foxl Code's composer matches. The inset content panel and the mobile sidebar drawer also get a defined border.
  • Removed the "AI can make mistakes" line under the composer in both Foxl Agent and Foxl Code - it added a row of clutter on every screen.

v0.4.9

Fixes

  • Remote access is stable again: no more connecting-then-dropping, and chat is fast. Three tunnel regressions from v0.4.7's connection-fencing rework are fixed, restoring the v0.3.x behavior.
  • A phone or browser no longer multiplies into many device rows on the dashboard. The relay was dropping the client fingerprint when routing a web connection to its per-user hub, so every reconnect from the same device looked brand-new and piled up a fresh connection on every network blip, token refresh, or app resume. The fingerprint is now forwarded and the hub keeps exactly one live socket per client, closing the stale one.
  • A desktop reconnect no longer drops in-flight requests. A reconnect (sleep/wake, network change) used to abort every request in flight with a "connection was replaced" error; because the web client also cycled its status socket on every token refresh, this fired constantly and looked like "connected for about ten seconds, then everything drops and chat gets slow." In-flight requests now survive a reconnect and complete from the original reply.
  • The web app stops needlessly cycling its status connection. It used to tear down and reopen the status WebSocket on every token refresh and app resume even when the socket was healthy; an open tunnel socket stays valid across a refresh, so it now stays put and only reconnects when it is actually down.
  • The desktop no longer shows two or three "Web client connected" pop-ups for a single connection. A phone or browser opens a few tunnel sockets at once (presence, chat, terminal sync) and each one, plus the chat socket's own end-to-end handshake, fired its own notification. The desktop now coalesces them into one notification (and one in-app toast) per device.

v0.4.8

Fixes

  • Mobile/web tunnel requests no longer hang for 10 seconds and then fail with a Gateway Timeout. When the desktop's machine ran out of local network ports (a socket-exhaustion storm that also breaks other apps), the desktop's loopback call to its own server could stall with no error and never reply, so the relay waited out its full request timeout and returned a 504 while the desktop still showed as connected. The desktop now bounds that local call and returns a real error instead of silence, and the relay always matches a desktop reply to its pending request - even if the desktop reconnected while the request was in flight - so a live desktop stops surfacing phantom timeouts.

v0.4.7

Features

  • Sessions on the Account page now reflect real devices. Every Foxl installation and browser profile mints a stable client identity, so the session list groups by actual device instead of by browser version string. Old duplicate rows (the same Safari appearing many times) collapse into one entry, and revoking a session signs out exactly that installation.
  • Per-provider usage breakdown on the Account page. The 30-day usage table now separates the same model served by different providers (AWS Bedrock vs OpenAI OAuth), shows month-to-date credits from the immutable usage ledger, and prices them consistently at the credit rate.

Fixes

  • Foxl Desktop now starts without internet. When the machine was offline (DNS unresolvable), macOS proxy auto-discovery failures made even the local 127.0.0.1 app page fail with ERR_ADDRESS_INVALID, so the app never got past the startup screen. Loopback now bypasses any system proxy, and subframe or embed failures no longer knock a healthy app page back to the startup splash - which also removes the rapid splash/app flashing loop seen while offline.
  • The startup screen matches the app's light theme. The splash was a dark-only page with an inverted monochrome logo; it now uses the light palette and the brand-color logo, so launching no longer flashes a black screen on light-mode systems.
  • Signing in on two app surfaces at once no longer logs you out. When the renderer and the Electron shell refreshed the same session within a few seconds of each other, the relay treated the second refresh as token theft and revoked the whole session family. Concurrent refreshes are now idempotent: both callers get the same replacement token, while replays outside the short concurrency window still revoke the family.
  • A reconnecting desktop can no longer be marked offline by its own old connection. Tunnel connections are now fenced by a connection id, so a delayed close event from a previous WebSocket cannot flip the replacement connection to offline. Wake-from-sleep reconnects collapse into a single jittered backoff owned by the tunnel client instead of three racing timers.
  • Mobile/web tunnel status is push-first. The always-on HTTP status polling loop is gone; status arrives over the push channel and HTTP is only used as a bounded recovery probe, which also cuts steady-state relay reads.
  • Credit balances update on activity instead of polling every 15 seconds. The sidebar and Account balances refresh when a chat turn completes, when the app resumes, or on manual refresh, removing a constant background request loop on every open Foxl surface.
  • Model favorites are provider-aware. Starring a model on one provider no longer stars the same model id on every provider; existing favorites are migrated in place.
  • Foxl Code's collapsed desktop sidebar now keeps long task histories contained. Pressing Command-B no longer expands every task avatar down the icon rail and pushes the remaining navigation away. The task section now matches code.foxl.ai with a bounded, independently scrolling list and a clipped bottom edge that indicates more tasks.

v0.4.6

Fixes

  • GPT tool runs no longer stop with an empty answer. Bedrock can report a terminal Responses API failure after a long tool run. Strands 1.9 ignored that event and finalized the turn as a successful but empty response. Foxl now turns it into a model error so transient failures can retry and final failures appear through the same error toast used by other models.
  • Bedrock GPT context limits now match the actual 272K window. GPT-5.6 Sol/Terra/Luna, GPT-5.5, and GPT-5.4 were shown and configured as 1M-context models even though Amazon Bedrock Mantle rejects prompts above 278,528 tokens. The AWS and Foxl relay paths now advertise and configure the real limit, and the chat context meter uses it. Direct OpenAI and ChatGPT OAuth keep their 1M windows.

v0.4.5

Features

  • Launch at login. Foxl now starts automatically when you sign in to your computer, so your 24/7 agent is always running. Enabled by default; toggle it off under Settings -> About.

Fixes

  • Offline behaves like a normal desktop app now. Losing internet used to flash a retrying error panel on and off (the reconnect ticker strobed the overlay). The connection-lost screen was redesigned into one calm panel that distinguishes "you're offline" (just waits and auto-reconnects, no blinking) from "the local agent server stopped" (offers Restart), and both edges are debounced so a flaky network can't make it flicker. Sending a chat while offline now shows a plain "You're offline" message instead of a raw "Failed to fetch", and the app recovers on its own when the network returns.
  • GPT-5.6 on AWS: a transient hiccup mid-conversation no longer makes the agent quit tool-calling or go silent. GPT-5.6 (Sol/Terra/Luna) runs on the Amazon Bedrock Mantle OpenAI Responses API, which surfaces transient server errors (503/500/502) in the OpenAI SDK's error shape (a plain status), not the AWS shape our retry logic recognized ($metadata). So a brief Bedrock blip during a long GPT-5.6 tool loop was treated as fatal instead of retried, and the turn stopped mid-way or returned nothing. The retry policy now recognizes both error shapes (plus connection/timeout errors), so these blips are retried with backoff on every GPT-5.6 path. Verified end-to-end against real Bedrock: single and multi-round tool loops complete cleanly.
  • Favoriting a model no longer shows it (and a lit star) twice. A favorited model was rendered both in the pinned Favorites group and again in its provider group, so a single favorite looked like two selected stars. Favorited models now appear only in the Favorites group.
  • GPT-5.6 Sol, Terra, and Luna now read distinctly in the model picker. All three tiers showed the same "Advanced reasoning" subtitle; they now describe their actual role - Sol for flagship reasoning, Terra for balanced performance at half the cost, Luna for fast, cost-efficient inference. The Claude model subtitles were also refreshed to match Anthropic's current descriptions.
  • No more "Tool 'workspace_memory_save' not found in registry". The system prompt always told the model to use the workspace-memory tools, but some setups (Claude Code subscription provider, or memory tools disabled in Settings) run without them - so the model called a tool that wasn't there and the turn errored. The prompt is now generated from the tools actually available for the turn: it only mentions memory, subagents, exec, and scheduling when those tools are present, on every agent path (chat, subagents, channels, scheduled runs, heartbeat).
  • Foxl Code: per-task budget is a hard cap under concurrency. A coding task's budget was checked by reading spend that is only written after a response finishes, so several requests running at once could all pass the check and blow past the budget (and the account's credits). Each request now atomically reserves its worst-case cost before the model runs and settles to the real cost afterward, so parallel requests can't collectively exceed the cap.

Changes

  • Upgraded the Strands Agent SDK to v1.9.0 (from 1.7.0 on desktop, 1.5.0 on the Forge orchestrator). Picks up the fix for tool-use metadata in streamed contentBlockDelta on non-standard models (GPT-5.x / GLM / Kimi routed through the SDK), tool usage after reasoning content, and durable message identifiers. No API changes on our side - all the SDK symbols Foxl uses are unchanged, and the one breaking rename (LocalMemoryStore -> TestMemoryStore) is a store we don't use.

v0.4.4

Features

  • OpenAI GPT-5.6 Sol, Terra, and Luna - day-one support. OpenAI's newest model family (GA on Amazon Bedrock today) is available across Foxl: the chat model picker on desktop / app.foxl.ai / Foxl Notes, and as Codex coding-agent models in Foxl Code. Sol is the flagship reasoner ($5/$30 per 1M tokens), Terra the everyday workhorse ($2.50/$15), Luna the fast, affordable tier ($1/$6) - Pro plans and up, priced at OpenAI first-party rates. All three support reasoning effort up to the new max level. Available two ways: on your Foxl credits via Amazon Bedrock, or on your own ChatGPT Plus/Pro subscription through the OpenAI (OAuth) provider - no API key needed.
  • Accurate prompt-cache billing for GPT models. GPT-5.6 introduces billed cache writes (1.25x input) and discounted cache reads (90% off); the relay meter now decomposes OpenAI's combined input-token count into plain input, cache reads, and cache writes, so cached GPT traffic is billed at the discounted rates instead of full input price.

Fixes

  • Chat no longer fails with "Invalid or expired token" while the sidebar still shows you signed in. The relay access token expires every 12 hours; the sidebar and account surfaces silently refresh it, but sending a chat message hit the relay with the stale token and treated the 401 as a dead session - wiping both tokens instead of refreshing. The message path now refreshes the token (sharing the same in-flight refresh as the rest of the app) and retries the send once; you only get signed out when the refresh token itself is no longer valid.
  • AWS provider: GPT-5.6 listed once and actually works. The desktop AWS provider briefly listed each GPT-5.6 tier twice (once under Bedrock, once under OpenAI-on-Bedrock); the Bedrock-routed copy failed with "The provided model identifier is invalid" because these models are served only by the Mantle Responses endpoint. The provider split is now derived from the catalog (any openai.* Bedrock id is Mantle-only), and a stale saved selection self-heals onto the right route instead of erroring.
  • Images stay part of the conversation. Attached images used to reach the model only in the turn you sent them; after the app restarted (or the agent was rebuilt), later turns saw just a file-path hint - so asking "read that image again" got "I don't see an image". Following the standard ChatGPT/Claude conversation model, image attachments are now part of the durable conversation record and are rehydrated into real vision blocks when history is restored (newest 10 images; older ones fall back to the path hint), so the model can keep referring to what you showed it.
  • Pasted screenshots stay readable. Chat image attachments over the API size limit were converted to JPEG with quality walked down as far as 30% (and dimensions halved as a last resort), which smeared screenshot text - the model would sometimes answer that the image resolution was too low. Oversized images now try lossless PNG first, then WebP, with a gentler quality floor and a 0.75x (not 0.5x) fallback downscale; the raw size cap is also corrected to fit the API's 5MB base64 limit (a ~4MB paste used to slip through unmodified and get rejected).
  • Signing in from Foxl Notes no longer lands you in Foxl Chat. The desktop deep-link login (and one web OAuth fallback path) hardcoded the post-login destination to Chat, so the sidebar said Notes while the content pane showed Chat. Every sign-in path now returns to the product you were in - Notes stays Notes, Code stays Code - and history navigation keeps the sidebar product and the content pane in lockstep.

v0.4.3

Fixes

  • Foxl Notes: duplicate transcriptions are structurally impossible now. Live-translate mode used to run TWO parallel transcription streams (your microphone + the meeting's system audio); on speaker setups the mic re-heard the remote party, so the same sentence landed twice - and the text-similarity filter that tried to catch this was unreliable. The two captures are now MIXED into a single stream before transcription, so every utterance reaches the transcriber exactly once. This also removes the phantom "Remote N" speaker label space, and the saved audio recording now includes the remote party (it was mic-only before).
  • Foxl Notes: fewer phantom speakers. The speaker label for a line is now the majority vote across the line's words instead of the first word's label, so a single misattributed word no longer spawns a new "Speaker N"; single-stream capture also halves the label spaces (no more parallel Speaker/Remote numbering for the same voices).
  • Foxl Notes: in-progress (italic) lines are readable again - they keep the italic style but drop the hard-to-read faint gray in both the transcript panel and the live glass panel.

v0.4.2

Fixes

  • Foxl Notes: no more duplicate transcriptions. On speaker (non-headphone) setups the microphone re-heard the remote party, so the same utterance could appear twice - once as "Remote N" (system audio) and once as "Speaker N" (mic). The mic now captures with echo cancellation, and a cross-feed duplicate filter drops the echo copy when both still slip through.
  • Foxl Notes: the live panel accents are back to the classic yellow (the blue accent experiment is reverted) in both dark and light themes.
  • Foxl Notes: the live panel's Notes tab is the real editor. Same rich editor as the main window - toolbar, headings, lists, task lists, tables, code blocks, undo/redo - instead of a plain-text box, with edits syncing live in both directions.
  • Foxl Notes: "Open saved file" in the note's right-click menu opens the auto-saved Word/Markdown export directly (or the save folder if the file isn't there yet).
  • Foxl Notes: full editor toolbar everywhere. The live panel's Notes tab and the mobile editor now carry the complete formatting toolbar (headings, emphasis, lists, quotes, code, tables, images, alignment) scrolling horizontally, instead of an 8-button subset; the panel toolbar wears the glass styling.
  • Foxl Notes: better live translations. Once a sentence finishes, it is re-translated with the surrounding dialogue as context and the rough in-progress translation is replaced in one shot; the "translating..." placeholder is gone - translations simply appear as they stream.
  • Foxl Notes: honest sign-in messaging. Recording and transcription need a (free) Foxl account; the empty screen, mobile home, and onboarding now say so up front - the onboarding sign-in step carries a "Required for recording" badge and the start button reads "Sign in" when signed out instead of a Start Recording button that silently did nothing.

v0.4.1

Features

  • Foxl Notes: click a transcript line to hear it. Recordings now keep their audio on disk (desktop), and clicking any line in a saved note's transcript plays the recording from that exact moment - the line under the playhead stays highlighted, and clicking it again pauses. Timestamps stay accurate across long recordings (they previously reset every few minutes internally), and deleting a note removes its audio file too.
  • Foxl Notes: light and dark glass panel. The floating meeting panel now follows the app theme automatically, with an override (Auto / Dark / Light) in its settings menu. Accents moved from yellow to Foxl blue.
  • Foxl Notes: mini mode is a real caption strip. No recording dot or timer - just the latest lines, with the visible row count adapting to however tall you drag the window (newest bright at the bottom, older lines dimmed). Your mini size is remembered. The expand button stays visible.

Fixes

  • Foxl Notes: clear error when credits run out. Starting (or continuing) a recording with exhausted credits now shows the actual reason instead of silently doing nothing; a mid-recording denial stops the recording with a message.
  • Foxl Notes: one unified sign-in. Signing in from Notes (including onboarding) now returns to this app via foxl:// - it previously deep-linked to the retired standalone Notes app (foxlnotes://), which could open the wrong window and land you on Chat.
  • Foxl Notes: transcript playback highlights exactly one line - previously the last line of every earlier speaker group lit up too.
  • Foxl Notes: settings dropdown no longer clips its values at the panel edge.

v0.4.0

Features

  • Foxl Notes: floating meeting HUD (glass panel). Starting a recording on the desktop now opens a compact always-on-top companion window with the live transcript, translations, timer, and stop/pause controls - so you can follow the meeting while other apps are full screen. On macOS 26+ it renders with the native liquid-glass material. Toggle in Notes Settings > Recording.
  • Foxl Notes: meeting coaching report. A new Report tab analyzes your meeting after it ends: overall score, speaking share and pace, a skill breakdown (language use / fluency / grammar), sentence-level feedback with suggested phrasing, action items, and expressions to learn. Turn on "Report for every meeting" in Settings to generate one automatically after each recording.
  • Foxl Notes: sample report on first run. New users see a complete sample meeting note with a finished coaching report before their first recording.
  • Foxl Notes: first-run onboarding. Opening Notes for the first time now walks through language, sign-in, and microphone setup; replay it any time from Settings > Show guide.
  • Google profile photo as your default avatar. Signing in with Google now uses your Google profile picture across Foxl and Foxl Notes; you can replace or reset it from the Account page.

Improvements

  • Foxl Notes: live translation now translates complete sentences. Instead of translating each speech fragment as it arrived (choppy half-sentence output), the transcriber's fragments are stitched into full sentences before translation, with a short flush timeout so trailing fragments still arrive.
  • Foxl Notes: turning on live translation picks a sensible target language automatically (your UI language) instead of staying inert until a second setting was found and set.
  • Foxl Notes: Settings reorganized into clear sections - Recording and transcription, AI features, Live translation, Auto-save and export, General, About and updates - matching the Foxl Agent settings layout.

Fixes

  • Foxl Notes: the Start button works with live translation on. Recording with live translation captures the other party's system audio; the desktop app was missing the screen/audio capture handler, so the presigned capture request failed instantly and the Start button appeared dead. Both dev and production Electron builds now register the handler (with loopback system audio on macOS/Windows).
  • Foxl Notes: recording no longer fails with "Failed to execute 'start' on 'MediaRecorder'". System-audio (live translation) and some virtual audio devices reject the local audio-copy recorder; that copy is optional (it was never saved to disk), so the error is now non-fatal and transcription proceeds normally.
  • Foxl Notes: exports now default to a "Foxl Notes" folder inside Documents instead of scattering files in the Documents root. Still configurable in Settings > Auto-save location (an existing custom folder choice is respected).
  • Foxl Notes: HUD transparency slider in Settings > Recording controls how see-through the floating meeting panel is, updating live while it is open.
  • Foxl Notes: the live panel grew into a full meeting companion. Live / Notes / Background tabs (notes are editable right in the panel, markdown supported), an AI chat with message bubbles and one-tap reply suggestions, a hamburger menu (transparency, fully-transparent ghost mode, text size, live translation, suggestions, always-on-top), and a mini mode that shrinks the panel to a tiny caption pill for screen sharing. The panel stays open after Stop so it works across back-to-back meetings; auto-open on record start is a setting. Live captions auto-scroll but pause when you scroll up (jump back with the Latest button).
  • Foxl Notes: translation keeps up with continuous speech. In-progress (italic) captions now translate in rolling chunks instead of waiting for the sentence to finish; Transcribe partial-results stabilization makes finals land in smaller, faster units; filler-only fragments ("I", "um") are dropped instead of translated; and the translator never replies with meta commentary ("I cannot translate...") anymore.
  • Foxl Notes: personal AI context in Settings > AI features - tell the assistant who you are and what your meetings are about, and HUD answers and reply suggestions take it into account.
  • Foxl Notes: auto title works independently of auto summary, and auto-saved files are named after the generated title (never "New Transcript"), prefixed with the date: 2026-07-10 - Title.docx.
  • Foxl Notes: speakers are diarized again ("Speaker 1/2", system audio as "Remote 1/2") instead of everything being labeled ME.

v0.3.28

Features

  • Find any past conversation from the agent. A new conversation search lets the assistant look back through your earlier chats by keyword (full-text search), so it can recall what was actually discussed instead of only what was saved to memory. The chat search box is faster and more accurate too.
  • Foxl Notes: live translation. Turn on live translation in Notes settings, pick a target language, and each incoming line of the other party's speech is translated on the spot as the meeting happens - built for following meetings in a language that is not your first. Uses a fast model by default.

Improvements

  • Sidebar shows the current chat's title in the header instead of a generic "Chat" label.
  • Scroll date overlay on the chat and Notes lists shows the exact date of each session (Today / Yesterday, then the real date) as you scroll, so it is clear which conversation happened when.
  • Notes controls pack cleanly in small windows - buttons collapse to icons and an overflow menu instead of overlapping.

Fixes

  • Foxl Notes no longer crashes to an error screen when switching between Notes and Chat while a summary or transcript is loading. A tiptap editor teardown race ("Cannot read properties of null") is now guarded.

v0.3.27

Fixes

  • Chat no longer loses earlier messages from the model's memory on long or interrupted conversations. The conversation the model remembered could drift from what the chat showed on screen: a long chat silently dropped its opening turns, a stopped turn left a phantom "Cancelled by user" reply the model learned to imitate, and a turn interrupted by a crash could vanish from the model's view while still showing in the chat. The app now rebuilds the model's memory directly from the same messages the chat displays every time a conversation is resumed, so what you see is always what the model sees. Prompt caching and tool calling are unchanged.
  • Foxl Notes no longer crashes to an error screen while an AI summary is streaming in. A timing race during editor teardown could throw "Cannot read properties of null (reading 'cached')" and blank the Notes screen when a summary arrived as the editor was being replaced. The editor now guards against that teardown window.
  • Foxl Code task icons now line up vertically when the sidebar is collapsed. In the collapsed icon rail, the Foxl Code task list kept its full-width left-aligned rows, so the task avatars sat off to the left instead of centering in the narrow rail like the nav icons above them. Collapsed rows now show a single centered agent avatar (matching the Chat conversation list), and the expanded list is unchanged.

v0.3.26

Fixes

  • Long thinking-enabled conversations no longer break with an "Invalid signature in thinking block" error. After the move to structured conversation persistence, resuming a long conversation (especially across an app restart or a model switch) could fail with a Bedrock 400 (Invalid signature in thinking block). Extended-thinking blocks carry a cryptographic signature tied to the exact moment and model that produced them; replaying those historical blocks verbatim made the provider reject the whole request. Foxl now drops prior turns' thinking blocks when restoring a conversation for the model (the current turn still thinks normally), which is the provider-recommended behavior and verified against real Bedrock. No loss of functionality: reasoning still streams live, it just isn't replayed from history. The relay now applies the same guard on its Bedrock path as defense-in-depth, so older desktop builds and other clients are protected too.

v0.3.25

Fixes

  • Opus 4.8 now reliably runs tools instead of printing them as text. In longer conversations Opus 4.8 could reply with a literal [Tool: ...] line instead of actually running the tool. Root cause: prior turns' tool calls were replayed to the model as a TEXT summary glued onto the assistant's message, and 4.8 (the most instruction-following model) copied that shape as its own output. Foxl now persists and restores the full STRUCTURED conversation (real tool-use / tool-result blocks) via the Strands SessionManager, backed by our existing local database, so the model sees past tools as typed actions - not text to imitate. Existing conversations are upgraded automatically the first time they're opened, and conversations now survive an app restart mid-thread.
  • Type-ahead message queue no longer double-sends or fragments (desktop). When you type follow-up messages while Foxl is working, they queue and splice into the running turn at the next tool boundary (Claude Code style). A dual-path race between the client-side drain and the server-side boundary flush could enqueue the same message twice, or send queued messages one-at-a-time instead of merging them into a single follow-up. Each queued message now has a single owner from the moment you send it, so it is delivered exactly once and always merged with its siblings.
  • Same queue hardening on mobile + web (app.foxl.ai, iOS). The relay-mode chat used by the mobile and web apps had the same class of race: a rapid burst of follow-ups could launch concurrent sends (duplicate messages/bubbles), and the queue drain ran its send inside a React state updater, which double-fires under StrictMode. Both now go through one synchronous in-flight latch and drain the whole queue as a single merged turn - delivered exactly once.
  • Conversation snapshots no longer duplicate your first message. The structured-persistence upgrade could store the first message of a turn twice (it was written by the app before streaming and appended again by the agent), permanently doubling it in the model's memory of the conversation.
  • Memory and skill updates now reach ongoing conversations. Restored conversations were frozen on the system prompt captured when they were first saved, so new memories, skills, and workspace changes never reached them. Snapshots no longer store the system prompt - it is rebuilt fresh every turn.
  • Editing or deleting a message now really removes it from the model's context. Edit, regenerate, reset, and single-message delete previously left a stale conversation snapshot behind, so the model could still "remember" turns you had deleted. All four flows now invalidate the snapshot, which is rebuilt from the message history.
  • Restored conversations can no longer hit a Bedrock validation error. Snapshots could contain empty text blocks (a side effect of streaming), which Bedrock rejects when the conversation is restored after a restart. They are now filtered out on save and restore.
  • Removed a wasteful no-op compaction step. Long conversations triggered a paid "context compaction" model call that operated on a text copy of history the model no longer reads - it reduced nothing while showing a "Context compacted" notice. Context is now bounded by the agent runtime itself (sliding window + automatic overflow recovery).
  • Foxl Notes: AI summaries are now sanitized before rendering. A crafted meeting transcript could smuggle active HTML through the AI summary into the editor. Summaries and AI-generated markdown are now sanitized (DOMPurify) with no change to how markdown renders.
  • Web/mobile chat storage survives quota pressure. If browser storage filled up (large pasted images/files), conversation saving silently stopped for every conversation. On quota errors Foxl now strips attachment payloads from local history and keeps the newest conversations instead of dropping everything.

v0.3.24

Fixes

  • Claude Fable 5 works reliably again. Amazon Bedrock flipped which inference profile serves Fable 5: the global. profile Foxl used since launch now returns server errors, while the standard us. profile (the same kind Opus and Sonnet use) now works from every region. Foxl switched Fable to the us. profile and removed the special us-east-1 routing it needed at launch. Fable now runs through the normal region like every other model, so the intermittent failures are gone. No action needed on your part.

Features

  • New model: Claude Sonnet 5. Anthropic's most capable Sonnet - near-Opus 4.8 intelligence at the same Sonnet price ($3/$15 per million tokens), with a 1M-token context window and 128K max output. It is a drop-in successor to Sonnet 4.6: same adaptive thinking, same everything, just smarter. Sonnet 5 is now the default model for chat and the autonomous code orchestrator (Opus 4.8 remains the default for the coding agents and the desktop app), and it is available on the free tier alongside Sonnet 4.6 and Haiku 4.5. Adjustable reasoning effort (low through max) is supported, defaulting to medium - the best speed/quality tradeoff for everyday work. Pick it from the model selector on desktop, app.foxl.ai, Foxl Code, and Foxl Notes.

v0.3.22

Features

  • Type a follow-up while Foxl is working and it queues, then sends at the next natural break - just like Claude Code. Previously a second message sent mid-response either waited until the whole turn finished or cut the running turn off entirely. Now it is held and spliced in at the next tool-call boundary: the current tool finishes cleanly, your queued message lands as its own turn, and Foxl responds to it - without restarting the work. Queue several and they merge in order into a single follow-up. Press Esc (or Stop) to interrupt immediately instead of waiting. This works on the desktop app and on remote-connected desktops (via the relay tunnel); the cloud-only chat at app.foxl.ai keeps its end-of-turn queue since it has no tool loop to break at. Verified end-to-end against real Bedrock (the queued message is provably consumed only after a completed tool call, never mid-tool) and in a real browser (the queued text renders as its own message and gets its own reply).

Internal

  • Upgraded the Strands agent SDK to v1.7.0. The mid-turn queue is built on the SDK's tool-boundary hooks (AfterToolsEvent / AfterInvocationEvent), using only public APIs - no SDK patching.

v0.3.21

Features

  • Message action buttons (copy, edit, regenerate) now appear on tap on mobile. On desktop they were already shown on hover. On mobile they were always visible, cluttering every message. Now they start hidden and appear when you tap the message bubble - tap again to hide.

Fixes

  • Attaching files with the AWS (Bedrock) provider no longer fails with "The model returned the following errors: ...content.N.type: Field required". Root cause (found via real end-to-end reproduction against Bedrock): with prompt caching on, the agent SDK appends a cache marker to the end of your latest message, and Bedrock rejects that marker when the block right before it is a non-PDF document - which is exactly how a pasted .txt/.csv/.md file lands. (PDFs and images coexist with the cache marker fine.) Foxl now suppresses prompt caching only for a message that carries a non-PDF document attachment, so PDF and image turns keep their cache savings, and the conversation is re-used correctly afterward. Verified end-to-end on the real desktop AWS-provider path (the exact failing request now succeeds, PDFs still cache).
  • The relay path is also hardened against malformed attachment blocks. Two related causes were fixed for chats that go through the relay (app.foxl.ai, mobile, relay-routed desktop): (1) some attachments reached the model as a content block missing its type field, which the Anthropic API rejects; (2) non-PDF documents (txt, csv, md, json, docx, ...) were sent as native document blocks, but Bedrock's Claude only accepts PDF that way. Non-PDF files are now inlined as text (their contents still reach the model), PDFs stay document blocks, and the relay defensively repairs any malformed block before it reaches Bedrock. Verified end-to-end against real Bedrock.
  • Attaching two files with the same (or non-Latin) name no longer errors. Bedrock rejects messages with duplicate document names, and the name sanitizer collapsed non-Latin filenames (e.g. Korean) to the same fallback name. Document names are now de-duplicated before sending.

v0.3.20

Fixes

  • Agent-created terminals now appear in the UI. Terminals opened by the AI agent were invisible in the desktop app: the terminal panel never opened and the tab never appeared. Root cause: the internal WebSocket that listens for terminal spawn/exit events was not sending the connection security token, so the server immediately closed it (code 4003) in production builds. The token is now attached, the connection stays open, and agent-spawned terminals show up and stream live as expected.
  • Web/mobile app no longer refreshes when your desktop connects. On app.foxl.ai (and the mobile app) the app starts in offline mode and used to do a full page reload the moment your desktop came online - a jarring refresh that interrupted whatever you were doing. Now the switch to live desktop data is seamless: the chat list and open conversation refresh in place (an in-progress reply is never dropped), and a small "Desktop connected" note appears instead of a reload. Coming back to the app after it was in the background no longer risks a surprise refresh either.

v0.3.19

Fixes

  • Terminals now sync live everywhere, no matter who opened them. A terminal that appears on your desktop - opened by the AI agent (its terminal tool), a background task, or the desktop UI itself - now shows up and streams its output live on every connected surface: the desktop window AND the web/mobile app (app.foxl.ai). Before, an agent-created terminal could be added to the tab bar without ever becoming the active tab (so it never connected and showed no output), and the phone never learned about a terminal it didn't open itself. Now the desktop forwards every terminal it opens to your connected phone/web, and each surface auto-selects the new terminal so it streams immediately.

v0.3.18

Changes

  • GLM 5 and Kimi K2.5 are no longer offered on Foxl relay credits. Their quality was below the bar we want for hosted models, so they've been removed from the model picker on app.foxl.ai, mobile, and the web app. They remain available on the desktop app if you connect your own AWS Bedrock account (Settings -> Providers), where they run on your AWS bill rather than Foxl credits and stream natively.

Fixes

  • Remote access status is now instant and always accurate. The Mobile/Web page could show your desktop green ("connected") while chat, the channel list, and remote actions all failed with "Desktop is offline" - and even when correct, it could lag up to ~10s behind the real state. Two fixes: (1) the live relay tunnel is now the single source of truth - the desktop's background heartbeat only updates "last seen", while online/offline is owned by the tunnel itself, so the badge can't disagree with whether remote features actually work; (2) the desktop coming online or dropping is now pushed to the web/phone instantly over a live connection instead of being discovered by polling, so the status flips the moment it changes. Even a desktop that dies ungracefully (crash, power loss, network drop with no clean disconnect) is now detected - previously that left the badge stuck green while every request silently timed out; now the connection's missing heartbeats are noticed and the status flips to offline within ~2 minutes (instantly if you try to do something, which fails fast as "offline" instead of hanging). This was also re-built to stay well within free-tier infrastructure limits as usage grows (status rides a near-free idle socket and the heartbeat write is coalesced, instead of every open tab polling on a timer).
  • Mobile/Web page: tidied the device controls. The row of unlabeled icon buttons (refresh / check for updates / restart / unpair) is now a single "⋯" menu with clear labels, so it's obvious what each action does. The remote-access on/off switch stays where it was.
  • Model selector always reflects what's actually available now. It could keep showing a stale selection cached from a previous session or from when the desktop was connected (e.g. a desktop-only model after the desktop went offline). The list now refreshes the instant the desktop connects or disconnects, and if your selected model is no longer offered it snaps to an available one instead of showing a dead choice.
  • Mobile terminal: reverted the iOS keyboard rework that broke typing. The recent change that let you type straight into the terminal on iOS (with a keyboard accessory bar) regressed the experience - tapping the terminal made the keyboard flicker up and down, and Korean/CJK still split into separate jamo. The terminal is back to the previous keyboard behavior on mobile: a dedicated command box that composes Korean correctly, with the quick-key row (Tab/esc/^C/arrows) below it. The terminal chrome redesign and the rotation/resize fixes are kept.
  • Stopping a reply now also stops the "Thinking…" shimmer. When you cancelled a response mid-thought, the reasoning header kept its animated "Thinking…" shimmer forever because the cancel path never marked the reasoning block as finished. Cancelling now ends the reasoning block (it switches to "Thought for N seconds") in chat and in the relay/web app, and also tears down a re-attached background stream so it can't restart the animation. (The underlying generation and any in-flight tool were already stopped server-side; this was a display-only leak.)
  • Terminal tab status now updates live. A terminal tab's status dot stayed green even after its process had ended - the dot only changed when you deleted the tab by hand, so a shell you exited (typed exit, the process died, or an agent-spawned command finished) kept looking like it was still running. The dot now turns gray the instant the process exits, in the desktop app and over remote access (Mobile/Web), and dead tabs are cleared when you open a new one.
  • Terminal: reconnect button + auto-reconnect on resume. Next to the fit-to-width button in the terminal toolbar there's now a reconnect (refresh) button that tears down and re-establishes the connection for the current terminal, re-loading its scrollback - handy when a session looks wedged or shows "[Disconnected]". On top of that, the terminal now reconnects automatically when you bring Foxl back to the foreground: backgrounding the app (especially on mobile) can let the OS drop the connection, and instead of sitting on a dead "[Disconnected]" terminal until you tap reconnect, it re-establishes itself the moment the app resumes (only when the connection was actually lost, so an active session is left untouched).

v0.3.16

Changes

  • Free credits now refill on your own monthly anniversary. Instead of every free account refilling on the 1st (a date that had nothing to do with when you joined), your 10 monthly credits now top up on your sign-up day each month. If you joined on the 31st, months without a 31st refill you on their last day (Feb 28/29, Apr 30, etc). The Account page shows your exact next refill date (now displayed correctly in all time zones - it previously could read one day early west of UTC). Your welcome credits remain permanent (no expiry) as before.
  • Foxl Code: one-tap "Connect GitHub". The connect flow was redesigned to a single button. Instead of choosing between "open GitHub install", typing a GitHub login to adopt, and a dead-end "configure" screen, you now click "Connect GitHub" once, authorize on GitHub, and every organization and account you can access is connected automatically (repos synced, membership granted with your real org role). If your Foxl account had no GitHub identity yet, the authorize step links it. No more guessing which button connects your repos.

Fixes

  • Mobile search palette (Cmd/Ctrl+Shift+F) now docks above the keyboard. On phones the global search palette (shared by chat conversations, Notes recordings, and Foxl Code tasks) opened as a full-screen sheet whose results list ran behind the on-screen keyboard - so the list could not be scrolled and the keyboard could not be dismissed without closing the palette. The palette now shrinks to the real visible height when the keyboard is up (the list always keeps a scrollable area above it), and dragging the list retracts the keyboard. Desktop keeps the centered command card.
  • Conversation search (Cmd/Ctrl+Shift+F) reads more clearly and focuses the chat you pick. Results now show each conversation's last-activity date instead of a repeated message icon, and stay sorted newest-active first. Opening a result selects it in the left sidebar and scrolls that row into view, even for an older chat that wasn't yet loaded in the list.
  • Foxl Code repos list is calmer on mobile. Every repo row used to show a full "Start task" button, repeated down the whole list. On phones each row now shows a single compact chevron; desktop keeps the hover-revealed "Start task" button.
  • iOS terminal: Korean (and other IME) input works. Typing Hangul straight into the on-device terminal previously produced broken jamo because the terminal's built-in text field can't commit IME composition inside the iOS web view. The terminal now routes keystrokes through a dedicated invisible composition field and sends only completed characters to the shell - so Korean/Japanese/Chinese type correctly while still feeling like typing directly into the terminal (no separate command box).
  • Mobile terminal reflows on rotation. On phones the terminal width was pinned to its initial value, so rotating the device (or showing/hiding the keyboard) left the columns wrong and text clipped. It now recomputes its size on orientation and viewport changes.
  • Rate limiting can no longer be burst past under load. The free-tier daily request quota used a check-then-record sequence that two simultaneous requests could both slip through; admission is now a single atomic step, so the quota holds exactly even under concurrent traffic.
  • Subscription credit recovery is now once-per-period. A safety net that re-grants a paid subscriber's monthly credits if a renewal webhook is missed could, in some cases, re-grant the full allotment every few minutes once the balance hit zero. Recovery is now locked to exactly one grant per billing period (and correctly ignores already-expired credits), so paid balances refill on the real billing cycle and never double up.

Security

  • Foxl Code: stricter input validation on team-member admin actions. The endpoints that remove a member or change their role now validate the target account id format before touching the database - defense-in-depth hardening on the org/team management surface added in v0.3.15.

v0.3.15

Security

  • Foxl Code: membership is now proven and revocable (SEC-004). Connecting a GitHub organization or account to Foxl Code now requires proving you personally have GitHub access to it (a GitHub authorization step), instead of trusting a typed login. Membership is also continuously re-verified: if you leave a GitHub org, or an admin removes you, your access is revoked and your running tasks for that install are stopped. The Repos page gained a "Who can use this install" panel so you can see exactly which Foxl accounts can act on your repos, with admin controls to change roles or remove members. This closes a cross-tenant access hole and adds the offboarding lifecycle (departures, role changes, team moves).

Fixes

  • iOS terminal types directly, like a real terminal. Opening the terminal from the chat bar on iPhone/iPad no longer shows a separate command box below the keyboard. You now tap the terminal and type straight into it, exactly like on desktop, with the quick keys (Tab/Esc/Ctrl-C/arrows) riding on the keyboard itself. This removes the duplicate input surface and makes the on-device terminal feel native.
  • Foxl Code: tapping a repo no longer jumps to chat. On mobile, tapping a repo row in the Repos list used to fling you into the new-task composer just from browsing. Repos now only start a task from an explicit "Start task" button (always visible on mobile, hover-revealed on desktop).
  • Foxl Code: stop auto-syncing repos on every tab switch. The Repos page used to re-sync (and flash "Synced N repos") every time the tab regained focus. It now only syncs after you actually visit GitHub to change an install, and that implicit sync is silent.
  • Foxl Code: disconnect / leave an installation. Each install's access panel now has a gear menu with "Manage on GitHub", "Change repo access", and "Disconnect / leave" - so you can relinquish your own access (and, if you are the last member, fully disconnect the install from Foxl) without uninstalling the GitHub App.
  • Foxl Code: back from a runtime returns to Runtimes, not chat. Opening a task from the Runtimes page and pressing back used to drop you on the chat composer. Back now returns to wherever you opened the task from.
  • Foxl Code: redesigned repo picker. The repo selector now matches the model picker - a searchable list with a Favorites group on desktop, and a full bottom sheet with tall touch rows + a search box on mobile.
  • Account & Notes-settings pages scroll again. Inside Foxl Code (and Foxl Notes) the Account page and the Notes settings page were clipped with no way to scroll to the lower content (usage, billing, delete account). Both now own their vertical scroll inside the shell.

v0.3.14

Features

  • Terminal redesigned for the new app shell. The terminal panel no longer has its top row clipped when it opens inside the rounded app window, and fullscreen now fills the content area cleanly instead of overlapping the header. The tabs, buttons, and resize handle were restyled to match the rest of the app (rounded controls, consistent hover, smooth motion). On phones the command bar is cleaner and docks right above the keyboard, with bigger, evenly sized quick keys (Tab/Esc/Ctrl-C/arrows) and a proper send button. On iOS those quick keys now ride ON the keyboard itself (a native accessory bar that appears only while the terminal input is focused), so they move perfectly in step with the keyboard like a real terminal app.
  • Edit and scroll pasted text in the composer. When you paste a long block of text it collapses into an attachment chip so the input stays tidy. You can now expand that chip to scroll through the whole thing (no more 2,000- character preview cutoff) and edit it inline before sending - trim it, fix a typo, or clear it to drop the attachment. Large pastes stay smooth: only the on-screen portion is rendered, so editing a huge paste no longer lags.

Fixes

  • Refreshing during a long reply no longer drops the beginning. When you reloaded the page while the assistant was streaming a long answer, the recovered message could come back missing its opening - only the tail survived. The live recovery buffer is capped to bound memory, and a very long reply overflowed it. Recovery now reads from a separate uncapped record of the in-flight turn, so the whole reply (text, reasoning, and tool calls) comes back intact no matter how long it is. Reconnecting also targets the exact in-flight message, so a follow-up turn can never get glued onto the previous answer.
  • Switching chats mid-reply and back now resumes the live stream. If you left a chat while it was still answering, read another conversation, then came back, the reply used to look frozen at wherever it was when you left (it kept generating on the server, but the screen stopped following it until a full reload). Coming back now re-attaches to the live stream the same way a page refresh does, so the answer keeps flowing in. Leaving it running in the background and finishing there still works too - it is marked unread and floats to the top of the list when done.
  • Failed scheduled tasks now show as failed. A scheduled task that errored out was still recorded as "completed", which also meant a repeatedly-failing schedule never auto-disabled itself. Failures are now recorded as failed (with the error message), count toward the auto-disable threshold, and the run is still openable as a chat so you can see where it stopped.

Changes

  • Personal Brain removed. The For You dashboard's "Today brief" and "Personal Brain" cards and the foxl-brain skill that fed them have been pulled out. For You now shows your upcoming schedules and today's usage. No data you created elsewhere is affected.

v0.3.13

Features

  • Open any background run as a chat. Scheduled tasks, the Feed Generator heartbeat, and chat subagents now save their full run as a conversation - every step the agent took, the tools it called, and what each tool returned. Click a run in Schedules or Activities (or "Open as chat" on a subagent in Agents) and it opens in the normal chat view with the same tool bubbles a live chat shows. This makes it obvious why a scheduled task did what it did (for example, whether it actually read a skill or where it got blocked), instead of only showing a one-line summary. These run conversations are kept out of your normal chat list and are reached only from those run views, and they are pruned automatically so they never grow without bound.

Fixes

  • Deleting a conversation now fully removes it. Foreign-key enforcement is on, so removing a conversation also clears its messages, tool calls, and reasoning instead of leaving orphaned rows behind.
  • Subagent and scheduled-run transcripts are faithful and cache-friendly. A forked subagent inherits its parent's conversation so repeated requests reuse the prompt cache (faster, cheaper); the saved transcript now shows only that subagent's own work instead of replaying the parent's. The inherited context is no longer truncated before the model sees it, so the cache is actually reused on longer conversations.
  • Mobile: repository names use the full row width. In Foxl Code on a phone, the Repos list no longer clips long owner/name titles behind an invisible button; the name spans the whole row and the row itself taps to start a task.
  • Mobile: workspace search fills the screen. The search-all-conversations palette (Cmd+Shift+F, or the header search button on a phone) opens as a full-height sheet on phones instead of a small centered card, so the input is reachable and results use the whole screen. On desktop it stays the centered dialog.

Improvements

  • Schedule runs open straight to their transcript. In Schedules, a run with a saved transcript opens as a chat in one click (no expand, no extra button), and a slim "Back to Schedules" replaces the header title while you read it.
  • Cleaner run + subagent status. Schedule run rows and the sidebar subagent list now use a single quiet status dot (running, done, failed) instead of competing full-color icons, matching the rest of the app.
  • Clearer schedule details. The schedule detail dialog leads with the type, status, and cadence, then lists last run, next run, run count, timeout, and created time as full, untruncated values.

v0.3.12

Fixes

  • Model responses no longer cut off mid-answer. The relay was parsing Amazon Bedrock's binary streaming format as if it were text, which let a random checksum byte silently swallow the rest of a long response. The stream is now parsed by its real binary framing, so long answers, tool-heavy turns, and code blocks always stream to completion. Verified against a real captured stream that previously dropped 70 of 119 events.
  • Mobile chat keeps following new messages. Opening the keyboard or growing the composer no longer turns off auto-scroll, so replies keep scrolling into view without tapping the scroll-to-bottom button. Auto-scroll now only pauses on a deliberate upward scroll and resumes when you return to the bottom or send a new message.
  • Foxl Notes mobile home fits the screen. The Record-a-meeting screen no longer overflows sideways: the Start Recording button and recent-note cards stay within the viewport, recent-note previews show clean text instead of raw HTML tags, and the duplicate bottom Start button is gone. Note summaries are now stored as markdown so titles and previews stay readable everywhere.

Improvements

  • Settings is scoped to each product. Opening Settings inside Foxl Agent now shows only agent settings; Foxl Notes and Foxl Code each have their own Settings within their product. No more cross-product settings mixed into one list.

v0.3.11

Features

  • For You dashboard. The Feed page is now "For You": an at-a-glance dashboard with a Today brief, your personal knowledge brain (people, companies, meetings and recent pages), upcoming schedules, and today's usage, with the suggestions inbox below. The sidebar item and all languages follow the new name.
  • Personal Brain (beta). Foxl can now maintain a personal knowledge brain as plain markdown in your workspace: people, companies, meetings, concepts, and your own original ideas, cross-linked and consolidated nightly by an opt-in dream cycle. Ask Foxl about anyone you have met and it answers from your own notes, with sources cited and gaps called out. Powered by the new foxl-brain skill; the For You page shows the brain at a glance.
  • Account deletion and data export. Delete your account (with full data purge) directly from the Account page, and download your data as JSON or your usage history as CSV at any time.
  • Billing lifecycle emails. Welcome email on signup, usage alerts at 80% and 100% of your credits, and a heads-up email if a subscription payment fails, with a banner in the app until it is resolved.

Improvements

  • Cold start is much lighter. The main bundle dropped by about 360 kB and the Notes page by about 650 kB (the editor and sub-agent chat view now load on demand), so the app paints noticeably faster on first open.
  • Fairer plan changes. Downgrading a subscription now keeps your current credits until the end of the paid period instead of dropping them immediately; refunds claw back only the matching top-up.
  • Abuse protection. Per-minute rate limits on the relay, burn-rate monitoring, and welcome credits sized by signup method keep shared capacity safe without affecting normal use.

Fixes

  • Sign-in deep links are now CSRF-protected. The desktop and Notes apps reject any sign-in callback they did not initiate, closing a session-fixation vector. Transcription metering is now bound to the recording session server-side.
  • Chat streaming cleanup. Fixed a timer leak in the streaming batcher that could fire after leaving the page, and capped the page cache so very long sessions no longer grow memory without bound.
  • TypeScript board cleared. Removed seven dead Notes components and fixed all five long-standing type errors; the web app now typechecks clean.

v0.3.10

Features

  • AI-first Foxl Notes on mobile. The phone experience is redesigned around the AI: a hero Start-recording screen with your recent notes, a full-height live transcript while recording (no more duplicated half-screens), and a new Summary | Transcript | Notes view switcher that lands you on a streaming, read-only AI summary the moment the recording stops. Ask AI is now a labeled button with suggestion chips during the meeting, and the editor becomes an explicit edit mode with a slimmed-down mobile toolbar.
  • One motion system across the app. Page and section switches, list items, cards, sidebars, and buttons now animate on a single set of durations and easing curves (the chat language), including press feedback on every button and restored accordion animations. Respects reduced-motion preferences.

Improvements

  • Pages load dramatically faster. The statistics dashboard, Workspace, Account, Agents, Settings, Schedules, Activities, Logs, Skills, and Integrations pages now render instantly from cache on revisit and refresh in the background instead of blanking behind spinners. Server-side, the dashboard, workspace tree, workspace search, skills scan, and agent-session queries were rewritten or cached - the worst offenders were full-database aggregations and per-file disk scans running on every poll.
  • Chat streaming is smoother. Streaming tokens are batched into far fewer screen updates, completed messages no longer re-render while new ones stream, and auto-scroll is frame-synced.
  • Build identity everywhere. Every About/version display now shows the exact build as version + git commit (for example 0.3.10 (dd21869)), and the iOS build number is now the commit count, so TestFlight re-uploads no longer masquerade as a different version.

Fixes

  • The 30-day usage chart on the Account page now actually shows 30 days of real data (it silently fell back to 24 hours and dropped every row of the model breakdown).
  • Accordion sections animate again (the open/close animation was lost in the Tailwind v4 migration and content has been snapping since).

v0.3.9

Fixes

  • Opening the sidebar no longer crashes the app. The first v0.3.9 build could blank the whole app (black overlay on mobile, white screen in Foxl Code) the moment the sidebar rendered a non-empty Code task list: the task rows were wired to a sidebar context from the wrong component library, which threw on mount and took the app down with it. The rows now use the shell's own sidebar primitives. A second crash path - an unexpected repo-list response wiping the repo cache and crashing every repo consumer - is also hardened. The over-aggressive document pin (body { position: fixed }) that fought the sidebar drawer's scroll lock is removed; push-up protection is fully carried by scoped auto-scrolling, the scroll-reset guard, and the native web-view pin.
  • The mobile app no longer gets pushed up off-screen during recording. On iOS, starting a recording in Foxl Notes (or any streaming/keyboard-heavy screen) could shove the whole app upward so the navigation bar disappeared and never came back. The cause was scrollIntoView and focus calls scrolling the entire app shell - and the keyboard plugin snapping the web view to the wrong resting position. Auto-scroll and focus everywhere are now scoped to their own scroll container, a scroll-reset guard snaps any stray document offset back, and the iOS shell pins the web view to its correct resting offset, so the push-up can no longer happen.
  • The chat usage HUD shows the real prompt size. "Input tokens" now counts the full prompt the model read (uncached input plus cache-read and cache-write tokens) with a "Cached" breakdown, instead of showing only the few uncached tokens - which made a large skill+system prompt read as a nonsensical "2". All numbers come straight from the model's reported usage.

Changes

  • Foxl Code Repos is a clean list. The repos page is now a list (with a grid toggle) that leads with the repo name, branch, language, and description, instead of repeating "Connected / Installation #... / tokens are minted per task" and an inline task form on every card. "Start task" routes to the Tasks page; describing a task lives there now.
  • One place for the task budget. The per-repo and per-task budget inputs are gone - the default task budget is a single setting in Foxl Code Settings.
  • Right-click menus across Foxl Code. Task rows, repo rows, and the task list all have right-click context menus (open, open on GitHub, copy id/branch, resume, cancel, delete, delete all). The always-visible "Delete all" button is gone - deleting is behind right-click now, matching Foxl chat.

v0.3.8

Features

  • The sidebar conversation list reorders live, with a smooth animation. Sending a message (or a background conversation finishing its reply) now floats that conversation to the top of the sidebar immediately - no reload needed - and rows glide to their new position instead of snapping.
  • Foxl Code's model picker now matches the chat one. The composer model picker in Foxl Code (code.foxl.ai and in-app) gains search, sticky provider section headers, right-click favorites pinned to a Favorites group, a bottom sheet on mobile, and live models from the Foxl catalog with Pro-only models badged - the same selector experience as Foxl chat.
  • Foxl Notes got a real mobile layout. On a phone, Notes no longer renders the squeezed desktop chrome (header buttons overlapped the tabs, the side transcript dock left a sliver of editor, and picking a note from the sidebar appeared to do nothing). Mobile now has a thumb-reachable bottom action bar (record/stop + timer + pause, AI, summarize, transcript), the transcript opens as a portrait half-split under the editor, the AI assistant opens as a bottom sheet over the editor, and tapping a note closes the sidebar overlay and shows the note.
  • The app shell got the Codex-style curve. On desktop the content area now floats as a rounded panel over the sidebar surface - the sidebar blends into the window chrome and curves into the content instead of meeting it at a hard border line. The sidebar drag-resize indicator also stops before the curve instead of running the full window height.
  • Dashboard pages share one column width. Usage, Agents, Schedules, Feed, Logs, and Mobile/Web all use the same max width (some were wider or narrower), and the last fully-circular action buttons (Channels/Integrations connect buttons, Feed back button, onboarding close) moved to the standard rounded shape.
  • Settings is now a two-pane surface. A left nav with search (flat, borderless style) and consolidated sections - General, Model & provider, Heartbeat, Notifications, Safety, Advanced - plus a Products group that embeds Foxl Notes and Foxl Code settings, so all three products configure from one place.
  • The HUD shows per-chat statistics. With a chat open, the title-bar popover shows that conversation's exact input/output/cache tokens and caching-aware cost ("This chat"); otherwise app-wide last-24h totals. Historical $0 costs were backfilled from catalog rates, and the metrics render as label/value rows. All HUD text is localized.
  • The app detects a dead local server and restarts it cleanly. If the desktop's agent server stops responding, a quiet overlay offers one Restart button: the app frees the server port (killing any orphaned process tree holding it) and relaunches the server as its own child, identical to a normal boot.
  • Refreshing mid-reply no longer loses the streaming answer. The desktop now saves the in-progress reply continuously (not just at tool boundaries), and reconnecting after a refresh resumes from the fuller of the saved draft and the live stream snapshot - including the case where the reply had not started yet (no more gluing new text onto the previous answer).
  • "Relay" is now "Mobile/Web" (and "Desktop" when viewed from the web/mobile app). The page header shows a compact status row instead of a giant Online/Offline headline, and the legacy local gateway (self-hosted LAN server) was removed - the Foxl relay is the only remote-access path.
  • Settings looks like a modern settings screen. Each section is now one flat panel with hairline-divided rows instead of a stack of floating cards.
  • The colorful Integrations and Skills heroes are back. The crossfading per-item gradient backdrops returned behind the sample-prompt cards.
  • Buttons and inputs share one shape language. Pill-shaped (fully round) buttons, search fields, selects, and segmented filters across Agents, Schedules, Tools, Skills, Channels, Activities, Logs, Integrations, and the remote-access page now use the standard slightly-rounded shape; status dots stay round. The Agents Run button also dropped its paper-plane icon.
  • The status HUD in the title bar is cleaner and stays in sync. Regular UI type in a soft pill instead of terminal-style monospace, and the "Running: tool" / thinking line now resets reliably when a reply finishes (it could previously stick after a reconnect).
  • Every page now speaks the chat design language. Skills, Tools, and Channels dropped their centered marketing-style titles for the same left-aligned header Settings and Integrations use; the Skills hero lost its hardcoded gradient (which broke in dark mode) for the flat panel Integrations has; pill-shaped search fields and CTAs became the standard rounded inputs/buttons; and Account, Notification Settings, and Notes Settings now sit in the same centered column as Settings instead of pinned to the left edge.

Fixes

  • The agent now splits long shell commands instead of failing silently. The agent's instructions tell it to never inline large content into one exec call (such commands can fail with no output at all) and to build big files in small appended chunks across multiple calls, retrying any silent no-output failure as smaller steps.
  • Foxl models and your local AWS provider no longer mix in the model picker. Models served on Foxl credits were labeled by their upstream infrastructure ("AWS"), which split them into duplicate sections and merged them with models from your own local AWS (Bedrock) credentials. All Foxl-served models now group under one "Foxl" section; "AWS" is reserved for the local provider. Within every section models are ordered Claude first, then GPT, then open-weight.

v0.3.7

Fixes

  • The agent's shell tool no longer silently stalls on long replies. When a model on the Foxl relay produced a long response (for example writing a big file in one command), the relay could drop a piece of the streamed response at a network boundary, so the tool call arrived incomplete and ran nothing with no error. The relay now reassembles split stream frames correctly, so long commands and long answers come through whole.
  • The shell tool reports an error instead of hanging on an oversized command. A command longer than the operating system's limit used to fail with no result at all. It now returns a clear error explaining the limit and suggesting writing large content incrementally.

Features

  • The model picker groups models by provider with a sticky header. As you scroll the model list, the provider name (AWS, OpenAI, ...) stays pinned at the top so you always know whose model you are looking at. Favorites pin to the top of the list.
  • Right-click a model to favorite it. Favorited models pin to a Favorites group at the top of the picker (a star also appears on hover).
  • Fable 5 is marked Pro in the picker (like Opus), so it is clear which models the free tier cannot run. The Pro gate is now derived from the relay's tier rules, not hardcoded model names.
  • Task Budget moved to Settings. The reasoning toggle and per-model effort stay in the message bar, but the advanced Task Budget control now lives in Settings so it does not clutter the quick picker. Reasoning settings share one source of truth between Settings and the picker, so they can never disagree.

Foxl Code

  • "Delete all" is now a visible action at the top of the task list (not only in the right-click menu). Tasks that are still running are kept; only finished tasks are removed.

Design

  • Settings and Integrations match the rest of the app. Both pages dropped the centered marketing-style headers, oversized width, and gradient hero in favor of the same flat, left-aligned layout the chat surface uses.

Mobile

  • The model picker is a smooth bottom sheet on phones. Instead of a small popup that flipped up from the bottom and crowded the keyboard, tapping the model name now slides up a proper bottom sheet with large tap targets and one-tap effort pills.

v0.3.6

Features

  • Reasoning controls live in the message bar now. The reasoning toggle, per-model effort levels (Low through Max), and the task budget moved from Settings into the model selector next to the send button, so you can tune reasoning per model right where you pick it. Each model shows exactly the effort levels it supports, picking an effort turns reasoning on, and your choice applies immediately to the next message. The selected effort now shows inline in the bar (for example "Sonnet 4.6 Low") instead of a generic "Thinking" badge, and the menu itself is a tighter, lighter design with the effort levels tucked behind an "Effort" row.
  • Search the model list. The model selector now has a search box - type a model name or provider to filter the list instead of scrolling.

Removed

  • The "Auto" model option is gone. Auto-routing picked a model by guessing the message's complexity and did not work reliably. You now always know exactly which model answers: pick one and it stays. Anyone previously on Auto is moved to their default model.

v0.3.5

Foxl Code

  • The send button works as you type on mobile. In Foxl Code on phones (and the iOS app), text you typed was treated as empty until the input lost focus, so the send button stayed disabled and a tap sent nothing. The composer now registers what you type immediately, exactly like Foxl Agent, so send enables the moment there is text and always sends what is on screen.
  • No more blank gap under Tasks in the Foxl Code sidebar. On the desktop app, when you had no tasks (or were signed out) the Foxl Code sidebar showed an empty stretch between Tasks and Repos where placeholder rows were reserved. An empty task list now collapses to nothing, matching the Foxl Agent conversation list.

Models

  • Fable 5 reasoning is now correct for Foxl Code's autonomous agents too. The Foxl Code orchestrator picked each model's thinking mode by matching on the model name, which could send a new model the wrong shape (Fable 5 only accepts adaptive thinking and rejects the older budgeted shape). It now reads the thinking mode from the same shared model catalog the rest of Foxl uses, so any model added to the catalog gets the right reasoning behavior with no code change.

Security

  • Closed two command-injection paths in the local desktop server. The "reveal in Finder/Explorer" and "open folder" actions, and external skill installs, now pass paths and package names as arguments instead of building a shell command string, so a crafted path or skill name can no longer run arbitrary commands.
  • Background and channel agents now obey approval gates. Agent runs started by a connected channel (e.g. Telegram), a scheduled task, or the browser extension now go through the same permission deny-rules and approval prompts as the main chat, instead of running tools ungated.
  • Sign-in links can no longer be forged on desktop. The desktop only accepts a foxl:// sign-in callback when you actually started a sign-in, so a malicious link cannot silently swap your account.
  • The local dev server binds to localhost only. In development the API and WebSocket are no longer exposed to your local network by default.
  • Closed a WebSocket auth bypass. The browser-extension WebSocket path was matched by a loose substring, so a crafted URL containing "/extension" could skip the connection-token check. The check now matches the exact path.

Fixes

  • Windows downloads and auto-update work again. The v0.3.4 release went out with macOS files only, which broke the fixed Windows download links on foxl.ai and docs.foxl.ai and silently stopped auto-update for existing Windows installs. The Windows installer, portable ZIP, and update manifest are back on the latest release, and the release script now carries Windows files forward automatically and refuses to finish if any download link would break.
  • Model pricing reconciled. GLM-5 and GPT-4o were priced inconsistently in different places, and Kimi K2.5 had no pricing row on the staging backend (where it failed as "unknown model"). All three are now consistent.
  • Sign-in is rate-limited everywhere. The token-refresh endpoint now has the same per-IP rate limit as the other sign-in endpoints.
  • foxl.ai shows the current model lineup. The pricing and demo screens named retired models; they now show Claude Fable 5, Opus 4.8, and GPT-5.5.

v0.3.4

Foxl Code

  • Settings sits at the bottom of the sidebar again. In the Foxl Code workspace, Settings was rendered directly under Runtimes with a large blank gap beneath it. It now pins to the bottom of the sidebar (above your account), matching the Foxl Agent layout, while Tasks / Repos / Files / Runtimes stay grouped at the top. Applies to both the in-app Foxl Code and code.foxl.ai.

Foxl App (mobile)

  • Swipe from the left edge to open the sidebar. On the iOS app you can now drag in from the left edge of the screen to slide the sidebar open, the same way native apps do. Tapping outside still closes it. Desktop and web are unchanged.

Fixes

  • Reasoning toggle now shows correctly for every foxl.ai model. The model list served by foxl.ai did not carry each model's reasoning capability, so Settings wrongly said "This model does not support adjustable reasoning" for models that do (including Fable 5). The model list now carries the reasoning spec, and the chat path picks the correct reasoning mode from the shared model catalog instead of matching model names, so newly added models work without a code change.

Security

  • Google sign-in now requires a verified email. The Google login path did not check Google's email-verified flag before matching an existing account, unlike the GitHub and Apple paths. It now rejects unverified Google emails, closing an account-takeover vector.
  • Relay CORS fails closed. When the allowed-origins list was unset the relay reflected any caller's origin together with credentials; it now serves a credential-less public CORS posture in that case (the relay uses header auth, not cookies, so nothing was exploitable, but this is the correct default).
  • Desktop no longer exposes the process environment to the web layer. The unused get-env bridge (which would have carried AWS credentials) was removed from both Foxl Desktop and Foxl Notes, and the standalone Notes window now blocks navigation to external origins.
  • Foxl Code agents validate repo and branch names before using them in git commands, preventing argument-injection from repository metadata.

v0.3.3

Models

  • Claude Fable 5 is now available. Anthropic's new state-of-the-art model is selectable across Foxl App, Foxl Code, and Foxl Notes. Fable 5 is built for ambitious, long-running work with advanced vision and is top-tier on most benchmarks. It is a Pro/Ultra model (excluded from the free tier like the Opus tiers). Opus 4.8 remains the default; pick Fable 5 from the model selector when you want the most capable model. Pricing is $10 / $50 per million input / output tokens. Fable 5 is also available through your Claude Pro/Max subscription (Claude Code OAuth) on the desktop.

Foxl App

  • Sign in on mobile now finishes cleanly. On iPhone, after signing in through the in-app browser the sign-in sheet stayed open on top of the app showing an "Open Foxl" button that did nothing (the app behind it was already signed in). The sheet now closes by itself the moment sign-in completes, so you land straight in the app. The unhelpful "Copy link" button is gone on mobile.

Foxl Code / Foxl App

  • Fixed "Sign in with Apple" failing on the first try. Apple periodically rotates its signing keys; when it did, the next Apple sign-in failed once and only worked on a retry. Sign-in now refreshes Apple's keys and retries automatically, so it works the first time across a key rotation.

v0.3.2

Foxl Code

  • The task list now sits directly under Tasks in the sidebar, and loads instantly. In the in-app Foxl Code, the left sidebar task list used to drop below the Settings row and take a few seconds to appear (while the right rail was instant). It now renders right under the Tasks nav item, matching code.foxl.ai, and the list starts loading the moment you open Foxl Code (with a brief skeleton instead of a blank gap) rather than waiting for the page to finish loading.
  • Editable per-task budget. Settings now exposes the default per-task budget in dollars, so you can set the absolute spend ceiling a single task runs under (previously this was an internal fixed value and only the multiplier was adjustable). The per-task override on the new-task dialog still wins.
  • More coding agents. The coding-agent runtime was rebuilt on the AWS AgentCore interactive-shell model, adding Cursor, Hermes, and OpenCode alongside Claude Code, Kiro, and Codex. Each runs in its own isolated microVM and opens a pull request the same way. Cursor brings its own key like Kiro; Hermes and OpenCode run on Bedrock.

Foxl App

  • Onboarding logo renders correctly in dark mode. The welcome screen logo was color-inverted in dark mode, which flipped its colors; it now shows the correct mark on any theme.
  • Onboarding is fully translated. The "Get the Desktop App" step on the web app was English-only; it now follows your app language in all 10 supported languages.

v0.3.1

Foxl Code

  • Fixed code.foxl.ai rendering with square corners and wrong spacing. After the Foxl Code product moved into a shared package, the standalone code.foxl.ai stopped generating the styling used only by that product, so the composer, tool rows, and message bar lost their rounded corners and padding. They now render the same rounded, properly spaced UI as the in-app Foxl Code and the desktop app.
  • The repo name in the message bar no longer overflows. A long owner/repo name now truncates with an ellipsis inside the composer instead of pushing past the edge, matching the model picker next to it.
  • The Files page fills the window. The workspace file browser rendered short with empty white space below it; it now uses the full height in every shell (web, desktop, and in-app).
  • Sign-in nudge when you are not signed in. Like Foxl Notes, starting a Foxl Code task now prompts you to sign in (with a one-click sign-in action) instead of the button quietly doing nothing, since Foxl Code runs on your Foxl account and credits.

Site & Docs

  • docs.foxl.ai home now lists Foxl Notes. The documentation home page added Foxl Notes alongside Foxl Desktop and Foxl Code, both as a product card and in the browse-by-section grid, so all three products are discoverable from the landing.
  • foxl.ai/code refreshed for the in-app launch. The Foxl Code marketing page now reflects that Foxl Code runs inside the Foxl app (web, desktop, and phone) in addition to code.foxl.ai, and a broken docs link was corrected.

v0.3.0

Foxl Code

  • Foxl Code is now built into the Foxl app. The coding-agent product that runs at code.foxl.ai is now available as a third product inside Foxl, next to Foxl Agent and Foxl Notes. Pick "Foxl Code" from the product switcher to see your tasks, repos, files, and runtimes, open a task to watch its live agent terminal, and start new coding tasks - all without leaving the app, signed in with the same account. The standalone code.foxl.ai keeps working as before.
  • A failing screen no longer blanks the whole app. The app now wraps each product view in an error boundary, so if one screen hits an error it shows a recoverable message with a way back to Chat instead of a blank window.
  • In-app Foxl Code polish. The Task Plan side panel and chat now read in your app language instead of showing internal text labels; the message bar keeps its send button visible and shortens a long model name instead of pushing the button off-screen; the Task Plan panel gained a close button (with a header toggle to reopen it); and the Runtimes screen no longer scrolls sideways on a phone when it shows a long status message.

Foxl Mobile

  • Mobile layout respects the notch and home indicator. On iOS the WebView insets its content for the Dynamic Island / status bar and the home indicator, so headers and the bottom composer clear them. (The earlier attempt to add a CSS-level viewport-fit=cover inset on top of that was reverted - combining it with the WebView inset desynced render and touch coordinates, so taps landed in the wrong place.)
  • Foxl Code mobile polish. Agent icons (Claude Code / Kiro / Codex) now load correctly; the content pages (Repos, Runtimes, Settings, Account) get the same page gutter as code.foxl.ai instead of sitting flush against the screen edge; and the Code header is decluttered on phones (the repo picker, which also lives in the composer, is hidden in the header on narrow screens).
  • Keyboard-docked message bar on iOS. Tapping the chat box now behaves like the Claude / ChatGPT mobile apps: the keyboard slides up and the message bar rides up to sit directly on top of it, the conversation above shrinks to fit, and the header stays put - no more page scrolling or the input getting hidden behind the keyboard. Applies to both Foxl Agent and Foxl Code chats.
  • Foundation for Foxl on iOS and Android. Groundwork for a native mobile app that wraps the Foxl web experience (Agent chat, Notes, and Code) with native sign-in, microphone recording for Notes, and push notifications. Billing on mobile is read-only with an external link to manage your plan on the web. The mobile app is not yet in the App Store or Google Play; this release lays the technical foundation.

v0.2.53

Foxl Notes

  • Fixed "Start Recording" doing nothing (the actual cause). Recording opens a secure WebSocket to the transcription service, but the production app's content-security policy allowed https: connections without also allowing secure WebSockets (wss:), so the transcription socket was blocked and recording never started - in production only, while development builds (which have no such policy) worked. The policy now permits the secure WebSocket, so Start Recording connects and transcribes as expected. Production builds also now mirror renderer errors into the app log so issues like this are diagnosable without a debugger.
  • Fixed the Notes header overlapping on narrow windows. On small or mobile-width windows the Notes/Background tabs and the recording controls could overlap. The recording controls now keep their own space and the tabs shrink, so the header stays readable and tappable at any width.
  • Notes now follows your app language, in 10 languages. The Foxl Notes interface used to render in your browser's default language regardless of the language you picked for the app; it now stays in sync with the app's language selector. Added Russian and Arabic translations (Arabic also switches the interface to right-to-left), so Notes is now fully translated in every language the app supports.

Foxl Desktop

  • Fixed the sidebar and main view disagreeing after a restart. On a fresh launch the sidebar could show Foxl Notes while the main area still showed the Agent chat (or the reverse). The app now restores both the sidebar and the content to the same product you used last.

Site & Docs

  • docs.foxl.ai model and tool pages refreshed. The Models page now lists Kimi K2.5 and shows that GPT-5.5 / GPT-5.4 run on Foxl relay credits (not only via a ChatGPT subscription), and the Agent Tools page tool-profile counts were corrected to match the app.

v0.2.52

Foxl Notes

  • Fixed "Start Recording" doing nothing (for real this time). The previous release added the microphone permission handling but the production build did not pick up the microphone usage description, so on a signed, hardened build macOS still silently refused mic access and Start Recording did nothing - while development builds worked. The production build now ships the correct microphone usage string, and Foxl asks for microphone access before the first recording (with a clear message pointing you to System Settings if access is blocked). Recording now starts as expected.

Site & Docs

  • foxl.ai/note refreshed. Tighter hero copy focused on what Notes does (transcription, AI summaries, action items, any language), and the product mockup now matches the real Foxl Desktop app - the product switcher and recordings live in one shared sidebar, with the recording controls in the app header.
  • docs.foxl.ai navigation matches across pages. The documentation pages now use the same top-bar order as the docs home: the section links sit next to the brand, with the search box on the right.

v0.2.51

Foxl Desktop

  • Fixed GPT-5.5 / GPT-5.4 returning an error on your Foxl account. Picking a GPT-5.x model while signed in with your Foxl account still failed with "Model gpt-5.5 is an OpenAI Responses-API model" in the main chat. The previous release routed most paths correctly, but the primary streaming-chat path still sent GPT-5.x to the Claude-style endpoint, which these models reject. That path now uses the same single routing helper as everywhere else, so GPT-5.5 / GPT-5.4 stream correctly on your Foxl account, in the desktop app and at app.foxl.ai. Claude, GLM, Kimi, and Gemini are unchanged.

Foxl Notes

  • Fixed "Start Recording" doing nothing. When Foxl Notes moved into the unified Foxl Desktop app, the microphone permission setup did not come with it, so on a fresh install clicking Start Recording silently failed - the app was never allowed to open the mic. Foxl now requests microphone access correctly (with the proper macOS permission prompt and entitlement), so recording starts and the system asks for mic access the first time, as expected.

Site & Docs

  • foxl.ai/note redesigned for the unified app. The Foxl Notes page now reflects that Notes ships inside the Foxl Desktop app - every download points at the single Foxl Desktop installer instead of a separate Notes download, and the standalone-only release notes were removed. One download, one account, one balance of credits.
  • Docs top navigation no longer wraps to two lines. Adding the Foxl Notes tab pushed the docs.foxl.ai header wide enough to wrap the section labels; the nav now keeps every label on a single clean row.

v0.2.50

Foxl Desktop

  • Fixed duplicate messages and empty replies when sending quickly. Firing several messages in a row (or re-sending after a slow turn) could duplicate your message, leave blank assistant bubbles, and bind replies to the wrong message. The send path gated new turns on React state that updates asynchronously, so a rapid burst slipped through and started several streams at once. Turn-start is now serialized with a synchronous per-conversation latch, so a burst becomes one turn plus the rest queued into a single follow-up. The fix is keyed by conversation only - it is model- and provider-agnostic.
  • Reasoning controls now adapt to the selected model. The thinking/effort setting was a single fixed list (low/medium/high/max) that did not match what each model actually accepts, and the effort never reached OpenAI-on-Bedrock (GPT-5.5/5.4) at all. Each model now declares its reasoning style and supported effort levels in one place (the model catalog), and both the server request and the Settings UI are driven from it: GPT-5.5/5.4 expose none/low/medium/high/xhigh and now actually send their reasoning effort; Claude Opus exposes low through max (plus task budget); Claude Sonnet exposes low through max; Haiku and GLM/Gemini show a simple on/off; models without reasoning hide the control entirely. Switching models clamps the effort to one the new model supports. GPT-5.x reasoning summaries are not shown on Bedrock yet (a known upstream limitation); the UI says so rather than showing an empty trace, and will surface them automatically once available.
  • Fixed GPT-5.5 / GPT-5.4 repeating their answers. Picking a GPT-5.x model (on AWS or through your Foxl account) and asking anything with reasoning on produced an answer that restated itself 3-8 times, growing each time. The cause is upstream: Amazon Bedrock's OpenAI service streams GPT-5.x as several message chunks where each new chunk repeats everything said so far. Foxl now collapses those repeats back into a single clean response - both as it streams and in the saved note - at the point where Foxl talks to Bedrock, so every surface (desktop, app.foxl.ai, Foxl Notes) is fixed at once. GPT-5.4 and Claude were unaffected, and the fix turns itself off automatically once the platform issue is resolved.
  • GPT-5.5 / GPT-5.4 now work when routed through your Foxl account. Selecting a GPT-5.x model while signed in to Foxl (rather than using your own AWS keys) failed with "Model gpt-5.5 is an OpenAI Responses-API model." The desktop always sent chat through the Claude-style endpoint, which these models reject. Foxl now detects GPT-5.x and routes it to the correct OpenAI-style endpoint automatically; Claude, GLM, Kimi, and Gemini are unchanged.

Foxl Notes

  • Foxl Notes AI summaries support GPT-5.5 / GPT-5.4. Notes shares the same fixed GPT-5.x routing and de-duplication, so picking a GPT-5.x model for a meeting summary produces a clean, single summary instead of a repeated one.

v0.2.49

Foxl Desktop

  • GPT-5.5 / GPT-5.4 work again when selected directly on AWS. Picking GPT-5.5 or GPT-5.4 with the AWS (Bedrock) provider in the desktop app returned "The provided model identifier is invalid." These models are served only through the native OpenAI Responses API on Bedrock, but the desktop chat path had no branch for the OpenAI-on-Bedrock provider, so it fell through to the Claude Bedrock path and sent the request to the Converse API, which does not recognize the OpenAI model id. The chat model builder now routes the OpenAI-on-Bedrock provider to the Responses endpoint (SigV4, no API key), matching how the relay (app.foxl.ai) already handled it. The relay path was unaffected.

v0.2.48

Foxl Code (code.foxl.ai)

  • Kiro backend gated off until it has working auth. The Kiro coding-agent backend never had a working headless auth path (the CLI ignores the relay route, has no provisioned key, and its SigV4 mode is unimplemented upstream), so a Kiro task would stall on an interactive browser-login prompt inside the sandbox and end in a confusing failure. Kiro is now disabled at the environment level unless explicitly enabled, the Settings picker greys it out, and starting a Kiro task returns a clear error instead of launching the broken path. Bring-your-own-key scaffolding (paste a Kiro/Q API key in Settings, stored encrypted) is wired in for when the backend is turned on; Kiro runs on your own Kiro/Q account, not Foxl LLM credits.

Foxl Desktop + Foxl Code

  • GPT-5.5 / GPT-5.4 streaming fixed on the relay. OpenAI-on-Bedrock models are served through the native Responses API; the relay's streaming proxy could throw an uncaught error and drop the stream when a client disconnected mid-response (the normal case for the Codex CLI and browsers). The passthrough now handles client disconnects cleanly and always meters the tokens it observed, so streaming GPT responses are reliable.
  • GPT-on-Bedrock now shows under AWS. In the desktop model picker, GPT-5.5 / GPT-5.4 are badged "AWS" (they run on Amazon Bedrock, like the Claude models) instead of an internal provider name.
  • Open-weight gpt-oss models removed. Foxl exposes the frontier GPT-5.5 / GPT-5.4 only; the gpt-oss-20b / gpt-oss-120b entries were dropped from the catalog, pricing, and routing.

v0.2.47

Foxl Desktop

  • Update "Relaunch" banner now appears on first launch. The "Updated to vX / Relaunch" prompt sometimes only showed up after a manual reload (Cmd-R). The preload cleaned up IPC listeners with removeAllListeners, so any component unmounting (e.g. leaving the Settings page) silently tore down every other subscriber to the same channel - including the update banner - and the next "update ready" push reached no one. Each subscription now removes only its own handler, and the main process re-emits the ready state on every page load so the banner surfaces deterministically.

Docs (docs.foxl.ai)

  • Fixed blank article body and rebuilt the layout. The documentation article column had been rendering blank under the new top section-tabs (a tab bar stretched over the article and painted an opaque panel over the text). Moved docs to a full-width top bar with the section tabs, search, version selector, and a light/dark theme toggle, and put Home / App / Download in a proper page footer that no longer covers the sidebar.
  • Foxl Code docs expanded. The Foxl Code section grew from a single page into Overview, How it works, Tasks, Coding agents, GitHub, Budgets and tiers, Autonomous loop, and Resume from review.
  • Themed, not just gray. Added Foxl brand blue for links and active navigation, tinted info/warning callouts with their own accent color, and gave code blocks a crisper surface - all correct in both light and dark mode.

v0.2.46

Foxl Code (code.foxl.ai)

  • Autonomous multi-PR runs. One command now goes all the way: the orchestrator publishes a structured plan (one checkbox = one PR), you confirm ONCE, and from there the autonomous loop fans out a coding agent per checkbox, tracks each PR, retries failures, and marks the plan complete - no babysitting. The confirm button now wakes the loop immediately (it used to dead-end until your next chat turn), a plan carries its own repo + installation so the loop can start it with no live chat, and the heartbeat tick performs the initial fan-out for any confirmed-but-unstarted plan. Autonomy is on by default for every Foxl Code user.
  • OpenAI Codex backend (GPT-5.5/5.4 on Amazon Bedrock). A third coding-agent backend alongside Claude Code and Kiro. The orchestrator runs the OpenAI Codex CLI in an isolated AgentCore microVM with all model inference routed Bedrock-direct via the container IAM role (no API key, AWS SDK credential chain). Say "use codex" on a task, or set Codex as your default coding assistant in Settings and pick GPT-5.5 (most capable) or GPT-5.4 (best price-performance). New forge/agent-codex runtime, agent_backend='codex' end to end.
  • Per-family coding-assistant settings. Settings now lets you choose a default coding-assistant family (Claude Code / Kiro / Codex) and the model within the Codex family. Tasks with no explicit backend use your default; you can still name a backend per task and the orchestrator honors that. Backends not provisioned in your environment are greyed out.
  • Security: webhook task matching hardened. The pull_request webhook now matches a PR back to its task by exact 12-hex-char branch suffix (substr(id,-12)=?) instead of a LIKE pattern, and rejects non-hex branch names. Closes a path where a crafted branch name on a shared org installation could flip another member's task.
  • Coding agent always opens its PR on the right branch. The agent re-derives the canonical foxl/<task> branch at push time instead of trusting the working branch, so a mid-task branch switch never produces a self-referential PR or defeats the task matcher.
  • Stg now mirrors prod branding. The staging Foxl Code surface shows the real "Foxl Code" name + logo (it was previously white-labelled), so staging is a faithful dress rehearsal.

Foxl Desktop + Foxl Code

  • Opus pricing corrected across estimates and docs. Cost estimates, the desktop pricing table, and the docs now all state Opus 4.6/4.7/4.8 at $5/$25 per MTok (cache read $0.50) - matching what the relay meter actually charges. Some estimate/doc surfaces had inherited a stale $15/$75; users were never overcharged (the meter was always correct), but pre-flight task estimates and budget gating were 3x high.
  • Adaptive thinking kept on with task budgets (relay path). Enabling a Task Budget on the default relay transport no longer silently drops adaptive thinking; it now layers the budget on top, matching every other transport.

Docs (docs.foxl.ai)

  • Claude-style top navigation. The docs site now has section tabs across the top (Get Started, Foxl Desktop, Foxl Code, Reference), each scoping the sidebar to its own tree, plus a refreshed landing page. Old page URLs 301-redirect to their new homes.

v0.2.45

Foxl Desktop + Foxl Code

  • Claude Opus 4.8 added across the stack. New Anthropic flagship: state-of-the-art coding (SWE-bench Pro 64.3%, SWE-bench Verified 87.6%, Terminal-Bench 2.0 69.4%), longer autonomous runs, lower output variance for enterprise workflows. 4.8 is now the default Opus tier in Foxl Desktop, Foxl Code (orchestrator + coding agents), and the relay model registry. Migration is a model-id swap; same adaptive-thinking shape, same 1M context, same output_config.effort semantics. Pricing matches 4.7 ($5/$25 per MTok, cache read $0.50/MTok, cache write $6.25/MTok).
  • Opus 4.7 stays in the catalog. Users on 4.7 can keep using it via the model picker. The legacy claude-code/opus short alias now points at 4.8 (current default Opus tier); the explicit claude-code/claude-opus-4-7 id keeps resolving to 4.7.
  • Default model bumped. currentModel default in the desktop provider registry is now claude-opus-4-8; the model alias smart and opus resolve to 4.8.
  • Forge defaults bumped. New users get Opus 4.8 as both coding_agent_model and default_model from /api/settings. Existing users keep their persisted selection.
  • D1 migration 0024_opus_4_8_pricing.sql. Seeds model_pricing so the relay's meter.canRequest() resolves 4.8 instead of returning "Unknown model" the way 4.7 did at launch.
  • Task budgets (beta). Settings page exposes a new Task Budget selector (off / 25K / 50K / 100K / 250K / 500K tokens). When enabled with thinking on Opus 4.7+, the desktop attaches output_config.task_budget = {type:'tokens', total:N} and the task-budgets-2026-03-13 beta header to the AnthropicModel-backed transports (Anthropic API direct + foxl relay). Bedrock Converse silently drops output_config today, so the budget is a no-op on the direct-Bedrock path; we will switch to Bedrock Mantle Messages API later to fix that.
  • Sampling-param hardening for 4.7+. Anthropic provider's complete() and stream() no longer send temperature: 0.7 when the model id matches Opus/Sonnet/Haiku 4.7+. Those models reject non-default temperature / top_p / top_k with HTTP 400 per the field guide; Foxl now lets the API use its calibrated default. Older Claude/non-Claude paths are unchanged.
  • resolveEffectiveContextWindow recognizes 4.8. Like 4.7, Opus 4.8 reports the catalog's full 1M context on the Claude Code OAuth transport. Sonnet 4.6 and Haiku 4.5 are still capped at 200K on the subscription pool.
  • Account / Usage charts add 4.8. App.foxl.ai AccountPage and code.foxl.ai UsagePage label and color the new tier so the per-model bar charts don't fall back to "claude-opus-4-8" raw text.

v0.2.44

Foxl Code (code.foxl.ai)

  • Goal-first task rows. Both the left Tasks sidebar and the right Task plan rail now lead with the goal (title or prompt preview) instead of the repo name. The agent's avatar carries its lifecycle status as a dot, repo + timestamp drop to a muted second line. Three tasks in the same repo no longer read like the same row repeated.
  • Account menu in the topbar. Sign-in / Sign-out, credits balance, Service status, and account links live in a dropdown under your avatar. The Orchestrator-degraded indicator surfaces here when /health returns non-OK so you know new tasks may queue.
  • Right rail polish. "Open in full page", "Back to tasks", and a "Prompt" header on the task plan rail. Search bar inside the rail. Accessible Open/Close labels for screen readers.
  • Edit your display name. Account page now lets you set the name shown across Foxl. Saves through the relay's new PATCH /auth/me endpoint, so the name follows you to Foxl Desktop too.
  • Quieter Runtimes page. Removed the bottom "Recent activity" event log; the active-runtime grid stays. Each runtime card still shows its own mini-terminal preview of the last few events.

Foxl Desktop (app.foxl.ai)

  • Display-name editing in Relay-Only mode. Profile edit now persists to the Foxl account on relay (not just local state). The new name carries across browsers, the Foxl Code SPA, and Foxl Desktop on macOS / Windows.

Relay

  • PATCH /auth/me. New authenticated endpoint to update displayName (max 100 chars; pass null or empty to clear). CORS allow-list now includes PATCH.

Foxl Code (code.foxl.ai) - operational

  • Default per-task budget floor raised to $500. Previously a 30-min Opus task auto-estimated at ~$1.30 and got killed mid-flight with forge task budget exceeded even when the user had thousands of credits. The auto budget now floors to $500 (override + multiplier paths still respected); daily-cap default lifted from $0.50 to $500 with a $1000 ceiling.

Foxl Desktop

  • Streaming-text shimmer restored to v0.2.30 timing. The Tailwind v3 -> v4 migration shipped in v0.2.41 lost the original keyframes; v0.2.42 wrote them back at 1/4 of the original travel range, which made the shimmer "tick" visibly at the seam every half-second. Keyframes now match the v0.2.30 config (200% -> -200%) - smooth, uni-directional sweep, no visible loop. Shared @foxl/ui Shimmer also now sets the duration on every variable name in use across the workspaces.

v0.2.43

Foxl Code (code.foxl.ai)

  • Cmd+Shift+F global task search. New CommandPalette + GET /api/search/tasks endpoint. Match across title, repo full name, prompt body, and id; results scoped to the user via the relay JWT. Hard-capped at 50 results, 150 ms debounce. Press Enter (or click) to navigate to the matched task.
  • Cmd+F in-chat search. New ChatSearchBar mounted on TasksPage and TaskDetailPage. Walks text nodes inside the chat container, highlights matches via the CSS Custom Highlight API, and steps prev/next with Enter / Shift+Enter. Falls back gracefully on browsers without the API.
  • Auto-refresh sidebars on task mutations. New TASKS_CHANGED_EVENT window event fires after every cancel / set-status / retry / resume / delete / delete-all. AppSidebar inline list and TaskDocSidebar In-progress/Recent sections listen for it and refetch immediately, so right-rail and left-sidebar both stay in sync without waiting for the 5 s poll.

v0.2.42

Foxl Code (code.foxl.ai)

  • Kiro CLI as a peer coding-agent backend (INC-017). New forge/agent-kiro AgentCore Runtime container ships the AWS-distributed Kiro CLI (kiro-cli + kiro-cli-chat + kiro-cli-term). The orchestrator picks per task via the new agent_backend zod arg on spawn_agent, defaulting to Claude Code unless the user explicitly says "use kiro". Settings shows backend availability read-only; the orchestrator owns the per-task choice. Kiro auth (KIRO_API_KEY / SIGV4) is still pending upstream so Kiro tasks land at the login prompt today.
  • Per-task agent backend persisted on tasks rows. New tasks.agent_backend D1 column captures which CLI ran each task. RuntimeCard + TaskDetailPage header render the backend icon (Claude Code orange mascot vs Kiro logo) so post-mortem context survives even if defaults change.
  • Bulk Delete-all from right-click context menu. New DELETE /api/tasks endpoint wipes every terminal-state task (queued/running rows skipped, returned in the response). Right-click any task row in the AppSidebar inline list, or anywhere in the right-rail TaskDocSidebar list, to surface "Delete all".
  • Repos page connection flow. "Add another install" is now a dropdown with two paths: open-on-GitHub (the standard flow) and Connect-by-login (adopt an install Foxl never picked up). Each install card gets an "Add repo" button that jumps to GitHub's per-install Configure page; the Repos tab auto-syncs on focus when you come back. Manual-add escape hatch reachable even when installs already exist.
  • One-click GitHub repo jump. The topbar repo picker now has an external-link button next to the trigger that opens the selected repo on github.com. Each row inside the dropdown also gets a hover-revealed open-on-GitHub action.
  • Orchestrator session bumped v6 -> v8. Forces AgentCore to spin up fresh containers so the new spawn_agent schema + Kiro-aware system prompt take effect immediately.
  • Relay proxy: strip Bedrock-incompatible beta fields. Claude Code 2.1.x sends context_management and output_config in every request body. Bedrock InvokeModel rejects them with 400 "Extra inputs are not permitted", which the SDK retried until the agent gave up. The relay now strips these fields before forwarding to Bedrock.
  • Agent API key prompt eliminated. Pre-seed the per-task JWT into Claude Code's customApiKeyResponses.approved so the "Detected a custom API key" interactive prompt never fires. Previously the agent stalled on this prompt every invocation.
  • Resume without alert. The "Resume" button no longer pops a text-input dialog. It flips the task back to running immediately and the user types directly in the live terminal.
  • Resize-jiggle on mount and resume. The terminal sends a shrink-then-restore resize pair (two SIGWINCHes) on every page load and on resume, forcing Claude Code to do a full repaint. Fixes partial rendering on fresh loads.
  • Deduplicated task events. Removed SSE backlog replay from the Durable Object subscriber. Events are now delivered once via the REST backlog, then live-only via SSE. Timestamps no longer mismatch.
  • "live" badge restricted to running tasks. The sidebar badge now only shows on running/queued tasks, not review (where the terminal is idle).
  • Compute usage metering. The agent container now emits wall_clock_seconds and io_wait_pct in the finished event. The relay uses this to calculate and deduct AgentCore vCPU + memory credits alongside LLM token credits.
  • Expanded agent container toolbox. Added bash, vim, nano, jq, ripgrep, htop, tree, ping, dig, nc, gpg, ssh, rsync, and more to the agent Docker image.
  • Telemetry isolation. Agent containers set CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 so per-task JWTs are never sent to api.anthropic.com.

Foxl Desktop (app.foxl.ai)

  • Shimmer effect restored. The streaming text shimmer animation (animate-shimmer) was lost during the Tailwind v3-to-v4 migration. Keyframe and utility definition re-added to index.css.

v0.2.41

Foxl Code (code.foxl.ai)

  • Autonomous loop. Your coding agents now check back on running tasks automatically. Enable it in Settings - the orchestrator wakes up on a configurable interval (default 5 min), checks if anything has progressed since its last look, and follows up if needed. Quiet hours and a daily spend cap keep it from running up costs overnight.
  • Per-task spend metering. Every LLM call a coding agent makes is now tracked in real time against the task's budget. You can see cumulative cost on the task detail page. When a task hits its budget ceiling the agent stops gracefully - no surprise charges.
  • Custom budgets. Set a spending limit before launching a task. The composer now has a "Budget (USD)" field. Values below the auto-estimate are rejected; the system caps runaway spend at whatever you set.
  • Resume from review. When a coding agent pauses for your review (e.g. waiting for approval on a risky change), you can now hit "Resume" to continue exactly where it left off - same container, same git state. If the container was reaped, the UI falls back to a retry automatically.
  • Agent screen and input. The orchestrator can now read a running agent's terminal screen and send input to it. This is the foundation for multi-agent coordination - one agent can check on another and unblock it.
  • Dual storage architecture. Two orchestrator runtimes: Session Storage (default, per-session physically isolated) and S3 Files (shared mount with prefix-based isolation). Pick in Settings.
  • Stop button. Cancel streaming responses mid-flight via the composer's stop button.
  • Thinking block interleaving. Multiple thinking blocks render independently with separate collapsible sections.
  • Tool call shimmer fix. Tool result events now correctly stop the running animation.
  • Workspace page file browser. Browse your agent's working directory - session storage or S3 Files mode detected from settings.
  • Mobile: compact New Task button. The topbar "New Task" button collapses to a "+" icon on small screens so it no longer overflows.

Foxl Desktop

  • Monorepo workspace fix. Independent deploy units (docs, site, agent) no longer block the shared workspace install. Speeds up npm install and removes the linux-only platform error on macOS dev machines.

Infrastructure

  • Per-task JWT replay window. Relay now checks the task's D1 status before honoring a per-task token. If the task is already in a terminal state (merged/failed/cancelled), the token is rejected even if it hasn't expired - prevents spend after completion.
  • Heartbeat cron (1-min global trigger). A single Cloudflare cron fires every minute, prefilters eligible users from D1, and fan-outs to per-user HeartbeatDOs. The DO handles interval gating, quiet hours, daily cap, and event-sequence dedup so idle users cost nothing.
  • Budget multiplier and daily cap columns. D1 migrations 0021-0022 add per-user budget_multiplier, heartbeat_interval_seconds, daily_cap_usd, and quiet-hours fields to forge_user_settings.
  • Session storage orchestrator runtime. New AgentCore runtime with sessionStorage at /mnt/workspace (14-day idle expiry, per-session isolated).
  • Terraform apply clean in stg workspace. IAM policy updated for new AP ARN.

v0.2.40

Cross-product

  • Foxl Desktop and Foxl Code now share one version line. Both products ship under the same v0.2.40 tag. Every workspace package.json carries the same "version". Per-product version drift removed.
  • Stg environment for every customer-facing surface. stg.foxl.ai, stg.app.foxl.ai, stg.code.foxl.ai, stg.relay.foxl.ai now run the same source as prod with separated D1 (foxl-relay-stg), JWT secrets, GitHub App (foxl-bot-stg, App ID 3747233), AgentCore Runtime (foxl_forge_shared_stg-CQYYNv28k2), and S3 bucket (foxl-forge-repos-stg). Stg cannot reach prod and vice versa. Each wrangler.toml exposes an [env.stg] block; --env stg flips the deploy. forge/web carries a yellow STAGING banner only when built with VITE_FOXL_ENV=stg (dead-code-eliminated for prod). Marketing/docs has no stg.
  • Docs versioning starts at v0.2.39. docs/scripts/snapshot-version.mjs snapshots content/docs/ to content/docs/v<version>/ before edits land for the next release. Old versions stay reachable at docs.foxl.ai/v<version>/....

Security

  • GitHub login account-takeover bypass closed. The relay's GitHub OAuth callback used to match the foxl user by email, so anyone who controlled a GitHub mailbox could log in as a foxl account that was created via magic link or another provider. Login now matches by GitHub's immutable numeric id (stored in the new users.github_user_id column, migration 0017) and refuses to auto-link to a pre-existing email-only account. Affected accounts are asked to sign in with their original method first and connect GitHub from settings.
  • Cross-tenant install ownership transfer closed. INSERT INTO github_installations ... ON CONFLICT(installation_id) DO UPDATE no longer touches user_id, and /api/github/setup now refuses to write when the install is already owned by another foxl user (audit-logged as cross_tenant_denied). Combined with the existing /api/installations/adopt ownership check this closes the "Foxl user A reclaims Foxl user B's install" path.
  • FORGE_WEB_URL env wired through OAuth callback. Three hardcoded https://code.foxl.ai/tasks redirects in relay/src/auth.ts now consult c.env.FORGE_WEB_URL first (default unchanged for prod). Stg sets FORGE_WEB_URL=https://stg.code.foxl.ai. Closes the leak where stg-originated GitHub OAuth would land tokens on prod code.foxl.ai.
  • Repo selection mode reclassified. Forcing foxl-bot installs to repository_selection: "selected" was on the launch-block list; that conflicts with the multi-tenant SaaS model where each user installs on their own account/org and picks the mode at install time. Tenancy is enforced at the github_installations.user_id layer (single owner per install, ON CONFLICT does not change owner, audit log on every mint). A user who picks all only enables Foxl Code on their own repos under their own install. Removed from the launch checklist; forge/SECURITY.md and forge/TODO.md updated.

Foxl Code (code.foxl.ai)

  • Mobile layout pass on every page. AppShell content padding drops from px-6 py-8 to px-4 py-6 on phones (matches app.foxl.ai), so the 375px viewport stops cropping cards and headers. Page-level fixes:
  • TaskDetailPage action bar (Pull request / Issue / Cancel buttons) now wraps to a second row instead of overflowing on phones; the header collapses to a stacked layout, the meta + budget cards switch to a 2-up grid above the terminal on tablets and 1-up under the terminal on phones, and the terminal's fixed 68vh shortens to 60vh so soft keyboards don't push the composer offscreen.
  • ReposPage repo grid drops to one column on phones (was breaking at md: only); the Sync + Connect buttons wrap when the heading is wide.
  • RuntimesPage activity rows wrap the repo name under the kind label on small screens; horizontal padding tightens.
  • SettingsPage card padding goes p-4 sm:p-6; the Save / Sign-out row wraps so neither button gets clipped.
  • UsagePage stat cards switch to a 3-up grid at sm: (was lg:-only), and ledger rows wrap when the timestamp wouldn't fit.
  • OnboardingPage outer padding drops to px-4 py-10 and the heading scales text-2xl sm:text-3xl.

Build

  • Foxl Desktop is no longer hoisted into the same node_modules as Foxl Code. foxl/apps/web and foxl/apps/electron were removed from the root workspaces list; they install their own node_modules and pin Tailwind v3 again. Foxl Code stays on Tailwind v4 in the root workspaces tree. Stops the cross-product break where forge bumping Tailwind silently dragged the desktop CSS pipeline along.
  • legacy-peer-deps=true + NODE_ENV=production no longer silently skips devDependencies. A stale shell NODE_ENV=production was making npm install resolve omit=dev, which left vite, @vitejs/plugin-react, @tailwindcss/vite, esbuild, and friends out of node_modules even though they were in package-lock.json. Builds (npx vite build, node bundle-server.mjs) then crashed with ERR_MODULE_NOT_FOUND. The integrity issue is now resolved against node_modules/.
  • Removed the duplicate site/landing entry in the root package.json workspaces list. npm tolerated it but it polluted npm ls and slowed install resolution.
  • scripts/release-all.sh docs deploy passes --project-name foxl-docs so wrangler 4.92+ does not fail with "Must specify a project name."

v0.2.39

Fixes

  • app.foxl.ai white screen fixed. A vite chunking quirk was bundling two copies of React into the relay-only build; the second copy hit the __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE symbol mismatch on boot and rendered nothing. The build now dedupes React across the workspace symlink and lands all of react, react-dom, and react/jsx-runtime in a single vendor-react chunk. Verified live: zero CLIENT_INTERNALS references in vendor-radix / vendor-ui / index chunks.
  • Sidebar borders no longer render black, electron no longer starts in dark mode. index.css was using @import '@foxl/ui/styles.css' after @font-face and @tailwind directives, which PostCSS silently drops. Every --background / --border / --sidebar-* HSL var was undefined; tailwind's border-border resolved to hsl() (invalid) and the browser fell back to black. Tokens are inlined into index.css again so the rule order does not matter. @foxl/ui/styles.css stays the canonical source for forge/web.

Cross-product

  • Foxl Code (code.foxl.ai) shipped as a separate product on the same monorepo. Foxl Desktop and Foxl Code share relay.foxl.ai for auth and the credit pool but version independently. See VERSIONING.md at the monorepo root for the full strategy. Foxl Code release tags carry the forge-v prefix so the two products do not interfere.
  • packages/ui now exposes shared layout primitives (AppShell, NavSidebar, TopBar, Breadcrumbs) consumed by Foxl Desktop and Foxl Code so the chrome stays in sync between the two products.
  • React bumped to 19. foxl/apps/web and packages/ui now agree on react ^19.0.0 and react-dom ^19.0.0; recharts bumped to ^3.8.1 to keep peer-dep alignment. No user-visible UI change beyond the rendering fixes above.

Foxl Code (code.foxl.ai)

  • /tasks rebuilt around a bottom-pinned composer. Active tasks (queued/running/review) and recent five closed tasks render above the composer on the empty-state view, with an 8s background poll so status changes show up without a manual refresh. Pressing Enter now surfaces a clear inline error if no repo is connected or no paste is typed - it used to swallow the keystroke silently. Submit + topbar GitHub buttons flattened (no shadow / border).
  • /repos populates after install. The orchestrator gained a state-bound install URL handler, a manual POST /api/installations/sync endpoint, an adopt-by-owner endpoint for the legacy install path, and webhook handlers for installation + installation_repositories so future installs sync without manual action. The Repos page auto-syncs once when installations exist with no repos and exposes a "Sync repos" button. Empty-install state shows both "Sync repos" and "Configure on GitHub".
  • Workspace page added at /workspace. Per-user view of the shared S3 Files mount (/mnt/repos) - finder-style lazy tree, resizable sidebar, search across loaded files, context menu (Copy path), text / binary preview with a 1 MiB inline cap. Shape ported from Foxl Desktop's WorkspacePage, data layer swapped for the orchestrator's new /api/files (S3 ListObjectsV2 + GetObject via aws4fetch). Read-only - the AgentCore container owns writes. Tenant isolation is the bucket prefix users/{user_id}/{org}/{repo}/... enforced server-side.
  • Terraform shared S3 Files mount enabled. forge/infra/terraform now provisions the VPC, NAT gateways, S3 bucket + S3 Files file system, mount targets per AZ, IAM service role, and the access point. AgentCore endpoint flipped from PUBLIC to VPC mode so the shared cache is reachable. Updated CLAUDE.md to reflect that Pro/Ultra share one mount with prefix-based tenancy (was previously documented as Enterprise-only).

v0.2.38

Gateway "Enable remote access" actually works now

  • Click was a no-op when no access token existed. The tunnel-toggle IPC handler returned {ok: true} immediately and only kicked off connectTunnel(at, rt, ...) if at was truthy. If the user wasn't signed in, at was empty, the function silently bailed, and the button looked frozen forever.
  • Handler now awaits the localStorage read, returns {ok: false, reason: 'no-access-token'} when the token is missing, and the renderer surfaces a "Sign in first (Account page)" message inline beneath the button.
  • For other failures the handler returns {ok: false, reason: '<exception text>'} instead of pretending success.
  • Renderer polls tunnelStatus() for up to 15 seconds after a successful start, refreshes fetchAll() once the WebSocket attaches, and shows a clear timeout message if it never does.
  • Loading state on the button - spinning Power icon + localized "Connecting…" copy + disabled while awaiting, so a click no longer looks like a no-op.

Gateway page i18n

  • Gateway "No desktop" copy now resolves in every locale. v0.2.37 added new English strings (relay_no_desktop_desc_v2, relay_turn_on_desktop, relay_desktop_not_connected, relay_desktop_not_connected_desc, relay_enable_remote_access) but didn't add them to the other 9 locale files - users on Korean / Japanese / Chinese / etc. saw raw key names. v0.2.38 ships translations for all 10 locales (en, ko, ja, zh, es, fr, de, pt, ru, ar) plus the new connecting/error strings.

v0.2.37

Sidebar tooltips

  • Collapsed sidebar (Cmd+B) now shows the conversation title as a dark tooltip on hover. Previously the title only rendered when expanded; with the sidebar collapsed to icons there was no way to read which conversation was which. Tooltip mirrors the Cmd+B nav-item style.
  • Top-level nav items and the settings group also surface their label as a tooltip when collapsed - Chat, Workspace, Usage, Settings, Account. Same dark popover styling.
  • Truncated rows show a hover tooltip with the full text in both the sidebar conversation list and the Workspace file/folder tree. The tooltip only opens when the inner span actually overflows (scrollWidth > clientWidth); short titles don't trigger it. 700ms delay so it's not noisy.

Workspace polish

  • Editor header reads MEMORY.md instead of WORKSPACE / MEMORY.md. The redundant WORKSPACE / crumb prefix was removed - the sidebar already says WORKSPACE, the breadcrumb just doubled the label.
  • File and folder rows restored to v0.2.15-era density (text-sm / py-1.5). The earlier compaction to text-[13px] made the tree feel cramped against the rest of the app.

app.foxl.ai conversation pagination fix

  • Sidebar conversation list now pages past the first 50. On app.foxl.ai (relay-only mode with desktop tunnel online) the IntersectionObserver attached to the conv scroll container saw convScrollRef.current === null even after the list had rendered, so the "load more" sentinel never fired. Switched to a callback-ref + state pattern so the effect re-runs the moment the scroll element actually mounts, plus replaced the IntersectionObserver with a plain scroll event listener for reliability inside the nested hidden-scrollbar container.

Gateway page "No desktop" actions

  • Web (app.foxl.ai): replaced the lone Download button with two CTAs - "Turn on desktop" (deep-links to foxl://open to launch the installed app) and "Download for macOS" (fallback if the app isn't installed yet).
  • Desktop: when looking at /gateway from inside the installed app, the page no longer suggests downloading the desktop app (you're already in it). Instead it surfaces an "Enable remote access" button that flips the tunnel toggle, with copy explaining what relay connection gets you.

v0.2.36

max_tokens overhaul (Claude Code parity)

  • Every Claude path now requests the model's full output capacity. Previously the desktop chat sent max_tokens: 4096 whenever thinking was off, the agent layer hard-coded 8192 for every provider, and the relay-only web app capped output at 64000 regardless of model. Long generations were silently truncated. Now Opus 4.7 / 4.6 ask for 128k, Sonnet 4.6 / Haiku 4.5 ask for 64k, matching what the Claude Code CLI sends.
  • Agent layer reads from the catalog instead of a hard-coded constant. strands-agent.ts now resolves entry.maxOutput per model for Bedrock, Anthropic, OpenAI, OpenAI-OAuth, Claude Code OAuth, and the foxl relay path.
  • Claude Code OAuth catalog corrected. The 32k metadata was misleading - real requests already went out at the catalog max. Updated to 128k (Opus) / 64k (Sonnet) so /context percentages and autocompaction triggers reflect actual behavior.

Relay billing fixes

  • Opus 4.7 unblocked on the relay. D1 model_pricing was missing a row for claude-opus-4-7, so meter.canRequest() rejected every request with "Unknown model" - even though the registry listed it. Migration 0011_opus_4_7_pricing.sql adds the row.
  • Opus pricing corrected to Anthropic's published rates. Catalog and pricing previously inherited Opus 4.1's $15/$75 per MTok. Both Opus 4.7 and Opus 4.6 are $5/$25 per MTok. Updated model-catalog.ts and the local D1 row.

Sidebar UX fixes

  • Cmd+N (and the File → New Chat menu item) always opens a fresh chat. Previously, pressing Cmd+N from a non-chat page resurrected the previous conversation because navigate('chat') re-pushed /chat/<oldId> from a stale closure value, and the popstate handler reloaded that conversation.
  • Clicking a different conversation actually opens that conversation. Selecting B from the sidebar after viewing A used to re-load A - same closure-staleness bug routed /chat/<A> instead of /chat/<B>. Now the click goes through navigate('chat', { conversationId: id }), which uses the explicit clicked id.
  • A → B switching no longer flashes empty state. Conversation messages stay on screen during the fetch; the new conversation's messages swap in once they arrive. No suggestions/greeting flicker between selections.
  • Conversations are no longer highlighted while you're on Workspace, Usage, or other non-chat pages. Sidebar conversation rows now check activeNav === 'chat' before applying the active style. Clicking the top-level Chat nav from those pages opens a new chat instead of resurrecting the previously-selected one.
  • Infinite-scroll loader no longer spins forever when conversation pagination fails. On app.foxl.ai (relay-only mode) the desktop conversation list endpoint isn't reachable; the failed fetch used to leave the sentinel mounted, retriggering the IntersectionObserver in a loop. Now any non-OK response or thrown error sets hasMoreConversations: false and the spinner goes away.

v0.2.35

foxl.ai migrated to Next.js SSG for SEO

  • Google can now index foxl.ai. The landing page was a pure CSR React SPA - crawlers saw empty HTML. Migrated to Next.js 15 App Router with static export. Every page is pre-rendered as full HTML with proper meta tags, canonical URLs, and Open Graph data.
  • JSON-LD structured data for sitelinks. Organization, WebSite (with SearchAction), SoftwareApplication, and SiteNavigationElement schema in root layout. Signals Google to show the site hierarchy (Blog, Pricing, Security, Changelog, Docs) as sitelinks beneath the main search result.
  • sitemap.xml with 22 URLs. All static pages + 17 blog posts. robots.txt allows AI crawlers (GPTBot, ClaudeBot, PerplexityBot) and blocks training-only crawlers.
  • worker.js simplified. Removed the entire SPA routing layer (HTMLRewriter meta injection). Next.js handles per-page metadata natively. Worker now only handles security headers, llms.txt proxy, and old .html redirects.
  • Blog preserved exactly. Same thumbnail grid, pagination, category filters, search, and individual post layout as before.

Landing page redesign

  • Pricing moved to dedicated /pricing page with detailed credit breakdown, BYOK explanation, local model info, and FAQ.
  • Security section redesigned. Clean 3-column architecture diagram with vertical mobile connectors, prose-style feature descriptions replacing card grid.
  • "What people ask" replaced with "What other agents can't do." 6 quote-heavy cards condensed to 3 focused differentiators: mobile coding, 24/7 background agent, multi-provider single interface.
  • FAQ trimmed from 11 to 5. Ordered by user priority (features, competitors, pricing, privacy, mobile access). First item open by default. Links to docs/Discord for more.

Agents page bug fixes

  • Running agents no longer flash as "completed" the moment the detail view opens. AgentChatView receives initialStatus from the Agents page (source of truth) so it starts with the correct status the user already saw, eliminating the race where in-memory state clears before the detail view fetch resolves.
  • Assistant responses stop rendering twice. broadcast() was double-recording every agent event to DB (once inside broadcast, once in the runAgent callback). Removed the redundant call. Also, runAgent() no longer emits intermediate message events for no-tool turns - only complete carries the final response.
  • New agents started from the Agents page now show their progress events. Session ID minted up-front so WS broadcasts and DB rows share one ID.

v0.2.34

Relay, Schedules, Feed, Activities, Logs redesigned

  • Unified hero-stat pattern across five pages. Each page now opens with a single headline answer ("12 active schedules", "Live: streaming to 2 clients", "9 unread items", "247 events", "1,248 lines streamed") plus three supporting stat cells — the same rhythm as Agents and Usage. Replaced the nested Card-in-Card chrome with flat sections separated by dividers.
  • Relay (Gateway) rebuilt. Flat device topology with a single connected-desktop row, inline quick-actions (update / restart / unpair), web and mobile clients as tree branches off the bottom edge, and audit history in a collapsible scroll panel below. Tunnel "Remote access" is now a pill toggle next to Refresh instead of a standalone card. Legacy local gateway drops into one collapsible at the bottom for advanced users. Cleaned up dead code from the deleted pairing-code flow.
  • Schedules stopped pretending to be a spreadsheet. Dense table became a divided list sorted enable-state-first, then by upcoming-run proximity. Each row leads with a status dot, the human-readable cron (raw expression lives in the tooltip), and prefers "next in 18m" over stale "last ran 3h ago". 7-day success rate and average runtime are now prominent hero stats. Recent Runs uses pill inputs and chip filters, grouped by day bucket. Heartbeat rows are labeled system-managed and can't be deleted.
  • Feed reads like an inbox. Segmented pill toggle (Inbox / Archive) with per-view counts. Each item is a single clickable row — click archives, click again unarchives. Urgent dot goes amber, unread dot stays foreground, archived items fade. Hero leads with unread count and amber urgent subtext when applicable.
  • Activities chip filter. Time range matches Agents' pill style; type filter is a horizontal chip bar derived from actual event frequencies so users can focus on tool_start vs thinking vs error without a dropdown. Outer Card wrapper removed so the list can breathe.
  • Logs terminal has a frame that doesn't fight it. Hero shows stream state (live vs paused+buffered count) plus error/warning/info totals. Level filter is a segmented pill; source filter is a chip row behind the Filter icon. Console is one bordered rounded-xl panel instead of a Card wrapping another Card.
  • UX ⇄ API alignment. Killed the duplicate "Connected Desktop" surfaces — the relay is now the single source of truth for devices and the local gateway is explicitly flagged as advanced/optional.
  • Mobile. Every page is single-column on narrow viewports, pill inputs wrap cleanly, hero drops to stacked layout, toolbar icons stay tappable (min 32px hit targets), horizontal overflow killed with overflow-x-hidden at every shell.
  • i18n. 100+ new keys across all 10 locales (en / ko / ja / zh / es / fr / de / pt / ru / ar). Key parity check passes at 97–100% per locale.

UX polish pass

  • Consistent semantic tones across hero stat blocks. Warning stats were mixing text-foreground, text-yellow-*, and text-amber-* across Feed, Activities, and Logs — every page now uses the same warn=amber / danger=destructive pair, so a 2 next to "Warnings" reads the same wherever it appears.
  • Feed rows stop auto-archiving on a misclick. The whole row used to be an archive button with a stealth time→action crossfade on hover; now the row is a passive list item and an explicit "Archive" hover-only pill handles the action. Unread dot uses bg-primary instead of pure foreground so it matches the brand.
  • Refresh / Auto collapsed into one control on Activities. The separate Refresh button next to the "Auto" pill was redundant — now the toolbar shows a live-pulse dot when auto-refresh is on (click to pause) and a Refresh icon when it's off. State change is explicit, not dual.
  • Activity hero totals match what the list shows. Hero used dbEvents while the list rendered mergedEvents (db + live), so in-flight live events were invisible to the tally and the type chip tallies. Both now derive from the same unfiltered merged stream.
  • Logs source filter comes out of hiding. The source chip row used to live behind a separate Filter icon toggle — only discoverable via curiosity. It's inline now, rendered whenever the server reports sources. One less click, one less icon.
  • Schedules filter rail simplified. Status is a segmented pill (the axis users actually filter on); Range / Type / Sort / Schedule-picker drop to auto-width dropdowns. Triple "shown of loaded of total" counter replaced with a single "N of M" that only shows when a filter is active.
  • Destructive actions gate on confirm. Schedules detail dialog and row dropdown no longer delete on a single click — a confirm prompt names the schedule so users see what they're about to lose.
  • Gateway audit rows stop showing a Clock icon next to every timestamp. Redundant with the time on the right side of the row. Dead relayConnected / tunnelConnected state and an unused Wifi import removed.
  • Schedules day-group labels respect locale. "Today / Yesterday / This week" were hardcoded English; now they go through chat.today / yesterday / this_week so they follow the UI language.
  • Overview "Top tools" aligned to 24h window. Hero counter is 24h but the top-tools list was pulling lifetime stats labeled "Most used" — both are now 24h so the page tells a single consistent story.

v0.2.33

Workspace on mobile actually scrolls now

  • Mobile Workspace stopped clipping the editor at ~50% of the viewport. The previous layout cut the internal h-full and overflow-hidden at the md breakpoint so the page could rubber-band on iOS, but the side-effect was that the frontmatter + editor textarea got pushed off-screen below the sidebar header. The page now clamps to 100dvh - 2.75rem (app header) on every breakpoint and manages scroll internally — the tree scrolls inside the sidebar, the textarea scrolls inside the editor, and mobile gets the same full-viewport behavior as desktop.

Demo preview caught up with the Usage rename

  • Demo/preview mode's "Connect your desktop to use Overview" card now says "Usage" (plus a fresh one-line description about token burn / cost / model breakdown). The rename in v0.2.32 only covered the live app; the preview copy still referred to the page by its old name. Updated across all ten locales.

Landing page redesign

  • Demo sidebar now matches the real app exactly. Icons corrected to match navigation.ts (Plug for Integrations, Clock for Schedules, Activity for Feed, Settings gear, Users for Agents, BarChart3 for Usage). Every sidebar item is now interactive with dedicated mock content panels for Usage, Schedules, Feed, and Settings.
  • Foxl blue brand color system. Added --brand CSS variable (desaturated blue from the Foxl logo) with light/dark mode variants. Applied as a gradient accent on the hero headline and subtle radial glows behind the hero and CTA sections.
  • Real provider icons in demo. The integrations grid now shows actual Microsoft, Slack, GitHub, Google Workspace, Notion, and Obsidian icons instead of placeholder letters.
  • Logo in demo uses logo-title.svg with correct size and spacing matching the actual app sidebar.

New tray icon

  • macOS menu bar icon redesigned with clean inner line separation. The new 2-piece SVG clearly distinguishes the left wing from the right body with a visible gap. Sized to 80% of the tray canvas for proper macOS menu bar breathing room.

v0.2.32

"Overview" is now "Usage"

  • The sidebar, page title, breadcrumb, and every localized label switched from "Overview" to "Usage" across all ten translations (en, ko, ja, zh, es, fr, de, pt, ru, ar). The page was never really an overview - it was the place users went to see token burn, cost, and model usage. The new name says that out loud. The internal route key stays overview so existing bookmarks, localStorage entries, and deep-links keep working.

Agents page editorial redesign

  • Agents leads with a headline number instead of admin chrome. The old header stacked a small h2 Agent team + subtitle + a row of badges (1 active / 2 done) that all competed for attention. The page now opens with one large tabular number for running agents ("2 agents running") plus an inline three-stat rail (Active / Completed / Failed), same uppercase-tracked labels as the Usage dashboard.
  • Run bar became a single pill input. Goal field is now a rounded-full search-style input with a leading Send glyph, Run sits as the primary action, and Stop-all + Pixel-office toggle collapse into rounded-full secondaries. No more cramped h-8 row stuck between the status badges and the list.
  • Session history dropped the per-row Card chrome and rebuilt as a <ul> with divide-y separators and uppercase date group labels ("ACTIVE / TODAY / THIS WEEK"). Status filters light up with bg-muted instead of swapping badge variants on every click. iter / tools / duration / error counts use tabular-nums everywhere so the row doesn't jitter as numbers tick up.
  • Consistent gutters. Agents now uses px-4 sm:px-8 max-w-6xl mx-auto, matching Usage / Settings / Skills / Integrations so mobile stops reading edge-to-edge.
  • Every hardcoded English string moved to i18n (agents.starting, agents.agent_running_singular, agents.no_sessions, agents.err, etc.) and the translation table got filled out across all ten locales.

Workspace gets the editorial treatment

  • Workspace page dropped the Card wrappers and now reads as one continuous surface: file tree on the left separated by a single border, editor on the right. Header uses the same uppercase-tracked label + tight title as Overview, file path renders in mono, and the save button sits inline. Frontmatter pills switched to compact key value badges.
  • Workspace action icons moved to the app header, matching Chat's pattern. Search / Open folder / Refresh now sit in the top header bar on the right, so the sidebar owns a single editorial label row instead of two competing action strips. The empty-state panel lost its large folder glyph in favor of a tiny uppercase WORKSPACE chip plus the hint copy, and the editor pane became edge-to-edge without border/ring chrome so it reads like a real Linear/Vercel writing surface.
  • Workspace tree now shows a spinner during the initial fetch instead of two bare border lines with a void between them. The spinner only fires before treeLoaded flips true, so manual refreshes don't flash it over a populated tree.

Overview loads faster

  • Dashboard query does fewer scans. The /api/dashboard endpoint was running seven separate SELECT COUNT(*) statements across conversations and messages, most of which had no usable index for their WHERE created_at >= ? / WHERE role = ? clauses. Replaced the per-metric counts with two CASE-sum aggregates (one per table) and added idx_messages_created, idx_messages_role_created, idx_conversations_created, and idx_tool_history_name. On a 12K-message / 365MB database the overview request dropped from a visible pause to effectively instant.
  • Overview caches its last render. Navigating away and back used to show a spinner for every round trip. The page now reads from sessionStorage on mount and refreshes silently in the background, so subsequent visits are immediate.
  • Removed the "Uptime 15m" badge from the hero row - it was visual noise next to the token total.
  • Usage Explorer range chips no longer clip off the left edge.

Overview + Usage Explorer redesign

  • Overview got a proper dashboard instead of four identical admin cards. The page now leads with a hero row - last-24h tokens as one large number plus cost, a live uptime dot, and a "View Usage Explorer" chevron - and demotes conversations / messages / tool calls into a compact three-column strip next to it. Activity, Model usage, and Top Tools became bare typographic sections separated by horizontal dividers; the bar chart and list rows have more room to breathe without card chrome eating 48px on every side.
  • Usage Explorer uses the same editorial layout. Breadcrumb + refresh on one row, chip-style range picker under it, 2x2 summary stats on mobile and 4-col on desktop, per-model rows with an inline progress bar and a 4-up breakdown (input / output / cache write / cache read) that stays on 2 columns on small screens. Custom date range inputs now flex to full-width on mobile instead of spilling off-screen.
  • Numbers use tabular-nums everywhere so columns don't jitter when values change during live polling.

Custom tool env-vars editor now behaves like a real textarea

  • Enter, Space, and blank lines work again in the MCP env-vars box. Editing an MCP tool's environment variables used to feel broken: pressing Enter did nothing, trailing spaces disappeared, and the cursor would jump every keystroke. Root cause: the textarea re-parsed the whole text on every keystroke, dropped the parsed map back into props, and the parent re-serialized it from scratch, which stripped newlines and whitespace. The editor now holds the raw text locally and only pushes the parsed map up, so typing feels normal. Comments (# ...) are also preserved across saves.

Heartbeat can run on any schedule now

  • Feed Generator frequency is no longer capped at 6 hours. Settings -> Feed Generator now shows preset chips (15m, 30m, 1h, 3h, 6h, 12h, Once a day) plus an "Other" option that takes hours + minutes directly, so you can pick 17h 30m, once every 2 hours, once a day, or anything up to 7 days. The preset chips replace the old single-select dropdown. Custom values are clamped to a minimum of 1 minute and a maximum of 7 days to keep the scheduler sane.
  • "Once a day" and "12 hours" are now first-class presets. Users who just wanted a morning briefing had to fake it with 7am cron schedules; now they can leave the Feed Generator on Heartbeat and pick the interval that matches their actual cadence.

v0.2.31

`exec` is back

  • exec and process are now core tools again. Some users reported the agent refusing to run a simple git status and falling back to the heavier terminal PTY path every time. Root cause: exec and process were gated behind the exec-tool skill, and a single enabled: false line in a synced SKILL.md was enough to silently delete both from the tool registry at startup. They are now unconditional built-ins alongside code_search, browser, browser_extension, and web_fetch. Approval gating still applies. Only OAuth-backed integration tools (Outlook, Slack) remain skill-gated, since they genuinely require a connected account to work.

v0.2.30

Critical hotfix (rebuild)

  • Fixed: app would not start after install. A route-pattern change that shipped with the first v0.2.30 build used /api/workspace/:filename(*) syntax, which is rejected by the Express 5 path parser at boot. Every launch crashed before the embedded server bound its port, so the app sat on a retry screen forever (Attempt 1, 2, 3…). The wildcard routes for workspace files and webhook triggers are back on the working *filename / *splat form. If you were stuck on the loading screen, updating to this build fixes it.
  • New startup screen. When the local server is still coming up or has crashed, the loading screen now shows phase, port, PID, the last server error line, a rolling log tail, and three buttons: Restart server, Open logs, Copy diagnostics. Replaces the previous "Attempt N…" spinner that gave no indication of what was wrong.

Faster search across all your conversations

  • Cross-conversation search now loads as you scroll. Before, Cmd+Shift+F only ever returned 20 results - anything past that was silently dropped, which was especially painful on large archives. The sidebar and the mobile search overlay now fetch the next page automatically when you scroll near the bottom, no extra "Load more" tap needed, until there's nothing left to match.

More auto-update fixes

  • Clicking "Install Now" on the macOS native notification no longer crashes the app. The notification's action handler was focusing the main window before applying the update, which raced with the server shutdown that runs during quitAndInstall. The install path now defers to the next tick and skips the focus step so the update applies cleanly.

Strands SDK 1.1.0

  • Upgraded @strands-agents/sdk from 1.0.0 to 1.1.0. Brings proactive context compression, interrupt support for human-in-the-loop workflows, per-tool timeouts, retry strategies with configurable backoff, and MCP server log surfacing. Agent behavior is unchanged for existing usage; the new features will roll out in follow-up versions.

Use Foxl in your language, on any screen

  • Integrations, Skills, Channels, and Tools pages now speak your language. Every page under the Integrations tab - including the Skills library, Channels, System tools, and Custom tools - reads in all 10 supported languages instead of always showing English. Section headings, filter buttons, search boxes, connect dialogs, error messages, and OAuth permission lists are all translated. Settings page too.
  • Mobile-friendly layout across the whole app. Pages used to overflow on phones - long tab rows cut off, filter buttons got squished, dialogs didn't fit the screen. Now the tab bar at the top scrolls sideways with a soft fade on the right edge (so you can tell there's more), filter pills scroll the same way instead of shrinking their text, dialogs fit inside narrow screens, and search + filter rows stack vertically when there isn't room side-by-side.
  • Preview mode on app.foxl.ai now matches the real app pixel-for-pixel. When you sign in without a desktop running, the sidebar shows every page (Agents, Workspace, Schedules, Feed, Relay, etc.) instead of only Chat + Settings. Clicking any data page shows a simple "Install Foxl" panel. The Install button auto-detects Mac, Windows, or Linux and shows the matching platform button.

Notes for developers

  • New i18n blocks in the locale files: integrations, skills_page, channels_page, tools_page, settings_page, header_tabs.
  • Demo components live in apps/web/src/components/demo/ (ConnectDesktopProvider, DemoPage, DemoIntegrations) so preview surfaces stay separate from the real pages.
  • None of the preview-mode behavior runs in the Electron desktop build - IS_RELAY_ONLY is compile-time false there.

v0.2.29

Auto-update fixes

  • Mac "Install Now" button actually works now. Clicking "Install Now" in the native macOS notification used to do nothing. Fixed.
  • Stale "update ready" notification cleaned up after install. After Foxl auto-updated itself, the old "ready to install" row would hang around in the notification bell and the button did nothing when clicked. Now the notification disappears automatically once the update has been applied.

Onboarding polish

  • Skill library count in onboarding replaced with "Extensible skill library". The skill count kept rotting (73 → 68 → 35) every time we trimmed the library. Removed the number so it stops going stale.

Small fixes

  • Clicking "Manage tools & MCP servers" in the HUD now goes to the right tab. It used to land on an older Tools page without the top tabs visible.
  • Workspace file rows click on Windows again. Left-clicking a file in the Workspace sidebar was broken on Windows; fixed.

Workspace: real folder tree

  • Workspace sidebar is now a proper folder tree you can expand and collapse. Replaces the three fixed sections (Core / Daily Memory / Sessions). Folders sort before files, hidden files stay hidden, and the tree remembers what you had open when you come back. Non-markdown files open in Finder instead of the editor.
  • Workspace remembers the last file you opened. Reopen Workspace and you land on the file you were editing, with the folders around it already expanded.

v0.2.28

Cleaner System and Custom tools pages

  • System and Custom tools pages redesigned to match Integrations and Skills. Centered title, pill-shaped search, and category-grouped rows instead of the old card grid. Built-in tools are now grouped by type (Memory, Files, Web, Browser, etc.) so the list reads at a glance.
  • Tool preset is now a dropdown. The four big preset cards became a single compact dropdown next to the search bar.

Sidebar restructure

  • Tools moved under the Integrations tab. "Built-in" and "Custom" tools now live as two tabs inside Integrations (next to Integrations, Skills, Channels) instead of having their own sidebar entry. URLs: /system and /custom.
  • Agents tab no longer shows sub-tabs. Agents used to have a Tools sub-tab next to it - that's gone.

Tray menu fixes

  • Menu bar dropdown now shows Recent chats and 7-day usage in the packaged app. This worked in development but was silently blank in the installed version - fixed.
  • Clicking the menu bar icon no longer pops the window open. It opens just the dropdown. Use "Open Foxl" in the dropdown to bring the window back.
  • First click after launch no longer shows an empty menu while the recent-chats data is still loading.

Skills cleanup

  • Removed the "Trigger" field. The trigger: manual / schedule / webhook field in skills never actually did anything (scheduling lives in the Schedules page, webhooks go through channels). Removed from the skill editor and from the UI.

app.foxl.ai URL fixes

  • Cleaner URLs when you open Skills, Channels, System, or Custom directly. No more #skills, #tools, etc. hanging off the URL.
  • Direct links to /agents, /integrations, /feed now work on app.foxl.ai. Before, refreshing on these pages would bounce you back to Chat.

Landing page demo mock updates

  • Desktop and mobile mocks on foxl.ai match the current app. Updated sidebar groups, model selector label ("Opus 4.7 Thinking"), Integrations/Skills/Tools panels rebuilt.
  • Subtle parallax tilt. The mocks lean toward your cursor when it's in the surrounding whitespace, snap flat when hovering over the mock itself.

v0.2.27 blog post

  • Published the v0.2.27 release notes as a blog post: "Trimming the Sidebar, the Skill Library, and the Tray."

Misc

  • Pricing and "Try it out" sections on the landing page now visually separate from the sections above and below.
  • SEO metadata updated on app.foxl.ai and docs.foxl.ai for Claude Opus 4.7.

v0.2.27

Integrations / Skills / Tools: cleaner separation

  • Sidebar reordered: Integrations → Skills → Tools → Schedules. The flow now reads left-to-right: connect a service → what the agent can do → when it runs.
  • Integrations page only shows real third-party services. Before, anything with a "requires" field showed up here - including local document processors (PDF, Excel, etc.) and developer tools (exec, git, browser). Those all moved to the Skills page. Integrations is now just the OAuth connectors (Microsoft 365, Slack) and external SaaS skills (Notion, GitHub, Google Workspace, Obsidian, Spotify, etc.).
  • Git removed as a built-in tool. The dedicated git tool was redundant - the agent handles git fine through the shell (exec) tool, which gives more flexibility for pipes and custom flags.

Integrations page polish

  • Rotating hero at the top now shows skills too, not just OAuth connectors. Each row gets its own gradient and sample prompt (e.g. "Review my pull requests and flag regressions" for GitHub).
  • Microsoft 365 and Slack open a proper connect dialog first. Before, clicking Connect immediately kicked you out to the browser. Now you see a preview with the permissions being requested (and Slack's workspace input) before the OAuth flow starts.
  • Channel icons show up properly. Every channel row was showing two-letter initials instead of its real logo - fixed.
  • Connected channels no longer show a redundant "+" button. Just Stop / Edit / Remove.

Slimmer skill library

  • Skill library trimmed ~60%. Deleted 32 rarely-used skills (Apple Notes, 1Password, various specialty tools). 21 commonly-used skills (browser, code search, exec, Notion, GitHub, Google Workspace, Outlook, PDF, etc.) stay enabled by default. Everything else defaults to off so they don't clutter the agent's context.

Streamlined tray menu

  • Menu bar dropdown trimmed to essentials. Clicking the Foxl icon in your menu bar now shows: 3 most recent chats (click to jump right to the conversation), 7-day usage summary, then New Chat / Open Foxl / Quit Foxl. Removed rarely-used toggles (Stop Agent, Dark Mode, Always on Top, etc.).

Pricing restored

  • Pricing section back on foxl.ai. Pro ($20/mo) and Ultra ($200/mo) plans, Credit Top-up, and the upgrade card in Account are all visible again. The brief "billing disabled" freeze from April is over.

Credit progress in the sidebar

  • Click your avatar to see your credit usage. Compact progress bar showing how much of your monthly credits you've used, with a Pro/Ultra tier badge. Bar turns amber above 80% and red above 95%. Free-tier users get an "Upgrade" shortcut.

Smaller fixes

  • Logos and icons render at full opacity everywhere. Removed the various opacity-50 / opacity-60 / opacity-70 dimming on the Foxl logo, platform icons under the download buttons, and the landing page's channel logos.
  • Docs site refreshed. Model pages, FAQ, and credits pricing now reference Claude Opus 4.7 as the flagship.
  • Landing page SEO refreshed. Updated titles, meta, and structured data to reflect the current product (Opus 4.7, Windows support, Pro/Ultra plans).

v0.2.26

New Foxl app icon (macOS + Windows + extensions)

  • New Apple-squircle brand mark. Replaced the orange polygonal fox with a dark Apple-style squircle (dark monochrome fox silhouette + blue crescent accent). Canvas/padding match the previous icon layout (100px margin inside 1024 canvas), so the app tile reads at the same size on the Dock and in Finder.
  • Covered every surface: icon.icns (macOS Dock), icon.ico (Windows NSIS + taskbar, multi-res 16/32/48/64/128/256), icon-256/512.png, Windows installer build/icons/*.png (16-512), Chrome extension toolbar icons (16/32/48/128), and the web PWA apple-touch-icon.png + icon-192/512.png.
  • macOS menubar tray now renders from a new menubar.svg (background-removed wordmark) at 22x22 standard and 44x44 retina, sized at ~80% of canvas so the tray icon visually matches surrounding menu-bar glyphs instead of looking oversized.
  • Unified brand across favicons and sidebar logos. All favicon SVGs (favicon.svg, favicon-home.svg), sidebar logo variants (logo-color/dark/light/title/tray.svg), web PNG favicons (favicon.png, favicon-16x16.png), and landing-page favicons now use the new transparent mark — web app, landing, and docs all share the same brand asset.

Message queue drains as a single turn

  • Multiple queued messages now combine into one turn. When you piled up several messages while the assistant was streaming, the old drain logic pulled them off the queue one at a time and ran a separate end-to-end turn per message — so three quick "also", "and", "oh one more thing" messages meant the model answered your first message fully, then your second, then your third, each without seeing the others. Drain now takes the whole queue for the current conversation on each wake-up, joins the entries with a blank line, and sends them as a single user turn. Matches Claude Code's behavior where rapid follow-ups land as one message.
  • Applied to all three chat hooks: useStreamingChat (local), useRelayChat (relay-only / app.foxl.ai), useTunnelChat (remote tunnel).

v0.2.25

Generated image context menu

  • Copy Image and Save Image As now work. Right-clicking a generated image (either the inline thumbnail or the zoom modal) and choosing "Copy Image" or "Save Image As..." was silently failing before. Two root causes: (1) the renderer's fetch('file://...') is blocked by the default webSecurity: true, so the saved-to-disk path fallback rejected with a network error; (2) after our async fetchcreateImageBitmapcanvas.toBlob round-trip, the browser had already dropped the user-activation window that navigator.clipboard.write requires and the write rejected with SecurityError. Both paths now route through new Electron main-process IPC handlers (copy-image-from-path, copy-image-from-data-url, save-image-as) that use nativeImage.createFromPath + clipboard.writeImage for copy and dialog.showSaveDialog + fs.copyFileSync/fs.writeFileSync for save. Browser-only builds still get a navigator.clipboard.write + anchor-download fallback.
  • Removed "Copy Image Data URL". The menu item duplicated "Copy Image" for most users' mental model and produced huge base64 blobs when pasted into a normal text field.
  • Explicit toast feedback. Copy and save outcomes now show a sonner toast on success/failure, so a silent navigator.clipboard.write rejection can no longer look like "nothing happened".

v0.2.24

Subagent recursion guard (the real one)

  • Subagents can no longer spawn subagents. Previously fork children kept the full sessions_* tool schema (for byte-identical prompt-cache prefixes) and relied on two guards to prevent recursion: a BeforeToolCallEvent hook that was referenced in comments but never actually registered, and an isInForkChild() scan that looked at the main conversation agent's messages via getParentMessagesFn / a hardcoded 'default' fallback — never the running child's own messages — so it always evaluated false. Net effect: a child that decided to "delegate search" could fan out another 5 children, each of which could fan out 5 more, etc. Tree depth was bounded only by the 6-concurrent-agent cap racing against new spawns.
  • New hard guard: sessionsSpawn.callback now checks getCurrentAgentId() (backed by a new AsyncLocalStorage context that runAgent enters for each subagent) and rejects if the caller isn't the 'default' main agent. runWithAgentId(agentId, () => runAgent(...)) wraps the spawn site in subagent.ts.
  • Belt + suspenders: the BeforeToolCallEvent hook that comments claimed existed is now actually wired up in strands-agent.ts for every subagent Agent instance (fork or not). It cancels any sessions_spawn / sessions_status / sessions_stop / sessions_message call at runtime, regardless of whether the tool schema was filtered out or left in for cache sharing.
  • Dead code removed: isInForkChild import and the two call sites that scanned the wrong message lists. parseForkResult was imported but never used — also removed.
  • parentId lineage fix: spawned subagents now record the real spawner's agentId via getCurrentAgentId() instead of a hardcoded 'default', so long-running-watch messages and UI parent links point at the agent that actually asked for the work. (Recursion is blocked before this matters in practice, but the registry data is now correct instead of lying.)
  • System prompt guidance rewritten to match Claude Code's delegation model. The old "RESEARCH & WEB SEARCH" block told the agent to "Spawn 3-5 subagents in parallel with different search angles" and to poll with exec sleep N between sessions_status calls — which encouraged fan-out on every research query and wasted tool calls on sleeps the runtime doesn't need (results arrive automatically). Replaced with explicit delegate-vs-work-directly rules: delegate for multi-file changes / refactors / debugging / broad research / verification / context-flooding outputs, work directly for trivial ops. Brief each subagent as a cold teammate (goal + in/out scope + brevity). Launch independent subagents in a single turn, don't duplicate delegated work, don't poll, and explicitly: subagents cannot spawn further subagents. Matching update in system-prompt.ts Multi-Agent System section.

Subagent result gathering matches Claude Code's Task-tool semantics

  • Batch-complete gather. Before, every individual subagent completion notified the server to drain, so a fan-out of 5 parallel subagents could trigger 2–5 separate auto-continue passes on the same conversation — the parent would synthesize mid-batch, then get poked again with the stragglers. onSubagentDone in subagent.ts now counts peers that share the same conversationId and status === 'running', defers the drain notification until it's the last one reporting, and only then fires autoContinueFn. Results still land in the durable DB queue as they arrive (so no completion is lost if the lock is briefly held by a mid-flight drain), but the synthesis pass runs once per batch — matching Claude Code's Task-tool behavior where a batch of parallel sub-tasks returns as a single tool_result on the parent's next turn.
  • Registry extended with conversationId. Required to scope peer-running counts to the right conversation so two concurrent chats don't delay each other.
  • Consolidated message shape. The auto-continue prompt is now "N subagents have returned. Synthesize their findings into a single response for the user. Do not delegate further; do not restate the mechanism." followed by labeled ### Subagent i/N — <goal> sections separated by ---, with failed ones carrying a [FAILED] tag. Previous boilerplate ("The following subagent results have arrived. Synthesize them into a clear, organized response...") encouraged the model to restate the mechanism back to the user.
  • Dead parser removed. strands-agent.ts had a branch that rewrote the prompt if an injected message contained [SUBAGENT COMPLETED: / [SUBAGENT FAILED:, but those tokens haven't been produced anywhere since auto-continuation moved to the DB queue — the branch never fired. Dropped.
  • Tool + prompt docs synced. sessions_spawn tool description, strands-agent.ts AUTONOMOUS_AGENT_INSTRUCTIONS, and system-prompt.ts Multi-Agent System section now all describe the same batch-complete delivery shape instead of the old "[SUBAGENT COMPLETED] message arrives per agent" promise.

Notification popover cleanup

  • Consolidated notification action buttons to a single "Open" per row. Previously each entry had a type-specific primary label ("Open Agent" / "View" / "Reply") plus a redundant "Dismiss" button; the action row could show "Open / Dismiss / Dismiss" when a notification was rehydrated with a stale secondary action. Now there's exactly one action button labeled "Open", and dismiss lives as a per-row X icon that appears on hover.
  • Native macOS banner actions also collapsed to a single "Open" button. macOS's notification shell already provides a close affordance, so an explicit "Dismiss" button was duplicating the OS chrome.

v0.2.23

Notifications: actions, deep-links, and a working Install Now

  • Action buttons on every notification type. Native macOS banners now carry "Open Agent / View / Reply / Dismiss" for agent done/failed, schedule done/failed, chat/channel message, and feed events. Previously only the update-ready toast had actions; everything else rendered as an unactionable banner that did nothing when clicked.
  • Notification body-click navigates to the event page AND deep-links to the specific resource. Clicking a "Schedule: daily-briefing" banner now opens /schedules#{scheduleId}, an "Agent Done" banner opens /agents/{sessionId}, a Slack channel message opens /chat/{conversationId}, and a feed alert opens /activities. Before, body-click only focused the window and dropped the user on the default page.
  • Action button clicks carry meta through the full stack. Server broadcast → WS → renderer → Electron main → back to renderer — the originating event's sessionId / conversationId / scheduleId is preserved end-to-end so deep-link navigation works for both the body click AND the action button.
  • Install Now on the update-ready toast actually installs. autoUpdater.quitAndInstall is now scheduled on the next tick (was racing with the notification dismiss on macOS, which is why the button looked like it did nothing), explicitly sets autoInstallOnAppQuit = true as a belt, and falls back to app.quit() if the native call throws.
  • Bell popover and native toast are consistent. The in-app bell popover shows the same action buttons as the OS toast, so the experience is uniform on Windows/Linux where native actions aren't available.
  • Server-side meta added to every emission site. subagent.ts now attaches {agentId, sessionId, conversationId} to completion notifications. server.ts schedule emissions carry {scheduleId, scheduleName}. Channel message emissions carry {conversationId, channel, channelId}. Single-agent start/goal endpoints carry {sessionId: 'default'}.

Notifications Settings cleanup

  • Settings test picker now goes through the real server broadcast path. The picker was using a CustomEvent shortcut that bypassed the WebSocket round-trip, which meant it could pass locally while production was broken. It now hits POST /api/test/notification which broadcasts over WS the same way production agents do, so clicking "Send test" exercises the exact same pipeline as a real event.
  • Settings test scenarios now mirror actual server emissions. Added channel_message_whatsapp and channel_message_web pickers (missing before). Dropped pet_expedition_return / pet_item_drop scenarios — no code ever emitted those types, so the pickers were dead UI. Also removed the matching pet toggles from the settings schema.
  • Test picker resolves deep-link IDs from the server. When you test an agent notification, the picker fetches your most recent agent session and uses its ID as meta.sessionId so the click actually lands on a concrete row instead of the bare list. Same for schedules and conversations.

Agents page

  • Active agents now render in the list. The header "N active" badge read in-memory team state, but the list below it only showed DB-persisted sessions — so chat-driven runs and not-yet-persisted agents appeared in the badge count but were missing from the list entirely. Live members are now merged as synthetic rows in a pinned "Active" group at the top, and running sessions bypass the Today / 7 Days / 30 Days time filter so a long-running agent stays visible even when the selected window excludes its start time.

Tests

  • notifications-e2e.spec.ts gained 17 new tests: meta propagation (5), Settings scenarios mirror server emissions (11, one per real type), subagent completion shape (1, skipped when no provider configured).
  • New notification-actions-ui-e2e.spec.ts covers the UI half: Settings picker hits the real endpoint, bell popover renders action buttons, each action's pushState observed via a history.pushState spy for race-free deep-link verification.

v0.2.22

Schedule timeout UI

  • Schedule execution timeout is now visible and configurable in the create/edit/detail dialogs. Displayed in minutes (stored as seconds), default 10 min. Hidden for heartbeat type (managed by server).

Fixes

  • Fenced code blocks without a language tag (triple backtick) were rendered as inline code, collapsing newlines into a single line. Now checks content for newlines to determine block vs inline rendering.

v0.2.21

Strands SDK v1.0.0 + Express 5 upgrade

  • Upgraded @strands-agents/sdk from v1.0.0-rc.5 to stable v1.0.0. Concurrent tool execution enabled by default - the LLM decides when to run multiple tools in parallel within a single turn.
  • Added BeforeInvocationEvent and BeforeModelCallEvent cancellation hooks (SDK v1.0.0 feature). Agent stop requests now prevent the next API call from firing, saving cost and reducing latency on user-initiated stops.
  • Refactored per-agent tool event routing from a global Map (agentToolEventFns) to SDK-native invocationState - each agent.stream() call carries its own callback via the per-invocation state bag, eliminating shared mutable state.
  • Upgraded Express from v4.18 to v5.2 with @types/express v5. Migrated all wildcard route patterns to Express 5 path-to-regexp syntax (:param(*) to *param, unnamed * to *splat). Fixed wildcard param handling - Express 5 returns arrays for * captures, now joined with / for path reconstruction.

Fixes

  • Workspace file read/write via nested paths (e.g. memory/daily/2026-04-30.md) broken by Express 5 array params - fixed with Array.isArray() guard and join('/').
  • Webhook trigger endpoint updated for Express 5 named wildcard (*splat).

Tests

  • Added sdk-upgrade-e2e.spec.ts with 11 new Playwright tests covering Express 5 wildcard routes, chat stop/cancellation, server health, and provider/model endpoints.

v0.2.20

Custom tools & MCP: servers now actually reach the agent

  • Custom tools stored in the custom_tools DB (shell, http, file, script, mcp_local, mcp_remote) were never wrapped as Strands tools — the LLM literally couldn't see or call them. Added buildStrandsToolsFromCustom() in server/tools/custom-tools.ts that wraps every enabled custom tool as a proper Strands tool() and appended them to getEnabledTools(). Custom tools bypass the profile system — if the user enabled them, the agent gets them.
  • MCP tools now default to expand-all mode: one MCP custom tool exposes every tool the remote server advertises. Each remote tool becomes its own Strands tool named <customName>__<remoteTool> (e.g. server_time__get_current_time, server_time__convert_time). Removed the stale mcpToolName single-target plumbing that was silently misrouting calls.
  • JSON Schema → zod converter ports the MCP server's inputSchema (types, required, enum, description) into the Strands tool. Fixes the bug where the agent saw an empty {} schema and had to guess argument names / required-ness.
  • executeMcpLocal / executeMcpRemote now honor a per-call __mcpToolName override injected by the wrapper, so expand-all routes correctly to the right remote tool on every call.

Connection status tracking & auto-probe

  • New McpStatus cache + refreshMcpStatus(def) / refreshAllMcpStatuses() helpers. States: unknown | connecting | connected | error | disabled, with toolCount, tools[] (name/description/inputSchema), and error.
  • Probe is triggered automatically on: server boot (for every MCP tool in the DB), custom-tool create, update (including enable toggle), delete (cache pruned for missing ids). No manual step needed.
  • New endpoints: GET /api/tools/custom/status (id → status map) and POST /api/tools/custom/:id/refresh (force re-check). Route ordering fixed so /status matches before the /:id catch-all.
  • inputSchema preserved in the cached status payload so the tool builder can forward the real JSON Schema (including required) to the agent. Without this the model couldn't tell that timezone was required on mcp-server-time.

HUD redesign: flat, obviously-clickable, with MCP status

  • ElectronTitlebar HUD rebuilt in the shadcn/ui design language: flat borderless pill with text-muted-foreground → text-foreground hover, chevron down indicator, status dot on the left, optional MCP badge on the right. No more raised button edges.
  • Popover expanded to 320px with clear sections separated by Separator: status header, metrics grid (Agents / Tool calls / Iteration), context usage bar, MCP servers list (per-server status dot + tool count or truncated error), recent tool calls, and a clickable footer row that navigates to the Tools page (amber alert icon when any MCP errored).
  • Trigger auto-fetches MCP statuses on mount and polls every 5s while the popover is open — the number-of-connected badge updates without a manual refresh.

Tools page: edit existing custom tools

  • Each custom tool row is now fully clickable (hover background, keyboard focus) and opens an Edit dialog that pre-populates every field (name, description, type, config, parameters). For mcp_local the space-joined command / args field is reconstructed so the UI round-trips cleanly.
  • Dedicated Pencil edit button next to Play / Delete / Refresh. Dialog header and save-button label switch between Create / Edit mode automatically. Saving an edited MCP tool triggers a re-probe immediately.
  • Non-MCP rows keep the same inline controls; action buttons stop click propagation so they don't accidentally open the edit dialog.

Misc

  • image-viewer.tsx tightened to match the rest of the tool-flip UI (generated / viewed images render with consistent collapsed / expanded states and zoom controls).
  • Landing site: FAQ additions, About / Legal / Blog copy edits, v0.2.19 blog post polish, new humans.txt, updated iphone-frame.svg, sitemap regen.
  • site/worker.js updated alongside new static asset routes (.well-known/, blog hero images).
  • Docs regenerated from latest MDX (docs/public/docs/{models,providers,tools}.md + llms-full.txt + sitemap) — covers the gpt-image-2 + OpenAI OAuth changes shipped in v0.2.19.
  • foxl/scripts/debug-codex.mjs, debug-image-tool.mjs kept in-tree for future Codex / image-gen wire triage.

v0.2.19

`generate_image` tool: gpt-image-2 through ChatGPT subscription

  • New built-in generate_image tool that produces or edits raster images via gpt-image-2 without an OpenAI API key. Powered entirely by the user's existing ChatGPT Plus/Pro OAuth session (~/.codex/auth.json / CODEX_HOME / CHATGPT_LOCAL_HOME); no per-image billing outside the $20/month subscription quota. The tool posts to chatgpt.com/backend-api/codex/responses with model: "gpt-5.4" carrying tools: [{ type: "image_generation", model: "gpt-image-2" }] — the same shape the official Codex CLI uses for its built-in image_gen tool.
  • Tool is gated to accounts with ChatGPT OAuth: only registered when the credential file is discoverable at module load, skipped otherwise so non-OAuth users don't see an unusable affordance.
  • Accepts multi-image input for edits and composition. inputImages: string[] (max 10 paths) switches gpt-image-2 from text-to-image into edit / compose mode — "이 사진 만화풍으로 바꿔", "이 두 이미지 합쳐줘", reference-guided generation, etc.
  • Token-efficient wire shape: only file paths cross the model's tool-call args, never base64. The tool reads each path from disk inside the server process and encodes it as input_image data URIs directly on the Codex request. Return payload to the model is trimmed to Saved to: <path> + a sharp-resized 768px JPEG preview (~100KB) — the full-resolution PNG stays on disk at outPath.
  • Attached chat images auto-persist to data/workspace/attachments/chat-<timestamp>-<rand>.<ext> and their absolute paths are injected into the user's text block as [Attached image paths: "..."]. The model therefore always knows the exact disk path to pass to generate_image({ inputImages: [...] }), closing the loop from drag-and-drop → edit.
  • Saved outputs live at data/workspace/generated/generated-<YYYY-MM-DD>-<prompt-slug>-<suffix>.png. Workspace root (SOUL/USER/MEMORY/TOOLS/AGENTS/HEARTBEAT/BOOTSTRAP.md) stays uncluttered; every generated image carries its date and a readable slug derived from the first six words of the prompt.
  • data/workspace/generated/ excluded from workspace file listing automatically (subfolder convention), accessible via the Open Folder button now on the Workspace page header.
  • ChatGPT-style UI: generated images render expanded by default directly in the chat stream (not tucked inside a collapsible tool flip), with the standard Task chevron for collapse and consistent sizing with other tool calls. view_image keeps its original collapsed-by-default compact UX. The full-resolution preview modal offers click-to-zoom (25%–400%) and an Open Folder button that reveals the saved PNG in Finder / Explorer / xdg-open.
  • Tool-profile wiring: added media category (['generate_image']) to tool-profiles.ts and included it in default, standard, and full profiles. minimal omits it to preserve its token budget.

OpenAI OAuth: catalog + model availability

  • Added openai-oauth/gpt-5.5 to the catalog (1M context, reasoning + streaming). Verified serving on the ChatGPT OAuth endpoint via live probe. gpt-5.5-codex, gpt-5.5-mini, gpt-5.5-pro are all gated to API-key accounts (400 Bad Request: "not supported when using Codex with a ChatGPT account") and therefore excluded.
  • Final catalog: gpt-5.5 (1M), gpt-5.4 (1M), gpt-5.4-mini (400K), gpt-5.3-codex (400K).
  • Removed openai-oauth/gpt-5.4-codex and openai-oauth/gpt-image-2 as top-level language-model entries. The ChatGPT OAuth backend returns 400 Bad Request: "The 'gpt-5.4-codex' model is not supported when using Codex with a ChatGPT account" (same for gpt-image-2) despite the OpenAI Developer Community announcement. gpt-image-2 is still reachable, but through the new generate_image tool above.
  • Wired up imageModel() / image() on createOpenAIOAuth regardless, backed by @ai-sdk/openai/internal OpenAIImageModel reused through the same OAuth fetch. Ready to flip on the moment OpenAI enables raw image models on the ChatGPT OAuth endpoint.

Fix: `openai-oauth/gpt-5.4` was silently routed to gpt-4.1

  • shared/model-resolver.ts had a stale NAMESPACE_ALIASES entry mapping openai-oauth/gpt-5.4gpt-4.1 (and openai-oauth/gpt-5.4-codexgpt-4.1). Any time the user selected the OAuth GPT-5.4, setModel → toCanonicalId resolved the alias and stored gpt-4.1 as the active model — which Codex then rejected with a bare 400 Bad Request because ChatGPT OAuth accounts don't serve gpt-4.1 either. Removed both aliases so the transport-prefixed id passes through untouched. Verified end-to-end: /api/providers/select now persists openai-oauth/gpt-5.4 verbatim and the follow-up /api/chat/stream returns reasoning + text deltas as expected.

Debug: surface real Codex upstream errors behind `FOXL_CODEX_DEBUG=1`

  • Added an opt-in FOXL_CODEX_DEBUG=1 env flag in openai-oauth/core/transport.ts that clones and logs the response body + request body on any non-2xx from chatgpt.com/backend-api/codex/*. Strands wraps upstream errors as "Language model stream error: Bad Request", which discards the real cause; this flag is the single switch that reveals it. Off by default (no logging overhead in production).

UX: Workspace page "Open Folder" button

  • New folder-open icon button in the Workspace header (next to Search and Refresh) that opens data/workspace/ in Finder on macOS, Explorer on Windows, and xdg-open on Linux. Electron shell path via window.pilot.openPath; non-Electron falls back to new POST /api/system/open endpoint.

Skills: remove duplicate image-gen skills from foxl-ai/skills

  • Removed openai-image-gen (OPENAI_API_KEY + Python script path) and nano-banana-pro (GEMINI_API_KEY + uv + Python) from the skills repo. Both are superseded by the native generate_image tool above. One canonical image path across the product.

Dependencies: Strands SDK → v1.0.0-rc.5

  • Bumped @strands-agents/sdk from ^1.0.0-rc.3 to ^1.0.0-rc.5. Picks up: mid-execution cancellation (agent.cancel() / cancellationSignal via AbortSignal.timeout()), agent-as-tool (agent.asTool()), multi-agent session persistence, Bedrock thinking+forced tool_choice conflict fix, Bedrock context window overflow detection matching the Python SDK, invocation lock leak fix on consumer stream break, AgentSkillsPlugin → AgentSkills rename, contextWindowLimit added to BaseModelConfig, and OTEL JS SDK v2 upgrade. No call-site changes needed in Foxl.

Frontend hygiene: zero web typecheck errors

  • Fixed 19 pre-existing TypeScript errors across the web codebase so tsc --noEmit in apps/web is now green. Bumped target/lib from ES2020 → ES2023 and added vite/client to the types array (unlocks Array.prototype.findLastIndex, stricter ArrayBuffer typing, and import.meta.env typing). Deleted unused FloatingLines.tsx (referenced a missing three dep). Tightened cast sites in useWebSocket.ts (WebSocketMessage had an [key: string]: unknown index signature that made field narrowing impossible), tunnel-crypto.ts (BufferSource / Uint8Array overloads), and search-bar.tsx (RefObject nullability). None of these were blocking the Vite build, but keeping tsc green is a non-negotiable guardrail for future refactors.

Claude Code (OAuth): Opus 4.7 gets its 1M context back

  • Opus 4.7 on the Claude Code OAuth transport now reports its true 1M context window. Since Opus 4.7 shipped in v0.2.11, claude-code/opus had been hard-coded to 200K because the CC OAuth catalog predated the 1M rollout. The result: /context usage percentages showed ~5× inflated values and auto-compaction kicked in five times earlier than it should have, effectively capping Opus 4.7 sessions at 200K. A live probe against api.anthropic.com with a 320K-token prompt confirmed Opus 4.7 on the subscription pool accepts the full input at service_tier: standard with no context-1m-* beta header — 1M is the native default, the beta flag is only for back-compat with older models.
  • Sonnet 4.6 on the same CC OAuth transport stays at 200K. A parallel probe (identical shape, only model swapped) returned HTTP 429 "Extra usage is required for long context requests" — Anthropic routes Sonnet's long-context requests into the pay-as-you-go pool instead of the subscription pool. Haiku 4.5 is likewise kept at 200K.
  • Added resolveEffectiveContextWindow(modelId) in shared/model-resolver.ts so UI context gauges (useStreamingChat.ts) and server-side auto-compaction (server/agent/compaction.ts) both see the transport-adjusted ceiling rather than blindly trusting the catalog entry. Catalog entries keep their paper-spec numbers (Sonnet 4.6 = 1M via Bedrock/BYOK) and the helper narrows them only for transports that impose a cap.

Claude Code (OAuth) model ids: full Anthropic name after the prefix

  • The CC OAuth catalog now exposes claude-code/claude-opus-4-7 and claude-code/claude-sonnet-4-6 as the canonical ids. The legacy short-form ids (claude-code/opus, claude-code/sonnet, claude-code/haiku) are preserved as aliases in CLAUDE_CODE_MODEL_ALIASES and in the shared NAMESPACE_ALIASES map, so previously persisted user selections (localStorage foxl-selected-model, relay /api/providers/select state) keep resolving correctly. Verified end-to-end with a live probe — all four id shapes (new/old × Opus/Sonnet) route to the expected Anthropic model with service_tier: standard.

Fix: model switch was a no-op on foxl.ai provider

  • Switching model mid-conversation on the foxl.ai provider (e.g. Kimi K2.5 → Opus 4.7) kept running the previous model because conversationAgents caches Strands Agent instances and Agent is constructed with a baked-in model + provider. The POST /api/chat/stream handler already called setModel(newModel) from the request body, but the cached agent ignored it. Added a parallel conversationAgentModels map that records each cached agent's construction-time model, and handleStreamingChat() now discards the cached agent as soon as cachedModel !== config.model. All 16 existing conversationAgents.delete(…) / .clear() sites were mirrored so the maps never drift.

Relay: prompt caching on the Bedrock forward path

  • relay/src/proxy.ts now injects block-level cache_control: { type: 'ephemeral' } breakpoints on every Anthropic-format /v1/messages body before it hands off to Bedrock InvokeModel. The tool list, the system prompt, and the last user turn each get one breakpoint (up to Bedrock's 4-breakpoint limit) so tools → system → messages prefix caching kicks in automatically across turns. Bodies that already carry explicit cache_control markers are left alone. Verified with a dedicated unit-test suite (relay/tests/09-cache-breakpoints.test.ts, 7 cases covering string/array system shapes, tool lists, multi-turn conversations, and tool_result blocks).
  • Strands' AnthropicModel config only exposes a cacheConfig that BedrockModel honors — AnthropicModel itself doesn't auto-inject cache points, so the relay-side injection is where caching on the foxl relay path actually turns on. Bedrock InvokeModel does not honor the top-level automatic-caching shorthand described in Anthropic's API docs (that's Claude API + Azure AI Foundry only), which is why block-level markers are the right place to hook.

Site: foxl.ai gets a real dark mode

  • Added a .dark palette to site/landing/src/index.css (background/foreground/card/muted/border/ring/accent all defined) and an inline pre-paint script in index.html that applies the saved or system theme before first paint so there's no FOUC on hard refresh. A new ThemeToggle component (site/landing/src/components/landing/ThemeToggle.tsx) sits in the Navbar next to the Download button on desktop and next to the hamburger on mobile, persisting the user's choice under localStorage['foxl-theme'] and falling back to prefers-color-scheme when unset.
  • Swept landing components for hardcoded light palette: Security.tsx cards switched from bg-white to the semantic bg-card, and the LegalPage changelog version badge switched from bg-zinc-200 text-zinc-700 to bg-muted text-muted-foreground. The only remaining hardcoded colors are intentional (the iPhone notch in MobileDemo.tsx stays bg-black, the toggle knob in DesktopDemo.tsx stays bg-white).

v0.2.18

Revert: Claude Code (OAuth) compat layer is back on

  • v0.2.17 disabled the Claude Code (OAuth) compat-mode tool rewriter based on raw /v1/messages probes that appeared to show Anthropic's Pro/Max subscription pool now accepting Foxl-native tool names. In production users immediately hit "Language model stream error: You're out of extra usage" — the raw probes did not reproduce the shape that Strands + Vercel AI SDK put on the wire in a real agent loop, so the subscription pool kept rejecting the request and Anthropic fell back to pay-as-you-go billing.
  • Reverted: strands-agent.ts and server/api/server.ts call buildCompatTools() again for providerType === 'claude-code', the tool-adapter banner is back to its v0.2.16 wording, and claude-code/haiku is excluded from the model catalog again (it was re-added in v0.2.17 based on the same faulty probes).
  • Compat mode returns to being the supported Claude Code (OAuth) path. Investigation to capture a real failing body and validate an end-to-end bypass is tracked in TODO.md; the probe scripts stay on disk as regression guards for the compat path.

Auto-update notification actions

  • Clicking "Install Now" (or the notification body) on the "Foxl update ready" toast now actually installs the update and restarts the app. Two separate notifications used to race on download completion: a renderer-side rich notification with action buttons and an actionless main-process Notification. The main-process toast usually won, its on('click') handler only focused the window, and the user saw "Install Now" do nothing. Removed the duplicate toast so the renderer's action-bearing notification is the only one the user sees.
  • show-notification native-toast click handler now treats type: 'app_update' as an install affordance rather than a focus-only click, so clicking the toast body (on any platform) installs the update the same way the explicit "Install Now" action does.

v0.2.17

Claude Code (OAuth): full native tool registry

  • Claude Code (OAuth) now sees Foxl's full native tool registry (memory, workspace memory, subagents, schedule, channel send, browser, view_image, etc.) — everything that was dropped by v0.2.16's compat-mode tool adapter. Anthropic's Claude Pro/Max subscription pool no longer gates on CC-shaped tool names, so the Bash/Read/Grep/WebFetch shim layer is bypassed in strands-agent.ts and server/api/server.ts. Proven by two new probe scripts that route every combination (Opus/Sonnet/Haiku × native tool lists) through api.anthropic.com/v1/messages and verify usage.service_tier === 'standard' on both the initial request and a full tool_use/tool_result round-trip.
  • server/providers/claude-code-oauth/compat/tool-adapter.ts is kept on disk (no longer imported) so the rewriting strategy is instantly recoverable if Anthropic re-enables the gate. compat/message-rewriter.ts is still wired up — the subscription pool remains sensitive to the SYSTEM block shape, so Foxl still relocates persona/context from system to a <foxl-context> prefix on the first user turn.
  • Re-added claude-code/haiku (Haiku 4.5) to the Claude Code (OAuth) catalog. The 2026-04-22 probe sweep showed Haiku now routes cleanly across the full native tool set — the instability that caused it to be excluded in v0.2.16 no longer reproduces.

Claude Code (OAuth) probe scripts

  • scripts/test-claude-code-oauth-compat-probe.mjs — 3×3 matrix (Opus/Sonnet/Haiku × no-tools/single-tool/full-CC-set) verifying subscription-pool routing against the CC-shape rewrite.
  • scripts/test-claude-code-oauth-native-tools-probe.mjs — 3×3 matrix using Foxl-native tool names (exec, file_read, code_search, web_fetch, memory_save, sessions_spawn) to prove the CC-shape rewrite is no longer required.
  • scripts/test-claude-code-oauth-roundtrip-probe.mjs — drives a full tool_use → tool_result → follow-up turn with Foxl-native names and asserts subscription routing on both turns.
  • scripts/test-claude-code-oauth-claims-probe.mjs — empirically confirms the "OpenClaw re-allowed" announcement's claims against the live API: service_tier: auto and standard_only work, cache_control is a no-op over OAuth, context-1m-2025-08-07 beta is rejected on sk-ant-oat-* tokens, claude -p CLI still runs, adaptive thinking plumbing returns thinking content blocks.

Notification click/action routing

  • Notification bell items now actually navigate to the relevant page when clicked. Previously, any notification that carried action buttons (Install / Later on "update ready", or anything with explicit actions) swallowed the body click and stayed on the current page. Agent-complete, feed, schedule, and channel notifications now route to their owning page on click and close the popover afterwards.
  • Action buttons whose id is not a special case (install-update, dismiss-update) now fall back to navigating to the notification's navTarget, so "Open Agents" / "View Feed" style buttons in test notifications and future richer actions work without extra wiring.
  • Native OS notification clicks now route for agent_complete, agent_error, feed, feed_urgent, and heartbeat types as well (previously only chat / schedules were handled; everything else just focused the window).
  • Deep-link resolution extended: navigating to chat with meta.conversationId now calls chat.loadConversation and updates the URL; navigating to schedules or activities with meta.scheduleId / meta.feedId writes the id into the URL hash so the target page can scroll or expand the relevant row.

Settings: interactive Test notifications

  • The Test card in Settings > Notifications is now a working end-to-end test instead of a preview-only helper. Picking a scenario and hitting Send inserts a live rich notification (with an "Open" action) directly into the bell popover via a CustomEvent bridge, so you can verify click and action routing without waiting for a real event.
  • Each scenario resolves a real deep-link target: agent scenarios fetch the latest /api/agent-sessions and route clicks to that session's detail page; schedule scenarios use the first /api/schedules row; channel_message scenarios use the most recent conversation. When no rows exist, the placeholder id still exercises the deep-link plumbing.
  • New "Also fire native OS notification" checkbox now calls pilot.showNotification directly from the renderer so the actions array reaches the Electron main process and the native banner renders the same "Open" button. Previously the test went through /api/test/notification which stripped actions and also inserted a duplicate row in the bell.
  • Dismiss action removed from the test notifications — macOS notifications have a built-in close and the bell popover closes on outside click, so a second dismiss button was redundant. The action label is now just "Open" across all scenarios, localized in all 10 locales.

v0.2.16

Claude Code (OAuth) compatibility mode

  • Re-enabled the "Claude Code (OAuth)" provider with Opus 4.7 and Sonnet 4.6 entries. Haiku stays excluded because even the official CLI tends to 429 once the tool list grows past a few entries on Haiku.
  • Added a transport-level rewrite layer (server/providers/claude-code-oauth/compat/) that conforms Foxl's agent-shape requests to what Anthropic's Pro/Max subscription pool actually routes. Two transforms run on every /v1/messages call:
  • message-rewriter.ts moves Foxl's persona/workspace context out of system and onto a <foxl-context> prefix on the first user turn, leaving system as the preamble-only single block the pool gates on.
  • tool-adapter.ts wraps each supported Foxl tool in an official-CC-named shim (exec -> Bash, file_read -> Read, code_search -> Grep, web_fetch -> WebFetch). Wrappers translate the CC-shape input back to Foxl-shape before delegating to the underlying Foxl tool, so Strands' agent loop keeps running existing callbacks unchanged.
  • Foxl-exclusive tools with no CC counterpart (memory, workspace memory, subagents, schedules, channel send, view image, browser extension, ...) are dropped from the tool list in compat mode - the model never sees them and cannot call them. First-time selection surfaces an AlertDialog explaining the trade-off (translated into all 10 supported locales).
  • Docs: restored the Claude Code (OAuth) sections in docs/content/docs/models.mdx and providers.mdx with compat-mode caveats.

v0.2.15

Empty-chat layout

  • When the terminal pane is open, the empty-state greeting + input no longer try to vertically center themselves over the terminal. The content now sits top-aligned above the terminal so both are fully visible.

Claude Code (OAuth) temporarily disabled

  • Hidden the "Claude Code (OAuth)" provider and its Opus/Sonnet/Haiku entries from the model picker, settings page, and /api/providers response. The transport, credential loader, and Strands wiring are kept in the codebase so this can be re-enabled later.
  • Why: Anthropic's Claude Pro/Max subscription pool rejects Foxl's agent-shape requests. Raw probes against api.anthropic.com using the real OAuth token showed that a 1-line preamble with no tools routes to the subscription pool (200 + service_tier: standard), but adding Foxl's 22-tool registry or a 23KB persona system prompt causes Anthropic to silently re-route to the pay-as-you-go API pool. Users on Pro/Max were burning "Extra usage" without realizing the calls had fallen off their subscription.
  • Investigation also aligned the OAuth transport with the official Claude Code CLI (anthropic-beta: oauth-2025-04-20,claude-code-20250219, user-agent: claude-cli/..., x-app: cli, single merged system text block, output_config stripped, Haiku uses budget_tokens thinking instead of adaptive). Those fixes stay in the tree for when Anthropic ships a subscription-compatible agent surface.
  • Workaround for users: use Anthropic API key (BYOK) or the foxl.ai relay for Claude access.

v0.2.14

Empty-chat redesign (desktop + web app)

  • New chats open with a Codex/Claude-style centered layout: a single "What should we work on?" greeting directly above the input box, vertically centered in the viewport. As soon as the first message is sent the input snaps back to the normal bottom dock.
  • Dropped the six hardcoded prompt cards (Web Search / File / Debug / Code / Terminal / Analysis). They were generic enough to be noise. Pill-style AI suggestions still render directly under the input when /api/suggestions/generate returns any.
  • Foxl logo no longer prints in the empty state.
  • Mobile keeps the earlier v0.2.11 layout (top-aligned logo + greeting + bottom-docked input) so the on-screen keyboard does not fight the centered overlay.

Fixes

  • Suggestions fetch used an AbortController whose cleanup fired during React StrictMode's double-invoke effect, cancelling the inflight request so pills never appeared in dev. Switched to a cancelled-flag pattern - the request completes and the cache is warmed, results are just ignored if the component unmounted first.
  • app.foxl.ai (relay-only mode) now pulls greeting + suggestions from the connected desktop via the tunnel API (/tunnel/api -> /api/suggestions/generate), so mobile web users see the same cached AI-generated pills their desktop already produced. Previously mobile only showed the greeting because relay-only short-circuited the suggestions fetch.
  • Desktop UI no longer calls /api/suggestions/generate on its own and no longer renders the "Try asking something like:" label. Suggestions are mobile-only now - the desktop empty state is just the centered greeting + input.

Changes

  • Sidebar icon label renamed from "Config" to "Settings" (English only; other locales already said "Settings"/"설정"/"設定").

Site

  • Added v0.2.13 blog post with pixel-office hero image; registered in blog.tsx, worker SPA meta, and sitemap. Post is marked featured so it pins to the top of /blog.

v0.2.13

Pixel Office — full redesign pass

  • New cozy startup aesthetic: warm cream walls with wainscot trim, light marble-tile floor (6x3 staggered slabs with veining), wood-framed windows with sills, wall decorations (framed picture, clock, cork pinboard), and slowly-rotating ceiling fans. Ambient golden light beams with dithered edges and drifting dust motes near windows.
  • Harmonized furniture palette: every piece now draws from the same ~18-color palette. Desks have warm oak tops with a single centered accessory (coffee mug, paper stack, or desk plant - deterministic per position). Chairs are backless 2-wide terracotta stools so a pet clearly perches on the cushion. Plants, lamps, shelves, whiteboards, and the water cooler all use coordinated wood + terracotta + sage tones.
  • 2.5D object sprites: tall items (floor lamp 1x2, floor plant 1x2, bookshelf 3x1 drawn 2 tiles tall, whiteboard 4x1 drawn 2 tiles tall) protrude upward beyond their grid footprint without colliding with surrounding furniture. No more "floating head" plants or clipped shelves at the wall edge.
  • Balanced layout: 4 workstations (left), meeting room with whiteboard + 3x3 rug + table + 2 chairs (center), lounge with rug + 2 cushions + tall lamp + tall plant (right), kitchenette with water cooler + bookshelf + pet feeder/bowl/cushion (far right). Mix of 1x1 and 1x2 items, perimeter plants and lamps anchor each zone.
  • Agent-to-pet assignment is randomized: earlier the leftmost free pet and leftmost free seat always got picked, so the same pet always worked. Now random pick means workstations rotate.
  • Clickable agent popover when a working pet is selected: compact 320px card with status dot, pet name, current task, live tool indicator with animated dots, last error, top-used tools, iteration/tool/elapsed stats, and Stop + Open Full actions. Much cleaner than the old cramped popover.
  • Real-time pet-position persistence: pet positions (plus direction and state) now save to localStorage every 3 seconds and on tab blur / window close. Returning to the Agents page keeps every pet exactly where it was. Writes are batched so there is only one localStorage set per cycle.
  • Notifications are deep-linkable: agent-completion notifications now carry the session id in their payload. Clicking "Agent Done" in the bell popover jumps straight into that agent's detail page. Works across the in-app bell, the Electron titlebar bell, and the Windows header bell.

Pixel Office - earlier in v0.2.13

  • Claude-Code-inspired rare encounter journal (18 critters across 5 tiers, seasonal/night/agent-completion gates).
  • Welcome-back summary modal with sparks/items/sightings earned while away.
  • Pets replace human agent sprites; each walks to a chair and "works" with an animated monitor.
  • Background pet simulation always runs when the Pixel Office is enabled (no separate opt-in).
  • Wall-clock catch-up simulation so pet stats and rare rolls progress accurately after long absences.
  • Server-side state backup via /api/pixel-office/state (single-row blob store, overwrites in place - no history accumulation).
  • Visitor system retired and unified under the rare-encounter journal (sightings-only).
  • Inventory now surfaces only placeable items; starter seed is a single comfy cushion.
  • Auto-forage removed; pets stay home.

Fixes

  • Feed sidebar black dot that couldn't be dismissed (legacy Activities-era code).
  • Goal-started agents now appear as separate rows in the history list (each run mints its own session id).
  • Agent popover used to show 2 running agents for 1 goal because the in-memory "default" row and the fresh session row both appeared - now deduped.
  • Sidebar label "Agent Team" simplified to "Agents" across all 10 locales.
  • i18n interpolation accepts both {var} and {{var}} placeholder styles.
  • Monitor flicker on working pet's desk now aligns to the desk's centered monitor and refreshes at a subtle 2 fps instead of strobing.
  • Wall-anchored tall items (whiteboard, shelf) previously got clipped or hidden when placed near the wall seam - render order fixed.
  • Settings showed a stray "Background Pet Simulation" toggle even though the feature is always on - removed.
  • Notifications now support action buttons. Previously the in-app bell dropdown only showed title + body - there was no way to trigger "Install", "Dismiss", etc. - so the new-version notification in particular had no actionable path. The Electron native OS notification also gains action buttons (macOS) and opens the bell popover when clicked (Windows/Linux), bringing the in-app action chips to every platform.
  • "Update ready" notification now posts to the in-app notification center with Install Now / Later buttons, not just a silent system toast. Dedupes across multiple download cycles via a fixed notification id.
  • Fix tunnel "restart desktop" and update-install restart paths leaking the spawned Node server subprocess. Previously app.exit(0) / quitAndInstall skipped the before-quit lifecycle, so the server kept running on port 13847 and the relaunched app could not bind the port - making restart worse for users who were trying to recover from a stuck state. Restart now explicitly tears down the server subprocess and tunnel client before handing off to the updater / relaunch.
  • Fix Claude Code OAuth credential detection on Windows. The previous code path tried to read tokens from Windows Credential Manager via the community Get-StoredCredential / New-StoredCredential cmdlets, which are NOT installed by default on Windows - the shell-out silently failed for every Windows user and then fell through to the file fallback. Claude Code on Windows actually stores tokens in %USERPROFILE%\.claude\.credentials.json (matches upstream openclaw / pi-ai reference behavior), so we now read/write that file directly with no PowerShell spawn and no module dependency. Token refresh writes back to the same file claude login uses.
  • Fix Feed Generator interval changes not applying. Changing "Frequency" in Settings → Feed Generator from 5 minutes to 1 hour updated only the heartbeat-runner but left the scheduler's paired Heartbeat schedule spinning its own setInterval at the old interval forever. Execution is now owned exclusively by the heartbeat-runner; the Heartbeat entry in the Schedules UI is display-only (scheduler skips attaching a timer for the auto-seeded entry). Settings ↔ Schedules UI are kept in sync both directions: interval/enabled changes from Settings mirror to the schedule row, and toggles/interval edits from the Schedules UI mirror back to HEARTBEAT.md + the runner.

Changes

  • Feed Generator is now the single Heartbeat schedule. Users can no longer create additional heartbeat-type schedules from the Schedules UI - that type is removed from the create dialog, and POST /api/schedules rejects type: "heartbeat" requests. Use Cron instead for custom periodic schedules.

v0.2.12

Features

  • New OpenAI (OAuth) provider: use your ChatGPT Plus/Pro subscription directly — no API key needed. Foxl reads ~/.codex/auth.json (created by npx @openai/codex login), auto-refreshes the OAuth token, and calls OpenAI's Codex Responses API directly through Strands' VercelModel adapter. No local CLI subprocess, no proxy server. Tool use, reasoning/thinking blocks, and streaming all flow through the normal Strands agent loop. Models: GPT-5.4, GPT-5.4 Codex.
  • Claude Code (OAuth) rewritten on Vercel AI SDK: drops the claude CLI subprocess. Foxl now reads the user's Claude Code OAuth tokens (macOS Keychain, Windows Credential Manager, or ~/.claude/.credentials.json) plus long-lived API keys from claude setup-token, auto-refreshes OAuth tokens, and calls api.anthropic.com/v1/messages directly through Strands' VercelModel adapter. Foxl's full tool registry, thinking/reasoning blocks, and streaming now work end-to-end on Claude Pro/Max subscriptions — same path as the OpenAI OAuth integration.
  • Settings > Providers list now groups each OAuth login right under its API-key counterpart (OpenAI (OAuth) under OpenAI, Claude Code (OAuth) under Anthropic, Gemini CLI under Google) with the provider's own icon.

Changes

  • Renamed the Claude Code provider surface from "SSO" to "OAuth" everywhere (UI labels, status field ssoConfigured -> oauthConfigured, docs). The underlying auth mechanism is unchanged — just more accurate terminology.
  • Removed the legacy Codex CLI provider (subprocess-based). Replaced by OpenAI (OAuth), which talks to OpenAI's servers directly using the same ~/.codex/auth.json credentials created by codex login.
  • Removed the legacy CLI-subprocess Claude Code provider. @anthropic-ai/claude-code is no longer a runtime requirement — Foxl just reuses whichever credentials Claude Code already stored (keychain entry or ~/.claude/.credentials.json).
  • Settings > Providers help text for Claude Code now points users to claude /login / claude setup-token instead of asking them to install the CLI.
  • Subscription-OAuth providers (OpenAI, Claude Code, Gemini CLI) now show a one-line disclaimer in Settings clarifying that they are unofficial community integrations using local subscription credentials — use at your own risk and never share the auth file.

Fixes

  • Fix scheduler (cron + heartbeat) + several helper endpoints that would throw openai-oauth requires async model creation / claude-code requires async model creation when those providers were the active default. All internal createModel() call sites now use createModelAsync() so OAuth-backed providers work everywhere, not just chat.

v0.2.11

Features

  • New Feed page (replaces Activities): For You tab for AI-curated items, Activities tab for agent event stream, Logs tab with live SSE log viewer. Persists selected tab per user.
  • New Feed Generator (was "Heartbeat" in settings): a background agent that periodically surfaces items in the For You feed. Most runs stay quiet; only items marked urgent trigger system notifications, so it can run hourly without spamming you.
  • New feed_add tool exclusive to the Feed Generator executor (not exposed to chat or subagents). Accepts title, body, priority (quiet/urgent), category.
  • Feed items support Archive / Unarchive / Clear with a clean Inbox/Archive view toggle. Hover anywhere on the row to archive in one click.
  • HEARTBEAT.md is the single source of truth for the Feed Generator prompt. Edit it in Settings or in the workspace; both refresh the runner immediately.
  • Windows taskbar overlay icon now renders the unread count (16x16 SVG) for parity with the macOS Dock badge.

Improvements

  • Sidebar restructured: Chat / Overview / Workspace in the top group; new "Extend" group with Agents, Tools, Skills, Schedules; Connect (Relay, Integrations); Feed.
  • Page header uses i18n via nav.<id> keys (was a static English NAV_TITLES lookup).
  • Schedules page Recent Runs gets a full filter bar: search, Status, Type (All / Excluding heartbeat / Cron / Heartbeat only / Webhook), Schedule, Time range, Sort. Grouped by Today / Yesterday / This week with relative timestamps.
  • Skills page: Enable/Disable-all toolbar button removed, replaced by a subtle counter pill ("3/12 on") with Enable all / Disable all / Invert actions. Per-skill right-click context menu with Enable, Open in Finder, Delete.
  • Notification settings redesigned: Behavior (Only in background / Sound) merged into the master toggle card at top; new Feed section with separate urgent/quiet toggles; test scenarios collapsed into a single dropdown plus Send Test button with a live preview card that shows the notification action chips.
  • Heartbeat-type schedules no longer emit the "Schedule: ..." system notification or bump the sidebar badge. They only surface via explicit feed_add calls.
  • Feed Generator default interval changed from 5 minutes to 1 hour (recommended). Interval options are now 15m / 30m / 1h / 3h / 6h, with 5m kept for debugging only.
  • Settings → Feed Generator card compacted: inline status strip, Frequency and Quiet Hours side-by-side, Instructions collapsed by default. Save button disabled unless there are unsaved changes; a Revert action discards local edits.

Removed

  • Live Logs section removed from Config page. Use the Feed page's Logs tab instead (same SSE stream).

Fixes

  • Fix black screen on app relaunch: retry loadURL up to 10 times on connection refused instead of showing error page immediately.
  • Error recovery page now probes multiple ports (13847-13851) to find server after EADDRINUSE fallback.
  • Fix relay model tier check rejecting prefixed model IDs (e.g. global.anthropic.claude-sonnet-4-6) for free tier users.
  • Fix crash in Feed Generator settings when activeHours is null in the heartbeat runner state.

v0.2.10

Features

  • Merge Channels and Integrations into a single "Integrations" tab (sidebar Connect section)
  • Slack OAuth workspace selector: enter workspace name (e.g. "mycompany") to connect a specific workspace directly
  • Slack App registered (OAuth V2, user-token scopes, any workspace installable)
  • Relay Slack exchange endpoint deployed with client_id/client_secret secrets

Fixes

  • Fix OAuth loopback server blocking on repeated Connect clicks (async close + explicit cancel of previous flow)
  • Fix Connect button staying disabled after first click (busy state now clears immediately)
  • Auto-register/unregister integration tools (slack, outlook) on connect/disconnect without server restart

v0.2.9

Features

  • New Integrations page (sidebar → Connect → Integrations) for connecting Microsoft 365 and Slack via one-click OAuth
  • New outlook tool (21 actions): email (inbox/read/send/reply/forward/search/folders/drafts/attachments/contacts/move/categories/update), calendar (view/meeting/availability/room booking/search/shared list), and Microsoft To-Do (lists/tasks/checklist) via Microsoft Graph API
  • New slack tool (16 actions) using the user's OAuth token: search_messages, whoami, get_recent_messages, channels_list, conversations_history/replies/add_message/open/members, check_replies_batch, users_lookup/profile_get, attachment_get_data, reactions_add/remove, file_upload
  • Both tools are skill-gated: only registered after the user connects the corresponding account (no noisy tool schema otherwise)
  • Microsoft OAuth uses PKCE + loopback (public client, no shared secret). Slack OAuth exchanges the auth code through relay.foxl.ai so the Slack client_secret is never bundled in the desktop app.
  • Deep-link fallback (foxl://integrations/callback) for environments where the loopback port is blocked
  • Electron openExternal IPC exposed for renderer → browser navigation (http/https only)

Changes

  • Existing outlook-web skill (browser-extension DOM scraping) marked as legacy/disabled - superseded by the native outlook tool
  • Existing slack skill rewritten from bot-token stub to real user-token tool

Infrastructure

  • New foxl/server/integrations/ module: shared OAuth loopback, token store (agent_memory-backed), Microsoft Graph wrapper (auto-refresh on 401), Slack Web API wrapper
  • New relay endpoint POST /integrations/slack/exchange holds the Slack client_secret
  • Skill eligibility now honors requires: [integration:<provider>] - auto-hides tools until connected

v0.2.8

Improvements

  • Migrate to SDK-native cooperative cancellation (agent.cancel()) for faster, more reliable stop
  • Stop button now cancels at SDK checkpoint (between model events and before tool execution) instead of polling flags
  • Subagent stop also uses SDK cancel
  • Strands SDK updated to 1.0.0-rc.3, Bedrock SDK to 3.1030

v0.2.7

Fixes

  • Fix Opus 4.7 thinking not displaying: Opus 4.7 defaults thinking.display to "omitted" (empty text, signature only). Now explicitly sets display:"summarized" to restore thinking content in responses.

v0.2.6

Fixes

  • Fix context usage percentage showing inflated values for Opus 4.7 (was using 200K instead of 1M as context window)
  • Context window size now reads from shared model catalog instead of hardcoded string matching
  • Future models automatically get correct context % without code changes
  • Fix Opus 4.7 thinking error: "reasoning content format incorrect" - Bedrock SDK updated to 3.1030 for new thinking block format (thinking field + signature)

Infrastructure

  • Add @shared Vite alias for frontend access to shared model catalog
  • Strands SDK updated to 1.0.0-rc.3

v0.2.5

New Model

  • Claude Opus 4.7 support - Anthropic's most capable model, available on AWS Bedrock (us.anthropic.claude-opus-4-7)
  • Opus 4.7 set as default model and routing target for expert-level tasks
  • Opus 4.6 retained in catalog for backward compatibility

Fixes

  • Fix Opus 4.7 thinking error: "thinking.type.enabled is not supported" - now correctly uses adaptive thinking for all Opus/Sonnet 4.6+ models
  • Fix Electron EPIPE crash when tunnel log writes to closed pipe (uncaughtException handler)

v0.2.4

Fixes

  • Fix context compaction triggering at 180K tokens instead of model's actual limit (Opus/Sonnet now compact at 900K, was 180K)
  • Fix scheduler cron times interpreted in system timezone instead of user's configured timezone
  • Fix hardcoded Asia/Seoul timezone in schedule display (now reads from USER.md)
  • Fix heartbeat active hours check using wrong timezone

Improvements

  • Context compaction now stays in the same conversation (no more "Continued:" new chats)
  • Compaction inserts a visible divider message so users know it happened
  • Context usage percentage resets after compaction
  • Sidebar conversation list now supports infinite scroll (was limited to 50)

v0.2.3

Fixes

  • Fix model ID resolution in agent core: canonical IDs now correctly converted to provider-specific ARNs via catalog (was passing claude-opus-4-6 directly to Bedrock instead of global.anthropic.claude-opus-4-6-v1)
  • Fix subagent model routing: subagents now resolve models through the same catalog as parent agent
  • Fix GLM-5 and Kimi K2.5 not receiving reasoning_config on Bedrock (string-match detection replaced with catalog family lookup)
  • Fix navbar hash links navigating to wrong page from blog (#security -> /#security)

SEO

  • docs.foxl.ai: favicon (SVG), robots.txt, sitemap.xml (21 pages), OG/Twitter meta, canonical URLs per page
  • foxl.ai: BreadcrumbList JSON-LD replaces SiteNavigationElement (fixes Google breadcrumb display)
  • app.foxl.ai: SVG-only favicon (remove PNG fallback)

Blog

  • New post: Foxl v0.2.2 release notes
  • New post: What Breaks When Your AI Agent Runs on a Real Desktop
  • Blog posts split into individual files with lazy loading (main bundle -28KB)

Build

  • foxl.ai: Vite plugin auto-generates sitemap.xml on build
  • docs.foxl.ai: npm run build auto-generates llms.txt + sitemap.xml from MDX sources

v0.2.2

Model Registry

  • Unified model catalog: single source of truth for all models across desktop, relay, and providers
  • Model IDs normalized to canonical short form (e.g. claude-opus-4-6 instead of global.anthropic.claude-opus-4-6-v1)
  • Adding a new model now requires editing 1 file instead of 5+
  • Usage tracking shows clean canonical names (no more duplicate model entries)
  • Relay derives model list from shared catalog

Settings

  • Moved Logs from sidebar to Settings > Live Logs (collapsible card)
  • System Report: download diagnostic file with system info, conversations, audit trail, and noise-filtered server logs
  • Reports generated server-side for speed and richer data (audit.jsonl, DB conversations)

Chat

  • Edit messages with attachment management: remove images/documents via X button before regenerating
  • Save & Regenerate works even without text changes (useful for re-running with removed attachments)
  • Auto-focus chat input on conversation switch (click sidebar conversation or new chat)

Sidebar

  • Click "Chat" nav to start a new conversation (when already on chat page)
  • Right-click "Chat" context menu: New Chat, Search, Delete All (all i18n)
  • Right-click conversation context menu items now fully localized

Relay

  • Non-Claude Bedrock models (GLM-5, Kimi K2.5) routed via Converse API instead of Anthropic InvokeModel
  • Full tool support and streaming SSE translation for non-Claude models

Browser

  • Dedicated Foxl browser profile (separate from personal Chrome)
  • Login state persists across sessions within the dedicated profile

SEO

  • docs.foxl.ai: add favicon (SVG), robots.txt, sitemap.xml (21 pages), OG/Twitter meta, canonical URLs
  • docs.foxl.ai: per-page OG title/description/URL for all docs pages
  • foxl.ai: replace SiteNavigationElement with BreadcrumbList JSON-LD (fixes Google showing all nav links as breadcrumb)
  • foxl.ai: per-route BreadcrumbList via Worker (blog posts get Foxl > Blog > Title)
  • app.foxl.ai: remove PNG favicon references, SVG-only favicon

Dev

  • RELAY_URL=http://localhost:4200 for local dev with foxl relay mode

v0.2.1

Skills

  • Install skills from [skills.sh](https://skills.sh) registry directly in the Skills page

Scheduler

  • Fix cron weekday schedules firing on wrong days after laptop sleep/wake

Overview

  • Redesigned dashboard: today-focused metrics, cleaner layout, reduced polling
  • Token usage by model with provider labels (Bedrock, Ollama, etc.)
  • Usage Explorer shows which provider handled each model request
  • Local data disclaimer in Usage Explorer

Search

  • In-chat search (Cmd+F): find text within current conversation with persistent yellow highlights
  • Cross-conversation search (Cmd+Shift+F): search across all conversations from sidebar
  • Multi-word search: "hello world" finds messages containing both words
  • Match navigation with up/down arrows and match counter (N/M)
  • Click sidebar search result to navigate to exact message with highlights
  • Korean and multi-byte text search support

UI

  • Increase button spacing in prompt input toolbar for mobile
  • Protocol-level WebSocket keepalive for more reliable connections

v0.2.0

Multi-Agent

  • DB-backed auto-continuation queue — replaces two competing in-memory queues that caused duplicate agent spawns (3 agents becoming 6)
  • SQLite lock table serializes drain execution — atomic INSERT OR IGNORE mutex, stale lock cleanup
  • Remove injectMessage for subagent completion — fixes raw [SUBAGENT COMPLETED] text appearing in chat during auto-continuation
  • Sidebar agent list redesign: elapsed timer, stop button (hover), shadcn Badge for collapsed mode
  • AgentChatView: group consecutive thinking+tool items into single Message block (matches main chat spacing)
  • AgentChatView: fix thinking blocks not displaying — each DB event rendered as separate timeline item
  • Per-agent tool event callbacks — each agent's tool calls scoped to its own instance (no cross-agent leaking)
  • Subagent thinking capture — model reasoning blocks (reasoningContentDelta/thinking_delta) recorded to DB
  • Auto-continuation triggers per-completion — each agent result delivered independently (no 30s batching)
  • Parent breaks after spawning subagents — waits for auto-continuation instead of re-prompting
  • Fork children keep full tool list for prompt cache sharing — spawn blocked at hook level
  • Block subagent spawning during auto-continuation turn (DB lock = spawn guard)
  • Remove goal-based dedup guard (Claude Code doesn't do this)
  • AgentChatView fully DB-driven timeline — survives WS disconnect, complete/error events rendered
  • Remove duplicate goal message bubble + duplicate result rendering
  • Completed agent goal display — merge DB goal into in-memory state
  • Remove all subagent result/tool truncation (was 1000-5000 chars)
  • Remove duplicate active agents section from Agents page (fork tags sanitized)

Tool Approval

  • "Always Allow" auto-approves remaining parallel pending tool calls matching new permission rule
  • Load DB permission rules at server startup — "auto approve all tools" was silently ignored (ESM require fix)

Channels

  • Auto-reconnect channels on server restart (Telegram, Signal)

Scheduler

  • Fix cron weekday field parsing — was completely ignored, causing schedules to run on wrong days
  • Support ranges (1-5), lists (1,3,5), and mixed weekday expressions

UI

  • Message queue redesign: accent background, line-clamp, hover-reveal delete button
  • Terminal session count sync: fix stale closure in WS handler, sessions refresh on spawn/exit events

Skills

  • Fix YAML folded scalar (>) and literal (|) block parsing in skill frontmatter
  • Multiline description fields now correctly joined instead of showing > literal

Build

  • Fix esbuild banner variable collision (_cr -> __foxl_cr) — prevented production app from starting
  • Fix 6 pre-existing TS errors: GoogleModel import, ProviderType ('foxl'), PermissionSource ('user'), SQLInputValue

v0.1.9

Relay Dashboard

  • New unified Relay card on gateway page with connection topology tree
  • Desktop node shows online/offline status, platform, connection time
  • Web client branches display browser, OS, and connection duration
  • Remote restart: restart desktop app from any device via tunnel
  • Remote update check: trigger auto-update remotely
  • Force disconnect individual web clients by fingerprint
  • Session history timeline with audit log (deduplicated, last 10 entries)
  • Tunnel toggle integrated into dashboard header (desktop mode)
  • Account email and relay connection status in card description
  • 15s auto-refresh with visibility-aware polling
  • Full i18n support across 10 languages (27 new keys)

Tunnel Cost Optimization

  • On-demand heartbeat: idle 5min, active 30s (was 24/7 30s)
  • HTTP heartbeat bypasses Durable Object entirely (zero DO request cost)
  • Slow/fast heartbeat switching on web client connect/disconnect
  • Dead connection detection maintained via HTTP liveness check
  • Estimated tunnel capacity: ~630 DAU on $5/mo Cloudflare plan (was ~115)

Mobile Terminal

  • Compact quick keys: smaller buttons prevent horizontal overflow
  • Scroll-to-bottom button in quick keys bar
  • Auto scroll-to-bottom after terminal resize (prevents mobile scroll jump)

Foxl Notes Landing

  • White/light theme redesign for foxl.ai/note
  • Pricing section removed
  • Modernized mockup styling

Landing Page

  • "Products" renamed to "Projects" (portfolio tone)
  • FAQ rewritten: free/open project, Claude Code/Dispatch comparison, mobile access, privacy
  • Hero subtitle: "A personal AI agent... Free and open."
  • CTA: "Try it out" with "No account required"
  • Footer: "An open project by foxl-ai" (was copyright notice)
  • Refund link removed from footer
  • Billing/subscription language hidden from Terms and Privacy (comment-preserved)
  • Nacho entity reference hidden from legal pages

Fixes

  • Model selector: foxl relay models now appear first when tunnel connected
  • Discord bot: pricing-disabled instruction prevents outdated billing answers
  • Terminal scroll position preserved across resize events

v0.1.8

Tunnel Stability

  • Fix DO hibernate state loss: persist userId/deviceId to durable storage, restore on wake
  • Fix tunnel status: check is_online flag for instant disconnect detection (was only using stale last_seen_at)

Tunnel Cost Optimization

  • Durable Object Hibernatable WebSocket API: DO sleeps when idle, wakes on message
  • Client-driven heartbeat: desktop sends ping every 30s (no more server-side setInterval)
  • Chat delta batching: 100ms window reduces DO wake-ups by ~90%
  • Estimated DO cost reduction: $8.38/mo to ~$0.41/mo per 2 tunnel users

Subagent Fork

  • Fork subagent: children inherit parent's full conversation as byte-identical prefix for prompt cache sharing
  • Identical system prompt + tool definitions across fork children (Claude Code pattern)
  • Anti-spawn via fork directive prompt (soft guard) + isInForkChild() code check (hard guard)

Terminal Reopen Fix

  • Terminal panel loads scrollback on reopen (no more blank black screen)
  • Works for both running and restored sessions

Mobile Chat Copy

  • "Copy Entire Text" works on app.foxl.ai (reads from localStorage in relay-only mode)
  • Message copy/edit/regenerate buttons always visible on mobile (no hover needed)

Fixes

  • Fixed auto-update "Relaunch" button only hiding window instead of restarting on macOS
  • Fixed 10+ TypeScript type errors across App, AgentEvent, ImageAttachment, ConversationItem, ScheduleExecution

v0.1.7

Native 1M Context Window

  • Opus 4.6 and Sonnet 4.6 now have native 1M context window (no beta header needed)
  • Removed separate "(1M)" model variants -- all Opus/Sonnet 4.6 are 1M by default
  • Simplified model selector: single entry per model instead of two

Adaptive Thinking Effort

  • New effort level selector: Low, Medium, High, Max (replaces token budget)
  • Adaptive thinking with effort parameter sent via Bedrock output_config
  • Max effort is Opus 4.6 exclusive (other models fall back to High)
  • Default effort level: Medium

Tool Approval

  • Claude Code-style permission prompts inline with tool calls: Allow, Always allow, Deny
  • Pattern-based trust: "Always allow" on exec ls creates exec(ls*) rule
  • Permission rules persist to DB across restarts, with * wildcard as default
  • Settings page: toggle auto-approve-all, add/remove patterns manually
  • Built-in safety: destructive commands (rm -rf /, mkfs, dd) are always denied

Agent Core v2

  • Context compaction: auto-summarize long conversations to stay within context window
  • Error retry with exponential backoff for transient failures
  • Hook system: BeforeToolCall / AfterToolCall lifecycle for permission checks and plugins
  • Fork subagent: spawn child agents from parent conversation context
  • System prompt token optimization (34K to 19K chars, 44% reduction)

GLM 5 + Kimi K2.5

  • GLM 5 (Z.AI) available on Bedrock + relay with reasoning_config thinking support
  • Kimi K2.5 (Moonshot AI) with 256K context, vision, and tool use

Context Usage in HUD

  • Context window usage percentage displayed in macOS titlebar HUD
  • Per-conversation tracking from actual token metrics
  • Real-time updates during streaming, persists across conversation switches

Claude Code SSO Fixes

  • Fixed double text output and shimmer stuck during streaming
  • Rewrote CLI stream parser for reliable tool result handling

File Attachments

  • Drag & drop files onto chat area with visual drop zone overlay
  • Accept any file type via paste or file picker (json, yaml, py, ts, etc.)
  • Unsupported Bedrock formats (json, xml, yaml) mapped to txt server-side
  • Document attachment pill constrained to message bubble (no overflow)

Subagents

  • Removed execution timeout — agents run until completion (no more premature stops)
  • Auto-continuation max-wait safety timer (30s) for result synthesis

Settings Persistence

  • AWS profile, region, and thinking effort persist across server restarts
  • Saved to server-config.json in data directory

Schedule Reliability

  • Schedules auto-disable after 3 consecutive failures (including stuck task timeouts)
  • Prevents infinite retry loops for broken schedules

Large Text Paste

  • Virtualized text viewer for attached text blocks (handles 1M+ chars without freezing)
  • indexOf-based parser replaces regex (no backtracking on huge content)
  • Copy button still copies full original content

Provider Detection

  • Bedrock provider correctly reports unconfigured when no AWS credentials exist
  • foxl.ai relay models listed above BYOK/bedrock models in model selector

Update Banner

  • "Updated to vX.X.X" with Relaunch button in sidebar when auto-update completes

Landing Page

  • Animated SoftAurora background with mouse interaction and fade-in
  • Redesigned Security section with CSS Grid layout
  • Discord button, pricing display, license URL fixes

Electron

  • Electron 41, electron-builder v26
  • Bundled Node.js runtime for non-developer users
  • Source map protection (never ship .map files)

Fixes

  • Model/provider sent in chat stream request body (fixes race condition)
  • Fixed tunnel double-connection on sleep/wake reconnect
  • Fixed production terminal, schedule persistence, provider switching
  • Auto-close terminal panel when last session killed
  • Fixed spinner stuck after stream completion (agentRunning:false broadcast)
  • OS-aware download button in navbar
  • Sidebar refresh after OAuth login

v0.1.6

Claude Code SSO

  • Use your Claude Pro/Max subscription directly in Foxl -no API key needed
  • Auto-detects credentials from macOS Keychain or ~/.claude/.credentials.json
  • Just run "claude auth login" once, then select Claude Code (SSO) in Settings
  • Token-level streaming with thinking/reasoning separation
  • Available models: Opus 4.6, Sonnet 4.6, Haiku 4.5 via your subscription

BYOK Relay Passthrough

  • Use your own Anthropic API key through app.foxl.ai -zero Foxl credits consumed
  • Relay acts as stateless proxy -your key is never stored server-side
  • Usage tracked for analytics only (cost: $0)

Terminal Relay Interface

  • Built-in terminal in Chat UI -spawn PTY sessions, tabs, split view, resize
  • JetBrains Mono Nerd Font bundled (Ghostty-style zero config)
  • Remote monitoring via relay tunnel -view desktop terminals from mobile
  • Terminal tool: agent can spawn, write, read, kill sessions programmatically
  • ANSI strip filter for clean LLM output

Chrome Extension Multi-Tab

  • Multi-tab browser control -switch between tracked tabs with labels
  • New commands: switch_tab, list_contexts for tab management
  • Sidepanel tab bar UI with chips and 3s polling

Bedrock Prompt Caching

  • Automatic prompt caching via cacheConfig strategy for Opus/Sonnet/Haiku
  • Applied across server, agent, and provider layers

Relay

  • Ultra tier upgraded to 10,000 credits/month
  • Free tier Opus access blocked (Haiku + Sonnet only)
  • Tunnel pending request cap (50) + chat stream cap (10) for stability

Async Subagents

  • Auto-continuation: when all subagents complete, main agent auto-synthesizes results
  • Completion queue prevents concurrent auto-continuations on same conversation
  • Schedule persistence across app restarts

Agents UX

  • Terminal fullscreen mode in chat panel
  • Crew-style suggestion cards on empty chat screen
  • AI-generated suggestions with structured defaults

Skills Sync

  • Auto-sync skills from foxl-ai/skills repo on first install
  • Skills sync button in SkillsPage UI
  • Local edits preserved via content comparison during sync

Mobile

  • Terminal persistence, mobile IME fix, mobile terminal UI
  • Mobile terminal return icon and Del key

Windows Support

  • Native Windows desktop app -NSIS installer + portable exe
  • CRLF line ending normalization for skills parsing
  • PowerShell terminal with smart shell detection (pwsh.exe, powershell.exe)
  • Native Windows title bar, portable Node.js detection
  • Code signing with self-signed certificate

Auto-Update Fix

  • Universal build targets -single DMG/ZIP works on both Intel and Apple Silicon
  • Fixed latest-mac.yml referencing non-existent arch-specific files

Discord Integration

  • Discord Q&A bot with /ask slash command (Cloudflare Worker)
  • Gateway bot with presence detection and auto-respond in channels
  • Relay auth with KV token persistence for bot sessions

Release Automation

  • Changelog automation pipeline: CHANGELOG.md as single source of truth
  • Release scripts: release.sh (full desktop release), sync-changelog.sh (changelog-only deploy)
  • Generated changelog surfaces: foxl.ai/#changelog, foxl.ai/changelog.md, GitHub Release notes

Fixes

  • Enable AI suggestions in relay-only mode via tunnel
  • Terminal mobile return button visibility and light theme text color
  • app.foxl.ai: relay-only sidebar now correctly shows only Chat and Account pages
  • Message copy handler preserves hyperlinks as "text (url)"
  • Gateway page i18n -hardcoded strings replaced with translations
  • Terminal line ending normalization for cross-platform PTY compatibility
  • Terminal tool: backspace character processing for clean AI output
  • Terminal tool: literal \n escape handling for reliable command execution
  • Schedule execution prevConvId not defined error
  • esbuild-bundle server to fix 5+ minute NSIS install time (16K to 420 files)
  • NSIS installer auto-closes running Foxl before install
  • Windows taskbar icon uses exe embedded icon for proper size
  • 800+ translation keys across 10 locales (en, ko, ja, zh, es, fr, de, pt, ru, ar)

v0.1.5

Auto-Update

  • VSCode-style silent auto-update -download in background, notify when ready
  • Settings toggle to enable/disable auto-update

Tunnel: Login = Access

  • Pairing code flow removed -relay auto-registers device on connect
  • Web clients connect immediately (no approval blocking)
  • E2E encryption (ECDH) on all WebSocket messages

Tunnel E2E Streaming

  • Chat streaming via relay tunnel with SSE passthrough
  • Image and document upload through tunnel
  • Reconnect recovery with snapshot hydration

Fixes

  • Electron UA: real platform/arch (was hardcoded Intel Mac)
  • Session detection: Foxl/ UA parsing for device info
  • Model naming: "Opus 4.6[1m]" style (Claude Code convention)
  • sharp added to server-bundle for screenshot tool

v0.1.4

Multi-Agent Thread UI

  • Codex-style subagent orchestration with collapsible thread sidebar
  • Real-time subagent streaming via WebSocket events (200ms batched flush)
  • Event-driven child-to-parent result injection on subagent completion
  • SpawnIndicator inline in parent chat with live elapsed timer
  • Thread history endpoint (GET /api/agents/:agentId/history)

Streaming Recovery

  • Snapshot endpoint for instant page-refresh recovery (text, tool calls, threads)
  • Sequence-based SSE subscribe with gap detection
  • Recovery state machine (idle, fetching_snapshot, subscribing, live, disconnected)
  • WS streaming_state enrichment with currentText, toolCalls, threads
  • Fallback to SSE replay when snapshot unavailable

Model Selector

  • app.foxl.ai now follows desktop model/provider selection via tunnel
  • Desktop BYOK models visible in relay-only mode when tunnel connected
  • Model selection syncs back to desktop via tunnel API
  • Fix: model selector silently overriding local model with foxl relay

SDK

  • Strands Agents SDK upgraded to v0.7.0 (Plugin system, prompt caching)

Fixes

  • Credit exhausted popup removed from AccountPage
  • Chrome extension Pilot renamed to Foxl branding
  • Default provider fallback changed from 'foxl' to 'bedrock'
  • WS multi-subscriber Set pattern (prevents callback overwrite)

v0.1.3

Tunnel

  • Tunnel resilience: heartbeat 3x failure reconnect with backoff reset
  • Online-gated routing: __foxlTunnelOnline flag, sidebar isOnline
  • Tunnel auto-refresh on online/offline transition
  • Load desktop conversations via tunnel API when connected

Chat

  • Mobile-first ChatPage layout (relay-only always full-width)
  • Model ID resolution: compound prefix + version suffix handling
  • WS 4003 token mismatch auto-reload

Fixes

  • Chrome extension health check 500ms AbortSignal timeout
  • GatewayPage device field mapping normalized
  • Provider selection persists via localStorage key
  • All model tiers accessible on all plans (restriction removed)

v0.1.2

Web App

  • app.foxl.ai: relay-only chat with localStorage conversations
  • OAuth hash login, Google/Apple sign-in on web and desktop
  • AccountPage: credits display, subscription, lazy sessions
  • Onboarding flow: welcome, extension, login, chat

Relay

  • Welcome 200 credits on signup, monthly 10 credit refill (cron)
  • Atomic credit deduction (D1 batch transactions)
  • D1-backed rate limiting, OAuth CSRF protection
  • Strict model ID validation, 5 Claude models enabled
  • relay-worker/ consolidated to relay/

Desktop

  • Universal macOS build (arm64 + x64)
  • Random port + connection token (VSCode-style security)
  • Server crash protection, CORS hardening
  • sessions_status tool: waitSeconds parameter

Docs & Infra

  • Starlight documentation site (16 pages, full-text search)
  • llms.txt / llms-full.txt from real documentation
  • CI workflows: deploy-app, deploy-docs, deploy-relay, deploy-site
  • Version unified to 0.1.2 across all packages

v0.1.1

Agent

  • AgentsPage: make expanded session card scrollable

Chat

  • Channel: group mention filter, Signal greeting, conversation history API

UI

  • Topup UI, webhook idempotency, tray menu, deep link, build fix
  • i18n: add useTranslation hook to all 29 sub-components
  • i18n: apply t() to 109 strings across 6 pages

i18n

  • i18n expansion (496 keys, 10 locales), dev data path fix
  • 251 keys across 10 locales, sync script, comprehensive coverage
  • Expand to 10 languages, system language detection, complete translations

Skills

  • Revert nested skills scan, use symlink instead
  • Support nested skills dir + add .omc to gitignore

Fixes

  • Fix SettingsPage crash: add useTranslation hook to main component
  • Fix i18n: add useTranslation import and hook to all pages
  • Fix DialogTitle accessibility warning, add PILOT_SKIP_SERVER
  • Fix message queue leaking across conversations
  • CI cache-dependency-path for setup-node

Other

  • Add Foxl proprietary license
  • Security: path traversal protection, JWT production guard
  • Show git commit hash in app version (Settings > About)

v0.0.2

Agent System

  • OpenClaw-parity heartbeat runner with active hours, stuck detection, requests-in-flight skip
  • Context overflow auto-continuation (creates new conversation with summary)
  • Subagent spawn with result/error saved to conversation messages
  • Subagents blocked from spawning other subagents (infinite recursion prevention)
  • WebSocket reconnection restores agent state automatically

Chat

  • Tool call display with per-tool icons (15 icon types: Monitor, Globe, Terminal, Database, Git, etc.)
  • Human-readable tool titles for all 20+ tools
  • Confirmation component (shadcn AI pattern) for tool approval
  • Extended thinking with collapsible reasoning display
  • Image upload, paste, and document attachment support

Skills

  • 68 built-in skills (ported from OpenClaw)
  • Skills always loaded regardless of binary availability (install at runtime)
  • Lazy skill loading (list only, read on demand) for token savings
  • Skill eligibility check with missing dependency display

UI

  • Agents page redesign: date grouping, time range filter, status filter
  • Agent detail dialog: stepper activity timeline, tools used summary, last response
  • Settings: Heartbeat config card, provider SVG icons, active hours selector
  • Workspace/Skills: Cmd+F search with content search, search button
  • Usage Explorer: 30-day default, estimated cost per model
  • Dock badge: notifications + unread chat count

Providers

  • 7 relay proxy providers: Bedrock, Anthropic, OpenAI, Google, Groq, xAI, DeepSeek
  • 24 local providers via OpenAI-compatible API
  • Provider SVG icons (light/dark mode)
  • Credit system with 10% margin (1 credit = $0.04)

Channels

  • Telegram bot integration (non-blocking start)
  • Signal CLI integration (foxl-ai/signal-cli)
  • Channel send tool for proactive outbound messaging

v0.0.1

  • Initial Electron desktop app with embedded server
  • Pixel Office view with agent characters and pet system
  • Code splitting: 14 lazy-loaded pages (1,407KB to 177KB main bundle)
  • Token usage tracking with SQLite persistence
  • Session memory with LLM-generated summaries
  • Context compaction via Bedrock compact API
  • Tool approval system with always-allow option
  • Browser automation with accessibility tree snapshots (93% token reduction)
  • Workspace memory system (SOUL.md, USER.md, MEMORY.md, daily logs)
  • Scheduling system (cron, heartbeat, webhooks)
  • Multi-provider support (Bedrock, Anthropic, OpenAI, Google, Ollama)