Roadmap

August 15, 2026 · View on GitHub

The full roadmap (with grouped categories and per-item issue links) lives in ROADMAP.md at the repo root. The issue tracker is the source of truth for scope details, acceptance criteria, and alternatives considered.

current state: v1.9.0 stable

The current stable line is v1.9.0 (Cargo.toml version = "1.9.0", tagged 2026-08-16), the licensing line: gwm is dual-licensed MIT OR Apache-2.0 (#573). Nothing is taken away, MIT stays in full under LICENSE-MIT; LICENSE-APACHE joins it for §3, an express patent grant from every contributor that MIT has no clause for at all, and it is the pair rustc, cargo, clap, serde, ratatui and git2 already ship. You pick either one and never have to say which. The libraries statically compiled into the binary now ship their notices too (#577): libgit2 is GPLv2 with a linking exception conditional on that notice travelling with the distribution, and zlib's terms say its notice may not be removed. The rest of the line is the text gwm prints: 165 em dashes across 161 string literals, plus 49 in gwm --help (#567); the Settings panel sizing to its active tab rather than to a flat 60% of the frame (#569); and one spelling for a worktree path everywhere it is printed in full (#568). See changelogs/1.9.0.md.

v1.8.0 (tagged 2026-08-13) was the density line: the TUI became compact by default (#545), panes and sidebar sections dropping their box rules for a filled one-line header, two rows and two columns back each, with modal titles moved into the top rule (#549), the Status block folded onto a single row (#547) and [tui] layout = "bordered" as the opt-out. Every bounded overlay resolved its width through one policy instead of four (#550), two of which used to get narrower as the terminal widened, and four truncators moved from counting characters to counting terminal cells (#554 / #560 / #562 / #563). A default layout is outside the SemVer promise on purpose: the policy leaves any visual detail of the interface free to change in a minor.

v1.7.1 (tagged 2026-08-12) was a documentation patch with the binary unchanged: the agent session pane got its own page, five text-only pages got a capture, and a guard now fails the build on a broken image link instead of letting the docs deploy fail. v1.7.0 (tagged 2026-08-12) is the largest feature line since 1.0: per-worktree notes, the rich PR/Issue view with its inline review comments, container execution on exec profiles, multi-row selection with a batch delete, and the Symfony preset. It closes the four capability gaps the comparative read of the field turned up, so the comparison page now reports parity where it reported a deficit. See changelogs/1.7.0.md. The previous line, v1.6.1 (tagged 2026-08-04), closed the gaps left by the v1.6.0 security fix. That fix affects every version up to and including 1.5.0: see changelogs/1.6.1.md, changelogs/1.6.0.md and the sections below. The machine-readable contracts frozen at 1.0.0 are unchanged: the CLI subcommands / flags / exit codes, the --format=json schemas, the daemon JSON-RPC protocol, and the .gwm.toml section set will not break without a major bump (see Stability & compatibility). The project MSRV is 1.95.

Since the 1.0.0 milestone (tagged 2026-06-26): three 1.0.x patches hardened the stable line, v1.1.0 shipped the first outside-report-driven pair (#363: persisted sidebar layout + OSC52 clipboard fallback over SSH) with v1.1.1 fixing global config resolution on macOS, v1.2.0 shipped the distribution train (#383: Scoop, .deb / .rpm, AUR, aqua, winget automation), v1.3.0 made gwm agent-aware, v1.4.0 finished the help overlay and the TUI-polish trio, v1.5.0 made gwm multi-forge, and v1.6.0 fixes a command injection through branch names in lifecycle hooks while landing the naming-flexibility line: the section below. Per-version notes live under changelogs/.

v1.6.1: bidi follow-up and self-maintaining documentation

The v1.6.1 line closes what the 1.6.0 neutralisation missed and puts the documentation on rails. Consolidated notes: changelogs/1.6.1.md. Key items:

  • The bidi controls the sanitisers missed (#502): the 1.6.0 rule rests on char::is_control, which covers C0, DEL and C1. It does not cover the twelve characters carrying the Bidi_Control property, which are Cf and not Cc: they reorder how a terminal renders the text around them without ever being a control byte. The site that matters is the pre-trust bootstrap summary, whose whole job is to let someone decide whether to authorise a shell command out of a repo they have not vetted; a summary that can be made to misrepresent that command is worse than no summary. An [aliases] expansion is refused rather than neutralised, because it becomes argv before clap parses it.
  • Branch names reaching the TUI table (#506): the sinks the CLI goes through are not on the TUI's path, and what protected it so far was incidental. Measured on ratatui 0.30, every render path drops the zero-width control bytes, but List and Table keep the Bidi_Control characters, and git's ref rules refuse the ASCII controls but not the Unicode format ones. The neutralisation goes in the width-clipping funnel every constrained cell already passes through, so a column added later inherits it.
  • The documentation publishes itself (#423): the tree under docs/ is served at https://gwm.kbrdn.dev. A merge into main touching docs/, changelogs/ or Cargo.toml triggers a resync and a redeploy without anyone asking. The in-repo tree stays the source of truth, the site is generated from it and never edited on the other side.
  • herdr integration page (#511): herdr-plugin-gwm drives gwm from inside the herdr multiplexer, documented in English and French. The plugin never creates a worktree of its own: gwm creates, herdr adopts, which is what keeps a single source of truth.
  • Test hardening around the same class of mistake: a rule about the $HOME guard that was stated in a doc comment rather than checked is now derived by construction (#507), and two harness races never reachable from the product are closed (#500).

v1.6.0: security fix and naming flexibility

The v1.6.0 line closes a command injection and drops the <type> <issue> <desc> requirement. Consolidated notes: changelogs/1.6.0.md. Key items:

  • Security: a branch name could inject a command into a lifecycle hook (GHSA-fffq-vg6f-gxqm, high, CWE-78 / CWE-88): hook placeholders were substituted into the step's run string and handed to sh -c, and git permits ;, |, &, $, backticks and redirections in a ref name. A branch pushed by somebody else, a fork PR branch is enough, could therefore run arbitrary commands as anyone who had trusted their own repo's hooks, with no trust prompt anywhere in the path: the gate asks about the repo's hooks and never covered the branch name flowing into them. Every version up to and including 1.5.0 is affected and there is no backport. Values are now shell-escaped on expansion; env values stay unescaped because they never see a shell.
  • Free-form worktree names (#416): gwm create --name spike-redis names a worktree freely instead of composing the <type> <issue> <desc> triple. The name becomes the branch verbatim, so branch_pattern / path_pattern do not apply, and the features that read a branch name back (issue auto-linking, gitmoji) stay inactive on it; gwm link remains available.
  • The TUI forms follow the repo's own patterns (#418): create and rename present the fields the configured patterns actually ask for, in the order those patterns write them, rather than the canonical triple. A repo whose convention is {type}/{desc} is no longer shown an Issue field it would discard. Both forms move between the structured and free-form shapes with the same verb, in both directions.
  • Hook context as environment variables: GWM_BRANCH, GWM_PATH, GWM_TYPE, GWM_ISSUE, GWM_DESC, GWM_USER, GWM_OWNER, GWM_REPO alongside the {placeholder} syntax. A hook that reads "$GWM_BRANCH" never has to think about quoting, because a shell does not re-parse metacharacters coming out of a variable.
  • The declared MSRV is 1.95, and CI holds it (#491): Cargo.toml had claimed 1.86 for a whole release line while the locked graph needed more, silently, because rusqlite's bundled libsqlite3-sys declares no floor of its own and no manifest read finds it. A job now installs the declared floor and both resolves and compiles the committed lockfile against it, on all three runners.
  • Hardening found while verifying the above: .gwm.toml values no longer reach the terminal with their control bytes intact (#473), placeholder expansion is single pass so an expansion is a value rather than more template (#494), a failed gwm create no longer leaves the branch it created behind (#487), and a free-form name is validated against Windows path rules on every platform (#475).

v1.5.0: multi-forge (GitLab)

The v1.5.0 line puts a Forge trait behind the network layer and ships a second backend for it. Consolidated notes: changelogs/1.5.0.md. Key additions:

  • A Forge trait and a GitLab (glab) backend (#419): issue and pull/merge request lookups go through an abstraction with two implementations, gh and glab. Worktrees, bootstrap, branch naming and the branch.<name>.gwm-* link storage are unchanged and forge-neutral, so nothing about a repo becomes forge-specific on disk. Full page: GitLab (multi-forge).
  • Explicit forge selection (#419): a new forge = "github" | "gitlab" key in .gwm.toml. Omitted, the forge is inferred from the origin host, but only on the vendors' own domains (github.com, ghe.com, gitlab.com): a self-hosted instance lives on an arbitrary domain, so the explicit key is how you name the backend, and it always wins over inference.
  • Authorising a self-hosted host is a separate decision (#419): a host gwm does not recognise is not assumed to be GitHub, because guessing would send an authenticated call, and whatever token the environment carries, to whatever host a cloned repo's origin named. Authorisation comes from a new [forge_hosts] table read from your own global config, or from approving the repo's .gwm.toml in the TOFU trust ledger. New gwm trust add approves a repo without running anything, since the existing prompt only fires when there is a bootstrap surface to execute.
  • GitLab specifics absorbed at the parse boundary (#419): iid as the user-visible number, nested subgroup paths, the /-/ URL infix, date-only milestone due dates, project labels separated from inherited group labels, and a pipeline-to-CI-state map in which an unrecognised status is reported as unknown and never aggregates to a green CI. $GWM_GLAB overrides the binary, mirroring $GWM_GH.
  • The trust ledger keys on the repo again, not on its host (#463): the new forge gate built its half of the (origin, sha256) key from scheme + host only, which shared one approval across every repo on that host whose .gwm.toml hashed identically. All four call sites now go through one helper.

v1.4.0: help overlay completeness + TUI polish

The v1.4.0 line closes the #436 / #437 / #438 TUI-polish trio and completes the ? help overlay. Consolidated notes: changelogs/1.4.0.md. Key additions:

  • Complete help overlay (#453): the ? overlay documents every key context: one section per modal overlay, each verb resolved live against [tui.keys.modal.<context>] so rebinds show through, with a per-section completeness guard extending the #334 one to every modal verb. The statusline which-key was re-audited (exec / agents joined the worktrees footer), and the review loop hardened a reserved-typing contract across every input sub-mode: keys a text input legitimately consumes cannot be bound to modal verbs (rejected at config time), and an unbound modified Backspace still erases.
  • CI checks overlay (#436): C (or c while the status pane holds focus) lists every check of the linked PR's statusCheckRollup: state icon per row, owning workflow + run duration in a muted detail column, j / k selection, Enter opens the check's details URL, / filters, f re-fetches in place; verbs rebindable under [tui.keys.modal.ci_checks].
  • Working Tree scroll (#437): with the status pane focused, J / K (rebindable wt_scroll_down / wt_scroll_up) scroll the file tree independently, clamped to the granted viewport; the offset resets on worktree navigation and the commits ↔ stashes toggle.
  • Responsive sidebar heights (#438): the Agents / Working Tree / Recent Commits sections share the column through a pure layout solver: natural heights while everything fits, guaranteed floors on short terminals (7 lines for Working Tree, 5 for Recent Commits), proportional split of the remainder, the non-scrollable Agents pane never clipped, and a scrollbar on an overflowing Working Tree.
  • Housekeeping: a project logo (dark / light SVG pair heading the README), persist-credentials: false on every read-only workflow checkout (#433), and the red-on-every-release winget-publish job removed in favour of the manual komac recipe (#448).

v1.3.0: agent sessions + the Windows daemon

The v1.3.0 line makes gwm aware of the AI-agent sessions working in its worktrees, and finishes the daemon's platform story. Consolidated notes: changelogs/1.3.0.md. Key additions:

  • Agent session pane (#408): gwm detects AI-agent coding sessions (Claude Code, Codex, opencode, Mistral Vibe) per worktree by reading each tool's on-disk session artefacts (std::fs only, no process scanning, identical behaviour on Linux / macOS / Windows). Surfaced as an AGENT column in the worktree table, an Agent: summary line plus a pinned-sessions pane in the sidebar, an interactive detail overlay on a (select / pin / unpin, rebindable under [tui.keys.modal.detail]), an additive experimental-tier agents field on the JSON / daemon rows (SCHEMA_VERSION stays 1), and an active-agent segment in gwm statusline.
  • gwm agents + manual pinning (#408): the same detection as a CLI surface: gwm agents lists sessions per worktree (human or --format=json), the plain gwm list table gains the AGENT column, and gwm agents attach <worktree> <session-id> / detach pin a session when the recorded directory is not enough. Sessions carry a human-readable name when their artefacts have one.
  • Windows named pipe transport for the daemon (#439): gwm daemon and gwm statusline now work on Windows: the daemon binds an owner-only named pipe under \\.\pipe\ with the same JSON-RPC surface, DoS guards and graceful degradation as the unix socket, and the statusline client rides it. The docs' Unix-only caveats are lifted.
  • Process-level liveness for Claude Code sessions (#441): on Unix, a Claude Code session whose recorded PID is gone drops to idle immediately instead of riding the 5-minute activity window.
  • Hardening + fixes (#429 / #430 / #440 / #445): release-workflow checkouts only persist credentials when they push, the silently-failing AUR publish job is gone, gwm clean --yes tolerates ENOTEMPTY races from concurrent watchers, and the agent overlay's attach prompt keeps a fixed frame while typing.

v1.0.0: the 1.0 commitment

The post-rc.4 stable delta completes the 1.0 commitment: frozen, versioned machine contracts plus the additive features that freeze anticipated. Consolidated notes: changelogs/1.0.0.md. Key additions:

  • Frozen, versioned machine contracts (#317): tests/contract_tests.rs pins SCHEMA_VERSION = 1, the daemon schema_version, and the four machine surfaces (--format=json on list / doctor / path, plus status --json) against baselines; the per-field tiers live in docs/schema/README.md.
  • Published stability & compatibility policy (#318): what's covered by SemVer versus free to change in a minor / patch, EN + FR (Stability & compatibility).
  • Frozen exec / clean surface (#319): the gwm exec / gwm clean flag surface is locked for the 1.0 line (all non-frozen extensions deferred as additive), pinned by a contract_tests canary.
  • Named [exec] / [clean] profiles + bounded --jobs (#324): reusable command / reclaim profiles selected with --profile, plus opt-in bounded parallelism (--jobs) for the fan-out.
  • --workspace fan-out for gwm exec / gwm clean (#326): run the fleet chores across every repo one level below a workspace root, not just the current repo's worktrees.
  • TUI exec / clean overlays (#325): x runs an [exec] profile and X a [clean] profile from inside the TUI, with a live output overlay.
  • Help-overlay + overlay polish (#334): the ? help overlay now documents every action (pinned by a completeness test), plus assorted overlay refinements.

preceding TUI cycle: v0.9.0

The v0.9.0 line built on the v0.8.0 configurability cycle and added the TUI train:

  • Full theme-role coverage (#170 / #210 / #211 / #214): the resolved [theme] is threaded through every TUI render site, with dedicated name, path, staged, modified, and untracked roles. Defaults are preserved and pinned by tests/tui_theme_audit_tests.rs.
  • git2 0.21 source migration (#169): the breaking accessor API change from the deferred v0.8.0 bump is now handled in source, pruning the old url transitive tree.
  • TUI statusbar, layout, and modal polish (#217 / #220 / #222 / #224): contextual statusbar, animated GitHub-fetch spinner, direct pane-focus keys (1 / 2), stacked-by-default sidebar, wider overlays, and refined create/link/delete/Issue-PR modals.
  • Async-task spine (#231 / #255 / #258 / #256): worktree refresh, GitHub fetch, sync (S), and bootstrap (b) now run off-thread with coalescing, late-result drop, and statusbar progress instead of freezing the event loop.
  • Pane-key family 1 / 2 / 3 / 4 (#226 / #232): direct focus for Worktrees / Status, a Command Logs overlay, and a Configuration panel showing the resolved config with repo / user / default source attribution.
  • Docs key (.) (#233): open the documentation from inside the TUI; rebindable as open_docs.

The full v0.9.0 release notes live at changelogs/0.9.0.md. The MSRV was raised to 1.86 in the v0.10.0 line by the PTY overlay's portable-pty / tui-term dependencies (tui-term declares rust-version = "1.86.0"); the current floor is stated at the top of this page.

v0.10.0: Settings editability + TUI enrichment

The first theme of v0.10.0 (originally cut as v0.10.0-rc.1, 2026-06-10) is Settings editability + TUI enrichment. RC notes: changelogs/pre-releases/0.10.0-rc.1.md. Key additions:

  • Editable Settings panel (#279): category tabs (Theme / Worktree / TUI / All), per-project ↔ global layer selector (L), live-persist into TOML with on-the-fly apply; herdr-style scrollbar on all scrollable modals.
  • Working Tree colour-coded counts (#287): nerdfont created / modified / deleted footer counts + matching row recolouring; Status pane Diff +ins -del vs base (three-dot semantics).
  • Issue/PR enrichment (#283 / #285): ●/● pastilles in the worktree table, nerdfont state-chip badges, cached GitHub state that survives restarts, initial startup refresh, periodic [tui].auto_refresh_secs auto-refresh.
  • Async loaders (#257 / #276 / #267): reusable LoaderWidget, async create-worktree and quit-wait on the spine (delete, create, and quit no longer block the render loop).

v0.10.0: overlays, workspace, JSON API, and the GitHub inbound half

The second theme of v0.10.0 (the post-rc.1 trains, rc.2 / rc.3) is the larger feature batch: embedded overlays, multi-repo workspace mode, the JSON API + daemon and its first consumers, config presets, fleet chores, and the TOFU trust ledger. Per-RC deltas live under changelogs/pre-releases/. Key additions:

  • Embedded PTY overlays (#35): l / L open lazygit, r / R open the configured review tool, and o / O open a native $SHELL session inside the TUI (no alternate-screen swap; Esc closes), powered by portable-pty + tui-term. This is what raised the project MSRV to 1.86.
  • TUI keymap redesign (#290): unified list-view bindings (p / P pull / push, c edit-worktree, e exit-to-worktree, y / w yank, t mux pane, h / H macros) plus user-defined [tui.macro1] / [tui.macro2]. Pre-#290 slugs still load via backward-compat aliases.
  • Rebindable contextual modal keys (#219 / #294): every modal verb is remappable under nested [tui.keys.modal.<context>] tables, and the Settings panel gains a Keys tab to edit every binding live (keystroke capture + validated write-back).
  • Multi-repo workspace mode (#36): gwm --workspace ~/Projects (and bare-gwm auto-detect) opens the TUI across every git repo one level below a root with a REPO column; gwm list --workspace prints the merged table; gwm create --repo <name> picks the target.
  • Config presets (#37): gwm init --preset <name> seeds an opinionated .gwm.toml for laravel / node / nuxt / rust / go / python-uv / generic; --list-presets enumerates them, --show prints the resolved TOML without writing.
  • JSON API + daemon (#38): --format=json on gwm list / doctor / path (stable schemas under docs/schema/), and gwm daemon, a JSON-RPC 2.0 server over a unix socket with list / doctor / path methods plus a subscribe push stream, for editor / statusbar integration.
  • Status sidebar (#299 / #300): the Issue/PR section surfaces the linked PR's overall CI state (passing / failing / running, derived from the already-fetched rollup), and the Working Tree pane renders git status as a git-coloured nerd-font file-explorer tree.
  • Inbound GitHub: gwm review <PR#> (#308): materialise an existing GitHub PR (cross-fork aware) into an isolated worktree by fetching refs/pull/<N>/head and creating a review/pr-<N>-… branch, so you can check out a teammate's PR to review / test / fix it. Safe-by-default: bootstrap and lifecycle hooks are off unless you pass --bootstrap (the PR's code is untrusted input); --name overrides the local branch name. This closes the inbound half of the worktree⇄GitHub loop and turns the CI indicator (#299) into a complete review workflow.
  • First daemon consumer: gwm statusline (#309): a dependency-free one-line worktree summary for shell prompts (tmux / starship / zsh), the first real client of gwm daemon (#38). Prints once by default; --watch rides the subscribe push stream and reprints on every change; --socket overrides the socket path. Degrades to a blank line when no daemon is running.
  • Fleet chores across worktrees (#313): gwm exec [<slug>...] -- <cmd> runs a command in each worktree sequentially (every non-main worktree by default, or the slugs listed before --; everything after -- is forwarded verbatim), prints a per-worktree ✓ / ✗ rollup, and exits non-zero if any failed. gwm clean [<slug>...] [--yes] reports, and with --yes reclaims, heavy build artifacts (target/, node_modules/, dist/, build/); --yes only deletes directories git treats as ignored, so a tracked dist/ or build/ is skipped.
  • TOFU trust ledger on .gwm.toml (#95): the first gwm create / gwm bootstrap against a repo prints the bootstrap surface and prompts before running it; an approval is recorded in $XDG_CONFIG_HOME/gwm/trust.toml keyed on (origin URL, sha256 of .gwm.toml), and any byte change re-prompts. For non-interactive environments, the global --allow-bootstrap flag (or GWM_ALLOW_BOOTSTRAP=1) bypasses the prompt and --deny-bootstrap refuses bootstrap outright. Inspect and manage the ledger with gwm trust list / gwm trust revoke <origin> / gwm trust show.

previous stable cycle: v0.8.0

For reference, v0.8.0 promoted the large configurability and personalisation cycle:

  • Release hardening, Windows CI, CLI aliases, and Gitmoji tooling (v0.8.0-rc.1, #146 / #147 / #112 / #85 / #86): reliable release publishing, [Unreleased] duplicate guard, windows-latest in the test matrix, [aliases], gwm commit-prefix, gwm types --gitmoji, and an opt-in commit-msg hook.
  • Safety daily (v0.8.0-rc.2, #29 / #31): --dry-run on gwm remove / gwm prune, plus gwm undo / gwm history backed by $XDG_DATA_HOME/gwm/history.toml.
  • Config CLI, lifecycle hooks, GitHub templates, and TUI personalisation (v0.8.0-rc.3, #88 / #89 / #83 / #84 / #87 / #32 / #33 / #34): gwm config, [hooks.*], gwm new, gwm pr, remappable [tui.keys], the : command palette, role-based [theme] presets, and sidebar stashes mode.
  • Quick wins (v0.8.0-rc.4, #24 / #27): gwm sync [<pattern>] [--merge] and cargo-binstall support.
  • Global config and chrome polish (v0.8.0-rc.5, #190 / #188 / #185 / #187 / #180 / #179 / #181 / #175): user-level ~/.config/gwm/config.toml, responsive sidebar, claude-dark, modal polish, single-line statusline, working-tree colourisation, ephemeral PR auto-detection, and {repo_path} / {repo_parent} placeholders.

The full v0.8.0 notes live at changelogs/0.8.0.md.

what's next

The lot below shipped in the v1.7.0 cut (2026-08-12), in the order the root ROADMAP.md lists it. The order is not by size: each step sits where it is cheapest to land, which usually means ahead of the thing that would otherwise have to be reopened to accommodate it.

  • Bulk selection (#484 ✅, merged into dev, awaiting the cut): Space marks a row and d deletes the marked set behind one confirm, with gwm remove a b c as the non-interactive half. It went first because it changes what "the current row" means, and the two features behind it both open on the current row. Only d reads the mark set, by design: every other verb keeps acting on the cursor row, and the pane footer carries the count so a live selection is never invisible. cycle_sidebar_layout moved off Space onto z to make room.

  • Symfony preset (#392 ✅): a seventh gwm init --preset, merged and waiting for the cut. Modelled on the Laravel one but not a copy of it: Symfony commits .env and gitignores .env.local, the reverse of Laravel, so the preset copies the local override and seeds its guard from the committed .env. It was queued here as the one item sequenced against nothing, which held for the merge order but not for its reach: every stack preset puts its commands in [hooks.*], and two gwm doctor checks read [[bootstrap.command]] only, so the preset arrived with a clean report about a file the doctor had barely read. Fixed alongside it.

  • Rich PR / Issue view (#420 ✅): metadata, checks, reviews and comments in the TUI. It was deliberately queued behind multi-forge so it is born speaking to both forges rather than being rewritten later. I opens it on the description, the metadata, the CI rollup, the reviews and the conversation, at no extra request: the fields ride along in the call gwm already made for the rollup. The comments anchored to a diff hunk followed in #528: GraphQL-only, so they landed as a second transport rather than a wider field list, on a request the view fires for itself so gwm status does not pay for it.

  • Per-worktree notes (#515 ✅): gwm knows the branch, the linked issue, the diff and the agent session, but nothing of where you were. A note attached to a worktree, editable from the TUI, closes the gap between holding eight worktrees and remembering what each one was for. N opens it in an editable modal rather than suspending the TUI for $EDITOR, since a note is usually three lines written between two thoughts; Ctrl+e inside still hands the file to the editor and reloads what it wrote. Storage is a plain markdown file under .git/gwm/notes/ in the main checkout, which survives gwm remove and needs no sweeper, since "the branch is gone" is a question git answers in one call.

  • Container execution (#421 ✅): a [container] block on an exec profile. It left the deferred pile because the comparison page now sits behind it, and container execution is a column in that table. The cost is not the wrapper but the mount: a linked worktree's .git is a file holding an absolute host path, so mounting the worktree alone yields a container in which git does not answer, which is a bug the reference implementation ships. gwm mirrors host paths and mounts the main checkout's gitdir alongside. Three fields rather than the reference's nine (image, runtime, extra_args), because -w / -e / -v are already docker run flags; no interactive, since a TTY per container means nothing across a fan-out; and profile-only, because the inline gwm exec -- <cmd> is the frozen 1.0 surface.

  • Comparison page (#422 ✅): gwm against gwq and lazyworktree, shipped at Comparison in English and French. The issue's premise did not survive the re-read it asked for: it listed agent sessions, container execution, GitLab and per-worktree metadata as lazyworktree's lead, and gwm now has all four, so the page reports parity there instead of a gap. Re-measured on 2026-08-12, the star spread narrowed from 30 / 270 / 456 to 126 / 281 / 461, and neither competitor carries a git binding in its go.mod, which turns the vendored-libgit2 difference into something checkable rather than claimed. What stays ahead is named: lazyworktree's rich worktree metadata, its per-worktree .wt hooks, and seven more months of use.

  • Docs in German, Spanish and Japanese (#522): five locales instead of two, last in the lot and after the comparison page. The audience data does not ask for it, so it is a forward bet, and each language carries a different one: German is the largest non-English bloc already reading the project, Spanish buys reach that does not exist yet, and Japanese is the one with a competitive argument, since the incumbent gwm is positioned against is Japanese-authored. Roughly 155,000 words, which is worth naming before it is scheduled.

Three launch prerequisites are tracked alongside the lot rather than inside it: re-recording the demo GIF (#523), the 26 documentation pages out of 41 that carry no image (#524), and the directory and search-index submissions (#525).

The naming-flexibility line (#415 through #418, plus #475 and #479 to #482) shipped in v1.6.0 and is closed. Publishing the documentation (#423) shipped in v1.6.1.

For fresh work, start from the issue tracker:

how to contribute

  1. Pick an issue or open a new one with --label enhancement / --label bug describing the scope.
  2. gwm create <type> <issue> <slug> to spin up an isolated worktree (the issue auto-links itself; see GitHub linking).
  3. Follow the conventions in CONTRIBUTING.md. See Contributing for the docs-site version.
  4. Open a PR targeting dev. Stable releases ship via a dev → main merge PR following the convention 🔀 chore(release): merge dev → main for vX.Y.Z.