diff --git a/CHANGELOG.md b/CHANGELOG.md index f201512e..45e9cfca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,56 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this ## [Unreleased] +This release turns Dispatch from a TUI-only tool into a scriptable CLI: most session operations are now available as non-interactive commands with JSON output, and the TUI gains a git status overlay plus several navigation and organization features. + ### Added -- **Configurable auto-refresh** — set `auto_refresh_seconds` (also in the settings panel) to tune the session-list poll interval, or set it to `0` to turn polling off and refresh only with `r` or reindex -- **Machine-readable doctor output** — `dispatch doctor --json` prints diagnostics as a single JSON object so scripts and CI can parse them instead of scraping text -- **Search query argument** — pass a search string on the command line (`dispatch auth` or `dispatch fix auth bug`) to launch the TUI with the search box pre-filled and the list already filtered + +#### CLI commands +- **`dispatch open`** — resume a session by ID, alias, or short ID prefix. Supports `--last` (most recent), `--print` (print the resume command without launching), `--stdin` (batch resume piped IDs), `--mode` (inplace, tab, window, pane), scoped resume (`--repo`, `--branch`, `--folder`, `--current` to auto-detect from the working directory), and per-launch `--agent`, `--model`, and `--yolo` overrides +- **`dispatch new`** — start a fresh session from the CLI in the current or a given directory, with the same per-launch overrides as `open` +- **`dispatch stats`** — session totals and breakdowns by repository, branch, and host type, with `--json`, `--csv`, `--calendar` (activity heatmap), `--top`, and date/scope filters +- **`dispatch search`** — non-interactive session search with `--json`, `--table`, and `--ids` / `--format ids` output, `--deep` search, and repo/branch/date/limit filters +- **`dispatch export`** — save a session as Markdown, JSON, or HTML, with `--redact` (mask secrets), `--stdout`, and batch export by `--repo`, `--branch`, or `--query` +- **`dispatch config`** — `list`, `get`, `set`, `unset` (reset to default), `edit` (open in your editor), and `path` +- **`dispatch tags`** — list every tag in use with per-tag session counts +- **`dispatch tag `** — add, remove, or set tags on a session (`--add`, `--remove`, `--set`, `--json`) +- **`dispatch notes`** — get, set, or clear a session's local notes +- **`dispatch views`** — list named views and switch the active view +- **`dispatch aliases`** — list every session alias +- **`dispatch compare`** — compare two sessions side by side (metadata, files, refs), with `--json` +- **`dispatch info `** — print a concise summary of one session +- **`dispatch watch`** — monitor attention state across sessions; stream transitions or take a one-shot `--once` snapshot, with `--json` and `--interval` +- **`dispatch prune`** — report and remove stale config entries for sessions that no longer exist (`--apply`, `--json`) +- **`dispatch man`** — generate a roff man page +- **`dispatch completion`** — bash, zsh, fish, and PowerShell scripts, with dynamic completion of session aliases and config keys +- **`dispatch doctor --json`** — machine-readable diagnostics; doctor also reports the detected Copilot CLI version and stored session count + +#### TUI +- **Git status overlay** (`i`) — shows the git status of the folder a session is mapped to: current branch and upstream, push/pull stats (commits ahead to push, behind to pull), working-tree counts (staged, modified, untracked, deleted, conflicts), and a scrollable changed-file list. The same push/pull stats appear inline on each session row and in the preview pane +- **Open linked reference** (`b`) — open a session's linked pull request, issue, or commit on github.com +- **Frecency sort** — rank sessions by a blend of launch frequency and recency +- **Session tags** (`#`) — attach comma-separated tags and filter with the `tag:` search token +- **Session aliases** (`A`) — give a session a short alias and resume it with `dispatch open ` +- **Fullscreen preview zoom** (`z`) — view the preview pane fullscreen +- **Configurable list columns** — choose which optional columns (repo, folder, turns, host) appear in the session list +- **Jump navigation** — `g` / `Home` jump to top, `G` / `End` jump to bottom +- **Date search tokens** — `after:` and `before:` narrow the list by session activity date +- **Waiting notifications** — optional desktop notification when a session enters the waiting state +- **Configurable keybindings** — remap any key via `config.json` +- **Split-pane launch** — open sessions in a tmux split when running inside tmux - **Open working directory** (`O`) — open the selected session's working directory in the system file manager (Explorer, Finder, or the Linux file manager) -- **Bulk hide and favorite** — with sessions marked via `Space`, `h` and `*` now apply to the whole selection instead of just the cursor session +- **Bulk hide and favorite** — with sessions marked via `Space`, `h` and `*` apply to the whole selection instead of just the cursor session +- **Search query argument** — pass a search string on the command line (`dispatch auth` or `dispatch fix auth bug`) to launch the TUI with the search box pre-filled and the list already filtered + +#### Configuration +- **`DISPATCH_CONFIG`** — environment variable to override the config file path +- **Configurable auto-refresh** — set `auto_refresh_seconds` (also in the settings panel) to tune the session-list poll interval, or set it to `0` to turn polling off and refresh only with `r` or reindex + +### Changed +- Upgraded Go and website dependencies to latest + +### Fixed +- Hardened the swarm CLI commands: `open` scoped resume now picks the most recently active match, `open --current` errors instead of resuming an unrelated session when nothing can be detected, `watch` counts interrupted sessions separately, `stats --csv` neutralizes spreadsheet formula injection, `prune` refuses to apply against an empty store, and `tag` resolves ID prefixes ## [v0.13.0] — 2026-06-30 diff --git a/README.md b/README.md index f5ce0a1a..bf2de97f 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Dispatch reads your local Copilot CLI session store and presents every past sess - **Copy resume command** (`Y`) — copy the selected session's full resume command to the system clipboard. With a multi-select active, copies one resume command per selected session, one per line - **Open working directory** (`O`) — open the selected session's working directory in the system file manager (Explorer on Windows, Finder on macOS, the default file manager on Linux) - **Open linked reference** (`b`) — open the selected session's linked pull request, issue, or commit on github.com in your browser. Picks the pull request first, then the issue, then the commit +- **Git status overlay** (`i`) — show the git status of the folder the selected session is mapped to: current branch and upstream, push/pull stats (commits ahead to push, behind to pull), working-tree counts (staged, modified, untracked, deleted, conflicts), and a scrollable list of changed files. The same push/pull stats also appear inline on each session row and in the preview pane's git section - **Four launch modes** (`Enter` / `t` / `w` / `e`) — in-place, new tab, new window, split pane (Windows Terminal, or tmux when running inside a tmux session) with per-session overrides - **Multi-session open** (`Space` / `L` / `a` / `d`) — select multiple sessions with Space, launch all at once with L, select/deselect all with a/d. Shift+↑/↓ for range selection, Ctrl+click and Shift+click for mouse selection. With a selection active, `h` (hide), `*` (favorite), and `Y` (copy resume command) apply to every selected session at once - **Attention indicators** — colored dots showing real-time session status: working (blue, executing tools), thinking (cyan, generating response), compacting (magenta, context compaction), waiting (purple), active (green), stale (yellow), interrupted (orange ⚡), idle (gray). Jump to next waiting session with `n`, resume interrupted sessions with `R`, filter by status with `!` @@ -338,6 +339,17 @@ dispatch compare 0a1b2c3d 9f8e7d6c --json The output shows metadata differences (summary, branch, turn count), files that appear in only one session, ref differences, and checkpoint title lists. Use `--json` for machine-readable output. Session IDs accept the same prefix shorthand as `open` and `export`. +### Info + +Print a concise summary of one session with `dispatch info `: + +```sh +dispatch info 0a1b2c3d +dispatch info 0a1b2c3d --json +``` + +The summary covers the session's repository, branch, working directory, host type, turn and file counts, timestamps, tags, alias, and any linked refs. Use `--json` for scripting. The session ID accepts the same prefix shorthand as `open`. + ### Aliases List every session alias with `dispatch aliases`: @@ -414,6 +426,17 @@ The query can be passed as a positional argument or with `--query`. Filters mirr Each JSON result includes `id`, `summary`, `cwd`, `repository`, `branch`, `created_at`, `updated_at`, `turn_count`, and `file_count`. No JSON matches prints `[]`; no ID matches prints nothing. Both exit 0. Invalid flags or an unreadable store exit non-zero with a message on stderr. +### Man + +Generate a roff man page for `dispatch` with `dispatch man` and write it wherever your system keeps manual pages: + +```sh +dispatch man > dispatch.1 +man ./dispatch.1 +``` + +The page targets section 1 (user commands) and mirrors the built-in usage: commands, flags, environment variables, and examples. It takes no flags and writes to standard output. + ### Key Bindings #### Navigation @@ -503,13 +526,29 @@ Dates accept `YYYY-MM-DD` or full RFC3339 timestamps (e.g. `after:2024-01-15` or | `v` | View plan in preview pane | | `o` | Toggle conversation sort order (oldest/newest first) | | `c` | Copy session ID to clipboard | -| `O` | Open session working directory in file manager | -| `g` | Open linked PR, issue, or commit in browser | | `Y` | Copy resume command to clipboard | | `PgUp` / `PgDn` | Scroll preview | | `r` | Refresh session store | | `,` | Open settings panel | +#### Session Actions + +| Key | Action | +|---|---| +| `i` | Git status overlay for the selected session's folder | +| `b` | Open linked PR, issue, or commit in browser | +| `O` | Open working directory in file manager | +| `F` | Open a file the session touched | +| `D` | Compare two selected sessions | +| `T` | Activity timeline in the preview pane | +| `V` | Switch named view | +| `X` | Export selected sessions to Markdown | +| `m` | Edit note on current session | +| `C` | Copy working directory path to clipboard | +| `y` | Copy preview text to clipboard | +| `x` | Expand or collapse all groups | +| `:` | Open the command palette | + #### Time Range (when search is not focused) | Key | Action | diff --git a/internal/tui/screenshot.go b/internal/tui/screenshot.go index bed935c0..2ec15d66 100644 --- a/internal/tui/screenshot.go +++ b/internal/tui/screenshot.go @@ -646,6 +646,37 @@ func (c *captureCtx) captureFeatures(subDir string) []Screenshot { addOverlay("cmd-palette", m) } + // ── Git status overlay ─────────────────────────────────────────── + { + m := newBase() + m.gitStatusView.SetStatus(platform.GitStatus{ + Dir: "/home/me/code/dispatch", + Exists: true, + IsRepo: true, + Branch: "feature/git-status", + Upstream: "origin/feature/git-status", + HasUpstream: true, + Ahead: 2, + Behind: 1, + Staged: 1, + Modified: 3, + Untracked: 2, + Deleted: 1, + Files: []platform.GitFileStatus{ + {Code: "M ", Path: "internal/tui/model.go"}, + {Code: " M", Path: "internal/tui/components/gitstatusview.go"}, + {Code: " M", Path: "internal/platform/gitstate.go"}, + {Code: " D", Path: "internal/tui/old_preview.go"}, + {Code: "??", Path: "docs/specs/git-status/spec.md"}, + {Code: "??", Path: "docs/specs/git-status/test-plan.md"}, + }, + }) + m.gitStatusView.SetSize(m.width, m.height) + m.state = stateGitStatusView + m.recalcLayout() + addOverlay("git-status", m) + } + return shots } diff --git a/web/public/screenshots/campbell/git-status.png b/web/public/screenshots/campbell/git-status.png new file mode 100644 index 00000000..d87e5ace Binary files /dev/null and b/web/public/screenshots/campbell/git-status.png differ diff --git a/web/public/screenshots/dispatch-dark/git-status.png b/web/public/screenshots/dispatch-dark/git-status.png new file mode 100644 index 00000000..d5b54534 Binary files /dev/null and b/web/public/screenshots/dispatch-dark/git-status.png differ diff --git a/web/public/screenshots/dispatch-light/git-status.png b/web/public/screenshots/dispatch-light/git-status.png new file mode 100644 index 00000000..3a424234 Binary files /dev/null and b/web/public/screenshots/dispatch-light/git-status.png differ diff --git a/web/public/screenshots/one-half-dark/git-status.png b/web/public/screenshots/one-half-dark/git-status.png new file mode 100644 index 00000000..61df9faf Binary files /dev/null and b/web/public/screenshots/one-half-dark/git-status.png differ diff --git a/web/public/screenshots/one-half-light/git-status.png b/web/public/screenshots/one-half-light/git-status.png new file mode 100644 index 00000000..b55fb8e6 Binary files /dev/null and b/web/public/screenshots/one-half-light/git-status.png differ diff --git a/web/src/pages/cli.astro b/web/src/pages/cli.astro index 31ef493f..a84b9bd1 100644 --- a/web/src/pages/cli.astro +++ b/web/src/pages/cli.astro @@ -24,9 +24,27 @@ import CliTable from '../components/CliTable.astro';

Commands

', description: 'Resume a session by ID, alias, or short prefix. Flags: --last, --print, --stdin, --mode, --repo, --branch, --folder, --current, --agent, --model, --yolo.' }, + { name: 'new [dir]', description: 'Start a new session from the CLI, with --mode/--agent/--model/--yolo overrides.' }, + { name: 'search [query]', description: 'Non-interactive session search with --json, --table, --ids, --deep, and filters.' }, + { name: 'stats', description: 'Session totals and breakdowns, with --json, --csv, --calendar, --top.' }, + { name: 'export ', description: 'Export a session as Markdown, JSON, or HTML, with --redact, --stdout, and batch by --repo/--branch/--query.' }, + { name: 'info ', description: 'Print a concise summary of one session.' }, + { name: 'compare ', description: 'Compare two sessions side by side, with --json.' }, + { name: 'tags', description: 'List all tags with per-tag session counts.' }, + { name: 'tag ', description: 'Add, remove, or set tags on a session (--add, --remove, --set, --json).' }, + { name: 'notes', description: "Get, set, or clear a session's local notes." }, + { name: 'views', description: 'List named views and switch the active view.' }, + { name: 'aliases', description: 'List all session aliases.' }, + { name: 'watch', description: 'Monitor attention state across sessions (--once, --json, --interval).' }, + { name: 'prune', description: 'Report and remove stale config entries (--apply, --json).' }, + { name: 'config', description: 'Read and set preferences (list, get, set, unset, edit, path).' }, + { name: 'doctor', description: 'Print setup diagnostics, with --json.' }, + { name: 'completion ', description: 'Generate a completion script (bash, zsh, fish, powershell).' }, + { name: 'man', description: 'Generate a roff man page.' }, { name: 'update', description: 'Check GitHub Releases for a newer version and upgrade in-place.' }, + { name: 'version', description: 'Print the version number and exit.' }, + { name: 'help', description: 'Show usage information and exit.' }, ]} />
@@ -46,6 +64,7 @@ import CliTable from '../components/CliTable.astro'; @@ -55,6 +74,15 @@ import CliTable from '../components/CliTable.astro';
{`# Launch the TUI
 dispatch
 
+# Resume the most recent session
+dispatch open --last
+
+# Search sessions in table form
+dispatch search auth --table
+
+# Print stats as JSON
+dispatch stats --json
+
 # Check for updates
 dispatch update
 
@@ -62,14 +90,7 @@ dispatch update
 dispatch --demo
 
 # Use a custom database
-DISPATCH_DB=~/my-sessions.db dispatch
-
-# Enable debug logging
-DISPATCH_LOG=/tmp/dispatch.log dispatch
-
-# Reset config and reindex
-dispatch --clear-cache
-dispatch --reindex`}
+DISPATCH_DB=~/my-sessions.db dispatch`} diff --git a/web/src/pages/features.astro b/web/src/pages/features.astro index 7d7a3617..cb392f7a 100644 --- a/web/src/pages/features.astro +++ b/web/src/pages/features.astro @@ -682,6 +682,34 @@ import Carousel from '../components/Carousel.astro'; + +
+
+
+

Git Status Overlay

+

+ Press i on any session to see the full Git status of the + folder it is mapped to, without leaving the TUI. Git commands run + under a bounded timeout so the interface never blocks. +

+
    +
  • Current branch and upstream ref
  • +
  • Push/pull stats — commits ahead to push and behind to pull
  • +
  • Working-tree counts — staged, modified, untracked, deleted, and conflicts
  • +
  • A scrollable changed-file list with status codes
  • +
  • c copies a plain-text summary; Esc closes the overlay
  • +
+

+ The same push/pull stats also appear inline on each session row and + in the preview pane's Git section. +

+
+
+ +
+
+
+
diff --git a/web/src/pages/keys.astro b/web/src/pages/keys.astro index e8cb6974..682173dc 100644 --- a/web/src/pages/keys.astro +++ b/web/src/pages/keys.astro @@ -20,6 +20,8 @@ import KeyTable from '../components/KeyTable.astro'; @@ -31,9 +33,7 @@ import KeyTable from '../components/KeyTable.astro'; { keys: 'Enter', action: 'Launch selected session (or toggle folder)' }, { keys: 'w', action: 'Launch in new window' }, { keys: 't', action: 'Launch in new tab' }, - { keys: 'e', action: 'Launch in split pane (Windows Terminal)' }, - { keys: 'h', action: 'Hide/unhide current session' }, - { keys: 'H', action: 'Toggle visibility of hidden sessions' }, + { keys: 'e', action: 'Launch in split pane (Windows Terminal, or tmux inside a tmux session)' }, ]} />
@@ -54,7 +54,7 @@ import KeyTable from '../components/KeyTable.astro';

Search & Filter

@@ -65,18 +65,40 @@ import KeyTable from '../components/KeyTable.astro'; { keys: 's', action: 'Cycle sort field' }, { keys: 'S', action: 'Toggle sort direction' }, { keys: 'Tab', action: 'Cycle grouping mode' }, + { keys: 'Shift+Tab', action: 'Reverse grouping order' }, { keys: 'p', action: 'Toggle preview panel' }, { keys: 'P', action: 'Cycle preview position (right → bottom → left → top)' }, + { keys: 'z', action: 'Toggle fullscreen preview' }, { keys: 'v', action: 'View plan in preview pane' }, { keys: 'o', action: 'Toggle conversation sort order (oldest/newest first)' }, - { keys: 'c', action: 'Copy session ID to clipboard' }, + { keys: 'x', action: 'Expand or collapse all groups' }, { keys: 'PgUp', action: 'Scroll preview up' }, { keys: 'PgDn', action: 'Scroll preview down' }, - { keys: 'r', action: 'Reindex sessions' }, + { keys: 'r', action: 'Refresh session store' }, { keys: ',', action: 'Open settings panel' }, ]} /> +
+

Session Actions

+ +
+

Time Range

@@ -165,6 +189,7 @@ import KeyTable from '../components/KeyTable.astro';
  • Multi-Select
  • Search & Filter
  • View & Sorting
  • +
  • Session Actions
  • Time Range
  • Attention & Status
  • Settings