v0.8.0
Stable promotion of the full 0.8.0 release train. This consolidates every
pre-release delta from rc.1, rc.2, rc.3, rc.4, and rc.5 into the stable
notes. The headline of this cycle is configurability + personalisation:
CLI aliases and a Gitmoji mapping, a config CLI and lifecycle hooks, GitHub
issue / PR templates, a full TUI personalisation axis (remappable keymap with
chords, command palette, role-based themes, sidebar stashes mode), a
user-level global config layer, and a responsive / polished TUI chrome - plus
the safety-daily tranche (--dry-run, gwm undo / gwm history), the
gwm sync and cargo-binstall quick wins, and the v0.7.0 release-pipeline
post-mortem fixes.
Upgrade notes
Section titled “Upgrade notes”Install with cargo install gwm --version 0.8.0, cargo binstall gwm, or
from the release archives. MSRV is 1.82.
No .gwm.toml migration is required. Legacy [[bootstrap.command]] entries
are auto-aliased to [[hooks.post_create]], so existing configs keep working
unchanged. The new user-level global config (~/.config/gwm/config.toml) is
purely additive - with no global file, loading is identical to a repo-only
0.7.0 setup.
The git2 0.20 → 0.21 bump (#157)
is intentionally deferred out of 0.8.0: it is a breaking accessor-API
migration (several Option-returning accessors now return Result,
Oid::zero deprecated) tracked as a dedicated source migration in
#169. The Dependabot PR stays
open until that lands.
Stable-only delta after rc.5
Section titled “Stable-only delta after rc.5”- 📝 Refresh the
docs/tree to the full v0.8.0 surface and add a French i18n mirror underdocs/fr/(#199 / #200). Documents every v0.7.0 → v0.8.0 addition that was still missing or only listed as planned:gwm commit-prefix,gwm hooks install commit-msg,gwm undo/gwm history,gwm theme list/show,gwm tui keys,gwm types --gitmoji, and--dry-runongwm remove/gwm prune; the role-based[theme]presets, the remappable[tui.keys]keymap with chord support, the:command palette, the sidebar stashes mode, and the rc.5 TUI chrome polish; the[theme]/[tui.keys]schema, the user-level global config (~/.config/gwm/config.toml), and the{repo_path}/{repo_parent}placeholders; the 8thgwm doctorkeymap check,cargo binstallpackaging, and the PR auto-detection provenance. Adds three pages (tui/themes,tui/keymap-and-palette,configuration/global-config), fixes typos / capitalisation / cross-links throughout, and ships a complete French translation (33 pages, English remains canonical).
Historical delta: [0.8.0-rc.1] - 2026-05-23
Section titled “Historical delta: [0.8.0-rc.1] - 2026-05-23”Delta against v0.7.0 stable. Merged PRs: #148, #149, #150, #151, #152.
First RC of the 0.8.0 series. Bundles the first tranche of the configurability axis - CLI aliases and a Gitmoji mapping - plus the v0.7.0-stable post-mortem fixes on the release / pre-release CI pipeline and the addition of windows-latest to the test matrix.
- CLI aliases (
[aliases]in.gwm.toml+ user-level fallback) (#86 / #151).git configships with[alias];gwmnow mirrors the shape. Declare an alias under[aliases]in.gwm.toml(repo-level, follows the repo across machines) or in~/.config/gwm/aliases.toml(user-level fallback).gwm <alias>is expanded to argv tokens BEFORE clap parses, sowip = "create feat 0 wip"makesgwm wipbehave asgwm create feat 0 wip. Resolution order: built-in subcommands always win (gwm listcan never be shadowed), then repo, then user. Shell pipelines (&&,||,|,;, backticks) in alias values are refused at load time - use a shell alias for shell semantics. Newgwm aliases listsubcommand prints the resolved chain grouped by source, with shadowed user entries flagged inline. Tolerant of non-UTF-8 argv (usesstd::env::args_os()+Cli::parse_from). - Gitmoji mapping +
gwm commit-prefix+ opt-incommit-msghook (#85 / #152). The repo’s Gitmoji + Conventional Commits convention is now first-class. Three new surfaces:gwm commit-prefix [--branch <name>] [--unicode]prints the canonical commit prefix (e.g.:sparkles: feat(#41):or✨ feat(#41):) - handy for shell prompts, AI assistants, and scripted commit composition. Reads.gwm.tomleven when--branchis supplied.gwm types --gitmojiextends the existing branch-type list with two more columns (unicode emoji +:shortcode:).gwm hooks install commit-msg [--force]installs an opt-in.git/hooks/commit-msgthat auto-prepends the resolved prefix when the user’s commit message doesn’t already start with one. Non-destructive by default (refuses to overwrite a pre-existing hook without--force). Honorscore.hooksPath, resolves linked-worktree.gitfiles viaRepository::discover, and degrades gracefully ifgwmis not in$PATHat commit time.
- New
[gitmoji]block in.gwm.tomllets teams override individual shortcodes without redeclaring the whole table (the ten built-in defaults are baked into the binary). Custom branch types are supported -migration = ":truck:"round-trips throughgwm types --gitmoji. - Under
--unicode,gwm commit-prefixand the unicode column ofgwm types --gitmojinormalise known:shortcode:overrides (e.g.feat = ":rocket:"→🚀 feat(#1):instead of:rocket: feat(#1):). The known-shortcode set extends to the most commonly-swapped Gitmoji entries (:rocket:,:fire:,:lock:,:art:,:lipstick:,:hammer:,:bookmark:,:truck:,:rotating_light:, …). Unknown shortcodes fall through verbatim - no panic, no substitution. (#85)
- Pre-release publishing now fails before upload when root
[Unreleased]repeats bullets or issue references already shipped in the immediately previous RC notes. (#147 / #149) - Stable GitHub Releases now publish through the GitHub CLI with the workflow token and clobberable asset uploads, avoiding the
softprops/action-gh-releasebad-credentials failure seen on v0.7.0. (#146 / #148)
- 👷
windows-latestadded to the test matrix (#112 / #150). The maincargo testjob now runs onubuntu-latest,macos-latest, andwindows-latest. Companion portability fixes ship in the same PR train (config path escaping, unix-only test gating, portable shell-script execution, drive-prefix rejection on Windows).
- ✅ E2E coverage for
gwm aliases list(built-in / repo / user precedence, shadowing rejection, shell-pipeline refusal, non-UTF-8 argv tolerance) - 21 new unit tests intests/aliases_tests.rs+ 9 intests/cli_binary.rs. - ✅ E2E coverage for
gwm commit-prefix(shortcode + unicode +--branch+ override) andgwm hooks install commit-msg(fresh install, refuse overwrite without--force, linked worktree,core.hooksPath) - 9 tests intests/gitmoji_tests.rs, 7 intests/hooks_tests.rs, 9 intests/cli_binary.rs.
Historical delta: [0.8.0-rc.2] - 2026-05-23
Section titled “Historical delta: [0.8.0-rc.2] - 2026-05-23”Delta against v0.8.0-rc.1. Merged PRs: #153, #154, #155.
Second RC of the 0.8.0 series. Ships the Safety daily tranche - preview before you destroy, then gwm undo if you destroy anyway - plus the codified v0.7.0 retrospective in CLAUDE.md and a sibling AGENTS.md mirror.
--dry-runflag ongwm removeandgwm prune(#31 / #154). Preview destructive operations before running them.gwm prune --dry-runwalks the worktree list, prints every prunable entry (name + path + reason), and exits 0 without touching the admin files. Empty case reports0 worktree(s) to pruneso scripted callers get a stable signal. Output is sorted by name for deterministic stdout diffing.gwm remove <pattern> --dry-runresolves the fuzzy pattern, prints the would-remove plan (name + path + branch, with(would be deleted)next to the branch when--delete-branchis also passed), and exits 0. An ambiguous pattern fires the same non-zero candidate-list error as the destructive form ---dry-runonly suppresses destruction, not resolution failures.- Detached HEAD worktree edge case: combining
--dry-run --delete-branchon a worktree with no resolvable branch now printsbranch: - (no branch to delete)instead of the misleading(would be deleted)rider, mirroringworktree::remove’s actual behaviour (it only drops a branch when one is resolvable). - Column widths in the prune plan are computed in Unicode characters (
.chars().count()), not bytes, so non-ASCII worktree names or paths stay aligned in a fixed-width terminal. worktree::prunenow consumesworktree::prunable_worktrees(the same scanner that backs--dry-run), so the preview and the destructive pass can never drift on what “prunable” means.- No breaking change: existing call sites without
--dry-runkeep the destructive default.
gwm undo+gwm history+ operation journal (#29 / #155). Recover from a misfiredgwm removewithoutgit reflogarchaeology.- Operation journal: every destructive op (
gwm remove, with or without--delete-branch) appends an entry to$XDG_DATA_HOME/gwm/history.toml(override via$GWM_HISTORY_FILE; macOS fallback underApplication Support, Windows under%LOCALAPPDATA%). Each entry captures the timestamp, worktree name, branch name, branch OID at deletion time, on-disk path, the--delete-branchflag, and the canonicalisedrepo_rootso per-repo separation works across symlink chains. - Rotation cap: 100 entries max across the whole journal; oldest-by-timestamp dropped on overflow.
gwm undo [--bootstrap]: pops the most recent op for the current repo, recreatesrefs/heads/<branch>at the saved OID viaRepository::reference, re-adds the worktree at the saved path withreuse_branch: true. The--bootstrapflag opts into re-running the per-worktree bootstrap (off by default to keep undo cheap). The journal entry is consumed only after a successful resurrection - a mid-flight failure keeps the recovery anchor intact. Detached-HEAD entries are refused with an explicit error rather than silently doing nothing.gwm history [--limit N] [--all]: lists the recent ops newest-first. Default--limitis 20. By default filters to the current repo’s canonicalised workdir;--allsurfaces every entry across every repo for forensic / multi-repo grep. Empty result printsno operations recordedas a stable scripted signal.--limit 0keeps the count line distinct from an empty journal so scripts can tell “I asked for nothing” from “there is nothing”.gwm remove --dry-rundoes NOT write to the journal - previewing a destruction must never allow “undoing” something that never happened.- Journal IO failures are logged to stderr but never block the destructive op: failing a remove because we couldn’t write
~/.local/share/gwm/history.toml(disk full, read-only FS, sandboxed CI runner) would be more surprising than losing recoverability.
- Operation journal: every destructive op (
- Codify v0.7.0 retrospective rules + AGENTS.md mirror (#153). Seven recurring patterns from the v0.7.0 post-mortems land in
CLAUDE.md: stack depth (max 2-3 PRs), encapsulation-nit batching after a stack merges, parallel-agent ownership rule (only when file ownership is disjoint), follow-up issues beating scope creep, MSRV verification against the whole codebase, root CHANGELOG hygiene against rc duplicates, and the release-workflow credentials proof.AGENTS.mdis added as a sibling mirror so the same house rules apply whether Claude Code or Codex is driving.ROADMAP.mdCurrent state bumps to v0.7.0, and.gitignorepicks up.claude/and.serena/.
- ✅ 7 new unit tests in
tests/cli_format_tests.rspinning theformat_remove_plan/format_prune_planhelpers extracted in the Copilot follow-up on #154 (detached-HEAD safety, unicode column alignment). - ✅ 9 new E2E tests in
tests/cli_binary.rsand 4 intests/worktree_integration.rscovering--dry-runfor bothremoveandprune(#154). - ✅ 10 new E2E tests in
tests/cli_binary.rsand 8 new unit tests intests/history_tests.rscovering the journal IO contract,gwm history,gwm undo, theremovejournal hook, and detached-HEAD refusal (#155). - 840 tests total across the
cargo testmatrix (ubuntu-latest,macos-latest,windows-latest) wired inci.yml. Each merge intodevis gated on the matrix turning green; pre-release artifacts are built from the same commit bypre-release.yml.
Historical delta: [0.8.0-rc.3] - 2026-05-29
Section titled “Historical delta: [0.8.0-rc.3] - 2026-05-29”Delta against v0.8.0-rc.2. Merged PRs: #161, #162, #163, #164, #165, #166, #167, #168, #158, #159, #160.
Third RC of the 0.8.0 series and the largest. Lands the remaining configurability tranches (config CLI, lifecycle hooks, GitHub issue / PR templates) and the full TUI personalisation axis (remappable keymap with chord support, command palette, role-based themes, sidebar stashes mode), plus three dependency bumps. The git2 0.21 bump is deferred - it is a breaking accessor-API migration tracked in #169.
gwm config get/set/unset/list/validate/path/edit(#89 / #161). Git-config-style CLI over.gwm.toml.get/set/unsetoperate on dotted keys,listdumps the resolved config,validatere-runs the load-time checks and reports the first error,pathprints the resolved config file location,editopens it in$EDITOR. Writes go throughtoml_editso existing comments, ordering, and formatting survive aset.- Lifecycle hooks under
[hooks.*](#88 / #162). Declarativepre_create/post_create/pre_bootstrap/post_bootstrap/pre_remove/post_removephases, each a list of commands with placeholder expansion, a per-stepon_fail = abort|warn|ignore, and a global--skip-hooksescape hatch. Legacy[[bootstrap.command]]entries are aliased to[[hooks.post_create]]so existing configs keep working (soft-breaking, no action required). [issue_template]defaults +gwm new <type> <desc>(#83 / #163). Create a GitHub issue from per-branch-type issue-form templates and immediately spin up the linked worktree in one command.[pr_template]defaults +gwm pr [--draft] [--base <ref>] [--render](#84 / #164). Render per-branch-type PR bodies with{commits}/{files_changed}placeholders and shell out togh pr create.--renderprints the body without opening a PR;--baseoverrides the resolved trunk (with a common-trunk fallback). Body-supplied content wins over the template default.[tui.keys]configurable keymap with chord support (#87 / #165). Rebind every TUI list-view action (down,up,top,bottom,quit, …) with crossterm-grammar keys, including multi-key chords likeg g. Overrides are validated at load time (unknown actions, parse errors, chord conflicts, and prefix collisions are hard errors). Addsgwm tui keysto print the resolved keymap with per-row source, agwm doctorcheck for an unboundquit, and a keymap-driven help overlay (?) so the documentation always matches the resolved bindings.- Sidebar stashes mode (#34 / #166). Toggle with
s(rebindable astoggle_sidebar_modein[tui.keys]). Cycles the Details panel betweencommits(git log --oneline+git status --short, the pre-existing behaviour) andstashes(git stash list). The panel title shows the active mode; the bottom hint switches toEnter: copy stash@{N} to statusin stashes mode. Cache is keyed by(worktree-path, mode)so toggling re-shells the right git command without leaking stale content between modes. - Command palette overlay (#32 / #167). Opened by
:(rebindable ascommand_palettein[tui.keys]). Type to fuzzy-filter the registered actions (:create,:bootstrap,:yank, …);Enterfires,Tab/Down/Upcycles the highlight,Esccancels. The palette and the keystroke dispatcher share the sameActiondispatcher under the hood, so the two surfaces can never drift on which verbs are addressable or how they behave. [theme]role-based colours (#33 / #168). New[theme]block in.gwm.tomlfor role-based colours (focus,accent,branch,clean,dirty,main,locked,prunable,muted,selection_bg). Built-in presets ship forcatppuccin,gruvbox,tokyo-night; per-role overrides win over presets. Values accept named (cyan), indexed (220), or hex (#89b4fa). Validation runs at load (unknown preset, unknown role, bad colour value all reject). Addsgwm theme listto print preset names andgwm theme show <name>to dump a preset as a copy-pasteable, round-trippable[theme]block. The TUI threads the resolved theme throughApp.theme; a full colour audit of everydraw_*site is tracked as a follow-up (#170).
Dependencies
Section titled “Dependencies”- ⬆️ Bump
serde_json1.0.149 → 1.0.150 (#158). - ⬆️ Bump
sha20.10 → 0.11 (#159). Verified MSRV-clean against the 1.82 floor (cargo clippy --all-targets -- -W clippy::incompatible_msrv). - ⬆️ Bump
criterion0.5 → 0.8 (#160). The benches migrate off the deprecatedcriterion::black_boxtostd::hint::black_boxsocargo clippy --all-targets -- -D warningsstays green under the bump.
Deferred
Section titled “Deferred”git20.20 → 0.21 (#157) is a breaking accessor-API migration (severalOption-returning accessors now returnResult,Oid::zerodeprecated) and does not build as-is. Tracked as a dedicated source migration in #169; the Dependabot PR stays open until that lands.
- TDD throughout: each feature shipped with its companion unit / E2E / state-machine tests (config CLI in
tests/, lifecycle hooks intests/bootstrap_tests.rs, issue / PR templates intests/cli_binary.rs, keymap / palette / stashes / theme intests/tui_app_tests.rsand config tests). - 973 tests total green locally and on the
ubuntu-latest/macos-latest/windows-latestmatrix.
Historical delta: [0.8.0-rc.4] - 2026-05-29
Section titled “Historical delta: [0.8.0-rc.4] - 2026-05-29”Delta against v0.8.0-rc.3. Merged PRs: #172, #173.
Fourth RC of the 0.8.0 series. A short delta: the two remaining Quick wins that landed after rc.3 - gwm sync (#24) and cargo-binstall support (#27). Cut as a dedicated RC rather than folded into the stable so the “stable == last soaked RC” discipline holds. The git2 0.21 bump stays deferred to #169 (Dependabot #157 left open).
gwm sync [<pattern>] [--merge](#24 / #172). Fetch a worktree’s upstream and rebase its branch onto it - or merge with--merge. Resolves the target worktree by fuzzy pattern (defaults to the CWD worktree). Refuses a dirty working tree and a branch with no upstream; a conflicting rebase/merge is aborted so the worktree stays usable, with an actionable error. Read-side inspection uses libgit2; the fetch/rebase/merge steps shell out togitso the user’s configured credentials are honoured.cargo-binstallsupport (#27 / #173).[package.metadata.binstall]inCargo.tomlletscargo binstall gwmpull the prebuilt archive (gwm-v{version}-{target}.tar.gz,.zipon Windows) straight from the GitHub Release - no Rust toolchain or libgit2 compile at install time. Pinned against artefact-naming drift bytests/binstall_metadata_tests.rs.
- TDD throughout:
gwm syncshipped withformat_sync_reportcontract tests intests/cli_format_tests.rsplus E2E coverage;cargo-binstallmetadata pinned bytests/binstall_metadata_tests.rsagainst artefact-naming drift. - 989 tests total green locally and on the
ubuntu-latest/macos-latest/windows-latestmatrix.
Historical delta: [0.8.0-rc.5] - 2026-06-01
Section titled “Historical delta: [0.8.0-rc.5] - 2026-06-01”Delta against v0.8.0-rc.4. Merged PRs: #176, #178, #182, #183, #184, #186, #189, #191, #192, #195, #197.
The largest RC of the 0.8.0 series - the personalisation + polish wave on top of rc.4’s quick wins: a user-level global config layer, a responsive TUI sidebar, the claude-dark preset and a reworked header, a full modal polish pass, a single-line statusline, working-tree colourisation, PR auto-detection, and {repo_path} / {repo_parent} config placeholders - plus a test-hermeticity fix so cargo test no longer reads the contributor’s real global config. The git2 0.21 bump stays deferred to #169 (Dependabot #157 left open).
- User-level global config at
~/.config/gwm/config.toml(XDG:$XDG_CONFIG_HOME/gwm/config.toml), merged underneath each repo’s.gwm.toml. Set a preference once - e.g.[theme] preset = "…"- and it applies to every repo. The merge is a deep TOML overlay: the repo wins on conflicting scalars, tables ([theme],[worktree],[tui], …) merge key-by-key, and arrays ([[labels]],[[bootstrap.copy]], …) are replaced wholesale by the repo when present. Validation runs on the merged result. With no global file, loading is identical to before (repo-only, then the built-in default). SetGWM_NO_GLOBAL_CONFIG=1to force strictly repo-only loading (used by CI for deterministic runs). (#190) - Responsive TUI sidebar - layout orientation and position. On a narrow terminal (
< 120cols) the details sidebar no longer disappears: instead of hiding, it now stacks under the worktree table (table on top, sidebar below). A newVkey cycles the layoutauto → side-by-side → stacked → auto(autois the width-driven default; the other two pin the orientation regardless of width). The sidebar can also sit on the left of the table: a new[tui] sidebar_position = "left" | "right"knob (defaultright, preserving prior behaviour) sets the default side, andHtoggles it live. The left/right preference applies to the side-by-side layout; the stacked layout always keeps the sidebar at the bottom. (#188) - Ephemeral PR auto-detection for a branch’s pull request. When no PR is explicitly linked (
gwm link --pr), gwm now resolves the branch’s PR from GitHub (gh pr list --head <branch> --state all) and surfaces it markeddetected- never written to git config, so it stays fresh and an explicit link always wins. Wired intogwm status(always, one worktree), the TUI sidebar (on theFrefresh, marked “ (detected)“), and a new opt-ingwm list --detect-prflag that adds aPRcolumn (oneghcall per worktree; plaingwm liststays network-free). NewLinkSource::Detectedprovenance alongsidebranch-name/explicit. (#181) {repo_path}and{repo_parent}placeholders for.gwm.tomlpaths/patterns.{repo_path}expands to the main repo’s absolute working directory and{repo_parent}to its parent, so a base can be expressed relative to the repo on disk - e.g.base = "{repo_parent}/worktrees"puts worktrees in a siblingworktrees/dir, matching an editor’s../worktreesconvention (Zed’sgit.worktree_directory) without a per-project editor config. Purely additive; existing{home}/{repo}bases are unchanged. (#175)claude-darkbuilt-in theme preset, a port of the Claude dark palette (orange accent#D4825D/#C15F3C, green/yellow/purple/red semantics). Discoverable viagwm theme listandgwm theme show claude-dark(also resolves under the aliasclaude). (#185)- Colourisation of the Working Tree sidebar block in the TUI, with three distinct status colours so modified and created files stay visually apart: the staged (X) status column renders cyan, a worktree modification (Y) yellow, and untracked
??entries green. Each file name takes its dominant status colour (green when untracked, yellow when modified, cyan when staged-only). The displayed text is unchanged - only colour is added - so each entry still shows the exactgit status --shortcodes. (#179)
Changed
Section titled “Changed”- TUI modal polish - every overlay (
confirm delete,help,new worktree,bootstrap report,open,link,command palette) now shares one frame: a rounded border with a bold themed title, colours pulled from the resolved[theme]instead of hard-coded values, and a box sized to its content rather than a fixed percentage of the screen (the confirm and create modals no longer dwarf their few lines). The confirm overlay gained selectable[ Confirm ]/[ Cancel ]buttons (navigate with←/→/Tab,Enteractivates the focused one), with focus defaulting to Cancel so a strayEntercancels rather than deletes; the classicy/n/Escshortcuts are unchanged. A long worktree path is tilde-compressed and middle-ellipsized to one line. An animated spinner sits beside the safety-countdown progress bar as a live loader. The help overlay renders each key chord as its own coloured badge (the statusline chip style) with themed section headers. (#187) - TUI statusline is now a single line. Key hints render as reverse-video badge chips (the key painted with the theme accent, followed by a short label) and the status message (action log) is pinned flush-right with absolute priority - when the terminal is too narrow, the hint list is truncated with an
…marker while the log stays visible. Previously the footer occupied two rows and wrapped, which could push the log off-screen. No keybindings changed. (#180) - TUI header is now a single borderless row with a clear visual hierarchy instead of a boxed, flat cyan string. The version renders as a reverse-video badge chip (matching the #180 footer chips), the repo name is bold, and the working directory is tilde-compressed and dimmed as secondary context. The
pickerflag is now its own reverse-video chip. The layout is width-driven: under width pressure the path is truncated/dropped first, the repo name next, and the version chip survives last. Dropping the border reclaims two rows for the worktree table.gwm --versionparity is preserved (version still sourced fromCARGO_PKG_VERSION). (#185)
- Test hermeticity - config-dependent tests no longer read the contributor’s real
~/.config/gwm/config.toml. After #190 added the global-config layer,aliases::loadandApp::new_atmerged the runner’s actual global config, socargo testfailed on any machine whose global config diverged from the built-in defaults (e.g. a[theme] presetunknown to the checked-out build). Added injectable seamsaliases::load_layered(repo, global, user)andApp::new_at_layered(start, global)mirroringConfig::load_layered(#190); the leaking tests now injectNonefor a fully repo-only, deterministic resolution. Runtime behaviour ofaliases::load/App::new_atis unchanged - they still read the real global config. The remaining call sites across the suite (config_tests.rs,bootstrap_tests.rs,doctor_tests.rs,tui_app_tests.rs,tui_chord_tests.rs,tui_state_palette_tests.rs) were swept onto the same seams - plus a newApp::new_picker_at_layered- socargo testis now green withoutGWM_NO_GLOBAL_CONFIG=1regardless of the contributor’s global config. (#194 / #196) - The focused panel border (worktree list ↔ sidebar, toggled with
Tab) now paints with the themefocusrole instead of a hardcodedColor::Cyan, so the active “tab” honours the configured palette (e.g. theclaude-darkpreset’s orange) rather than always rendering cyan. The default theme is unchanged (focusis stillCyan), so default-theme users see no difference. (#185)
- TDD throughout; the full suite is green locally (without
GWM_NO_GLOBAL_CONFIG=1after the #194 / #196 hermeticity sweep) and on theubuntu-latest/macos-latest/windows-latestmatrix.