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_queryrather 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_contenttakes apropertyoption- The macOS permissions check is cached for five seconds (#440)
Changed
- chromiumoxide over the Chrome DevTools Protocol replaces the abandoned
playwrightcrate - 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_tokensrises 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
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
Dropcalledbrowser.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_choiceand 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
expectcalls are gone from the Rust backend (#536) - vite, react-router, and @babel/core are upgraded past their open advisories (#487)