tasktree-manager 2.10.0__tar.gz → 2.11.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/CHANGELOG.md +15 -0
  2. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/PKG-INFO +1 -1
  3. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/README.md +24 -10
  4. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/configuration.md +63 -14
  5. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/troubleshooting.md +3 -3
  6. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/user-guide.md +52 -13
  7. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/pyproject.toml +1 -1
  8. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/_version.py +2 -2
  9. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/app.py +287 -58
  10. tasktree_manager-2.11.1/tasktree_manager/cli.py +431 -0
  11. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/commands.py +10 -2
  12. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/__init__.py +4 -0
  13. tasktree_manager-2.11.1/tasktree_manager/services/agent_sessions.py +157 -0
  14. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/config.py +91 -23
  15. tasktree_manager-2.11.1/tasktree_manager/services/forge.py +349 -0
  16. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/git_ops.py +56 -11
  17. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/models.py +16 -2
  18. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/task_manager.py +117 -7
  19. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/create_modal.py +55 -3
  20. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/worktree_list.py +78 -25
  21. tasktree_manager-2.11.1/tests/conftest.py +363 -0
  22. tasktree_manager-2.11.1/tests/test_agent_sessions.py +170 -0
  23. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_app.py +0 -36
  24. tasktree_manager-2.11.1/tests/test_cli.py +453 -0
  25. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_config.py +71 -16
  26. tasktree_manager-2.11.1/tests/test_forge.py +318 -0
  27. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_git_ops.py +131 -12
  28. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_task_manager.py +189 -0
  29. tasktree_manager-2.11.1/tests/test_worktree_badges.py +234 -0
  30. tasktree_manager-2.10.0/tasktree_manager/cli.py +0 -198
  31. tasktree_manager-2.10.0/tests/conftest.py +0 -207
  32. tasktree_manager-2.10.0/tests/test_cli.py +0 -237
  33. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/SKILL.md +0 -0
  34. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/README.md +0 -0
  35. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/dashboard_app.py +0 -0
  36. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/data_viewer.py +0 -0
  37. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/todo_app.py +0 -0
  38. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/worker_demo.py +0 -0
  39. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/references/layouts.md +0 -0
  40. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/references/official-guides-index.md +0 -0
  41. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/references/styling.md +0 -0
  42. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/references/widgets.md +0 -0
  43. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.github/templates/CHANGELOG.md.j2 +0 -0
  44. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.github/workflows/ci.yml +0 -0
  45. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.github/workflows/release.yml +0 -0
  46. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.gitignore +0 -0
  47. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/CONTRIBUTING.md +0 -0
  48. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/LICENSE +0 -0
  49. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/OPENSPEC.md +0 -0
  50. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/ROADMAP.md +0 -0
  51. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/claude-code-integration-spec.md +0 -0
  52. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/installation.md +0 -0
  53. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/mise.toml +0 -0
  54. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/scripts/bump_version.py +0 -0
  55. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/__init__.py +0 -0
  56. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/claude_hooks.py +0 -0
  57. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/themes.py +0 -0
  58. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/__init__.py +0 -0
  59. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/app_header.py +0 -0
  60. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/messages_panel.py +0 -0
  61. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/setup_modal.py +0 -0
  62. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/status_panel.py +0 -0
  63. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/task_list.py +0 -0
  64. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/__init__.py +0 -0
  65. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_claude_hooks.py +0 -0
  66. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_commands.py +0 -0
  67. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_integration_git.py +0 -0
  68. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_memory.py +0 -0
  69. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_messages_panel.py +0 -0
  70. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_modals.py +0 -0
  71. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_setup_modal.py +0 -0
  72. {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_status_panel.py +0 -0
@@ -15,6 +15,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
15
  - Git hooks support
16
16
  - Custom task metadata
17
17
 
18
+ ## [2.11.1] - 2026-07-31
19
+
20
+ ### Fixed
21
+ - **tui**: Open editor in new terminal tab, drop Enter shell binding
22
+
23
+
24
+ ## [2.11.0] - 2026-07-30
25
+
26
+ ### Added
27
+ - Add agent dashboard, forge-aware safety, finish/status CLI
28
+
29
+ ### Changed
30
+ - **cli**: Collapse multi-line f-string per ruff format
31
+
32
+
18
33
  ## [2.10.0] - 2026-07-23
19
34
 
20
35
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tasktree-manager
3
- Version: 2.10.0
3
+ Version: 2.11.1
4
4
  Summary: TUI application for managing worktree-based tasks
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.10
@@ -18,7 +18,10 @@
18
18
  - ⌨️ **Keyboard-First** - Navigate and control everything without touching the mouse
19
19
  - 🚀 **Fast & Responsive** - Parallel git operations with loading indicators
20
20
  - 🔧 **Flexible Configuration** - TOML config file, custom keybindings, environment variables
21
- - 🤖 **Headless CLI** - Create, list, and delete tasks from scripts and AI agents without opening the TUI
21
+ - 🤖 **Headless CLI** - Create, list, inspect, finish, and delete tasks from scripts and AI agents without opening the TUI
22
+ - 🛰️ **Agent Dashboard** - Live Claude Code session state per worktree (from `claude agents`), plus one-key background-agent dispatch — the multi-repo agent view Claude Code lacks natively
23
+ - 🔀 **Forge-Aware Safety** - MR/PR and CI state via `glab`/`gh`; squash- and rebase-merged branches count as merged instead of blocking deletion forever
24
+ - 📦 **Finish Flow with Archives** - Ending a task saves its combined diff (committed-but-unmerged + uncommitted) to an archive before deleting
22
25
 
23
26
  ## 📊 Status Indicators
24
27
 
@@ -26,12 +29,15 @@
26
29
  |-----------|---------|
27
30
  | `●` red | Uncommitted changes |
28
31
  | `◆` blue | Has CLAUDE.md file |
29
- | `⟳` magenta | Claude Code session running |
32
+ | `⟳` magenta | Claude Code session running / agent working |
30
33
  | `!` yellow | Claude Code session waiting for input |
34
+ | `▣` green | Agent session ready (idle) |
31
35
  | `✓` green | Clean worktree / Claude session ended |
32
36
  | `✗ N` red | N files changed |
33
37
  | `↑N` green | N commits ahead of remote |
34
38
  | `↓N` yellow | N commits behind remote |
39
+ | `○` green / `●` magenta / `×` red | MR open / merged / closed |
40
+ | `◐` yellow / `✔` green / `✘` red | CI running / passed / failed |
35
41
 
36
42
  ## 🚀 Quick Start
37
43
 
@@ -57,7 +63,7 @@ On first run, you'll configure:
57
63
  ### Basic Workflow
58
64
 
59
65
  1. **Create a task** - Press `n`, enter task name, select repositories
60
- 2. **Work on code** - Press `e` for editor, `g` for lazygit, or `Enter` for shell
66
+ 2. **Work on code** - Press `e` for editor, `g` for lazygit, or `o` for a shell in a new terminal tab
61
67
  3. **Review changes** - Press `h` to view the diff in [hunk](https://github.com/modem-dev/hunk) (all repos from the task panel, one repo from the worktree panel)
62
68
  4. **Push changes** - Press `p` to push all worktrees
63
69
  5. **Delete task** - Press `d` when finished
@@ -74,11 +80,16 @@ tasktree-manager create DIC-1901-argocd-tls --repos backend,frontend # --base o
74
80
  tasktree-manager list --json # tasks with repos and dirty state (plain text without --json)
75
81
  tasktree-manager repos # available repos in REPOS_DIR
76
82
  tasktree-manager add-repo DIC-1901-argocd-tls infra
77
- tasktree-manager delete DIC-1901-argocd-tls # refuses on unfinished work; --force overrides
83
+ tasktree-manager status # current task inferred from $PWD; also --json / --oneline / --forge
84
+ tasktree-manager finish DIC-1901-argocd-tls # safety sweep -> archive diff -> delete; --push / --no-archive / --force
85
+ tasktree-manager delete DIC-1901-argocd-tls # low-level delete; refuses on unfinished work; --force overrides
78
86
  ```
79
87
 
80
- Exit code is 0 on success, 1 on failure with the reason on stderr. `delete` runs the same
81
- safety check as the TUI (uncommitted, unpushed, or unmerged work blocks deletion).
88
+ Exit code is 0 on success, 1 on failure with the reason on stderr. `delete` and `finish` run
89
+ the same safety check as the TUI (uncommitted, unpushed, or unmerged work blocks deletion);
90
+ with `glab`/`gh` installed, squash/rebase-merged branches are recognized as merged.
91
+ `status --oneline` emits a compact `TASK repoA✓ repoB●2↑1` summary that slots straight into
92
+ a Claude Code statusline or shell prompt.
82
93
 
83
94
  ## 📖 Documentation
84
95
 
@@ -96,8 +107,9 @@ safety check as the TUI (uncommitted, unpushed, or unmerged work blocks deletion
96
107
  | `a` | Add repo | `h` | Show diff (hunk) |
97
108
  | `d` | Delete task | `e` | Open editor |
98
109
  | `p` | Push all | `o` | Open folder |
99
- | `P` | Pull all | `Enter` | Open shell |
110
+ | `P` | Pull all | `y` | Clone task |
100
111
  | `c` | Claude (resume) | `C` | Claude (new) |
112
+ | `b` | Dispatch agent | `D` | Delete worktree |
101
113
  | `r` | Refresh | `s` | Sort tasks |
102
114
  | `S` | Group worktrees | `m` | Messages |
103
115
  | `t` | Cycle theme | `Tab` | Next panel |
@@ -177,11 +189,13 @@ For comprehensive troubleshooting, see the [Troubleshooting Guide](docs/troubles
177
189
 
178
190
  ## 🗺️ Roadmap
179
191
 
180
- Current: **v0.2.0** - Configuration system, themes, comprehensive documentation
192
+ Recently shipped: agent dashboard (per-worktree Claude session badges + background dispatch),
193
+ forge-aware merged detection (glab/gh, squash/rebase merges), MR/CI status badges,
194
+ guided `finish` flow with diff archiving, `status` subcommand for scripts and statuslines.
181
195
 
182
196
  Upcoming:
183
- - **v0.3.0** - Search/filter, task templates, archiving
184
- - **v0.4.0** - JIRA integration, git hooks, automation
197
+ - **v0.3.0** - Search/filter, task templates
198
+ - **v0.4.0** - JIRA status column, git hooks, automation
185
199
  - **v1.0.0** - Stable release
186
200
 
187
201
  See [ROADMAP.md](ROADMAP.md) and [CHANGELOG.md](CHANGELOG.md) for details.
@@ -79,6 +79,11 @@ repos_dir = "/Users/username/repos"
79
79
  # Created automatically if it doesn't exist
80
80
  tasks_dir = "/Users/username/tasks"
81
81
 
82
+ # Directory for finished-task diff archives
83
+ # Relative paths resolve under tasks_dir (never the current directory)
84
+ # Default: "" (uses <tasks_dir>/.archive)
85
+ archive_dir = ""
86
+
82
87
  # ============================================================================
83
88
  # UI Settings
84
89
  # ============================================================================
@@ -99,6 +104,16 @@ show_hidden_files = false
99
104
  # Default: 30
100
105
  refresh_interval = 30
101
106
 
107
+ # Claude agent session poll interval in seconds (0 = disabled)
108
+ # Polls `claude agents --json` for per-worktree session state badges
109
+ # Default: 10
110
+ agent_poll_interval = 10
111
+
112
+ # MR/CI forge status poll interval in seconds (0 = disabled)
113
+ # Polls glab/gh for MR and pipeline state badges in the worktree list
114
+ # Default: 60
115
+ forge_poll_interval = 60
116
+
102
117
  # ============================================================================
103
118
  # Git Settings
104
119
  # ============================================================================
@@ -165,10 +180,31 @@ claude_memory_dir = "~/.claude/tasktree-memory"
165
180
  # Default: true
166
181
  claude_repo_memory = true
167
182
 
168
- # Preferred shell
169
- # Leave empty to use $SHELL environment variable
170
- # Default: "" (uses $SHELL, falls back to /bin/bash)
171
- shell = ""
183
+ # Path to glab executable (GitLab CLI, used for MR/CI status)
184
+ # Default: "glab" (searches PATH)
185
+ glab_path = "glab"
186
+
187
+ # Path to gh executable (GitHub CLI, used for PR/CI status)
188
+ # Default: "gh" (searches PATH)
189
+ gh_path = "gh"
190
+
191
+ # ============================================================================
192
+ # Forge (MR/PR state via glab/gh)
193
+ # ============================================================================
194
+ [forge]
195
+
196
+ # Query MR/PR and CI state from GitLab/GitHub CLIs.
197
+ # Used for worktree badges, squash-merge-aware safety checks, and
198
+ # `status --forge`. Set to false to disable all forge lookups
199
+ # (e.g. air-gapped environments).
200
+ # Default: true
201
+ enabled = true
202
+
203
+ # Extra self-hosted GitLab hostnames. Hosts containing "gitlab" and
204
+ # github.com are auto-detected from each repo's origin URL; list hosts
205
+ # here only when the hostname doesn't contain "gitlab".
206
+ # Default: []
207
+ gitlab_hosts = []
172
208
 
173
209
  # ============================================================================
174
210
  # Keybindings
@@ -187,13 +223,13 @@ help = "?" # Show help modal
187
223
  new_task = "n" # Create new task
188
224
  add_repo = "a" # Add repository to current task
189
225
  delete_task = "d" # Delete/finish task
226
+ delete_worktree = "D" # Remove single worktree from task (shift+d)
190
227
 
191
228
  # Git operations
192
229
  open_lazygit = "g" # Open lazygit in selected worktree
193
230
  show_diff = "h" # Open hunk diff (task panel = all repos, worktree panel = one repo)
194
231
  open_editor = "e" # Open editor in selected task/worktree
195
232
  open_folder = "o" # Open folder in new terminal tab
196
- open_shell = "enter" # Open shell in selected worktree
197
233
  push_all = "p" # Push all worktrees in current task
198
234
  pull_all = "P" # Pull all worktrees in current task (shift+p)
199
235
  refresh = "r" # Refresh git status
@@ -201,6 +237,7 @@ refresh = "r" # Refresh git status
201
237
  # Claude Code integration
202
238
  open_claude_resume = "c" # Open Claude CLI (resume if a session exists, else new)
203
239
  open_claude_gui_code = "C" # Open Claude desktop on Code page in task folder (shift+c)
240
+ dispatch_agent = "b" # Dispatch background Claude agent in selected worktree
204
241
 
205
242
  # Messages panel
206
243
  toggle_messages = "m" # Show/hide the activity messages panel
@@ -245,6 +282,7 @@ blocklist = [
245
282
  |------------|------|-----------|---------------------|------------------------------------------------|
246
283
  | `repos_dir` | path | `~/repos` | `REPOS_DIR` | Directory containing your git repositories |
247
284
  | `tasks_dir` | path | `~/tasks` | `TASKS_DIR` | Directory where task worktrees will be created |
285
+ | `archive_dir` | path | `""` (`<tasks_dir>/.archive`) | - | Directory for finished-task diff archives |
248
286
 
249
287
  ### Details
250
288
 
@@ -280,6 +318,8 @@ tasks_dir = "/Volumes/FastSSD/worktrees"
280
318
  | `theme` | string | `tasktree` | `TASKTREE_THEME` | Color theme for the interface |
281
319
  | `show_hidden_files` | boolean | `false` | - | Show hidden files in listings |
282
320
  | `refresh_interval` | integer | `30` | - | Auto-refresh interval in seconds (0 = disabled) |
321
+ | `agent_poll_interval` | integer | `10` | - | Claude agent session poll in seconds (0 = disabled) |
322
+ | `forge_poll_interval` | integer | `60` | - | MR/CI forge status poll in seconds (0 = disabled) |
283
323
 
284
324
  ### `theme`
285
325
 
@@ -353,7 +393,23 @@ refresh_interval = 15 # Refresh every 15 seconds
353
393
  | `editor` | string | `""` | `EDITOR` | Command to launch your editor |
354
394
  | `lazygit_path` | string | `"lazygit"` | - | Path to lazygit executable |
355
395
  | `hunk_path` | string | `"hunk"` | - | Path to hunk diff-viewer executable |
356
- | `shell` | string | `""` | `SHELL` | Shell to use when opening terminals |
396
+ | `glab_path` | string | `"glab"` | - | Path to GitLab CLI (MR/CI status) |
397
+ | `gh_path` | string | `"gh"` | - | Path to GitHub CLI (PR/CI status) |
398
+
399
+ ## Forge Settings
400
+
401
+ MR/PR and CI state is looked up through the GitLab (`glab`) and GitHub (`gh`)
402
+ CLIs. The provider is auto-detected per repository from its `origin` URL:
403
+ `github.com` uses `gh`; hosts containing "gitlab" (or listed in
404
+ `gitlab_hosts`) use `glab`; anything else (including local-path remotes) is
405
+ skipped. Lookups power the worktree MR/CI badges, squash-merge-aware safety
406
+ checks, and `tasktree-manager status --forge`. Missing CLIs or network
407
+ failures degrade silently — features fall back to plain git behavior.
408
+
409
+ | Option | Type | Default | Description |
410
+ |----------------|------------|---------|----------------------------------------------------|
411
+ | `enabled` | boolean | `true` | Master switch for all forge lookups |
412
+ | `gitlab_hosts` | array[str] | `[]` | Extra self-hosted GitLab hostnames to auto-detect |
357
413
 
358
414
  ### Details
359
415
 
@@ -375,12 +431,6 @@ refresh_interval = 15 # Refresh every 15 seconds
375
431
  - Install hunk: `brew install hunk` (macOS) or `npm i -g hunkdiff`
376
432
  - Used when pressing `h`: from the task panel it opens a combined diff across all the task's repos; from the worktree panel it opens the selected repo's diff
377
433
 
378
- **`shell`:**
379
- - Leave empty (`""`) to use `$SHELL` environment variable
380
- - Fallback: `/bin/bash`
381
- - Examples: `"/bin/zsh"`, `"/bin/fish"`, `"/usr/local/bin/bash"`
382
- - Used when pressing `Enter` to open shell in worktree
383
-
384
434
  ## Symlinks
385
435
 
386
436
  When creating worktrees, tasktree-manager automatically symlinks gitignored files (like `.env`) from the source repository. This allows environment files to be shared without copying.
@@ -542,7 +592,6 @@ All 22 customizable keybindings with descriptions:
542
592
  | `show_diff` | `h` | Open hunk diff (task = all repos, worktree = one) | `show_diff = "ctrl+h"` |
543
593
  | `open_editor` | `e` | Open editor in task/worktree folder | `open_editor = "ctrl+e"` |
544
594
  | `open_folder` | `o` | Open folder in new terminal tab | `open_folder = "ctrl+o"` |
545
- | `open_shell` | `enter` | Open shell in selected worktree | `open_shell = "ctrl+t"` |
546
595
  | `push_all` | `p` | Push all worktrees in current task | `push_all = "ctrl+p"` |
547
596
  | `pull_all` | `P` | Pull all worktrees in current task | `pull_all = "ctrl+shift+p"` |
548
597
  | `refresh` | `r` | Refresh git status for all worktrees | `refresh = "F5"` |
@@ -612,7 +661,7 @@ focus_previous = "h"
612
661
  [keybindings]
613
662
  new_task = "ctrl+n"
614
663
  delete_task = "ctrl+d"
615
- open_shell = "ctrl+t"
664
+ open_folder = "ctrl+t"
616
665
  refresh = "F5"
617
666
  quit = "ctrl+q"
618
667
  ```
@@ -732,8 +732,8 @@ HEAD detached at abc1234
732
732
 
733
733
  **Solution:**
734
734
  ```bash
735
- # Open shell in worktree
736
- Press Enter
735
+ # Open worktree in a new terminal tab
736
+ Press o
737
737
 
738
738
  # Create/checkout branch
739
739
  git checkout -b FEAT-123
@@ -1008,7 +1008,7 @@ Create
1008
1008
 
1009
1009
  # Your work is in the remote branch
1010
1010
  # Pull it down in the new worktree
1011
- Press Enter (shell)
1011
+ Press o (new terminal tab)
1012
1012
  git pull origin FEAT-123
1013
1013
  ```
1014
1014
 
@@ -140,10 +140,10 @@ A **worktree** is a git working directory for a specific repository within a tas
140
140
  - Exit hunk (press `q`)
141
141
 
142
142
  4. **Or open a shell:**
143
- - Press `Enter` to open a shell in the worktree
143
+ - Press `o` to open the worktree in a new terminal tab
144
144
  - Make changes with your editor/IDE
145
145
  - Run build/test commands
146
- - Exit shell (type `exit`)
146
+ - Close the tab (or switch back) when done
147
147
 
148
148
  5. **Push changes:**
149
149
  - Press `p` to push all worktrees in the task
@@ -337,8 +337,7 @@ Useful when you're spinning up several similar tasks that share the same set of
337
337
  |---------|--------------------|------------------------------------------------------|
338
338
  | `g` | Open lazygit | Open lazygit in the selected worktree |
339
339
  | `h` | Show diff | Open hunk: all repos from the task panel, the selected repo from the worktree panel |
340
- | `e` | Open editor | Open editor in task/worktree folder (runs `$EDITOR .`) |
341
- | `Enter` | Open shell | Open a shell in the selected worktree |
340
+ | `e` | Open editor | Open editor in a new terminal tab at the task/worktree folder (runs `$EDITOR .`; the TUI keeps running) |
342
341
  | `p` | Push all | Push all worktrees in the current task (parallel) |
343
342
  | `P` | Pull all | Pull all worktrees in the current task (parallel) |
344
343
  | `r` | Refresh status | Refresh git status for all tasks and worktrees |
@@ -364,6 +363,7 @@ Useful when you're spinning up several similar tasks that share the same set of
364
363
  |---------|-------------------------|------------------------------------------------------------|
365
364
  | `c` | Open Claude CLI | Resume the task's Claude Code session if one exists, otherwise start a new one |
366
365
  | `C` | Open Claude desktop | Open the Claude desktop app on the Code page at the task folder |
366
+ | `b` | Dispatch agent | Run a background Claude agent (`claude --bg`) in the selected worktree |
367
367
 
368
368
  **How it works:**
369
369
  - `c` opens Claude Code CLI in a new Ghostty terminal tab at the task directory.
@@ -374,6 +374,35 @@ Useful when you're spinning up several similar tasks that share the same set of
374
374
  - Both variants point the session's Claude Code auto-memory at a shared pool (`claude_memory_dir`, default `~/.claude/tasktree-memory`). Task folders are not git repos, so without this each task would get its own memory directory that is orphaned when the task is deleted; with the shared pool, what Claude learns in one task carries over to future tasks.
375
375
  - Each worktree additionally gets its own `.claude/settings.local.json` pointing auto-memory at the **main repo's** memory directory (`claude_repo_memory`, enabled by default). Sessions started manually inside a worktree (`cd` + `claude`) would otherwise key their memory to the worktree path and lose it when the worktree is deleted; with this, what Claude learns about a repo persists across worktrees and is shared with sessions in the main checkout. The file is git-excluded so worktrees stay clean, and these sessions also report status back to the task indicator.
376
376
 
377
+ **Agent dashboard:**
378
+
379
+ Claude Code's native agent view is scoped to a single repository — it has no concept of a
380
+ task spanning several repos. tasktree-manager fills that gap:
381
+
382
+ - The worktree list polls `claude agents --json` (every `agent_poll_interval` seconds,
383
+ default 10) and shows a per-worktree session badge: `⟳` working, `!` needs input,
384
+ `▣` ready/idle. Any Claude session whose working directory is inside a worktree counts,
385
+ whether started from the TUI, the dashboard, or a plain terminal.
386
+ - `b` prompts for an instruction and dispatches a background agent
387
+ (`claude --bg -n <task>/<repo>`) into the selected worktree. Dispatch results land in
388
+ the messages panel (`m`), and the session appears in `claude agents` under the
389
+ `<task>/<repo>` name. Dispatch to several worktrees in parallel is fine.
390
+ - If the `claude` CLI is missing or too old for `agents --json`, polling disables itself
391
+ after three failed attempts (one note in the messages panel) — the rest of the app is
392
+ unaffected.
393
+
394
+ **Forge badges (MR/CI):**
395
+
396
+ With the GitLab (`glab`) or GitHub (`gh`) CLI installed and authenticated, the worktree
397
+ list also shows each branch's MR state (`○` open, `●` merged, `×` closed) and CI state
398
+ (`◐` running, `✔` passed, `✘` failed; GitHub only — GitLab's MR list API carries no
399
+ pipeline data). The provider is auto-detected from each repo's origin URL; self-hosted
400
+ GitLab works when the hostname contains "gitlab" or is listed under `[forge]
401
+ gitlab_hosts`. The same lookup makes safety checks recognize squash/rebase-merged
402
+ branches: a branch whose MR is merged no longer blocks task deletion even though
403
+ `git merge-base` cannot see the merge. Set `[forge] enabled = false` to turn all of
404
+ this off.
405
+
377
406
  ### General
378
407
 
379
408
  | Key | Action | Description |
@@ -404,9 +433,9 @@ Create
404
433
  # Work in backend
405
434
  Tab (to worktree list)
406
435
  j (to highlight backend)
407
- Enter (open shell)
436
+ o (open new terminal tab)
408
437
 
409
- # In shell: make changes
438
+ # In the tab: make changes
410
439
  cd src
411
440
  vim auth.py
412
441
  # ... make changes ...
@@ -486,7 +515,7 @@ Select: backend
486
515
  Create
487
516
 
488
517
  Tab
489
- Enter (open shell)
518
+ o (open new terminal tab)
490
519
  git fetch origin feat-789:feat-789
491
520
  git checkout feat-789
492
521
  exit
@@ -523,7 +552,7 @@ q (quit tasktree-manager)
523
552
  tasktree-manager
524
553
  j (select FEAT-999)
525
554
  Tab
526
- Enter (shell in first worktree)
555
+ o (new tab in first worktree)
527
556
 
528
557
  # Merge main into feature branch
529
558
  git fetch origin main:main
@@ -601,7 +630,7 @@ d (delete task)
601
630
  **Working in worktree:**
602
631
  - Press `e` to open editor directly in worktree
603
632
  - Press `g` for lazygit (recommended for git operations)
604
- - Press `Enter` for shell (for building, testing, or other commands)
633
+ - Press `o` for a shell in a new terminal tab (building, testing, other commands)
605
634
 
606
635
  **Git operations:**
607
636
  - **Staging/committing**: Use lazygit (`g`)
@@ -623,14 +652,24 @@ d (delete task)
623
652
  - tasktree-manager checks for uncommitted changes
624
653
  - Checks for unpushed commits
625
654
  - Offers to push before deletion
655
+ - With `glab`/`gh` installed, branches whose MR/PR was squash- or rebase-merged count as
656
+ merged (plain `git merge-base` cannot see those merges)
626
657
  - Force delete available (with confirmation)
627
658
 
628
659
  **What happens on delete:**
660
+ - ✅ The task's remaining diff (committed-but-unmerged + uncommitted work) is archived to
661
+ `archive_dir` (default `<tasks_dir>/.archive/<task>-<timestamp>.patch`) before anything
662
+ is removed — the messages panel (`m`) shows the archive path
629
663
  - ✅ Worktrees removed from `TASKS_DIR`
630
664
  - ✅ Branches remain on remote (if pushed)
631
665
  - ✅ Original repos in `REPOS_DIR` untouched
632
666
  - ❌ Local branches remain in original repos (cleanup manually if needed)
633
667
 
668
+ **From scripts:** `tasktree-manager finish <task>` runs the same guided flow headlessly
669
+ (safety sweep → optional `--push` → archive → delete), and `tasktree-manager status
670
+ [--json|--oneline] [--forge]` reports per-worktree state — see the README's Headless CLI
671
+ section.
672
+
634
673
  ### Manual Cleanup
635
674
 
636
675
  If tasktree-manager crashes or worktrees are corrupted:
@@ -724,9 +763,9 @@ editor = "nvim" # or "vim", "code", "emacs", etc.
724
763
 
725
764
  Or set the `$EDITOR` environment variable.
726
765
 
727
- **Alternative: Open shell first:**
728
- 1. Press `Enter` (open shell)
729
- 2. In shell:
766
+ **Alternative: Open a terminal tab first:**
767
+ 1. Press `o` (new terminal tab in the worktree)
768
+ 2. In the tab:
730
769
  ```bash
731
770
  vim . # Vim
732
771
  nvim . # Neovim
@@ -767,7 +806,7 @@ tasktree-manager creates normal git branches, so CI/CD works seamlessly:
767
806
  Integrate with GitHub CLI for PR creation:
768
807
 
769
808
  ```bash
770
- # In worktree shell (press Enter in tasktree-manager)
809
+ # In a worktree tab (press o in tasktree-manager)
771
810
  gh pr create --title "Add authentication" --body "Implements FEAT-123"
772
811
 
773
812
  # Or after pushing all worktrees
@@ -70,7 +70,7 @@ version-file = "tasktree_manager/_version.py"
70
70
  # Semantic Release Configuration
71
71
  [tool.semantic_release]
72
72
  version_toml = ["pyproject.toml:tool.semantic_release.version"]
73
- version = "2.10.0"
73
+ version = "2.11.1"
74
74
  tag_format = "v{version}"
75
75
  branch = "main"
76
76
  commit_message = "chore(release): {version} [skip ci]"
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '2.10.0'
22
- __version_tuple__ = version_tuple = (2, 10, 0)
21
+ __version__ = version = '2.11.1'
22
+ __version_tuple__ = version_tuple = (2, 11, 1)
23
23
 
24
24
  __commit_id__ = commit_id = None