Repository navigation
Conversation
The island was centred with translateX(-50%). While its width was animating, that put it on a fraction of a pixel, and anything painted during the animation in a compositing layer of its own — a scrolling list — kept that fraction once the island had settled: its text stayed blurry until something made it paint again. The offset is now rounded to a device pixel.
Folded or hidden, the views stay in the page with their opacity at 0, and their endless CSS animations (shimmer, typing, dash-march, pulse) went on being computed for nobody. They are paused while the island is not expanded and pick up when it unfolds.
The GitHub poller becomes a module of its own. With a read-only fine-grained token from the Credential Manager, it reads the year's contributions, the latest activity, the projects and their builds every two minutes — every twenty seconds for the builds alone while one is running — and, on demand, the sheet behind a project, a pull request, an issue, a push, a release, a run or a pull request's comments. Requests go out one at a time through one client, with ETags so unchanged answers cost nothing, and the rate limit is kept track of. A part the token cannot read is reported by the name of the permission it lacks. The token never leaves this side: the front only ever asks whether it exists. It also tells the island about two things as they happen: a build of yours that breaks, and a pull request of yours that is merged.
The GitHub card in the overview shows the year's contributions, the last seven days and the latest activity. Its figure opens a panel as tall as the window allows, with two tabs — Activity (the contribution graph, a day's work on a click, the latest events) and Projects — and a sheet behind every line: a project, a pull request with its checks and its files, an issue, a push, a release, a run with one mini Mochi per job, followed live, a pull request's comments, and a file's diff, syntax-coloured, opened on the line a thread is about. The trail on the left is the way back. A broken build or a merged pull request opens the island on a card with Open and OK. OK folds the island and leaves the news on the pill for five minutes; a click on Mochi or on the card goes to it. Mochi takes the colour of the day under the mouse and the state of the run on show; both are the view's to ask through ViewActions.
Switching GitHub on in Integrations opens its setup under its line: the token, the permissions to grant, and a connection test that checks each of them and names the one that is missing. An integration that needs more than its fields can declare a `setup` the same way.
dev/github-preview.html runs the real island on made-up GitHub data in a plain browser, so the card and the panel can be worked on without a token or the Rust side. Like upload-preview, it never ships in the app.
The relay dropped a tool's response whole and forwarded the rest as it came. The island can now follow a session and answer it, and each of these comes from the relay: - what an edit did to its file, as a unified diff with the lines' real numbers, from the hunks Claude Code puts in the tool's response; for an edit asking permission, the diff it would make, worked out from the file as it is — which is read, never written; - a few lines of what a tool gave back: the last lines a command printed, without the escape sequences that colour them, the first lines of a file that was read, the names a search found, the answers to a question. Forty lines at most, each cut at 240 characters; - the conversation's title and Claude's last message, read from the end of the session's transcript at a turn's ends. That file's format is Claude Code's own: if it changes, they simply stop showing; - which Claude Code the session runs in (CLAUDE_CODE_ENTRYPOINT). A question Claude asks with its question tool can be answered on the island: the answers go back on the permission request, in the tool's own input, and the session goes on as if they had been picked in Claude Code. A question left unanswered says so. Still only a permission request waits for a human; nothing here is written to the log.
The island showed one Claude Code session as a ticker of step names, and asked Allow or Deny on a tool's name. It now follows what a session does and lets the two things Claude waits on be answered where they are seen. The session's card is the prototype's: the step under way by its icon and its name, with the file or the command it is at, and a look at what it did; once the turn is over, Done and the first lines of what Claude replied. A click opens the session panel: Mochi's column with the last steps, and the session's journal, read like a conversation in the order things happened — what was asked, each file read, each edit with its diff typed as it lands, each command with the end of what it printed, questions with what was picked, permissions with what was decided, and Claude's reply. Behind it, every file the session changed with its whole diff. A question from Claude's question tool has its own card: its options with what they mean, several to pick and Send, a typed answer, Skip, or handing it back to Claude Code. A permission request for an edit shows the diff before Allow. Several sessions are followed at once, each with its own journal and its own request, one of them in front; the others are a tab away, and a request made while another is on the card waits its turn. Sessions started by a program (the Agent SDK) are left alone, and an event tagged for a third-party agent still goes to that agent's pill. Nothing changes at a stroke: what is new rises into place the way the island's views do. Windows only; nothing here is fetched, it is all in the hooks.
dev/claude-preview.html plays a made-up session through the island's own hook handler, so the card, the journal, the question and the approval cards can be worked on in a browser without Claude Code: a file being written, a command and what it printed, a question, a permission request with its diff, the end of a turn, several sessions at once.
What the session card and the journal show, answering from the island, several sessions at once, and what is read to do it — with their screenshots.
The two screenshots of the session panel were taken before its tab was settled: they showed the name of the last file Claude was at where the panel says Journal.
…'s diff With several sessions open their tabs sat under the session's card, which made it taller and crowded, and again at the foot of the panel's column, which took steps away from it. They are in the middle of the island's bar instead: out of the cards' way, and one click away from any view. Picking one brings Claude's pill forward if another had the front. An approval card that shows a diff let the diff take all the height, so the card's first line and its buttons touched its edges. It keeps the air the other cards have, and the island gives the diff the room the window allows.
The other sessions' tabs sat in the middle of the island's bar. On a Mac that is where the notch has its camera, so nothing can go there if this is to be ported, and a dot with a clipped title did not say what it was for. With more than one session the bar gets one more tab, with the others on the left, showing how many there are. It opens the list of them in the session panel: each with its name, its project and where it is at, the one on show marked as such. A click puts one in front, on its journal. The tab takes a colour when a session behind the one on show wants looking at.
The count of sessions was a tab of the island's bar, next to the ones that change what the island shows — it is not one of those: it is about Claude Code's sessions. It is a chip on the session's card, at the right of the conversation's title, and again in the panel's head beside the files: where a session is looked at. The bar is back to what it was.
… above its first The look at what a step did was cut for three lines in a card made for two rows of ticker: its last line sat on the card's bottom edge. The card now fills its height with the same margin at both ends and the preview takes what is left, and the island is twelve pixels taller while a session's card is on show, so the three lines fit.
… its lines The cards that tell something — a permission to give, a turn's end, an error — are a fixed height, cut for three short lines. With a conversation's title, a reply that takes two lines, or a detail under the title, their lines came within a few pixels of the card's edges, where the question card next to them keeps a wide margin. Each of these cards now measures what it holds and asks the island for the height that leaves at least 14 px above and below; one with room to spare stays as tall as it always was, and a card that tells an integration's news keeps its own height. The error card's second button opens where the session runs instead of saying n8n for a Claude Code session.
The six screenshots of the Claude Code section, taken again after the cards got their margins and the sessions their list.
…ne of your projects
The pill spoke up for two things: a build of yours that broke, and a pull request of yours that was merged. A pull request opened by somebody else on a project you work on went by unannounced, when it is the one that asks something of you.
The profile query now brings back the newest open pull requests of each project the Projects tab lists, at no extra request. One opened since the last look by anybody but you is news: a card that says who opened it, where and how big, and Open goes to it. As with merges, the first refresh only learns how things stand, and a broken build or a merge of yours is told first when several things happened at once.
The card's line ("pull request opened") now comes with the news instead of being guessed from good or bad.
News came from every project the Projects tab lists, with no way to keep one quiet: a busy repository you only follow drowns the ones you care about. Each project of the tab has a bell. A click mutes it — no broken build, merge or opened pull request is told for it — and another gives it its voice back. The choice is kept in the settings (githubMuted, the projects that are quiet, so a new project speaks up by default), and the Rust side reads it before telling any news. What happens on a muted project is still learnt as it happens: unmuting it later does not replay it.
# Conflicts: # windows/src/style.css # windows/src/views/icons.ts
…thers The time column of a row was sized for "19m": a project pushed less than a minute ago says "just now", which is wider, and its build badge and counts sat a few pixels left of every other row's. The column is as wide as the longest thing it says.
The rule that gave the session's lists a wider time column is now the GitHub panel's for every list: the copy goes.
A question with four options that each take two lines is taller than the island can be. Its card then filled up to its edges: the conversation's name sat against the top. The card keeps the least air a card has, and the list of options takes what is left and scrolls.
Every player tells the system what it plays — it is what the volume flyout shows — through the System Media Transport Controls. media.rs asks Windows for Spotify's session: the song, who plays it, the album, whether it plays or is paused, and its cover, and has it paused or skipped. Windows also says when any of it changes, so a new song is heard of as it starts; a look every few seconds is the net under that. A song's cover reaches Windows a moment after its name, so it is read again while the song is new. No key, no account, no request: nothing is asked of Spotify and nothing touches the network. No new dependency either: four more features of the Windows bindings already in use, and twenty lines of base64. A cover is only handed to the island when its bytes start as a JPEG or a PNG. The poller tells the island only when what it says has changed, so a song that goes on playing wakes nothing. One new setting, announceSongs, defaulted when absent from an older settings.json. The idea of a keyless Spotify pill is corefusiion's (Louis-CFM#80), which read the window's title — a title the app no longer puts on a window of its own class.
Spotify's card shows the cover of what plays, the song, who plays it and the album, with previous, play/pause and next. The cover stands where Mochi does on every other card, as large as the card allows: he steps out of this one. A title too long for its line runs to its end and back. The cover is the island's own picture, not the card's: with Spotify's pill in front the folded island shows it in Mochi's place, and unfolding carries it to the card on a spring, the way Mochi travels between views. It lives inside the island's shape, so it folds away with it. When the song changes the island unfolds on the card for a few seconds and folds back, the front going back to the pill that had it — under a green glow and a sheen across the cover, so it reads as news and not as an island that opened by accident. No sound. Never over something that waits for the user, nor while the island is open; a session that asked for something meanwhile gets its card once the song is put away. Settings has a switch for it. The card is built once and changed where it stands, so a pause does not play its entrances again.
dev/claude-preview.html exposes the island's own integration handler next to its hook handler: a pill's updates can be played from the console — a song, then the next — without the Rust side.
What its card and the folded island show, the announcement of a new song and its switch, where it all comes from and where it stops — with three screenshots.
Edurique
marked this pull request as ready for review
October 1, 2026 22:18
Coming to Spotify's card from another view of the open island, the cover was put straight on its place: over the view still fading out, before the card had come in. It now starts where Mochi stands, at his size, and travels to the card on the same spring that carries it there when the island unfolds.
# Conflicts: # windows/README.md
main moved everything that differs between Windows and Linux into platform/, and with it CREATE_NO_WINDOW and the Windows way of spawning a process. Opening the Claude desktop app still spawned rundll32 by hand, so the branch no longer compiled once main was merged in. It now goes through platform::open_url, like every other address the app opens, which also makes it work on Linux.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A Spotify pill for the Windows island, with no key and no account: the cover of what plays, the song, who plays it and the album, with previous, play/pause and next — and the island showing each new song for a moment.
This is stacked on #71 (Claude Code sessions), itself on #57 (the GitHub panel): it reuses their entrances, their palette and the settings drawer. Until those are merged GitHub shows their commits here too; the ones that are this pull request are the last four, about 1 060 lines in 20 files.
It overlaps with #80, where the idea of a keyless Spotify pill comes from — credit to corefusiion. #80 reads the Spotify window's title; this asks Windows instead (see below), which also gives the cover and a paused song. If you would rather take Spotify from #80, close this one.
Windows only. Nothing under
NotchBuddy/is touched.What it looks like
The card. The cover stands where Mochi does on every other card, as large as the card allows; he steps out of this one. A title too long for its line runs to its end and back.
The folded island. With Spotify's pill in front, the cover is in Mochi's place. Unfolding carries it to the card on a spring, the way Mochi travels between views.
A new song. The island unfolds on the card for a few seconds and folds back, giving the front back to the pill that had it — under a green glow and a sheen across the cover, so it reads as news and not as an island that opened by accident. No sound.
These are the real island on made-up data, not mock-ups.
How it works
media.rsfinds Spotify's session there: title, artist, album, playing or paused, and the cover. The keys go to that session, never to another player.island/cover.ts): one element, small in the folded island and large on the card, inside the island's shape so it folds away with it.How to read it
src-tauri/src/media.rs, the poller inintegrations.rs,settings.rssrc/island/cover.ts,island.ts,island/integrations.ts,views/integrations.ts,settings/main.ts,style.cssdev/claude-preview.tswindows/README.md,windows/screenshots/How to try it
With Spotify:
npm run tauri dev, Settings… → Integrations → Spotify, play something in the Spotify desktop app, click the pill.Without:
npm run dev, openhttp://127.0.0.1:1420/dev/claude-preview.html, and in the console:The rules of the house
Cargo.lock,package.jsonandpackage-lock.jsonare unchanged: four more features of thewindowscrate already in use (Media_Control,Storage_Streams,Foundation,Foundation_Collections), and twenty lines of base64 written here rather than pulled in.data:image/URL in an image.announceSongs, on by default and defaulted when absent from an oldersettings.json.tsc --noEmit,vite build,cargo checkpass;cargo test73 passed (2 new, on the base64 and on what counts as a picture);cargo clippyshows nothing new.windows/README.md. I leftCHANGELOG.mdto you.Things you should know before merging
What I did not check