Repository navigation
Windows & Linux: catch up with the Mac (0.1.1 → 0.2.x) - #307
Merged
Merged
Conversation
GNOME has no layer-shell and ignores where a Wayland window asks to go, so the island opened in the middle of the screen with no way to move it. On a GNOME Wayland session Coucou now runs through XWayland (GDK_BACKEND=x11, overriding one inherited from an editor or terminal), where set_position works, and the regular island window is a keep-above Dock: the only kind of window, besides the desktop, that "show desktop" leaves on screen. COUCOU_X11=0 keeps the native Wayland window, COUCOU_DOCK=0 makes it a utility window instead of a dock. Checked on Ubuntu GNOME (Wayland) with xprop: _NET_WM_WINDOW_TYPE_DOCK, _NET_WM_STATE_ABOVE and _NET_WM_STATE_STICKY, input hint False, top centre of the primary display. Co-authored-by: Cursor <cursoragent@cursor.com>
On KDE Plasma (layer-shell, Wayland) the expanded island often never folded back after the mouse left: - WebKitGTK does not send mouseout when the pointer really leaves the layer surface; - GTK's leave-notify fires spuriously while the pointer is still over the island, immediately followed by a re-enter, which cancels the collapse timer; - WebKitGTK can deliver a queued mousemove after the pointer has left, pulling the island back to "inside". Rust now polls GDK's pointer focus (it follows the compositor's wl_pointer enter/leave) every 100 ms while the island is shown, reports both edges to the page as `pointer-inside`, and emits the usual far-away cursor on leave. The page ignores its own mouse events while the compositor says the pointer is outside. The timer is removed while the island is hidden (set_pointer_watch from set_collapsed), so a hidden island still costs nothing. Windows is unchanged (no-op).
On a fresh Windows build, `npm run tauri dev` dies when Cargo reaches the last crates: Vite's watcher tries to watch target/debug/deps/coucou_lib.dll while Cargo holds it locked, throws EBUSY, and the beforeDevCommand exits. Ignore target/ and src-tauri/ in the Vite watcher. Tauri already watches src-tauri/ itself. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
AskUserQuestion arrived as a permission request and got the Deny / Allow
card, which says nothing about what is being asked and cannot answer it.
The question view now shows the question and its options as buttons. Picking
one sends the answer back to the session; several questions are stepped
through in turn, pick-several questions get toggles and a Done button, and
"Answer in terminal" hands the request back as before.
The answer travels as {"answers":{...}} on the relay connection. coucou-hook
turns it into an allow whose updatedInput is the question's own input plus
that map, and refuses anything else: no other field and no other tool's
input can be changed from the island.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A layer surface ignores set_position, so the island landed on whichever output had focus when it was mapped. Pin it with gtk_layer_set_monitor to the display target_monitor picked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BNUKEFycKsFCP5fKkhY1Uf
"Main display" means little on Wayland: GDK has no primary monitor, so it is whichever output GDK lists first. List every display in "Island lives on" and store the choice as at:<x>,<y> (logical origin). Names cannot be the key: two monitors of the same model report the same one. A display that is gone falls back to the primary one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BNUKEFycKsFCP5fKkhY1Uf
The card opens under a cursor that was busy with the window underneath, so a click meant for that window could land on Allow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BNUKEFycKsFCP5fKkhY1Uf
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BNUKEFycKsFCP5fKkhY1Uf
Files dragged from the classic Explorer folder view (Downloads, Documents...) got the "no drop" cursor: the island's innermost windows belong to msedgewebview2.exe and those drags never reached wry's drop target. Only the WinUI views (Home, Recent) got through. On Windows the island now lets WebView2 take the drop, as Edge does, and reads the real paths back through postMessageWithAdditionalObjects (webview_drop.rs). Linux keeps Tauri's drag events (tauri.linux.conf.json still enables them). Cancel on the dropped-file card never received the click: the hidden view and #content sat above the canvas buttons. It now also forgets the file, so the chat no longer picks it up, and a copy finishing late cannot bring it back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h step The ticker found new steps by their index in task.steps. That list is capped at 20: once it is full, every new step shifts the oldest out and the index stays at 19, so the ticker saw nothing new and showed steps 18 and 19 for the rest of the session, while the header went on reading 20/20. Tasks now carry stepSeq, the position of the newest step in the whole session, which keeps counting past the cap. The ticker scrolls by that, and takes the texts from the end of the list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Builds the existing Tauri app from windows/ with makepkg and installs it with its relay, icons and licenses. No change to the app itself.
Port of GithubPoller.swift, GitHubPulse.swift and GitHubActivity.swift: a GraphQL pulse (my PRs with CI, PRs waiting for my review, default-branch CI of recent repos) on the Mac cadence (10 s, then 60 s while CI runs, 5 min otherwise) and the contribution calendar (15 s, then 30 min). headSha-aware alert detection is emitted as github-alerts. Nothing polls while the pill is off or Coucou is paused; the island can ask for a refresh of stale data, and a token change drops in-flight answers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
recap.rs keeps per-turn counts (time, files and lines changed, commands, questions) and permission decisions in recap.json under the app data dir, with a 12-week window, a hard size cap and atomic writes. Only the agent's pill ID and the project folder's name are stored, never commands, paths or prompts. Also saves the shared PNG into Pictures/Downloads without ever replacing a file, and adds "Weekly recap" to the tray menu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The GitHub card follows GitHubPulseCardView once the pulse is in: stars and the last 7 days of contributions in the header, then My PRs, To review and Default branch CI. Each row opens its list; an item opens on github.com (http/https to github.com only). The header opens the past 23 weeks, and a day shows its count on hover or click. Without a pulse the card stays the existing stars + repositories overview. github-alerts from Rust badge the pill (when it isn't on screen) and play the Mac's sound: error for red CI, question for a review request, finish for green CI. Opening the card asks Rust to refresh stale data. The open button now goes to github.com/pulls, as on macOS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Classic token with the repo scope, or fine-grained with read access to Pull requests, Commit statuses and Actions — the Mac's hint, shown with the existing hint style. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LCS line diff with 3-line context hunks, the same 200 KB / 4 000-line / 1M-cell guards, toOneLine and the diff step encoding, plus buildFileDiff for Edit / MultiEdit / Write tool inputs. Tests mirror tests/DiffEngineTests.swift. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PostToolUse of Edit / MultiEdit / Write keeps old_string / new_string / content up to 256 KB each and 512 KB per event (other fields and events keep the 2 000-byte cap). Anything cut sets coucou_diff_truncated so the island shows no counts it cannot trust. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PostToolUse of a file edit stores its diff (50 per pill, forgotten after an hour or at SessionEnd / pill removal) and adds a ticker step: file name +N -M. - Clicking a diff row opens the diff in the overview's left card (DiffCardView); < or Esc goes back, leaving the overview closes it, and the arrow opens the file in VS Code through open_file_in_vscode (existing file by full path only; the fallback shows its folder, never launches the file). - Stop reads last_assistant_message (fallback message) through toOneLine: the first paragraph becomes the last step and finalLine. The ticker then holds still (no shimmer, check mark, #C9CDD4) until the next turn, and the finished card shows it on one line with an ellipsis. - Error and question views skip diff steps when showing the last step. - The ticker's dim text is pinned to top:0, where a one-line row already put it, so a text wider than the row no longer drops below it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port of the Mac's wardrobe (0.1.5, #195): party hat, beanie, crown, witch hat, Santa hat, bunny ears, bow, sunglasses, round glasses, scarf and pumpkin, from design/outfits/mochi-outfits.js and MochiOutfitDrawing.swift. Outfits follow the head in 3D, glasses sit on the eyes, pompoms and hat tips lag on a spring that reacts to taps and head turns, and outfits drop in and fade out. With an outfit on, a roll turns the whole character. Only the main Mochi is ever dressed. Auto mode picks the outfit from the season. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New mochiOutfit field (default "auto", the Mac's raw values). The struct's serde default keeps settings.json files from older builds loading; the island reads anything unknown as "auto". Node tests mirror MochiWardrobeTests.swift. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port of GreetingCanvasView.swift (0.1.5, #196): Mochi falls into the island through warp streaks, bounces, slides to the side and waves with a quick little hand, then comes back. Plays the Mac's new greeting.wav, faded out when the greeting is left (SoundEngine.fadeOut). The collapse into the compact island now uses the island's own 340 ms close curve: with the Mac's ease the island shrank ahead of Mochi and cut his body off when the greeting was left early. A Node test runs the island geometry frame by frame and checks he always fits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New island view styled like the others: hover an outfit to try it on Mochi, click to keep it (pop + proud). Right-click on Mochi toggles it, from the compact island too. The bot canvas gets side room for wide hats, and leaving the greeting view fades its sound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tauri-plugin-global-shortcut registers the Mac's global actions with AltGr-safe Ctrl+Alt defaults, stored in settings.shortcuts with serde defaults. Each press reaches the island as a `shortcut` event (the wardrobe as `open-wardrobe`). On Windows a Ctrl+Alt combination that types a character on an installed layout is left unregistered. On Wayland nothing is registered and `coucou --shortcut <id>` runs an action through the single-instance relay instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DMzyoPKtGVNBUemdZhnWRG
core/shortcuts.ts ports ShortcutLogic: accelerator parsing and display, the key recorder, duplicates, the AltGr table the defaults are checked against, card and pill navigation. island/shortcuts.ts runs the global actions and the in-island keys (Ctrl instead of Cmd). Tests mirror tests/ShortcutTests.swift and keep the Rust and TS defaults in step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DMzyoPKtGVNBUemdZhnWRG
Change, record or turn off each global shortcut, see the ones another app holds, the duplicates and the combinations that type a character, and the Wayland commands to bind instead. The island's own keys are listed read-only, as on the Mac. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DMzyoPKtGVNBUemdZhnWRG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DMzyoPKtGVNBUemdZhnWRG
…kout) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
window_owner is the rule the tests pin down; the Windows side walks ancestors itself, so it is test-only. Only the advisory's package is bumped in the lockfile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Microsoft reviewed the Trojan:Win32/Wacatac.H!ml false positive and removed the detection, so the READMEs link the installers again (windows-latest) and the Windows and Linux workflows publish on their tags. The workflow comment says to scan a manual build with Defender before tagging. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Louis-CFM
marked this pull request as ready for review
October 7, 2026 23:07
JhoanG956
added a commit
to JhoanG956/coucou
that referenced
this pull request
Oct 7, 2026
… CI / Google Calendar branch Main's Windows catch-up (Louis-CFM#307) brings its own GitHub card, and the Windows side of this work already lives in its own pull request (Louis-CFM#86). This branch now takes main's windows/ as is and stays the macOS part: the CHANGELOG entries and INTEGRATIONS section 8 no longer describe Windows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 7, 2026
This was referenced Oct 7, 2026
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.
The Windows and Linux app catches up with the Mac, from 0.1.1 to 0.2.1 — everything except Apple Music and the iPhone (macOS / iCloud only). Version bumped to Windows and Linux 0.2.0; nothing is tagged or published. See the new
CHANGELOG.mdsection for the user-facing notes.Community PRs
Each one was audited for the repo rules (secrets, no telemetry, never block an agent, never write a config without diff + backup + click, never approve without a click, no restyle of shipped views, stable pill IDs).
ingest_filenow accepts only paths a real drop delivered (WebView2 on Windows, Tauri's drag-drop event on Linux), once, within 2 minDISPLAYis setgtk_layer_is_supported()before GTK init turns layer-shell off everywhereGDK_DPI_SCALE= 1 / text-scaling-factor unless the user set itLICENSE-ASSETS.mdacceptsrule); multi-select sent as a list like the Mac; a question answered in the terminal takes the card down{"decision":"allow"}on every tool call, even with Coucou closed{"permission":"allow"}); builds on Linux; oneagent_cursorpillCOUCOU_ANTHROPIC_BASE_URL(not Claude Code'sANTHROPIC_BASE_URL, which would silently send the key to its proxy); https only except loopbackcmdLocalizable.xcstrings, 10 languages, no reload when switchingfocusWindow(true)on every expand would steal the keyboard from the editorclaude -p --allowedTools Read WebSearch WebFetchpre-approves tools without a clickPorted from the Mac (no PR existed)
Wardrobe and seasonal outfits, greeting v2 and its sound, Mochi on the desktop, live diff and the final message, GitHub pulse / alerts / contribution grid, keyboard shortcuts (AltGr-safe defaults), weekly recap, Codex / Copilot CLI / Muse Code with approvals, OpenCode / Amp / Hermes plugins, Claude Desktop sessions (Windows), pill catalog and main tool, hook pills without a key (#183), fold a pending approval (#290), auto-close delay followed live (#25), full chat answers (#67), first-name greeting (#154), "Open terminal" brings the session's window forward on Windows, 10 languages.
Still not on Windows/Linux: Apple Music, the iPhone app, sending a dropped file by email, dragging Mochi onto a window to attach it, the desktop-Mochi shortcut. Auto-update is not added: it would be a network call to a service the user didn't configure (rule), so it needs an explicit opt-in decision and a signing key.
Independent review
A separate review of the whole diff found and this branch fixes: the chat could attach any readable file named by the page (now only Coucou's inbox copies); the custom OpenAI-compatible key could be pointed at another address from the page (now bound to the address it was entered for, never over plain http off this computer); an unexpected
statusLinetype was replaced instead of refused; the relay waited for decisions from agents whose decisions are thrown away; symlinked configs on Windows; Codex's process tree on Windows; an unusedinnerHTMLpath.Tests
npm test: 314 pass ·cargo test --workspace: 200 + 34 pass ·tsc --noEmitclean ·vite buildOK · string catalog in syncNeeds a real machine (can't be tested in CI): the drag-out of Mochi on Windows, Cursor / Antigravity / Muse hook commands on Windows (their shell isn't documented), Claude Desktop detection path, layer-shell margins on KDE/COSMIC, Arabic layout and fonts.
🤖 Generated with Claude Code
https://claude.ai/code/session_01DMzyoPKtGVNBUemdZhnWRG
Generated by Claude Code