Commit Graph
203 Commits
Author SHA1 Message Date
thomasandClaude Opus 4.8 caec744bfa fix(shell-integration): report a Windows path from Git Bash
Git Bash's $PWD is an msys path (`/c/Users/x`, and `/tmp` for mounts with
no drive at all). The daemon runs Windows-side, where `/c/Users/x` is not
absolute but drive-relative, so it resolved to a bogus `C:\c\Users\x`:
`strip_uri_drive_slash` only un-prefixes the `/C:/…` shape.

That silently disabled the git-status probe and path completion in every
Git Bash pane, and broke split/new-tab outright — an inherited cwd wins
over every fallback in `initial_working_directory`, so the next shell was
spawned with a working directory that does not exist. Worse than either,
`/c/Users/x` is a *valid* drive-relative path, so a machine that happens
to have `C:\c\...` would have shown an unrelated repo's status as the
pane's own.

Use `pwd -W`, msys's own translation to the real Windows path, which also
maps msys-only mounts correctly (`/tmp` -> `AppData/Local/Temp`). It has
no leading slash, so add one for the file: URI shape. Falls back to $PWD
if it fails or returns empty, and the branch is taken once at install
time rather than on every prompt.

The live-PTY test now round-trips what Git Bash actually emits through
the daemon's own `parse_osc7` and asserts the path exists, so the two
halves are verified to agree rather than checked in isolation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 18:26:40 +08:00
thomasandClaude Opus 4.8 a95f890497 feat(shell-integration): support Git Bash on Windows
PowerShell was the only Windows shell that got OSC 133 integration. Git
Bash was excluded by two unrelated gates, neither deliberate:

`shell_kind` stripped `.exe` only for PowerShell, so the `bash.exe` that
`core::shells::find_git_bash` resolves matched nothing — even though the
comment right above it reasons about exactly that suffix. Strip it for
every shell instead.

The Git Bash dropdown row also ships `-i -l`, which tripped
`has_custom_args` and made `setup` decline bash outright. But that guard
exists to protect args the *user* configured; these are tty7's own, from
`detect_shells`. `ShellSpec` now carries who authored its args, so
integration may respell tty7's (`--rcfile … -i` plus the replayed
login-file chain means the same thing) while still leaving the user's
alone. The `-i -l` stay as the fallback for when integration doesn't
apply or fails to set up.

One msys2 detail: the rcfile path is now spelled with forward slashes,
which its runtime accepts just as readily and which carry no second
meaning in the bash string contexts the path can reach.

Verified end to end, not just by construction: a new live-PTY test
spawns the real Git Bash through the real `setup` output and asserts the
full A/B/C/D cycle plus OSC 7 come back. It skips when Git for Windows
isn't installed. Getting it green surfaced two ConPTY-isms worth
recording — the master doesn't reliably EOF when the child exits, and
closing its input side raises a console control event that kills the
shell with STATUS_CONTROL_C_EXIT — both noted at the call sites.

cmd and WSL stay unintegrated, now documented as decisions rather than
gaps: cmd's only hook is PROMPT, which cannot emit C or D, and since
only C clears `at_prompt` an A/B-only shell would leave the line editor
holding the keyboard for the whole of every command. WSL would need
per-distro shell detection and WSLENV path translation to reach the
shell that actually runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 17:39:19 +08:00
thomasandClaude Opus 4.8 3231d315bf fix(windows): stop console windows flashing on every git status probe
tty7 is a GUI process with no console, so launching a console-subsystem
child makes Windows allocate one for it — a black window that pops up
and vanishes. The git status probe is the worst offender: it shells out
four times (rev-parse --show-toplevel, branch name, --git-dir /
--git-common-dir, diff --numstat) and runs on every pane cwd change,
command end, and agent-turn end. Opening a shell in a repo flashed four
windows.

Add core::proc::hide_console — CREATE_NO_WINDOW on Windows, a no-op on
Unix so callers stay cfg-free — and route every non-PTY shell-out
through it: the status probe, worktree's git, the diff-review git calls,
the codex CLI, and shells.rs's WSL probe (which had its own copy of the
constant, now one source of truth).

PTY children are out of scope; daemon::spawn already passes its own
flags for those.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 16:37:43 +08:00
l0ng-ai 2e4cc77a47 Merge pull request #126 from l0ng-ai/feat/tab-close-overlay
feat(tab-strip): float the close button over the label instead of reserving a slot
2026-07-17 18:11:24 +08:00
l0ng-ai 30e6895dd5 Merge pull request #127 from l0ng-ai/feat/agent-hook-cwd
feat(agent-hooks): follow the agent's own cwd for the sidebar git line
2026-07-17 18:11:12 +08:00
l0ng-ai 29a429d0fd Merge pull request #125 from l0ng-ai/fix/agents-row-note-layout
fix(settings): keep Agents rows aligned and notes terse
2026-07-17 18:10:47 +08:00
l0ng-ai c70f9e0881 feat(agent-hooks): follow the agent's own cwd for the sidebar git line
Claude Code's EnterWorktree chdirs the agent without any shell cd, so the
sidebar's branch/diff line could not see the move on platforms without the
proc-cwd fallback. Forward the cwd field every Claude Code hook payload
already carries through the OSC 777 sentinel, keep it on the pane's agent
session state, and let it take precedence over the proc probe for the git
line. The claim is released on session-end (and when the agent leaves the
foreground), so an exited agent falls back to the pane's real directory.
2026-07-17 18:01:29 +08:00
l0ng-ai 58d0596015 feat(tab-strip): float the close button over the label instead of reserving a slot
Every chip permanently reserved a 6px gap + 20px slot for a close
button that is invisible until hover, which read as a hole between an
ellipsized label and the chip edge, and wasted label width on crowded
strips. Drop the in-flow slot: the label now runs the full chip width,
and on hover the ✕ floats over its right edge on a solid backing in
the chip's own fill with a short gradient run-in, so covered text
fades out and nothing reflows.

The ⌘N hint badge keeps an in-flow slot: it also shows on unhovered
inactive chips, which are transparent over the window background, so
an overlay has no solid colour to back onto.
2026-07-17 17:56:09 +08:00
l0ng-ai 72056f4195 fix(settings): keep Agents rows aligned and notes terse
The install/uninstall outcome note repeated the agent name and full
target path inside the row's shrink-proof control column; a long path
inflated the column past the 640px content cap and crushed the label
column (min_w_0) to zero width, wrapping the title one character per
line.

- Terse action summaries: "Installed" / "Removed" — the row already
  shows the agent and target path. Codex keeps the feature-flag
  failure advice; the launch-refresh log line carries the agent name
  and target path itself now.
- Control column gets items_end so status, buttons, and note share
  one right edge across all agent rows.
- Note is width-capped (max_w_80) and wraps, so long error text can
  never expand the column again.
- Outdated status text shortened to one word; the Update button says
  what to do.
2026-07-17 17:21:22 +08:00
l0ng-ai 96ff361209 chore(release): v26.7.1 v26.7.1 2026-07-17 16:42:28 +08:00
l0ng-ai f7270f2bc0 Merge pull request #124 from l0ng-ai/feat/duo-logo-refresh
feat(brand): "Duo" logo refresh — mint panes mark across all icon assets
2026-07-17 16:36:50 +08:00
l0ng-ai 6af47dfb53 feat(brand): "Duo" logo refresh — mint panes mark across all icon assets
Replace the orange window-and-cursor identity with the "Duo" mark: two
offset session panes (mint #3FDD8C behind, ink #17171A in front) with a
prompt chevron, on a cream tile following the Big Sur icon grid.

- app-icon.svg is the master; app-icon.png, tty7.icns and favicon.ico
  are re-rendered from it (rsvg-convert + iconutil + PIL)
- logo.svg/logo.png/logo@256.png carry the tile-less transparent mark
- tray.svg redrawn as the same mark in template form: solid front pane
  with the chevron masked out, back pane at partial alpha
- bare (non-bundled) macOS binaries now set the Dock icon at runtime
  via NSApplication.setApplicationIconImage, so cargo dev/run shows the
  logo instead of the generic executable icon
- README version badge and the social preview switch to the new brand
  green; social preview copy re-aligned with the current README slogan
2026-07-17 16:31:41 +08:00
l0ng-ai 55b5d0151f Merge pull request #123 from l0ng-ai/fix/flaky-reap-guard-test
test(daemon): poll for the child's exec before asserting its path
2026-07-17 15:52:35 +08:00
l0ng-ai 4d2094ff90 test(daemon): poll for the child's exec before asserting its path
Command::spawn returns after the fork, possibly before the child has
exec'd sleep; until then /proc/<pid>/exe still points at the test
binary itself, so asserting the basename immediately is a race. This
intermittently failed the Linux CI job on main (runs 29549626571,
29560431777, 29563049775). Poll process_path for up to 5s and carry
the last-seen basename into the failure message.
2026-07-17 15:48:25 +08:00
l0ng-ai 5b67d79805 Merge pull request #122 from l0ng-ai/fix/macos-tray-template-icon
fix(tray): keep the macOS icon a template image in every state
2026-07-17 15:25:42 +08:00
l0ng-ai 3f61bbbc34 fix(tray): keep the macOS icon a template image in every state
The attention state left template mode to carry the amber badge, which
forced the glyph to a hardcoded mid-grey that was illegible on many menu
bar appearances. Drop the badge (and the grey recolor) on macOS: the icon
now stays a template glyph the system recolors for the bar, and agent
status lives in the tooltip and tray menu. Windows/Linux keep the amber
corner badge on their colored icon.
2026-07-17 15:23:58 +08:00
l0ng-ai a31db6aa7f Merge pull request #121 from l0ng-ai/feat/theme-follow-system
feat(theme): follow the OS appearance with separate light/dark themes
2026-07-17 15:16:02 +08:00
l0ng-ai df36292db1 test(config): round-trip follow-system fields; docs + comment fixes from review 2026-07-17 15:11:11 +08:00
l0ng-ai 1cd801e902 feat(theme): follow the OS appearance with separate light/dark themes
Add a "Sync with system" mode: when on, the active theme resolves from
two user-picked slots (theme_preset_light / theme_preset_dark) by the
current OS appearance and switches live when the OS mode flips.

- config: theme_follow_system + theme_preset_light/theme_preset_dark
- theme: effective_preset_id() resolver; release the native appearance
  pin while following (it would blind the OS-appearance reads)
- app: observe_window_appearance re-applies the theme on OS flips;
  set_preset writes the slot matching the current appearance while
  following; explicit set_slot_preset for the Settings cards
- settings: sync switch + one card per slot; the picker panel aims at
  the slot whose card opened it

Closes #107
2026-07-17 14:57:48 +08:00
l0ng-ai 627f5fe174 Merge pull request #119 from l0ng-ai/fix/windows-hook-console-flash
fix(agent-hooks): stop console windows flashing on each Windows hook
2026-07-17 14:34:30 +08:00
l0ng-ai d5c4f347ed Merge pull request #120 from l0ng-ai/feat/tab-mark-unread
feat(tabs): add Mark as Unread to the tab context menu
2026-07-17 14:32:30 +08:00
l0ng-ai 37a894fc49 feat(tabs): add Mark as Unread to the tab context menu 2026-07-17 14:23:47 +08:00
l0ng-ai f8baebddfc Merge pull request #118 from l0ng-ai/fix/sidebar-group-worktree
fix(sidebar): group linked worktrees under their main repository
2026-07-17 10:18:56 +08:00
thomasandClaude Opus 4.8 3a70e62078 fix(agent-hooks): stop console windows flashing on each Windows hook
Debug builds are console-subsystem (so println! logging stays visible
while developing the GUI), so every `tty7 agent-hook <agent> <event>`
process Claude Code spawns for a hook gets its own console window. At
end of turn several hooks fire (Stop, SessionEnd, PostToolUse, ...), so
a cluster of terminal windows flashes open and vanishes as each tiny
emitter runs and exits.

The emitter never uses its own console for I/O — stdin is piped and it
writes to the agent's console via AttachConsole — so free the throwaway
console the instant run_agent_hook starts. With no other process
attached, the console and its window are torn down before they can
paint. No-op in release (GUI subsystem, no console) and on Unix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 09:48:24 +08:00
l0ng-ai 09810c3766 fix(sidebar): group linked worktrees under their main repository
The sidebar's repo grouping keyed on the git work-tree root
(rev-parse --show-toplevel), so every linked worktree of one repository
rendered as its own group. Probe the common git dir alongside and derive
a repository home — the main checkout's root — and group on that
instead. Branch and diff state stay cached per work tree, so each row's
branch line is unaffected.
2026-07-17 09:46:30 +08:00
l0ng-ai e1c0ed332e chore(release): v26.7.0 v26.7.0 2026-07-16 23:40:31 +08:00
l0ng-ai bb4d1a6bc9 Merge pull request #117 from l0ng-ai/feat/windows-clipboard-image-paste
feat(terminal): paste clipboard images as a file path off macOS
2026-07-16 23:30:02 +08:00
l0ng-ai 3155540acd Merge main: carry #113 selection-consume into the SYN fallback of paste_clipboard_image 2026-07-16 23:20:43 +08:00
l0ng-aiandl0ng-ai 17097ea207 fix(nightly): upload only packaged artifacts, not dist/ intermediates (#116)
Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
2026-07-16 23:15:39 +08:00
thomasandClaude Opus 4.8 ab91f910f3 feat(terminal): paste clipboard images as a file path off macOS
Pasting a screenshot into a coding-agent pane (Claude Code &co.) did
nothing on Windows/Linux. The clipboard-image branch only forwarded SYN
(0x16), relying on the agent to read the OS clipboard itself when it sees
Ctrl+V. That works on macOS, but Claude Code silently drops raw
screenshots off macOS (anthropics/claude-code#26679), so nothing landed.

gpui already hands us the image bytes via ClipboardEntry::Image, so off
macOS we now stage the image to a temp file and paste its shell-escaped
path — the same route drag-and-drop uses, which agents attach reliably.
Windows screenshots arrive as BMP (CF_DIB), which agent vision rejects,
so those are transcoded to PNG; PNG/JPEG/GIF/WebP pass through untouched.
The temp filename is keyed on gpui's content hash so re-pasting one image
reuses a single file. macOS keeps the higher-fidelity SYN path, and a
staging failure there falls back to SYN too.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 23:10:27 +08:00
l0ng-ai 89774b1800 Merge pull request #115 from l0ng-ai/feat/windows-agent-detection
feat(agent): detect coding agents on Windows via shell-integration command capture
2026-07-16 22:46:45 +08:00
l0ng-ai e16708956f fix(agent): only apply mark-derived detection when the C capture changes
A stray foreign A/B mark mid-command re-delivers the same capture; when
that capture names no agent (a wrapper script the matcher can't see
through), re-applying its None wiped an identity the sentinel events had
established. Gate the Windows apply on the capture changing, document
the bare-C trade-off (our own PowerShell fallback emits it), and cover
the gate, %0A multi-line decode, and whitespace-only payloads in tests.
2026-07-16 22:41:51 +08:00
l0ng-aiandl0ng-ai 8209fa1823 feat(nightly): unattended nightly build channel with prerelease-aware update check (#114)
* feat(nightly): unattended nightly build channel with prerelease-aware update check

* fix(nightly): upload assets before pruning stale ones; pin nightly-to-nightly no-prompt in tests

---------

Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
2026-07-16 22:40:22 +08:00
thomasandClaude Opus 4.8 6067f6b651 feat(agent): emit hook status events on Windows via ancestor console
The Windows agent status dot (working/waiting/done) never showed because
`write_to_controlling_tty` was a `false` stub on Windows — the hook's OSC
777 sentinel event was never injected into the pane's PTY, so the daemon
never learned the agent's turn state.

The hook has no `/dev/tty` on Windows, and agents (Claude Code, a Node app)
spawn hooks with CREATE_NO_WINDOW, giving the hook its own *hidden* console
— so a naive `CONOUT$` write succeeds into a dead-end buffer. Mirror the
Unix "write the agent's tty" strategy at the console layer: walk up the
parent chain to the shell tty7 spawned (the ancestor whose parent is the
tty7.exe daemon — the process actually on the pane's ConPTY), FreeConsole
off the hidden one, AttachConsole to the shell's, and write CONOUT$ there.
The OSC bytes then flow through ConPTY to the daemon exactly like the
shell-integration marks. Falls back to spraying every ancestor console
when the shell can't be pinned down.

Adds the windows-sys Win32_System_Console feature for Attach/FreeConsole.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 21:16:03 +08:00
l0ng-ai 775f0b7024 feat(agent): detect coding agents on Windows via shell-integration command capture
ConPTY has no foreground process group, so the Unix process-table poll
(pgid -> argv) has no Windows equivalent and foreground_agent was a stub
returning None. Follow Warp's approach instead: the shell integration
captures the submitted command line at preexec and carries it
percent-encoded on the OSC 133;C mark; the daemon detects the agent from
that string.

- shell_integration: all four bodies (zsh/bash/fish/PowerShell) append
  the submitted line to 133;C, truncated to 512 chars and escaped
  (% ESC BEL CR NL). PowerShell guards the surrogate-splitting truncation
  and wraps the emission in try/catch (EscapeDataString throws on lone
  surrogates under .NET Framework / PS 5.1).
- pane: ShellState.command stores the capture (cleared on D only, so a
  stray foreign A/B mid-command can't wipe the chip); on Windows
  apply_signals feeds it through the new detect_from_command_with.
- cli_agent: detect_from_command_with tokenizes a typed command line
  (quotes, & call operator, case-insensitive) and reuses the argv
  detection; base_stem handles backslash paths and .exe/.cmd/.bat/.ps1.
- ForegroundProbes::agent is now Option<Option<CLIAgent>>: None means
  'no process-table view' (native SSH, Windows) and is never applied,
  fixing the 0.5s poll wiping event-branded agents on native-SSH panes.
2026-07-16 20:23:47 +08:00
l0ng-ai 3aeece5598 Merge pull request #113 from l0ng-ai/fix/ctrlc-selection-consumed
fix(terminal): consume the selection on Ctrl+C copy and PTY paste so the next Ctrl+C sends SIGINT
2026-07-16 19:32:41 +08:00
l0ng-ai 606da8ada7 fix(terminal): consume selection on Ctrl+C copy and PTY paste so the next Ctrl+C sends SIGINT 2026-07-16 19:10:36 +08:00
l0ng-ai 98b4282a39 Merge pull request #110 from l0ng-ai/feat/sidebar-repo-grouping
feat(sidebar): group vertical tabs by git repository
2026-07-16 18:26:19 +08:00
l0ng-ai 9bc84679f7 style: wrap the activate_visual listeners to rustfmt width 2026-07-16 18:22:21 +08:00
l0ng-ai 14d5a8bfc3 Merge pull request #112 from l0ng-ai/fix/rustfmt-settings
style: run cargo fmt on settings.rs
2026-07-16 18:22:06 +08:00
l0ng-ai 0f7a0a9461 style: run cargo fmt on settings.rs 2026-07-16 18:21:41 +08:00
l0ng-ai eec003e4e7 feat(sidebar): visual-order ⌘N, persisted groups, deduped headers
Three follow-ups to the repo grouping:

- ⌘N now targets the N-th row as displayed (activate_visual over the
  same sections the render uses), so the badge digits read 1…9 top to
  bottom under grouping instead of scattering tab-vector indices.
- SessionTab persists the sticky sidebar group, so a restored session
  renders grouped on the first frame instead of starting flat and
  reshuffling as git probes land; reopen-closed-tab keeps its group too.
- Same-named repo roots disambiguate their headers by extending parent
  components until distinct (work/app vs fork/app); unique names stay
  short. Grouping/naming logic moved to pure functions with unit tests.
2026-07-16 18:14:08 +08:00
l0ng-ai e5ede1beb7 fix(sidebar): key repo group on first pane; document grouping
The group key now reads the first pane's cwd instead of the focused
pane's, so switching focus between splits in different repos never
relocates the row (the branch line still follows focus). Also documents
the repo-grouped sidebar and the sidebar_grouping setting in
features.md / features.zh-CN.md.
2026-07-16 18:03:31 +08:00
l0ng-ai 4d70cad3aa feat(sidebar): group vertical tabs by git repository
Group the left tab sidebar's rows under a per-repo header, keyed on the
git work-tree root only (not the branch), so a branch switch or an
in-repo cd never relocates a tab — only changing repos does. Non-repo
tabs collect in a trailing Scratch group; the list stays flat when no
tab is in a repo.

Each row is two lines: the title on its own (never crowded out) with the
branch and +N/-N diff on an indented second line. A sticky per-tab group
key holds across an in-flight probe so the list doesn't flicker on a cd.
New sidebar_grouping setting (repo default / none) toggles it.
2026-07-16 17:51:43 +08:00
l0ng-ai 0603aa99b8 Merge pull request #108 from l0ng-ai/feat/settings-sheet-refine
feat(settings): right-align controls with row hover, tighten column, richer theme card
2026-07-16 17:50:43 +08:00
l0ng-ai d0c2777fdd docs(settings): note both hosting caps for settings_row; refresh theme card doc 2026-07-16 17:50:04 +08:00
l0ng-ai d13c7878a9 Merge pull request #109 from l0ng-ai/fix/tray-glyph
fix(tray): redesign macOS menu bar glyph for legibility
2026-07-16 17:48:19 +08:00
l0ng-ai 530be0fe5c fix(tray): redesign macOS menu bar glyph for legibility
The tray reused logo.svg (window outline + title-bar rule + colored
cursor block), which turns to mush at 18pt in template mode: the color
flattens to alpha and the icon reads as a card/wallet, not a terminal.

Replace it with a dedicated tray.svg — a bold window outline with a
prompt chevron and underscore, drawn for menu-bar size. logo.svg is
untouched; the tray was its only code consumer.
2026-07-16 17:46:51 +08:00
l0ng-ai 6ae48ab950 feat(settings): right-align controls with row hover, tighten column, richer theme card 2026-07-16 17:38:20 +08:00
l0ng-ai 4aeed6fa46 Merge pull request #106 from l0ng-ai/feat/theme-background-visuals
feat(theme): render gradient and image backgrounds, global window opacity/blur
2026-07-16 16:44:01 +08:00