tasktree-manager 2.17.0__tar.gz → 2.19.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.
Files changed (85) hide show
  1. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/CHANGELOG.md +15 -0
  2. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/PKG-INFO +1 -1
  3. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/README.md +82 -50
  4. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/docs/configuration.md +11 -0
  5. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/docs/user-guide.md +89 -22
  6. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/pyproject.toml +1 -1
  7. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/_version.py +2 -2
  8. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/app.py +193 -36
  9. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/cli.py +162 -17
  10. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/agent_sessions.py +13 -4
  11. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/claude_sessions.py +35 -19
  12. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/config.py +22 -0
  13. tasktree_manager-2.19.0/tasktree_manager/services/epic_ask.py +246 -0
  14. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/epic_log.py +21 -2
  15. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/git_ops.py +1 -1
  16. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/models.py +4 -0
  17. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/task_manager.py +47 -7
  18. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_app.py +1 -0
  19. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_app_review_fixes.py +45 -6
  20. tasktree_manager-2.19.0/tests/test_epic_ask.py +402 -0
  21. tasktree_manager-2.19.0/tests/test_review_findings.py +208 -0
  22. tasktree_manager-2.19.0/tests/test_terminal_tabs.py +225 -0
  23. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/SKILL.md +0 -0
  24. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/assets/README.md +0 -0
  25. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/assets/dashboard_app.py +0 -0
  26. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/assets/data_viewer.py +0 -0
  27. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/assets/todo_app.py +0 -0
  28. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/assets/worker_demo.py +0 -0
  29. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/references/layouts.md +0 -0
  30. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/references/official-guides-index.md +0 -0
  31. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/references/styling.md +0 -0
  32. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.claude/skills/textual-tui/references/widgets.md +0 -0
  33. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.github/templates/CHANGELOG.md.j2 +0 -0
  34. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.github/workflows/ci.yml +0 -0
  35. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.github/workflows/release.yml +0 -0
  36. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/.gitignore +0 -0
  37. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/CONTRIBUTING.md +0 -0
  38. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/LICENSE +0 -0
  39. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/ROADMAP.md +0 -0
  40. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/docs/claude-code-integration-spec.md +0 -0
  41. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/docs/installation.md +0 -0
  42. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/docs/troubleshooting.md +0 -0
  43. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/mise.toml +0 -0
  44. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/scripts/bump_version.py +0 -0
  45. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/__init__.py +0 -0
  46. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/commands.py +0 -0
  47. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/__init__.py +0 -0
  48. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/claude_hooks.py +0 -0
  49. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/services/forge.py +0 -0
  50. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/themes.py +0 -0
  51. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/widgets/__init__.py +0 -0
  52. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/widgets/app_header.py +0 -0
  53. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/widgets/create_modal.py +0 -0
  54. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/widgets/messages_panel.py +0 -0
  55. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/widgets/setup_modal.py +0 -0
  56. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/widgets/status_panel.py +0 -0
  57. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/widgets/task_list.py +0 -0
  58. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tasktree_manager/widgets/worktree_list.py +0 -0
  59. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/__init__.py +0 -0
  60. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/conftest.py +0 -0
  61. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_agent_sessions.py +0 -0
  62. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_agent_sessions_decode.py +0 -0
  63. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_bump_version.py +0 -0
  64. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_claude_hooks.py +0 -0
  65. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_claude_sessions.py +0 -0
  66. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_cli.py +0 -0
  67. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_commands.py +0 -0
  68. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_config.py +0 -0
  69. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_epic_claude_md.py +0 -0
  70. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_epic_log.py +0 -0
  71. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_epic_tui.py +0 -0
  72. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_epics.py +0 -0
  73. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_forge.py +0 -0
  74. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_git_ops.py +0 -0
  75. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_integration_git.py +0 -0
  76. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_list_selection.py +0 -0
  77. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_medium_fixes.py +0 -0
  78. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_memory.py +0 -0
  79. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_messages_panel.py +0 -0
  80. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_modals.py +0 -0
  81. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_safety_fixes.py +0 -0
  82. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_setup_modal.py +0 -0
  83. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_status_panel.py +0 -0
  84. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_task_manager.py +0 -0
  85. {tasktree_manager-2.17.0 → tasktree_manager-2.19.0}/tests/test_worktree_badges.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.19.0] - 2026-10-29
19
+
20
+ ### Added
21
+ - Open zellij tabs that survive a terminal restart, and review fixes (#16)
22
+
23
+ ### Changed
24
+ - Split the headless CLI and epic sections into short parts (#15)
25
+
26
+
27
+ ## [2.18.0] - 2026-10-20
28
+
29
+ ### Added
30
+ - **epic**: Ask another task's session with epic ask (#14)
31
+
32
+
18
33
  ## [2.17.0] - 2026-10-20
19
34
 
20
35
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tasktree-manager
3
- Version: 2.17.0
3
+ Version: 2.19.0
4
4
  Summary: TUI application for managing worktree-based tasks
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.10
@@ -22,7 +22,8 @@
22
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
23
  - ✻ **Session Recap** - The Info panel shows each task's latest Claude Code session: title, last turn duration, and Claude's own idle recap of what was done and what comes next — read straight from the transcript, no CLI call
24
24
  - 🔀 **Forge-Aware Safety** - MR/PR and CI state via `glab`/`gh`; squash- and rebase-merged branches count as merged instead of blocking deletion forever
25
- - 🗂️ **Epics** - Group related tasks under an epic: a foldable row with rolled-up dirty and Claude state, `E` to attach tasks, and an epic log where the Claude sessions of one epic share notes
25
+ - 🗂️ **Epics** - Group related tasks under an epic: a foldable row with rolled-up dirty and Claude state, `E` to attach tasks, and an epic log and `epic ask` so the Claude sessions of one epic share what they know
26
+ - 🧷 **zellij Tabs** - Run the TUI inside zellij (or set `zellij_autostart`) and `o`/`e`/`c` open zellij tabs that keep running across a terminal restart; pressing the key again jumps to the open tab ([details](docs/user-guide.md#zellij))
26
27
  - 📦 **Finish Flow with Archives** - Ending a task saves its combined diff (committed-but-unmerged + uncommitted) and the task-folder files outside the worktrees (plans, ADRs, notes) to an archive before deleting
27
28
 
28
29
  ## 📊 Status Indicators
@@ -76,63 +77,93 @@ For detailed workflows and examples, see the [User Guide](docs/user-guide.md).
76
77
 
77
78
  ### Headless CLI
78
79
 
79
- Running `tasktree-manager` with arguments skips the TUI — useful for scripts and AI-agent
80
- workflows (e.g. a skill that creates a Jira ticket and then the matching task):
80
+ Running `tasktree-manager` with arguments skips the TUI. Use it from scripts and AI agents,
81
+ for example a skill that creates a Jira ticket and then the matching task.
82
+
83
+ #### Tasks
81
84
 
82
85
  ```bash
83
- tasktree-manager create DIC-1901-argocd-tls --repos backend,frontend # --base overrides the default base branch
84
- tasktree-manager list --json # tasks with repos and state: clean / dirty / error (plain text without --json)
85
- tasktree-manager repos # available repos in REPOS_DIR
86
+ tasktree-manager create DIC-1901-argocd-tls --repos backend,frontend # --base sets the base branch
86
87
  tasktree-manager add-repo DIC-1901-argocd-tls infra
87
- tasktree-manager status # current task inferred from $PWD; also --json / --oneline / --forge
88
- tasktree-manager finish DIC-1901-argocd-tls # safety sweep -> archive diff + task files -> delete; --push / --no-archive / --force
89
- tasktree-manager delete DIC-1901-argocd-tls # archive diff + task files -> delete; refuses on unfinished work; --force overrides
88
+ tasktree-manager list --json # tasks, repos and state: clean / dirty / error
89
+ tasktree-manager repos # repos available in REPOS_DIR
90
+ tasktree-manager status # task of the current folder; --json, --oneline, --forge
91
+ tasktree-manager finish DIC-1901-argocd-tls # safety check, archive, delete; --push, --no-archive
92
+ tasktree-manager delete DIC-1901-argocd-tls # archive, delete; refuses unfinished work
90
93
  ```
91
94
 
92
- Epics group related tasks, for example a Jira epic and its child tasks. An epic is a task
93
- folder with a `.tasktree_kind` marker. It can hold its own notes, Claude session and
94
- worktrees. A child task names its epic in `.tasktree_epic`. Folders never move:
95
+ `status --oneline` prints a compact `TASK repoA✓ repoB●2↑1` line for a Claude Code
96
+ statusline or a shell prompt.
97
+
98
+ #### Epics
99
+
100
+ An epic groups related tasks, for example a Jira epic and its child tasks. It is a task
101
+ folder too, so it can hold notes, a Claude session and worktrees. Tasks stay in their own
102
+ folders; a marker file names their epic. Epics don't nest.
95
103
 
96
104
  ```bash
97
- tasktree-manager epic create DIC-2466-pcaps-epic # --repos is optional for an epic
105
+ tasktree-manager epic create DIC-2466-pcaps-epic # repos are optional for an epic
98
106
  tasktree-manager create DIC-2861-pcaps-logs --repos infra --epic DIC-2466-pcaps-epic
99
- tasktree-manager epic add DIC-2466-pcaps-epic DIC-2862-pcaps-s3 # attach or move existing tasks
100
- tasktree-manager epic remove DIC-2862-pcaps-s3 # detach
101
- tasktree-manager epic mark DIC-2466-pcaps-epic # turn an existing task into an epic; unmark reverts
102
- tasktree-manager epic list # epics and their tasks; also --json
103
- tasktree-manager epic note "chose layout A for the S3 keys" # add a note to this task's file in the epic log
104
- tasktree-manager epic log # notes and latest session recap of every task in the epic
105
- tasktree-manager epic log DIC-2862-pcaps-s3 --json # one task (or a whole epic by its name), as JSON
106
- tasktree-manager epic sync # refresh the CLAUDE.md epic block after an upgrade
107
+ tasktree-manager epic add DIC-2466-pcaps-epic DIC-2862-pcaps-s3 # attach or move tasks
108
+ tasktree-manager epic remove DIC-2862-pcaps-s3 # detach
109
+ tasktree-manager epic mark DIC-2466-pcaps-epic # make an existing task an epic; unmark reverts
110
+ tasktree-manager epic list # epics and their tasks; --json
107
111
  ```
108
112
 
109
- Each task's `CLAUDE.md` gets a managed block naming its epic and how to find sibling
110
- tasks; it follows every epic change and leaves the rest of the file alone. The block
111
- also tells the session about the epic log: one notes file per task in `epic-log/` in the
112
- epic folder, written with `epic note` and read with `epic log`, which adds the recap of each
113
- task's latest Claude session (in the task folder or one of its worktrees). Inside a task
114
- folder, `epic note` writes only that task's notes and `epic log` reads only its epic;
115
- `epic note -` reads the text from stdin. Notes of a task that left the epic stay readable.
116
- Epics don't
117
- nest. `list --json` and `status --json` carry `kind` (`task` or `epic`) and
118
- `epic` (the parent epic or `null`). `delete` and `finish` refuse an epic that still has
119
- tasks, even with `--force`.
120
-
121
- Exit code is 0 on success, 1 on failure with the reason on stderr. `delete` and `finish` run
122
- the same safety check as the TUI (uncommitted, unpushed, or unmerged work blocks deletion);
123
- with `glab`/`gh` installed, squash/rebase-merged branches are recognized as merged. If the
124
- diff cannot be archived for any repo, the CLI stops before deleting and prints the path of
125
- the partial archive; the TUI warns and deletes anyway. Files in the task folder outside the
126
- worktrees are copied to `<task>-<timestamp>.files/` next to the patch:
127
-
128
- - Skipped silently: hidden files, symlinks, `node_modules`/`vendor`/`.terraform` folders and
129
- an unedited generated `CLAUDE.md`.
130
- - Left out with a warning: key material (`*.pem`, `*.key`, `id_rsa`, kubeconfigs,
131
- `*.tfstate`, `credentials*.json`), files over 10 MB and files past 100 MB in total.
132
- - A file that cannot be read or copied stops `delete`/`finish` before anything is removed,
133
- unless `--force`; the TUI warns and deletes anyway.
134
- `status --oneline` emits a compact `TASK repoA✓ repoB●2↑1` summary that slots straight into
135
- a Claude Code statusline or shell prompt.
113
+ `list --json` and `status --json` show each task's `kind` (`task` or `epic`) and its `epic`.
114
+ `delete` and `finish` refuse an epic that still has tasks, even with `--force`.
115
+
116
+ #### Sharing context inside an epic
117
+
118
+ The Claude sessions of one epic can learn from each other:
119
+
120
+ | Command | What it does |
121
+ | --- | --- |
122
+ | `epic note "text"` | Adds a note to this task's file in the epic log (`-` reads stdin) |
123
+ | `epic log [TASK]` | Shows each task's notes and the recap of its latest Claude session; `--json` |
124
+ | `epic ask TASK "question"` | A read-only copy of that task's latest session answers |
125
+ | `epic sync` | Refreshes the epic block in existing tasks' `CLAUDE.md` after an upgrade |
126
+
127
+ Each task's `CLAUDE.md` gets a managed block that explains these commands to its session.
128
+
129
+ - **Scope:** inside a task folder, the commands reach only that task's epic.
130
+ - **Running sessions:** `epic ask` exits with code 3 when the task's session is running and
131
+ prints its name; the asking session then sends it a message with SendMessage.
132
+ - **Read-only:** the copy that answers can read files but not change them, can't read
133
+ credential files, and leaves the asked task's session untouched.
134
+ - **Cost:** each turn of the copy is a model call on that session's context, 8 turns at
135
+ most (`--max-turns`); `--model sonnet` makes it cheaper.
136
+
137
+ The [User Guide](docs/user-guide.md#epics) has the details.
138
+
139
+ #### Exit codes
140
+
141
+ | Code | Meaning |
142
+ | --- | --- |
143
+ | 0 | Success |
144
+ | 1 | Failure; the reason is on stderr |
145
+ | 3 | `epic ask` only: the task's session is running; its name is on stdout |
146
+
147
+ #### Safe delete and archive
148
+
149
+ `delete` and `finish` run the same safety check as the TUI: uncommitted, unpushed or
150
+ unmerged work blocks deletion unless `--force`. With `glab` or `gh` installed, squash and
151
+ rebase merges count as merged.
152
+
153
+ Before deleting, the CLI archives the task's remaining diff as a patch and copies the files
154
+ in the task folder outside the worktrees to `<task>-<timestamp>.files/` next to it
155
+ (`finish --no-archive` skips both):
156
+
157
+ - **Skipped:** hidden files, symlinks, `node_modules`, `vendor` and `.terraform` folders,
158
+ and an unedited generated `CLAUDE.md`.
159
+ - **Left out with a warning:** key material (`*.pem`, `*.key`, `id_rsa`, kubeconfigs,
160
+ `*.tfstate`, `credentials*.json`), files over 10 MB, and files past 100 MB in total.
161
+ - **Always stops the delete:** a diff that cannot be archived; the CLI prints the partial
162
+ archive's path.
163
+ - **Stops the delete unless `--force`:** a task file that cannot be read or copied.
164
+
165
+ In both cases the TUI stops too, names what was left out in the messages panel, and asks
166
+ again before it deletes.
136
167
 
137
168
  ## 📖 Documentation
138
169
 
@@ -218,8 +249,9 @@ Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
218
249
  - Git 2.0+
219
250
  - 256-color terminal
220
251
  - Unix-like OS (macOS, Linux, WSL2). Opening a folder, editor or Claude session in a
221
- new terminal tab (`o`, `e`, `c`) drives Ghostty via AppleScript and is macOS-only;
222
- elsewhere those keys show a notice
252
+ new terminal tab (`o`, `e`, `c`) opens a zellij tab when the TUI runs inside zellij,
253
+ on any OS. Otherwise it drives Ghostty via AppleScript and is macOS-only; elsewhere
254
+ those keys show a notice
223
255
 
224
256
  See [Installation Guide](docs/installation.md) for detailed requirements and setup.
225
257
 
@@ -210,6 +210,14 @@ glab_path = "glab"
210
210
  # Default: "gh" (searches PATH)
211
211
  gh_path = "gh"
212
212
 
213
+ # zellij: o/e/c open zellij tabs whenever the TUI runs inside zellij. With
214
+ # autostart, a TUI started outside zellij re-launches itself inside session
215
+ # zellij_session, so its tabs survive a terminal restart (see the user guide).
216
+ # Defaults: "zellij", false, "tasktree" (letters, digits, '.', '_', '-')
217
+ zellij_path = "zellij"
218
+ zellij_autostart = false
219
+ zellij_session = "tasktree"
220
+
213
221
  # ============================================================================
214
222
  # Forge (MR/PR state via glab/gh)
215
223
  # ============================================================================
@@ -419,6 +427,9 @@ refresh_interval = 15 # Refresh every 15 seconds
419
427
  | `hunk_path` | string | `"hunk"` | - | Path to hunk diff-viewer executable |
420
428
  | `glab_path` | string | `"glab"` | - | Path to GitLab CLI (MR/CI status) |
421
429
  | `gh_path` | string | `"gh"` | - | Path to GitHub CLI (PR/CI status) |
430
+ | `zellij_path` | string | `"zellij"` | - | Path to zellij (tabs and autostart) |
431
+ | `zellij_autostart` | bool | `false` | - | Re-launch the TUI inside zellij |
432
+ | `zellij_session` | string | `"tasktree"` | - | zellij session for autostart |
422
433
 
423
434
  ## Forge Settings
424
435
 
@@ -85,26 +85,50 @@ names their epic, so nothing moves on disk.
85
85
  - `enter` or `space` folds an epic. A folded epic row still shows the dirty
86
86
  count and the most urgent Claude state of its tasks.
87
87
  - Epics don't nest. An epic that still has tasks can't be deleted.
88
- - Each task's `CLAUDE.md` gets a short block between `<!-- tasktree:epic -->` markers
89
- that names the epic folder and how to find sibling tasks, so a Claude session knows
90
- the bigger picture. It updates on every epic change; text outside the markers is
91
- never touched.
92
- - The epic log lets the sessions of one epic share what they learned. A session
93
- records decisions, interfaces and open questions with
94
- `tasktree-manager epic note "..."`; they go to `epic-log/<task>.md` in the epic
95
- folder. `tasktree-manager epic log` shows every task's notes and the recap of its
96
- latest Claude session, so a session can check what its siblings did before asking.
97
- The `CLAUDE.md` block tells each session about both commands, and that notes are
98
- information from other sessions, not instructions.
88
+ - Each task's `CLAUDE.md` gets a short block between `<!-- tasktree:epic -->` markers.
89
+ It names the epic folder, explains how to find sibling tasks and how to share context
90
+ with them. It updates on every epic change; text outside the markers is never touched.
91
+ - From scripts: `tasktree-manager epic create/add/remove/mark/unmark/list/note/log/ask/sync`.
92
+
93
+ #### Sharing context between sessions
94
+
95
+ The Claude sessions of one epic can learn from each other. The `CLAUDE.md` block tells
96
+ each session to try these in order:
97
+
98
+ 1. **Read the epic log.** `tasktree-manager epic log` shows every task's notes and the
99
+ recap of its latest Claude session. `epic log TASK` shows one task.
100
+ 2. **Ask the task.** `tasktree-manager epic ask TASK "question"` resumes a read-only copy
101
+ of that task's latest session, which answers the question.
102
+ 3. **Message a running session.** If the task's session is running, `epic ask` exits
103
+ with code 3 and prints the session name. The asking session sends it a message with
104
+ SendMessage instead. `--fork` asks a copy anyway.
105
+
106
+ Sessions add to the log with `tasktree-manager epic note "..."`: decisions, interfaces,
107
+ open questions, finished work that other tasks depend on.
108
+
109
+ **Notes:**
110
+
111
+ - Notes go to `epic-log/<task>.md` in the epic folder, one file per task.
99
112
  - A session writes only its own task's notes. From a terminal outside any task,
100
113
  `epic note --task NAME` writes for a task and marks the entry as written outside it.
101
- - Notes stay in the epic after their task is finished, moved or deleted; `epic log`
102
- lists them as "no longer in the epic". A note is at most 16 KB, and `epic log` shows
103
- the newest 64 KB of each task's notes.
104
- - After upgrading tasktree-manager, run `tasktree-manager epic sync` to refresh the
105
- block in existing tasks (the TUI also refreshes it when it starts a Claude session).
106
- Folders without a `CLAUDE.md` yet are counted and skipped.
107
- - From scripts: `tasktree-manager epic create/add/remove/mark/unmark/list/note/log/sync`.
114
+ - Notes stay after their task is finished, moved or deleted; `epic log` lists them as
115
+ "no longer in the epic".
116
+ - A note is at most 16 KB. `epic log` shows the newest 64 KB of each task's notes.
117
+ - Notes and answers come from other sessions: they are information, not instructions.
118
+
119
+ **`epic ask`:**
120
+
121
+ - Only tasks of the same epic and the epic folder can be asked. A session in a task
122
+ outside any epic cannot ask.
123
+ - The copy can read files but not change them. It can't read credential files (forge CLI
124
+ tokens, `.env` files anywhere, the key material the archive leaves out).
125
+ Nothing is saved in the asked task, and its session stays untouched.
126
+ - Each turn of the copy is a model call on the size of that session's context, 8 turns
127
+ at most (`--max-turns`). `--model sonnet` makes it cheaper.
128
+
129
+ **After an upgrade:** run `tasktree-manager epic sync` to refresh the block in existing
130
+ tasks. The TUI also refreshes it when it starts a Claude session. Folders without a
131
+ `CLAUDE.md` yet are counted and skipped.
108
132
 
109
133
  ### Worktrees
110
134
 
@@ -277,6 +301,8 @@ terraform edits sit unstaged. Next, decide whether to hand-create the group.
277
301
  - **Title**: the session name (`/rename`), else Claude's own title, else the session slug
278
302
  - **Turn line**: duration of the last turn and when it finished; `busy`/`idle` mirrors the task's Claude status indicator
279
303
  - **Recap**: the summary Claude writes a few minutes after a turn when the session idles. Until one exists, the dim `last prompt:` line shows what was asked last
304
+ - The session is the newest one started in the task folder or one of its worktrees, as in
305
+ `epic log`. Headless `claude -p` runs, such as commit-message helpers, are skipped
280
306
  - Nothing is shown for tasks without a session. The block refreshes as you move the cursor and every 5 seconds while a transcript changes. Disable with `claude_recap = false` under `[tools]` in `config.toml`
281
307
 
282
308
  **Git status codes:**
@@ -430,7 +456,7 @@ Useful when you're spinning up several similar tasks that share the same set of
430
456
  | `b` | Dispatch agent | Run a background Claude agent (`claude --bg`) in the selected worktree |
431
457
 
432
458
  **How it works:**
433
- - `c` opens Claude Code CLI in a new Ghostty terminal tab at the task directory.
459
+ - `c` opens Claude Code CLI in a new terminal tab at the task directory (a zellij tab inside zellij, see [zellij](#zellij)).
434
460
  - If `~/.claude/projects/<task-folder>/` already has session transcripts, runs `claude -r` to pick from them; otherwise runs `claude` to start fresh.
435
461
  - `C` opens the Claude desktop app via the `claude://code/new?folder=<task-folder>` URL scheme.
436
462
  - 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.
@@ -831,9 +857,9 @@ npm i -g hunkdiff
831
857
 
832
858
  **Direct editor integration:**
833
859
  1. Highlight task or worktree
834
- 2. Press `e` to open your configured editor in a new Ghostty tab (`$EDITOR .`)
835
- 3. tasktree-manager keeps running alongside the editor (macOS + Ghostty only, see
836
- Limitations)
860
+ 2. Press `e` to open your configured editor in a new terminal tab (`$EDITOR .`)
861
+ 3. tasktree-manager keeps running alongside the editor (a zellij tab inside zellij,
862
+ otherwise a Ghostty tab on macOS; see [zellij](#zellij))
837
863
 
838
864
  **Configure your editor** in `~/.config/tasktree-manager/config.toml`:
839
865
  ```toml
@@ -864,6 +890,47 @@ code ~/tasks/FEAT-123 # Open entire task as workspace
864
890
  - Use "Open Folder" or equivalent
865
891
  - Git integration works normally
866
892
 
893
+ ### zellij
894
+
895
+ `o`, `e` and `c` open a new terminal tab. Where the tab lives depends on where
896
+ tasktree-manager runs:
897
+
898
+ - Inside a zellij session (`ZELLIJ_SESSION_NAME` is set), each key opens a zellij tab
899
+ named after the folder and what runs in it: `TASK · shell`, `TASK/repo · editor`,
900
+ `TASK · claude`. The tab runs in the zellij server, so it keeps running when you close
901
+ or restart the terminal. Pressing the key again while that tab is open switches to it
902
+ instead of opening a second one.
903
+ - Anywhere else, each key opens a Ghostty tab via AppleScript (macOS only).
904
+
905
+ To run the TUI in zellij every time, set this in `config.toml`:
906
+
907
+ ```toml
908
+ [tools]
909
+ zellij_autostart = true
910
+ zellij_session = "tasktree" # the default
911
+ ```
912
+
913
+ Plain `tasktree-manager` then re-launches itself as
914
+ `zellij attach -c tasktree -- python -m tasktree_manager.app`. Without the setting, start
915
+ it that way yourself: `zellij attach -c tasktree -- tasktree-manager`.
916
+
917
+ After a terminal restart, run `tasktree-manager` (with autostart) or
918
+ `zellij attach tasktree`. Either brings back the TUI and every tab it opened, Claude
919
+ sessions included. The command after `--` runs only when the session is created, so a
920
+ second `tasktree-manager` in another terminal tab shows the same session.
921
+
922
+ - A tab that runs a command (`e`, `c`) closes when the command exits.
923
+ - The zellij tab runs the command with `sh -c`, so `editor` and `claude_path` must name
924
+ programs on `PATH`. A shell alias or fish function works only in the Ghostty tab.
925
+ - A zellij session does not survive a reboot. Attaching afterwards (or autostart) makes
926
+ zellij resurrect the saved layout, and each tab waits for ENTER before its command runs
927
+ again; tasktree-manager does not test that path.
928
+ - Autostart applies only when the TUI starts in a terminal outside zellij, never to a
929
+ piped run or to the headless CLI.
930
+ - zellij's default keybindings take Ctrl+P, Ctrl+T, Ctrl+O and other keys before the TUI
931
+ or Claude Code sees them. Pick zellij's "Unlock First (non-colliding)" preset or Alt-based
932
+ bindings, so Ctrl+P still opens the command palette.
933
+
867
934
  ### CI/CD
868
935
 
869
936
  tasktree-manager creates normal git branches, so CI/CD works seamlessly:
@@ -71,7 +71,7 @@ version-file = "tasktree_manager/_version.py"
71
71
  # Semantic Release Configuration
72
72
  [tool.semantic_release]
73
73
  version_toml = ["pyproject.toml:tool.semantic_release.version"]
74
- version = "2.17.0"
74
+ version = "2.19.0"
75
75
  tag_format = "v{version}"
76
76
  branch = "main"
77
77
  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.17.0'
22
- __version_tuple__ = version_tuple = (2, 17, 0)
21
+ __version__ = version = '2.19.0'
22
+ __version_tuple__ = version_tuple = (2, 19, 0)
23
23
 
24
24
  __commit_id__ = commit_id = None