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.
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/CHANGELOG.md +15 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/PKG-INFO +1 -1
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/README.md +24 -10
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/configuration.md +63 -14
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/troubleshooting.md +3 -3
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/user-guide.md +52 -13
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/pyproject.toml +1 -1
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/_version.py +2 -2
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/app.py +287 -58
- tasktree_manager-2.11.1/tasktree_manager/cli.py +431 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/commands.py +10 -2
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/__init__.py +4 -0
- tasktree_manager-2.11.1/tasktree_manager/services/agent_sessions.py +157 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/config.py +91 -23
- tasktree_manager-2.11.1/tasktree_manager/services/forge.py +349 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/git_ops.py +56 -11
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/models.py +16 -2
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/task_manager.py +117 -7
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/create_modal.py +55 -3
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/worktree_list.py +78 -25
- tasktree_manager-2.11.1/tests/conftest.py +363 -0
- tasktree_manager-2.11.1/tests/test_agent_sessions.py +170 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_app.py +0 -36
- tasktree_manager-2.11.1/tests/test_cli.py +453 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_config.py +71 -16
- tasktree_manager-2.11.1/tests/test_forge.py +318 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_git_ops.py +131 -12
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_task_manager.py +189 -0
- tasktree_manager-2.11.1/tests/test_worktree_badges.py +234 -0
- tasktree_manager-2.10.0/tasktree_manager/cli.py +0 -198
- tasktree_manager-2.10.0/tests/conftest.py +0 -207
- tasktree_manager-2.10.0/tests/test_cli.py +0 -237
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/SKILL.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/README.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/dashboard_app.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/data_viewer.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/todo_app.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/assets/worker_demo.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/references/layouts.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/references/official-guides-index.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/references/styling.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.claude/skills/textual-tui/references/widgets.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.github/templates/CHANGELOG.md.j2 +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.github/workflows/ci.yml +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.github/workflows/release.yml +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/.gitignore +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/CONTRIBUTING.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/LICENSE +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/OPENSPEC.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/ROADMAP.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/claude-code-integration-spec.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/docs/installation.md +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/mise.toml +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/scripts/bump_version.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/__init__.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/services/claude_hooks.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/themes.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/__init__.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/app_header.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/messages_panel.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/setup_modal.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/status_panel.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tasktree_manager/widgets/task_list.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/__init__.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_claude_hooks.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_commands.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_integration_git.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_memory.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_messages_panel.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_modals.py +0 -0
- {tasktree_manager-2.10.0 → tasktree_manager-2.11.1}/tests/test_setup_modal.py +0 -0
- {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
|
|
@@ -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 `
|
|
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
|
|
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`
|
|
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 | `
|
|
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
|
-
|
|
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
|
|
184
|
-
- **v0.4.0** - JIRA
|
|
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
|
-
#
|
|
169
|
-
#
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
| `
|
|
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
|
-
|
|
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
|
|
736
|
-
Press
|
|
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
|
|
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 `
|
|
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
|
-
-
|
|
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
|
-
|
|
436
|
+
o (open new terminal tab)
|
|
408
437
|
|
|
409
|
-
# In
|
|
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
|
-
|
|
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
|
-
|
|
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 `
|
|
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
|
|
728
|
-
1. Press `
|
|
729
|
-
2. In
|
|
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
|
|
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.
|
|
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.
|
|
22
|
-
__version_tuple__ = version_tuple = (2,
|
|
21
|
+
__version__ = version = '2.11.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 11, 1)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|