tasktree-manager 2.7.2__tar.gz → 2.9.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.7.2 → tasktree_manager-2.9.0}/.github/workflows/release.yml +4 -2
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/CHANGELOG.md +23 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/PKG-INFO +1 -1
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/docs/configuration.md +67 -9
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/docs/user-guide.md +6 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/pyproject.toml +1 -1
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/_version.py +2 -2
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/app.py +312 -242
- tasktree_manager-2.9.0/tasktree_manager/services/claude_hooks.py +178 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/services/config.py +22 -1
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/services/task_manager.py +154 -78
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/widgets/create_modal.py +27 -25
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/widgets/task_list.py +7 -2
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/widgets/worktree_list.py +6 -2
- tasktree_manager-2.9.0/tests/test_claude_hooks.py +274 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_config.py +10 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_task_manager.py +196 -17
- tasktree_manager-2.7.2/tasktree_manager/services/claude_hooks.py +0 -71
- tasktree_manager-2.7.2/tests/test_claude_hooks.py +0 -106
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/SKILL.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/README.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/dashboard_app.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/data_viewer.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/todo_app.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/worker_demo.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/references/layouts.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/references/official-guides-index.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/references/styling.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/references/widgets.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.github/templates/CHANGELOG.md.j2 +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.github/workflows/ci.yml +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/.gitignore +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/CONTRIBUTING.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/LICENSE +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/OPENSPEC.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/README.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/ROADMAP.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/docs/claude-code-integration-spec.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/docs/installation.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/docs/troubleshooting.md +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/mise.toml +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/scripts/bump_version.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/__init__.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/commands.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/services/__init__.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/services/git_ops.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/services/models.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/themes.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/widgets/__init__.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/widgets/app_header.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/widgets/messages_panel.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/widgets/setup_modal.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tasktree_manager/widgets/status_panel.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/__init__.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/conftest.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_app.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_commands.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_git_ops.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_integration_git.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_memory.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_messages_panel.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_modals.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_setup_modal.py +0 -0
- {tasktree_manager-2.7.2 → tasktree_manager-2.9.0}/tests/test_status_panel.py +0 -0
|
@@ -77,9 +77,11 @@ jobs:
|
|
|
77
77
|
release_type="${{ inputs.release_type || 'auto' }}"
|
|
78
78
|
|
|
79
79
|
if [ "$release_type" = "auto" ]; then
|
|
80
|
-
# Use semantic-release to determine bump type from commit history
|
|
80
|
+
# Use semantic-release to determine bump type from commit history.
|
|
81
|
+
# When no qualifying commits exist, `version --print` prints the
|
|
82
|
+
# CURRENT version — require an actual bump before releasing.
|
|
81
83
|
VERSION=$(semantic-release version --print 2>/dev/null || echo "")
|
|
82
|
-
if [ -n "$VERSION" ]; then
|
|
84
|
+
if [ -n "$VERSION" ] && [ "$VERSION" != "$current_version" ]; then
|
|
83
85
|
# Determine bump type by comparing versions
|
|
84
86
|
IFS='.' read -r cur_major cur_minor cur_patch <<< "$current_version"
|
|
85
87
|
IFS='.' read -r new_major new_minor new_patch <<< "$VERSION"
|
|
@@ -15,6 +15,29 @@ 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.9.0] - 2026-07-14
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **app**: Move blocking git work off the UI thread
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Format worktree settings call with ruff
|
|
25
|
+
- **app**: Extract Claude session preparation helper
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- Address review findings in async refresh and hook merging
|
|
29
|
+
- Harden task/branch validation, hook merging, markup rendering
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
## [2.8.0] - 2026-07-14
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- **claude**: Per-repo Claude memory for worktree sessions
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
- Release only when semantic-release bumps the version
|
|
39
|
+
|
|
40
|
+
|
|
18
41
|
## [2.7.2] - 2026-07-13
|
|
19
42
|
|
|
20
43
|
### Changed
|
|
@@ -153,6 +153,18 @@ claude_path = "claude"
|
|
|
153
153
|
# Default: "~/.claude/tasktree-memory"
|
|
154
154
|
claude_memory_dir = "~/.claude/tasktree-memory"
|
|
155
155
|
|
|
156
|
+
# Per-repo Claude Code memory for worktree sessions.
|
|
157
|
+
# Sessions started inside a worktree would otherwise key their auto memory to
|
|
158
|
+
# the worktree path — memory that dies with the worktree. When enabled,
|
|
159
|
+
# tasktree-manager writes .claude/settings.local.json into each worktree
|
|
160
|
+
# pointing "autoMemoryDirectory" at the main repo's own memory directory
|
|
161
|
+
# (~/.claude/projects/<encoded-repo-path>/memory). What Claude learns in any
|
|
162
|
+
# worktree of a repo survives worktree deletion and is shared with future
|
|
163
|
+
# worktrees of that repo and with sessions in the main checkout. The settings
|
|
164
|
+
# file is added to the repo's .git/info/exclude so worktrees stay clean.
|
|
165
|
+
# Default: true
|
|
166
|
+
claude_repo_memory = true
|
|
167
|
+
|
|
156
168
|
# Preferred shell
|
|
157
169
|
# Leave empty to use $SHELL environment variable
|
|
158
170
|
# Default: "" (uses $SHELL, falls back to /bin/bash)
|
|
@@ -210,7 +222,7 @@ cycle_theme = "t" # Cycle through the design-system themes
|
|
|
210
222
|
# Symlinks
|
|
211
223
|
# ============================================================================
|
|
212
224
|
# When creating worktrees, gitignored files are symlinked from the source repo.
|
|
213
|
-
# Blocklist specifies patterns to exclude (e.g., cache files).
|
|
225
|
+
# Blocklist specifies patterns to exclude (e.g., cache files, key material).
|
|
214
226
|
[symlinks]
|
|
215
227
|
blocklist = [
|
|
216
228
|
"*.pyc",
|
|
@@ -221,6 +233,9 @@ blocklist = [
|
|
|
221
233
|
".ruff_cache",
|
|
222
234
|
".coverage",
|
|
223
235
|
"*.log",
|
|
236
|
+
"*.pem",
|
|
237
|
+
"*.key",
|
|
238
|
+
"id_rsa",
|
|
224
239
|
]
|
|
225
240
|
```
|
|
226
241
|
|
|
@@ -376,7 +391,9 @@ When creating worktrees, tasktree-manager automatically symlinks gitignored file
|
|
|
376
391
|
|
|
377
392
|
### Default Blocklist
|
|
378
393
|
|
|
379
|
-
By default, these patterns are excluded from symlinking
|
|
394
|
+
By default, these patterns are excluded from symlinking. Caches and build
|
|
395
|
+
artifacts are excluded as noise; key material (`*.pem`, `*.key`, SSH keys)
|
|
396
|
+
is excluded so private keys never spread beyond the main checkout:
|
|
380
397
|
|
|
381
398
|
```toml
|
|
382
399
|
[symlinks]
|
|
@@ -397,14 +414,28 @@ blocklist = [
|
|
|
397
414
|
".nox",
|
|
398
415
|
"*.so",
|
|
399
416
|
"*.dylib",
|
|
417
|
+
"*.pem",
|
|
418
|
+
"*.key",
|
|
419
|
+
"*.p12",
|
|
420
|
+
"*.pfx",
|
|
421
|
+
"*.keystore",
|
|
422
|
+
"id_rsa",
|
|
423
|
+
"id_ecdsa",
|
|
424
|
+
"id_ed25519",
|
|
400
425
|
]
|
|
401
426
|
```
|
|
402
427
|
|
|
403
428
|
### How It Works
|
|
404
429
|
|
|
405
|
-
1. When a worktree is created, tasktree-manager
|
|
406
|
-
|
|
407
|
-
|
|
430
|
+
1. When a worktree is created, tasktree-manager asks git for the repo's
|
|
431
|
+
ignored files (`git ls-files --others --ignored --exclude-standard`), so
|
|
432
|
+
full gitignore semantics apply: nested `.gitignore` files work, and a
|
|
433
|
+
root pattern like `*.log` matches in subdirectories
|
|
434
|
+
2. Wholly-ignored directories (e.g. `node_modules/`) are skipped entirely —
|
|
435
|
+
their contents are never walked or symlinked
|
|
436
|
+
3. Files matching the blocklist (by filename or repo-relative path, so
|
|
437
|
+
patterns like `secrets/*` work) and anything under `.git/` or `.claude/`
|
|
438
|
+
are skipped
|
|
408
439
|
4. Remaining files are symlinked to the worktree
|
|
409
440
|
|
|
410
441
|
### Customizing the Blocklist
|
|
@@ -425,7 +456,9 @@ blocklist = [
|
|
|
425
456
|
]
|
|
426
457
|
```
|
|
427
458
|
|
|
428
|
-
**Add to default blocklist (must include
|
|
459
|
+
**Add to default blocklist (must include ALL default patterns — an explicit
|
|
460
|
+
blocklist replaces the defaults entirely, including the key-material
|
|
461
|
+
protection):**
|
|
429
462
|
```toml
|
|
430
463
|
[symlinks]
|
|
431
464
|
blocklist = [
|
|
@@ -433,22 +466,47 @@ blocklist = [
|
|
|
433
466
|
"*.pyc",
|
|
434
467
|
"*.pyo",
|
|
435
468
|
"__pycache__",
|
|
469
|
+
".pytest_cache",
|
|
470
|
+
".mypy_cache",
|
|
471
|
+
".ruff_cache",
|
|
436
472
|
".coverage",
|
|
437
473
|
"*.log",
|
|
474
|
+
"*.egg-info",
|
|
475
|
+
".eggs",
|
|
476
|
+
"dist",
|
|
477
|
+
"build",
|
|
478
|
+
".tox",
|
|
479
|
+
".nox",
|
|
480
|
+
"*.so",
|
|
481
|
+
"*.dylib",
|
|
482
|
+
"*.pem",
|
|
483
|
+
"*.key",
|
|
484
|
+
"*.p12",
|
|
485
|
+
"*.pfx",
|
|
486
|
+
"*.keystore",
|
|
487
|
+
"id_rsa",
|
|
488
|
+
"id_ecdsa",
|
|
489
|
+
"id_ed25519",
|
|
438
490
|
# Your additions
|
|
439
491
|
"*.tmp",
|
|
440
492
|
".DS_Store",
|
|
441
493
|
]
|
|
442
494
|
```
|
|
443
495
|
|
|
496
|
+
> **Upgrading note:** if your existing `config.toml` already contains a
|
|
497
|
+
> `blocklist`, it keeps overriding the defaults — the key-material patterns
|
|
498
|
+
> added in newer versions do NOT apply until you add them (or delete the
|
|
499
|
+
> `blocklist` line to inherit the defaults).
|
|
500
|
+
|
|
444
501
|
### Common Use Cases
|
|
445
502
|
|
|
446
|
-
**Symlink environment files, block caches:**
|
|
503
|
+
**Symlink environment files, block caches and keys:**
|
|
447
504
|
```toml
|
|
448
505
|
[symlinks]
|
|
449
|
-
blocklist = ["*.pyc", "__pycache__", ".coverage", "*.log"]
|
|
506
|
+
blocklist = ["*.pyc", "__pycache__", ".coverage", "*.log", "*.pem", "*.key", "id_rsa"]
|
|
450
507
|
```
|
|
451
|
-
This allows `.env`, `.mise.toml` to be symlinked while blocking cache files
|
|
508
|
+
This allows `.env`, `.mise.toml` to be symlinked while blocking cache files
|
|
509
|
+
and private keys.
|
|
452
510
|
|
|
453
511
|
**Block everything (disable symlinks):**
|
|
454
512
|
```toml
|
|
@@ -309,6 +309,11 @@ what is displayed. Press `?` for the full reference at any time.
|
|
|
309
309
|
5. Select repos with `Space` (can select multiple)
|
|
310
310
|
6. Tab to "Create" button, press `Enter`
|
|
311
311
|
|
|
312
|
+
Task names may contain letters, numbers, `.`, `_`, `/` and `-`. Because the
|
|
313
|
+
name becomes a directory under your tasks dir (and a git branch), names with
|
|
314
|
+
`.`/`..` path segments, empty segments, or a leading `-` are rejected; base
|
|
315
|
+
branch names must not start with `-` either.
|
|
316
|
+
|
|
312
317
|
**Clone task workflow:**
|
|
313
318
|
Useful when you're spinning up several similar tasks that share the same set of repos.
|
|
314
319
|
|
|
@@ -367,6 +372,7 @@ Useful when you're spinning up several similar tasks that share the same set of
|
|
|
367
372
|
- The CLI variant (`c`) generates a task-level `CLAUDE.md` with task/worktree context, copies each repo's own `CLAUDE.md` into worktrees whose branch predates it (never generating stub content), and installs hooks that report session status back to tasktree-manager.
|
|
368
373
|
- Session status (`⟳` running, `!` waiting, `✓` ended) appears next to the task name
|
|
369
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
|
+
- 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.
|
|
370
376
|
|
|
371
377
|
### General
|
|
372
378
|
|
|
@@ -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.9.0"
|
|
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.9.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 9, 0)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|