Custom cursor
0.7.0· 85 changes

Release 0.7.0

38 new features, 12 changes, 26 bug fixes, 3 removals, 6 security fixes

Added

  • The floating bar hosts the chat pane: a pill until you ask something, then the response streams in below it (#508)
  • The idle bar is a small pill that grows on hover into mic and type buttons, and drags from anywhere (#510)
  • The bar drags on the first click, even when Juno is not the active app (#509)
  • The bar drags freely and snaps into magnetic wells on release, with a drop-well indicator that dims the screen and cuts clear holes where the bar can land, and a dock-aware pane (#513, #517, #523)
  • A fresh launch parks the bar in the top-right well, and a saved position re-snaps to the nearest current well, so a remembered spot survives a resolution or monitor change (#523)
  • The bar follows your cursor across displays (#528)
  • You can reopen the chat pane from the tray, close it with a global Escape, and keep the history across opens (#526)
  • The response view scrolls to the bottom as new messages stream in (#478)
  • A unified trigger model replaces fixed shortcuts, pairing a method (push-to-talk, toggle, voice) with a target (agent or dictation) (#520, #521)
  • A voice trigger listens for a wake phrase with an optional "hey" prefix, so "juno" reaches the agent and "transcribe" reaches dictation (#520)
  • A global voice activation shortcut, Option+Shift+V, starts recording from anywhere without Juno focused
  • Conversation history persists across launches, with a browser and reload (#527)
  • The Settings window matches macOS System Settings, with sidebar vibrancy, inset traffic lights, row-level search that deep-links to the matching row, and an advanced toggle that hides the rest by default (#512, #505, #517)
  • Onboarding is a native setup assistant with permission auto-grant, live shortcut demos, hand-drawn macOS glyphs, and a system palette (#529, #531)
  • Onboarding polls macOS permissions once a second and advances the moment one is granted, and the state stays live on every step rather than only the permissions step (LAC-1880)
  • A permission dialog is asked for once per launch. Later clicks open System Settings instead of asking again. (#458)
  • Several agent sessions run at once, with a session registry, an input arbiter, per-session cursors in an eight-slot identity palette, a roster strip, and a session switcher
  • A background session posts a macOS notification when it finishes or fails, and Escape cancels only the focused session
  • Automations run on a schedule, gated behind a high-risk confirmation because they re-execute unattended with full tool access (#476)
  • Skill names complete as you type, fuzzy matched, in the bar and the main chat input (#480, #481)
  • Agent memory persists across sessions
  • Juno asks for human confirmation before a risky action
  • Companion mode observes without acting, with a hard tool boundary
  • Clicks go through the macOS accessibility tree by default and fall back to coordinates, and events post straight to the target process (LAC-1487)
  • A full-screen cursor overlay draws a Juno cursor sprite with per-state animations (#435)
  • Juno highlights the element she is about to act on before a computer-use action (#475)
  • Juno can point at something while she talks. A [POINT:x,y:label:screenN] tag in her reply flies a labelled cursor there on a bezier arc, and the tag is stripped from the text you read.
  • Speech to text sits behind a provider interface, with Parakeet as an engine (#448)
  • Kokoro-82M, Chatterbox, and Supertonic are local text to speech providers, and Whisper v3-turbo becomes the transcription default (LAC-1503)
  • A live audio waveform draws while you record (#422)
  • Agent replies render live React components, starting with a NowPlayingCard that reads real Spotify and Apple Music state and drives the player, plus a collapsed <Why> rationale block (#499, #503, #506)
  • Playback commands answer locally. "Pause Spotify", "skip this song", and "what's playing?" run one AppleScript call inside submit_query rather than a model round trip. (#503)
  • Claude Opus 5 becomes the default Anthropic model, then Fable 5.1, alongside Claude Sonnet 5 and Opus 4.8 (#492, #498, #472)
  • Thinking models get an adaptive thinking summary on 4.6 and newer, and a server-side fallback so a safety-classifier refusal is retried instead of surfacing as an error (#498)
  • TLS sessions warm before Anthropic API calls, which cuts first-request latency (#428)
  • Onboarding asks about your role and work type, and offers a Claude CLI connect card as the primary way in (LAC-1953)
  • browser_extract_content takes a property option
  • The macOS permissions check is cached for five seconds (#440)

Changed

  • chromiumoxide over the Chrome DevTools Protocol replaces the abandoned playwright crate
  • Every query entry point routes through one submission pipeline (#497)
  • Orchestrated queries register in the parallel-session registry, so the roster shows what a specialist agent is doing (#490)
  • Escape is watched with a passive NSEvent monitor instead of being claimed as an exclusive hotkey, so other apps still receive it (#507)
  • The Anthropic default max_tokens rises from 4096 to 16384, since component-rich replies were truncating mid-card (#498)
  • The cloud connector is off by default. The hosted backend is down, and the app reconnect-looped at every launch. (#498)
  • Sound cues play on the key edge rather than after audio setup or after Whisper finalizes, and resolved sound paths are cached, so starting and stopping dictation feels immediate (#519)
  • Releases are Apple Silicon only
  • Settings state is shared through one React context instead of each mount making its own IPC round trip
  • The Rust toolchain is pinned, and rustfmt and clippy are gated in CI
  • The repository is scanned with CodeQL on every push (#437)
  • Verbose init logging drops from info to debug (#444)

Removed

  • The chat-based onboarding system the setup assistant replaced is gone (#533)
  • Retired Claude models are gone from the provider definitions (#493)
  • 14MB of unreferenced marketing PNGs leave the bundle (#530)

Fixed

  • Escape cancels the Claude CLI subprocess, now that the session cancellation token reaches the provider (#495)
  • Multi-step tasks work again on thinking models. Thinking and redacted_thinking blocks are captured and replayed verbatim on the assistant turn that issued the tool calls, which the API rejects when they are dropped. (#498)
  • Finishing a browser session no longer closes your browser. Cleanup and Drop called browser.close() over an attach, which terminates every Chrome window and tab you had open.
  • A dropped clone of the browser controller no longer tears down the browser that every surviving clone is still using, and only pages Juno opened are closed
  • MCP servers that fail to start are removed instead of left disabled, and that decision persists through the race that used to lose it (#413, #414, #409)
  • ScreenCaptureKit captures exclude Juno's own windows (#418)
  • Screenshots are sized to the model in use across the whole capture pipeline (#425)
  • Onboarding state stops flapping when the frontend mounts, and chat input unblocks on complete or skip (#441, LAC-2072)
  • The system cursor is restored on quit, and the reference counting that left it scaled is fixed
  • The floating bar toggles from the menu, now that the event reaches the window manager (#491)
  • The settings sidebar keeps a fixed width across panes (#469)
  • Shortcut chips stop overlapping their descriptions (#504)
  • Any JSX component tag in a reply is detected, instead of matching an allowlist that had been stripping NowPlayingCard (#501)
  • NowPlayingCard shows Spotify artwork, now that the webview CSP allows the image host, and falls back to a music icon rather than an empty box (#502)
  • The compact and hover bar sizes apply in one setFrame, so the pill no longer snaps sideways for a frame during the transition (#525)
  • The status dot stops jumping when the pill grows on hover, and the window keeps one height and anchor across both idle layouts (#511)
  • The bar leaves its listening state the moment you stop from the keyboard, and shows the transcribing state while speech to text finalizes (#524)
  • Per-button hover works while Juno is unfocused (#524)
  • Sound cues stop blocking the async runtime for the length of the clip (#518)
  • Adding a trigger no longer flashes back to the previous list. A trigger with no binding yet persists as unconfigured. (#522)
  • A toggle agent trigger stops and submits on the second tap (#522)
  • Overlays stay visible above full-screen apps and never pull keyboard focus from the app you are using
  • The tool_choice and screenshot token settings persist, and the bar reads real text to speech state instead of fabricated voice fields (#538)
  • Juno's Info.plist merges correctly. The bundle had been shipping with no CFBundleIdentifier, which reset your permission grants on every update. (#532)
  • The onboarding window stops flashing on launch (#532)
  • An ActionButton command that does not exist routes through the agent instead of failing

Security

  • Cloud auth fails closed, spawning an MCP server needs your approval, and the entitlements are cleaned up (#534)
  • A shell injection path in the agent is closed, and the file-write workspace boundary is enforced (#535)
  • The browser runs behind sandbox flags, selector injection is closed, URL schemes are restricted, and the Gemini key no longer rides in the header it was leaking through (#537)
  • Safari JavaScript execution goes through the approval flow (#539, #540)
  • Strings truncate on character boundaries, and the panicking expect calls are gone from the Rust backend (#536)
  • vite, react-router, and @babel/core are upgraded past their open advisories (#487)