tasktree-manager 2.1.0__tar.gz → 2.2.0__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.1.0 → tasktree_manager-2.2.0}/CHANGELOG.md +6 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/PKG-INFO +1 -1
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/README.md +16 -22
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/docs/configuration.md +40 -5
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/docs/user-guide.md +33 -6
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/pyproject.toml +1 -1
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/_version.py +2 -2
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/app.py +45 -6
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/services/claude_hooks.py +1 -1
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/services/config.py +8 -1
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/services/git_ops.py +7 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/SKILL.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/README.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/dashboard_app.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/data_viewer.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/todo_app.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/worker_demo.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/references/layouts.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/references/official-guides-index.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/references/styling.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/references/widgets.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.github/templates/CHANGELOG.md.j2 +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.github/workflows/ci.yml +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.github/workflows/release.yml +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.gitignore +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/CONTRIBUTING.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/LICENSE +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/OPENSPEC.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/ROADMAP.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/docs/claude-code-integration-spec.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/docs/installation.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/docs/troubleshooting.md +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/mise.toml +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/scripts/bump_version.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/__init__.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/services/__init__.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/services/models.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/services/task_manager.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/widgets/__init__.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/widgets/create_modal.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/widgets/messages_panel.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/widgets/setup_modal.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/widgets/status_panel.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/widgets/task_list.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/widgets/worktree_list.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/__init__.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/conftest.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_app.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_config.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_git_ops.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_integration_git.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_memory.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_messages_panel.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_modals.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_setup_modal.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_status_panel.py +0 -0
- {tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tests/test_task_manager.py +0 -0
|
@@ -15,6 +15,12 @@ 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.2.0] - 2026-03-06
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- Add periodic auto-refresh for git status with selection preserv… (#3)
|
|
22
|
+
|
|
23
|
+
|
|
18
24
|
## [2.1.0] - 2026-02-10
|
|
19
25
|
|
|
20
26
|
### Added
|
|
@@ -19,26 +19,18 @@
|
|
|
19
19
|
- 🚀 **Fast & Responsive** - Parallel git operations with loading indicators
|
|
20
20
|
- 🔧 **Flexible Configuration** - TOML config file, custom keybindings, environment variables
|
|
21
21
|
|
|
22
|
-
##
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
│ Sync: ↑2 ↓1 │
|
|
35
|
-
│ │
|
|
36
|
-
│ M src/main.py │
|
|
37
|
-
│ ?? README.md │
|
|
38
|
-
│ M tests/test_app.py │
|
|
39
|
-
└──────────────────────────────────────────────────────────────────────────┘
|
|
40
|
-
n New task d Delete g Lazygit p Push r Refresh ? Help q Quit
|
|
41
|
-
```
|
|
22
|
+
## 📊 Status Indicators
|
|
23
|
+
|
|
24
|
+
| Indicator | Meaning |
|
|
25
|
+
|-----------|---------|
|
|
26
|
+
| `●` red | Uncommitted changes |
|
|
27
|
+
| `◆` blue | Has CLAUDE.md file |
|
|
28
|
+
| `⟳` magenta | Claude Code session running |
|
|
29
|
+
| `!` yellow | Claude Code session waiting for input |
|
|
30
|
+
| `✓` green | Clean worktree / Claude session ended |
|
|
31
|
+
| `✗ N` red | N files changed |
|
|
32
|
+
| `↑N` green | N commits ahead of remote |
|
|
33
|
+
| `↓N` yellow | N commits behind remote |
|
|
42
34
|
|
|
43
35
|
## 🚀 Quick Start
|
|
44
36
|
|
|
@@ -85,9 +77,11 @@ For detailed workflows and examples, see the [User Guide](docs/user-guide.md).
|
|
|
85
77
|
| `n` | New task | `g` | Open lazygit |
|
|
86
78
|
| `a` | Add repo | `e` | Open editor |
|
|
87
79
|
| `d` | Delete task | `o` | Open folder |
|
|
88
|
-
| `p` | Push all | `
|
|
80
|
+
| `p` | Push all | `P` | Pull all |
|
|
81
|
+
| `c` | Claude (resume) | `C` | Claude (new) |
|
|
89
82
|
| `r` | Refresh | `s` | Sort tasks |
|
|
90
|
-
| `S` | Group worktrees | `
|
|
83
|
+
| `S` | Group worktrees | `m` | Messages |
|
|
84
|
+
| `Enter` | Open shell | `Tab` | Next panel |
|
|
91
85
|
| `?` | Show help | `q` | Quit |
|
|
92
86
|
|
|
93
87
|
**Themes:** Press `Ctrl+P` to switch between 7 built-in themes (textual-dark, nord, gruvbox, tokyo-night, monokai, dracula, textual-light).
|
|
@@ -93,6 +93,11 @@ theme = "textual-dark"
|
|
|
93
93
|
# Default: false
|
|
94
94
|
show_hidden_files = false
|
|
95
95
|
|
|
96
|
+
# Auto-refresh interval in seconds (0 = disabled)
|
|
97
|
+
# Periodically refreshes git status in the background
|
|
98
|
+
# Default: 30
|
|
99
|
+
refresh_interval = 30
|
|
100
|
+
|
|
96
101
|
# ============================================================================
|
|
97
102
|
# Git Settings
|
|
98
103
|
# ============================================================================
|
|
@@ -160,6 +165,13 @@ push_all = "p" # Push all worktrees in current task
|
|
|
160
165
|
pull_all = "P" # Pull all worktrees in current task (shift+p)
|
|
161
166
|
refresh = "r" # Refresh git status
|
|
162
167
|
|
|
168
|
+
# Claude Code integration
|
|
169
|
+
open_claude_resume = "c" # Resume Claude Code session in task directory
|
|
170
|
+
open_claude_new = "C" # Start new Claude Code session (shift+c)
|
|
171
|
+
|
|
172
|
+
# Messages panel
|
|
173
|
+
toggle_messages = "m" # Show/hide the activity messages panel
|
|
174
|
+
|
|
163
175
|
# Navigation
|
|
164
176
|
focus_next = "tab" # Switch to next panel
|
|
165
177
|
focus_previous = "shift+tab" # Switch to previous panel
|
|
@@ -224,10 +236,11 @@ tasks_dir = "/Volumes/FastSSD/worktrees"
|
|
|
224
236
|
|
|
225
237
|
## UI Settings
|
|
226
238
|
|
|
227
|
-
| Option | Type | Default | Environment Variable | Description
|
|
228
|
-
|
|
229
|
-
| `theme` | string | `textual-dark` | `TASKTREE_THEME` | Color theme for the interface
|
|
230
|
-
| `show_hidden_files` | boolean | `false` | - | Show hidden files in listings
|
|
239
|
+
| Option | Type | Default | Environment Variable | Description |
|
|
240
|
+
|--------------------|---------|-----------------|-----------------------|------------------------------------------|
|
|
241
|
+
| `theme` | string | `textual-dark` | `TASKTREE_THEME` | Color theme for the interface |
|
|
242
|
+
| `show_hidden_files` | boolean | `false` | - | Show hidden files in listings |
|
|
243
|
+
| `refresh_interval` | integer | `30` | - | Auto-refresh interval in seconds (0 = disabled) |
|
|
231
244
|
|
|
232
245
|
### `theme`
|
|
233
246
|
|
|
@@ -245,6 +258,20 @@ Available themes (press `Ctrl+P` in app to switch):
|
|
|
245
258
|
|
|
246
259
|
Currently unused (reserved for future file browser features).
|
|
247
260
|
|
|
261
|
+
### `refresh_interval`
|
|
262
|
+
|
|
263
|
+
Automatically refreshes git status for all tasks and worktrees in the background:
|
|
264
|
+
|
|
265
|
+
- Default: `30` (every 30 seconds)
|
|
266
|
+
- Set to `0` to disable auto-refresh
|
|
267
|
+
- Runs in a background thread — does not block the UI
|
|
268
|
+
- Preserves current task and worktree selection during refresh
|
|
269
|
+
|
|
270
|
+
```toml
|
|
271
|
+
[ui]
|
|
272
|
+
refresh_interval = 15 # Refresh every 15 seconds
|
|
273
|
+
```
|
|
274
|
+
|
|
248
275
|
## Git Settings
|
|
249
276
|
|
|
250
277
|
| Option | Type | Default | Environment Variable | Description |
|
|
@@ -390,7 +417,7 @@ blocklist = ["*"]
|
|
|
390
417
|
|
|
391
418
|
## Keybindings Reference
|
|
392
419
|
|
|
393
|
-
All
|
|
420
|
+
All 21 customizable keybindings with descriptions:
|
|
394
421
|
|
|
395
422
|
### Application Control
|
|
396
423
|
|
|
@@ -419,6 +446,14 @@ All 18 customizable keybindings with descriptions:
|
|
|
419
446
|
| `pull_all` | `P` | Pull all worktrees in current task | `pull_all = "ctrl+shift+p"` |
|
|
420
447
|
| `refresh` | `r` | Refresh git status for all worktrees | `refresh = "F5"` |
|
|
421
448
|
|
|
449
|
+
### Claude Code Integration
|
|
450
|
+
|
|
451
|
+
| Action | Default | Description | Customization Example |
|
|
452
|
+
|----------------------|---------|------------------------------------------|--------------------------------------|
|
|
453
|
+
| `open_claude_resume` | `c` | Resume Claude Code session in task dir | `open_claude_resume = "ctrl+c"` |
|
|
454
|
+
| `open_claude_new` | `C` | Start new Claude Code session | `open_claude_new = "ctrl+shift+c"` |
|
|
455
|
+
| `toggle_messages` | `m` | Show/hide activity messages panel | `toggle_messages = "ctrl+m"` |
|
|
456
|
+
|
|
422
457
|
### Navigation
|
|
423
458
|
|
|
424
459
|
| Action | Default | Description | Customization Example |
|
|
@@ -177,7 +177,9 @@ Shows all your tasks:
|
|
|
177
177
|
|
|
178
178
|
- **Name**: Task identifier (e.g., `FEAT-123`)
|
|
179
179
|
- **Count**: Number of worktrees in parentheses (e.g., `(3)`)
|
|
180
|
-
- **Dirty indicator** `●`:
|
|
180
|
+
- **Dirty indicator** `●`: Red dot — task has uncommitted changes
|
|
181
|
+
- **CLAUDE.md indicator** `◆`: Blue diamond — task has a CLAUDE.md file
|
|
182
|
+
- **Claude session status**: `⟳` running (magenta), `!` waiting (yellow), `✓` ended (green)
|
|
181
183
|
- **Sort mode**: Press `s` to cycle through sort modes (name ↑/↓, date ↑/↓, dirty/clean first)
|
|
182
184
|
|
|
183
185
|
**Navigation:**
|
|
@@ -221,13 +223,24 @@ Shows detailed git status for the selected worktree:
|
|
|
221
223
|
|
|
222
224
|
### Visual Indicators
|
|
223
225
|
|
|
226
|
+
**Task & Worktree Status:**
|
|
227
|
+
|
|
224
228
|
| Indicator | Meaning |
|
|
225
229
|
|-----------|--------------------------------------------|
|
|
226
|
-
| `●` | Task has uncommitted changes
|
|
227
|
-
| `✗ N` | N files staged or modified
|
|
228
|
-
| `↑N` | N commits ahead of remote (unpushed)
|
|
229
|
-
| `↓N` | N commits behind remote (need to pull)
|
|
230
|
-
| `✓` | Clean worktree, in sync
|
|
230
|
+
| `●` | Task/worktree has uncommitted changes |
|
|
231
|
+
| `✗ N` | N files staged or modified |
|
|
232
|
+
| `↑N` | N commits ahead of remote (unpushed) |
|
|
233
|
+
| `↓N` | N commits behind remote (need to pull) |
|
|
234
|
+
| `✓` | Clean worktree, in sync |
|
|
235
|
+
|
|
236
|
+
**Claude Code Integration:**
|
|
237
|
+
|
|
238
|
+
| Indicator | Color | Meaning |
|
|
239
|
+
|-----------|---------|------------------------------------------|
|
|
240
|
+
| `◆` | Blue | Task/worktree has a CLAUDE.md file |
|
|
241
|
+
| `⟳` | Magenta | Claude Code session is running |
|
|
242
|
+
| `!` | Yellow | Claude Code session is waiting for input |
|
|
243
|
+
| `✓` | Green | Claude Code session has ended |
|
|
231
244
|
|
|
232
245
|
## Complete Keyboard Reference
|
|
233
246
|
|
|
@@ -318,12 +331,26 @@ All keybindings can be customized in [`config.toml`](configuration.md).
|
|
|
318
331
|
- When focused on task list: Opens the task folder (`~/tasks/TASK-NAME`)
|
|
319
332
|
- When focused on worktree list: Opens the selected worktree folder
|
|
320
333
|
|
|
334
|
+
### Claude Code Integration
|
|
335
|
+
|
|
336
|
+
| Key | Action | Description |
|
|
337
|
+
|---------|-------------------------|----------------------------------------------|
|
|
338
|
+
| `c` | Open Claude (resume) | Resume Claude Code session in task directory |
|
|
339
|
+
| `C` | Open Claude (new) | Start new Claude Code session in task directory |
|
|
340
|
+
|
|
341
|
+
**How it works:**
|
|
342
|
+
- Opens Claude Code in a new Ghostty terminal tab at the task directory
|
|
343
|
+
- Generates `CLAUDE.md` files with task/worktree context
|
|
344
|
+
- Installs hooks that report session status back to tasktree-manager
|
|
345
|
+
- Session status (`⟳` running, `!` waiting, `✓` ended) appears next to the task name
|
|
346
|
+
|
|
321
347
|
### General
|
|
322
348
|
|
|
323
349
|
| Key | Action | Description |
|
|
324
350
|
|---------|-------------------------|----------------------------------------------|
|
|
325
351
|
| `Ctrl+P`| Open Command Palette | Switch themes and run commands |
|
|
326
352
|
| `o` | Open folder | Open current folder in new terminal tab |
|
|
353
|
+
| `m` | Toggle messages | Show/hide the activity messages panel |
|
|
327
354
|
| `?` | Show help | Display help modal with keybindings |
|
|
328
355
|
| `q` | Quit | Exit tasktree-manager |
|
|
329
356
|
|
|
@@ -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.2.0"
|
|
74
74
|
tag_format = "v{version}"
|
|
75
75
|
branch = "main"
|
|
76
76
|
commit_message = "chore(release): {version} [skip ci]"
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '2.
|
|
32
|
-
__version_tuple__ = version_tuple = (2,
|
|
31
|
+
__version__ = version = '2.2.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 2, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -338,6 +338,10 @@ class TaskTreeApp(App):
|
|
|
338
338
|
# Poll Claude session status files every 5 seconds
|
|
339
339
|
self.set_interval(5, self._poll_claude_statuses)
|
|
340
340
|
|
|
341
|
+
# Periodic auto-refresh of git status
|
|
342
|
+
if self.config.refresh_interval > 0:
|
|
343
|
+
self.set_interval(self.config.refresh_interval, self._periodic_git_refresh)
|
|
344
|
+
|
|
341
345
|
def watch_theme(self, theme: str) -> None:
|
|
342
346
|
"""Save theme to config when changed."""
|
|
343
347
|
if hasattr(self, "config") and self.config.theme != theme:
|
|
@@ -449,6 +453,41 @@ class TaskTreeApp(App):
|
|
|
449
453
|
self._claude_statuses = statuses
|
|
450
454
|
task_list.refresh_claude_indicators(statuses)
|
|
451
455
|
|
|
456
|
+
def _periodic_git_refresh(self) -> None:
|
|
457
|
+
"""Trigger a background git status refresh."""
|
|
458
|
+
self._run_periodic_refresh()
|
|
459
|
+
|
|
460
|
+
@work(thread=True, exclusive=True, group="auto_refresh")
|
|
461
|
+
def _run_periodic_refresh(self) -> None:
|
|
462
|
+
"""Refresh git status in background thread."""
|
|
463
|
+
tasks = self.task_manager.list_tasks()
|
|
464
|
+
all_worktrees = [wt for task in tasks for wt in task.worktrees]
|
|
465
|
+
GitOps.update_all_worktree_statuses(all_worktrees)
|
|
466
|
+
|
|
467
|
+
current_task_name = self.current_task.name if self.current_task else None
|
|
468
|
+
current_worktree_name = self.current_worktree.name if self.current_worktree else None
|
|
469
|
+
|
|
470
|
+
def _apply():
|
|
471
|
+
try:
|
|
472
|
+
task_list = self.query_one("#task-list", TaskList)
|
|
473
|
+
if current_worktree_name:
|
|
474
|
+
self._preserved_worktree_name = current_worktree_name
|
|
475
|
+
task_list.load_tasks(tasks, preserve_selection=current_task_name)
|
|
476
|
+
|
|
477
|
+
if self.current_task:
|
|
478
|
+
for t in tasks:
|
|
479
|
+
if t.name == self.current_task.name:
|
|
480
|
+
self.current_task = t
|
|
481
|
+
worktree_list = self.query_one("#worktree-list", WorktreeList)
|
|
482
|
+
worktree_list.load_worktrees(
|
|
483
|
+
t.worktrees, preserve_selection=current_worktree_name
|
|
484
|
+
)
|
|
485
|
+
break
|
|
486
|
+
except Exception:
|
|
487
|
+
pass
|
|
488
|
+
|
|
489
|
+
self.call_from_thread(_apply)
|
|
490
|
+
|
|
452
491
|
def _refresh_current_task(self, preserve_selection: bool = False) -> None:
|
|
453
492
|
"""Refresh the current task's worktrees and status.
|
|
454
493
|
|
|
@@ -693,8 +732,8 @@ class TaskTreeApp(App):
|
|
|
693
732
|
except Exception as e:
|
|
694
733
|
failed.append((repo, e))
|
|
695
734
|
|
|
696
|
-
self._load_tasks()
|
|
697
|
-
self._refresh_current_task()
|
|
735
|
+
self._load_tasks(preserve_selection=True)
|
|
736
|
+
self._refresh_current_task(preserve_selection=True)
|
|
698
737
|
|
|
699
738
|
if added:
|
|
700
739
|
self.notify(f"Added {len(added)} repo(s) to task")
|
|
@@ -1129,7 +1168,7 @@ class TaskTreeApp(App):
|
|
|
1129
1168
|
task_name,
|
|
1130
1169
|
)
|
|
1131
1170
|
|
|
1132
|
-
self._refresh_current_task()
|
|
1171
|
+
self._refresh_current_task(preserve_selection=True)
|
|
1133
1172
|
finally:
|
|
1134
1173
|
worktree_list.loading = False
|
|
1135
1174
|
|
|
@@ -1164,14 +1203,14 @@ class TaskTreeApp(App):
|
|
|
1164
1203
|
task_name,
|
|
1165
1204
|
)
|
|
1166
1205
|
|
|
1167
|
-
self._refresh_current_task()
|
|
1206
|
+
self._refresh_current_task(preserve_selection=True)
|
|
1168
1207
|
finally:
|
|
1169
1208
|
worktree_list.loading = False
|
|
1170
1209
|
|
|
1171
1210
|
def action_refresh(self) -> None:
|
|
1172
1211
|
"""Refresh all status."""
|
|
1173
|
-
self._load_tasks()
|
|
1174
|
-
self._refresh_current_task()
|
|
1212
|
+
self._load_tasks(preserve_selection=True)
|
|
1213
|
+
self._refresh_current_task(preserve_selection=True)
|
|
1175
1214
|
self.notify("Refreshed")
|
|
1176
1215
|
|
|
1177
1216
|
def action_toggle_messages(self) -> None:
|
|
@@ -9,7 +9,7 @@ def _make_hook(status: str, status_file: str) -> dict:
|
|
|
9
9
|
safe_path = status_file.replace("'", "'\\''")
|
|
10
10
|
return {
|
|
11
11
|
"type": "command",
|
|
12
|
-
"command": f
|
|
12
|
+
"command": f'printf \'{{"status":"{status}","ts":%d}}\' $(date +%s) > \'{safe_path}\'',
|
|
13
13
|
"async": True,
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -59,6 +59,7 @@ class Config:
|
|
|
59
59
|
# UI settings
|
|
60
60
|
theme: str = "textual-dark"
|
|
61
61
|
show_hidden_files: bool = False
|
|
62
|
+
refresh_interval: int = 30 # Auto-refresh interval in seconds (0 = disabled)
|
|
62
63
|
|
|
63
64
|
# Git settings
|
|
64
65
|
default_base_branch: str = "main"
|
|
@@ -103,7 +104,8 @@ class Config:
|
|
|
103
104
|
Priority: Environment variables > Config file > Defaults
|
|
104
105
|
"""
|
|
105
106
|
config_dir = (
|
|
106
|
-
Path(os.environ.get("XDG_CONFIG_HOME", str(Path.home() / ".config")))
|
|
107
|
+
Path(os.environ.get("XDG_CONFIG_HOME", str(Path.home() / ".config")))
|
|
108
|
+
/ "tasktree-manager"
|
|
107
109
|
)
|
|
108
110
|
config_file = config_dir / "config.toml"
|
|
109
111
|
|
|
@@ -122,6 +124,7 @@ class Config:
|
|
|
122
124
|
ui_config = config_data.get("ui", {})
|
|
123
125
|
theme = ui_config.get("theme", "textual-dark")
|
|
124
126
|
show_hidden_files = ui_config.get("show_hidden_files", False)
|
|
127
|
+
refresh_interval = ui_config.get("refresh_interval", 30)
|
|
125
128
|
|
|
126
129
|
# Git settings
|
|
127
130
|
git_config = config_data.get("git", {})
|
|
@@ -185,6 +188,7 @@ class Config:
|
|
|
185
188
|
config_dir=config_dir,
|
|
186
189
|
theme=theme,
|
|
187
190
|
show_hidden_files=show_hidden_files,
|
|
191
|
+
refresh_interval=refresh_interval,
|
|
188
192
|
default_base_branch=default_base_branch,
|
|
189
193
|
auto_push=auto_push,
|
|
190
194
|
git_timeout=git_timeout,
|
|
@@ -286,6 +290,9 @@ theme = "{self._toml_escape(self.theme)}"
|
|
|
286
290
|
# Show hidden files in file listings
|
|
287
291
|
show_hidden_files = {str(self.show_hidden_files).lower()}
|
|
288
292
|
|
|
293
|
+
# Auto-refresh interval in seconds (0 = disabled)
|
|
294
|
+
refresh_interval = {self.refresh_interval}
|
|
295
|
+
|
|
289
296
|
# ============================================================================
|
|
290
297
|
# Git Settings
|
|
291
298
|
# ============================================================================
|
|
@@ -190,6 +190,13 @@ class GitOps:
|
|
|
190
190
|
True if current branch is merged into base_branch, False otherwise.
|
|
191
191
|
"""
|
|
192
192
|
try:
|
|
193
|
+
# Fetch latest remote refs so we detect merges done via GitLab/GitHub UI
|
|
194
|
+
subprocess.run(
|
|
195
|
+
["git", "fetch", "origin", base_branch],
|
|
196
|
+
cwd=worktree.path,
|
|
197
|
+
capture_output=True,
|
|
198
|
+
timeout=10,
|
|
199
|
+
)
|
|
193
200
|
# Use git merge-base --is-ancestor to check if HEAD is reachable from base
|
|
194
201
|
# This checks if the current branch has been merged
|
|
195
202
|
result = subprocess.run(
|
|
File without changes
|
{tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/README.md
RENAMED
|
File without changes
|
{tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/dashboard_app.py
RENAMED
|
File without changes
|
{tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/data_viewer.py
RENAMED
|
File without changes
|
{tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/todo_app.py
RENAMED
|
File without changes
|
{tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/assets/worker_demo.py
RENAMED
|
File without changes
|
{tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/references/layouts.md
RENAMED
|
File without changes
|
|
File without changes
|
{tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/references/styling.md
RENAMED
|
File without changes
|
{tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/.claude/skills/textual-tui/references/widgets.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tasktree_manager-2.1.0 → tasktree_manager-2.2.0}/tasktree_manager/widgets/messages_panel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|