@moberg_hr/work-tree 1.5.0
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.
- package/LICENSE +21 -0
- package/README.md +456 -0
- package/dist/bin.js +10476 -0
- package/dist/bin.js.map +1 -0
- package/dist/wd-bin.js +10452 -0
- package/dist/wd-bin.js.map +1 -0
- package/dist/web/assets/index-Quf37ngR.css +1 -0
- package/dist/web/assets/index-vD0svqIi.js +106 -0
- package/dist/web/assets/index-vD0svqIi.js.map +1 -0
- package/dist/web/index.html +13 -0
- package/package.json +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 moberghr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Work — Git Worktree Manager for AI-Assisted Development
|
|
4
|
+
|
|
5
|
+
### One terminal. Every branch. Every repo. Every Claude session.
|
|
6
|
+
|
|
7
|
+
**A cross-platform TypeScript CLI that turns git worktrees into a parallel-development cockpit. Spin up isolated workspaces per branch across one or many repos, auto-launch Claude Code, and orchestrate everything — PRs, Jira issues, and local tasks — from a single interactive dashboard.**
|
|
8
|
+
|
|
9
|
+
[](https://github.com/moberghr/cli-work-tree-manager/releases)
|
|
10
|
+
[](https://moberghr.github.io/cli-work-tree-manager/)
|
|
11
|
+
[](https://nodejs.org/)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
|
|
14
|
+
**[moberghr.github.io/cli-work-tree-manager](https://moberghr.github.io/cli-work-tree-manager/)** — the Work website.
|
|
15
|
+
|
|
16
|
+
[Quick Start](#quick-start) · [Why Work](#why-work) · [Commands](#commands) · [Dashboard](#interactive-dashboard) · [Groups](#groups-multi-repo-worktrees) · [Diff review (`wd`)](#diff-review-wd) · [Architecture](#architecture) · [FAQ](#faq)
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Why Work
|
|
23
|
+
|
|
24
|
+
Working on three branches in three repos with three Claude Code instances is a productivity superpower — *if* you can keep the cognitive overhead under control. Without tooling, you end up juggling terminals, losing track of which session is in which directory, and rebuilding mental context every time you switch.
|
|
25
|
+
|
|
26
|
+
Work is the missing layer between `git worktree` and your AI assistant. Every branch gets a real, isolated checkout. Every checkout gets its own Claude Code session, persisted across resumes. Every session is visible — alongside its PR status, assigned Jira issues, and pending tasks — in a single dashboard.
|
|
27
|
+
|
|
28
|
+
| Without Work | With Work |
|
|
29
|
+
|:---|:---|
|
|
30
|
+
| `cd ../some/path && git checkout -b feature/x && cp .env.local .` every time | `work tree api feature/x` — worktree created, dev settings copied, Claude launched |
|
|
31
|
+
| Three terminals, three editors, three lost contexts | One TUI: sessions, PRs, Jira, tasks — keyboard-driven, mouse-aware |
|
|
32
|
+
| "Which directory was that branch in again?" | `work resume` — recent sessions sorted by last access, one keystroke to re-enter |
|
|
33
|
+
| Multi-repo features = multiple `git worktree add` invocations and a hand-merged CLAUDE.md | `work tree mygroup feature/x` — every repo cloned in lockstep, combined CLAUDE.md generated automatically |
|
|
34
|
+
| Stale worktrees pile up after PRs merge | `work prune` — removes worktrees whose branches landed on main |
|
|
35
|
+
| Jira ticket → branch name → worktree → Claude prompt = manual every time | Select a Jira issue in the dash → branch slug auto-generated → worktree created → planning prompt sent to Claude |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# 1. Install (Node 18+, Git required)
|
|
43
|
+
git clone https://github.com/moberghr/cli-work-tree-manager work
|
|
44
|
+
cd work
|
|
45
|
+
npm install
|
|
46
|
+
npm run build
|
|
47
|
+
npm link
|
|
48
|
+
|
|
49
|
+
# 2. First-time setup — interactive
|
|
50
|
+
work init
|
|
51
|
+
|
|
52
|
+
# 3. Create a worktree and launch Claude Code
|
|
53
|
+
work tree api feature/login
|
|
54
|
+
|
|
55
|
+
# 4. Open the dashboard
|
|
56
|
+
work dash
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`work init` walks you through the worktrees root, your repo aliases, and tab-completion installation. Everything else is one keystroke away from the dashboard.
|
|
60
|
+
|
|
61
|
+
### Prerequisites
|
|
62
|
+
|
|
63
|
+
| Tool | Required | Used for |
|
|
64
|
+
|:---|:---|:---|
|
|
65
|
+
| **Node.js 18+** | yes | Runtime |
|
|
66
|
+
| **Git** | yes | Worktree operations |
|
|
67
|
+
| **[Claude Code CLI](https://claude.ai/code)** | recommended | Auto-launch on `work tree`, group CLAUDE.md generation |
|
|
68
|
+
| **[GitHub CLI (`gh`)](https://cli.github.com/)** | optional | PR pane in dashboard |
|
|
69
|
+
| **[Atlassian CLI (`acli`)](https://developer.atlassian.com/cloud/acli/)** | optional | Jira pane in dashboard |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Commands
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
work init # Interactive first-time setup
|
|
77
|
+
work tree|t <target> <branch> [flags] # Create or switch to a worktree
|
|
78
|
+
work remove <target> <branch> [--force] # Remove a worktree
|
|
79
|
+
work list [target] # List worktrees
|
|
80
|
+
work status [target] [branch] [--prune] # Show worktree merge/dirty status
|
|
81
|
+
work recent [count] # List recent sessions
|
|
82
|
+
work resume [--unsafe] # Resume a recent session
|
|
83
|
+
work dash [--unsafe] # Interactive TUI dashboard
|
|
84
|
+
work prune [--force] # Remove merged worktrees
|
|
85
|
+
work completion [--install] # Shell completions
|
|
86
|
+
|
|
87
|
+
work todo # List open tasks
|
|
88
|
+
work todo add|done|undo|edit|rm <args> # Manage tasks
|
|
89
|
+
work todo --all # Include completed tasks
|
|
90
|
+
|
|
91
|
+
work config add|remove|list|show|edit # Manage repos
|
|
92
|
+
work config group add|remove|regen <args> # Manage multi-repo groups
|
|
93
|
+
|
|
94
|
+
wd # PR-style diff in your browser (one-shot)
|
|
95
|
+
wd --watch # Background watcher; F5 to refresh
|
|
96
|
+
wd --stop # Stop the running watcher
|
|
97
|
+
wd -c # Interactive review with streaming comments
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`work tree` flags: `--base <branch>` (branch from a specific base), `--open` (open VS Code), `--unsafe` (skip Claude permission checks), `--prompt "..."` / `--prompt-file <path>` (send an initial prompt to Claude).
|
|
101
|
+
|
|
102
|
+
### Branch resolution order
|
|
103
|
+
|
|
104
|
+
When you run `work tree api feature/login`:
|
|
105
|
+
|
|
106
|
+
1. **Local branch exists** → checked out into the worktree
|
|
107
|
+
2. **Remote branch exists** → fetched and checked out as a tracking branch
|
|
108
|
+
3. **Neither** → a new branch is created from the configured base (or `--base`)
|
|
109
|
+
|
|
110
|
+
Branch directories normalize `/` → `-`, so `feature/login` lives at `<worktreesRoot>/<repo>/feature-login/`.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Interactive Dashboard
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
work dash
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
A keyboard-driven terminal UI built with [Ink](https://github.com/vadimdemedes/ink) and an embedded `node-pty` + `@xterm/headless` Claude Code session per worktree. Five panes, one focus model, zero context switching.
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
┌──────────────────────────────┬─────────────────────────────────────────────────┐
|
|
124
|
+
│ Sessions ▸ │ api · feature/login │
|
|
125
|
+
│ ▸ api · feature/login ● │ │
|
|
126
|
+
│ api · main │ > Implement the login page using the existing │
|
|
127
|
+
│ web · feat/dark-mode ● │ auth helpers... │
|
|
128
|
+
│ ──────────────────────────── │ │
|
|
129
|
+
│ Pull Requests │ ✓ Reading src/auth/AuthContext.tsx │
|
|
130
|
+
│ ★ #142 · feature/login ✓ │ ✓ Writing src/pages/login.tsx │
|
|
131
|
+
│ ✎ #138 · feat/dark-mode ✗ │ ✓ dotnet build (0 warnings, 0 errors) │
|
|
132
|
+
│ ──────────────────────────── │ │
|
|
133
|
+
│ Jira │ ⏵ │
|
|
134
|
+
│ In Progress │ │
|
|
135
|
+
│ PROJ-204 · Add 2FA │ │
|
|
136
|
+
│ ──────────────────────────── │ │
|
|
137
|
+
│ Tasks │ │
|
|
138
|
+
│ [ ] Refactor auth module │ │
|
|
139
|
+
│ [x] Document new endpoints │ │
|
|
140
|
+
└──────────────────────────────┴─────────────────────────────────────────────────┘
|
|
141
|
+
tab cycles · n new · d remove · g sync pane · G sync all · enter open · w worktree
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### What the dashboard does
|
|
145
|
+
|
|
146
|
+
- **Session pane** — every worktree as a row with a status indicator (`●` running, `○` idle, `▸` currently focused). Reactive to external `work tree` invocations via `fs.watch` on `history.json`.
|
|
147
|
+
- **PR pane** — open PRs across every configured repo via `gh pr list`. Decorated with check status (`✓` / `✗` / `●`), merge-conflict detection, your review state (`✔` approved, `✎` reviewed), draft dimming, and ownership (`★` your PR). Selecting a PR creates or resumes its worktree.
|
|
148
|
+
- **Jira pane** — issues assigned to you, grouped by status, fetched via `acli`. Selecting an issue prompts for project, generates a branch slug via Claude Haiku, creates the worktree, and sends a structured planning prompt to Claude. `o` opens the issue in your browser.
|
|
149
|
+
- **Tasks pane** — local tasks from `~/.work/tasks.json`. Press `a` to add, `e` to edit, `enter`/`x` to toggle, `d` to remove, `w` to spin up a `todo/<slug>` worktree.
|
|
150
|
+
- **Terminal pane** — the live Claude Code PTY for the focused session. Resumes prior conversations via `--continue`. Mouse scroll, Shift+drag for text selection.
|
|
151
|
+
- **Auto-sync on startup** — every repo remote fetched in parallel; PRs and Jira issues loaded immediately. `g` syncs the focused pane, `G` syncs everything.
|
|
152
|
+
- **Hook integration** — a local HTTP server (`tui/hooks.ts`) receives Claude Code lifecycle events (Stop, Notification, UserPromptSubmit) so session activity is reflected in real time. Hooks are auto-injected into `~/.claude/settings.json` on launch and cleaned up on exit.
|
|
153
|
+
- **Context-sensitive status bar** — keybinding hints change based on the focused pane.
|
|
154
|
+
|
|
155
|
+
### Keyboard reference
|
|
156
|
+
|
|
157
|
+
| Key | Action |
|
|
158
|
+
|:---|:---|
|
|
159
|
+
| `tab` | Cycle focus: sessions → PRs → Jira → tasks → terminal |
|
|
160
|
+
| `j` / `k` | Navigate within the focused pane |
|
|
161
|
+
| `enter` | Open / resume the selected item |
|
|
162
|
+
| `n` | New worktree (project + branch picker) |
|
|
163
|
+
| `d` | Remove the selected worktree |
|
|
164
|
+
| `w` | Create worktree from selected task / PR / Jira issue |
|
|
165
|
+
| `a` / `e` | Add or edit task (tasks pane) |
|
|
166
|
+
| `g` / `G` | Sync focused pane / sync everything |
|
|
167
|
+
| `u` | Rebase current worktree onto its base |
|
|
168
|
+
| `.` | Open worktree in editor |
|
|
169
|
+
| `o` | Open Jira issue in browser |
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Groups (Multi-Repo Worktrees)
|
|
174
|
+
|
|
175
|
+
When a feature spans several repositories — say a backend API change that ships with a frontend update — Work treats them as a single unit.
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Define a group
|
|
179
|
+
work config group add fullstack api web shared-lib
|
|
180
|
+
|
|
181
|
+
# Create one worktree workspace covering all three repos
|
|
182
|
+
work tree fullstack feature/new-checkout
|
|
183
|
+
|
|
184
|
+
# Combined directory layout
|
|
185
|
+
<worktreesRoot>/
|
|
186
|
+
fullstack/
|
|
187
|
+
feature-new-checkout/
|
|
188
|
+
api/ # worktree for api repo
|
|
189
|
+
web/ # worktree for web repo
|
|
190
|
+
shared-lib/ # worktree for shared-lib repo
|
|
191
|
+
CLAUDE.md # auto-generated combined instructions
|
|
192
|
+
|
|
193
|
+
# Tear it all down at once
|
|
194
|
+
work remove fullstack feature/new-checkout
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The combined `CLAUDE.md` is produced by invoking the Claude CLI to merge each repo's individual `CLAUDE.md` into a coherent multi-repo brief — so the Claude session that gets launched understands every codebase it can see. Regenerate any time with `work config group regen <name>`.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Diff Review (`wd`)
|
|
202
|
+
|
|
203
|
+
A second binary, **`wd`**, ships alongside `work` and gives you a GitHub-PR-style diff view in your browser — for the current worktree, or for every repo in a group.
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
wd # one-shot: render the current uncommitted diff, open in browser
|
|
207
|
+
wd --watch # background daemon: rewrites the file on every save, F5 to refresh
|
|
208
|
+
wd --stop # stop the watcher for this scope
|
|
209
|
+
wd -c # interactive review: leave comments inline, stream to stdout
|
|
210
|
+
wd main # diff vs an explicit ref
|
|
211
|
+
wd --branch # PR-style diff vs the branch this worktree was forked from
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
`wd` resolves the scope from your `cwd`: inside a single-repo worktree it diffs that repo; inside a group worktree (root or any sub-repo) it diffs every repo in the group and renders one tab per repo. Untracked files are included as synthesized "new file" diffs without touching your git index.
|
|
215
|
+
|
|
216
|
+
### Static and live modes
|
|
217
|
+
|
|
218
|
+
| Mode | What it does |
|
|
219
|
+
|:---|:---|
|
|
220
|
+
| `wd` | Renders once to `~/.work/diffs/<scope-hash>.html`, opens in your default browser. |
|
|
221
|
+
| `wd --watch` | Spawns a detached watcher (chokidar) that rewrites the same file on every save; per-repo dirty tracking so unchanged repos aren't recomputed. F5 in the browser to refresh. Stop with `wd --stop`. |
|
|
222
|
+
| `wd -c` | Foreground review server: same file plus a small HTTP server. Click any line number to drop an inline comment. Streams each comment to stdout as it's saved. Blocks until you click "End review" or Ctrl+C. |
|
|
223
|
+
|
|
224
|
+
### Interactive review (`wd -c`)
|
|
225
|
+
|
|
226
|
+
Designed to be driven by an AI assistant (or any process that wants to react to comments as they happen). When you save a comment in the browser it lands on stdout as a markdown chunk like:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
--- comment ---
|
|
230
|
+
**api/src/users.ts** : line 42 (right)
|
|
231
|
+
id: 1df977d4...
|
|
232
|
+
> use the new helper here
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Other features in review mode:
|
|
236
|
+
|
|
237
|
+
- **Live reload** via SSE — the page refreshes itself when files change; reloads are deferred while you're composing so your draft isn't lost.
|
|
238
|
+
- **Threaded replies** — a wrapping process can POST replies via `${URL}/api/comments` with `parentId` and `author: 'claude'`; they render inline under the original comment with distinct styling.
|
|
239
|
+
- **Outdated detection** — the line's raw content is captured at compose time; if the file changes underneath, the comment is dimmed with an "outdated" badge.
|
|
240
|
+
- **General comments** — a top-of-page composer for review notes that aren't tied to any line.
|
|
241
|
+
- **Sidebar comments list** — every comment for the active tab, click to scroll to it.
|
|
242
|
+
- **Stable file path** — `~/.work/diffs/<scope-hash>.html` — keep one tab open across `wd`, `wd --watch`, and `wd -c` invocations.
|
|
243
|
+
|
|
244
|
+
The live server URL is published to `~/.work/diffs/latest-review.url` at session start (deleted on exit) so any local tool can find it without scraping stdout. A ready-made Claude Code skill ships with the repo at `.claude/skills/wd-review/SKILL.md` — drop it into `~/.claude/skills/` and say *"review my changes with wd"* in any Claude session to drive the loop.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Configuration
|
|
249
|
+
|
|
250
|
+
Stored at `~/.work/config.json`:
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
{
|
|
254
|
+
"worktreesRoot": "/Users/you/worktrees",
|
|
255
|
+
"repos": {
|
|
256
|
+
"api": "/Users/you/repos/api",
|
|
257
|
+
"web": "/Users/you/repos/web"
|
|
258
|
+
},
|
|
259
|
+
"groups": {
|
|
260
|
+
"fullstack": ["api", "web"]
|
|
261
|
+
},
|
|
262
|
+
"copyFiles": [
|
|
263
|
+
"*.Development.json",
|
|
264
|
+
"*.Local.json",
|
|
265
|
+
".claude/settings.local.json"
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
`copyFiles` glob patterns are copied into every new worktree — the canonical use case is local dev settings (`appsettings.Development.json`, `.env.local`, `.claude/settings.local.json`) that are gitignored but needed to run the app. Edit via `work config edit` or manage via the `work config …` subcommands.
|
|
271
|
+
|
|
272
|
+
### Session tracking
|
|
273
|
+
|
|
274
|
+
Every `work tree` invocation upserts a row into `~/.work/history.json` keyed by `target + branch`. This powers:
|
|
275
|
+
|
|
276
|
+
- **`work status`** — joins history with live `git status` to show merge state, dirty trees, unpushed commits, and last-access timestamps.
|
|
277
|
+
- **`work recent`** — sessions sorted by last touched.
|
|
278
|
+
- **`work resume`** — interactive picker; one keystroke to re-enter the worktree and continue the prior Claude conversation.
|
|
279
|
+
- **Dashboard reactivity** — `fs.watch` on `history.json` means a `work tree` in another terminal shows up in the running dashboard immediately.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Architecture
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
bin.ts → cli.ts (yargs router) → commands/{tree,remove,list,status,recent,prune,dash,config,init,todo,diff}.ts
|
|
287
|
+
wd-bin.ts → forwards argv to the `diff` command (the `wd` binary shim)
|
|
288
|
+
│
|
|
289
|
+
▼
|
|
290
|
+
core/worktree.ts ← high-level setup / teardown
|
|
291
|
+
├── core/git.ts ← git wrapper
|
|
292
|
+
├── core/copy-files.ts ← glob-based file copying
|
|
293
|
+
├── core/resolve.ts ← group vs single-repo dispatch
|
|
294
|
+
├── core/history.ts ← session tracking
|
|
295
|
+
├── core/tasks.ts ← local task persistence
|
|
296
|
+
├── core/pr.ts ← GitHub PR fetching (gh)
|
|
297
|
+
├── core/jira.ts ← Jira issue fetching (acli)
|
|
298
|
+
└── core/setup-completions.ts
|
|
299
|
+
|
|
300
|
+
core/diff-*.ts ← `wd` diff + review feature
|
|
301
|
+
├── diff-parse.ts ← unified-diff parser
|
|
302
|
+
├── diff-pipeline.ts ← computeDiff(): git diff + synthetic untracked
|
|
303
|
+
├── repo-spec.ts ← RepoSpec + stableDiffPath
|
|
304
|
+
├── comment-server.ts ← HTTP + SSE server (review + read-only)
|
|
305
|
+
└── web-static.ts ← SPA static file handler
|
|
306
|
+
|
|
307
|
+
web/src/ ← React SPA (Vite → dist/web/)
|
|
308
|
+
├── apps/ReviewApp.tsx ← single-scope view (wd / wd -c)
|
|
309
|
+
├── apps/DashboardApp.tsx ← multi-session view (work web)
|
|
310
|
+
└── components/ ← Diff/, Review/, Sidebar/
|
|
311
|
+
|
|
312
|
+
tui-ink/ ← Ink/React TUI
|
|
313
|
+
├── App.tsx ← layout, keyboard, session mgmt
|
|
314
|
+
├── Sidebar.tsx ← session list, PR pane
|
|
315
|
+
├── TerminalPane.tsx ← xterm renderer
|
|
316
|
+
└── StatusBar.tsx
|
|
317
|
+
|
|
318
|
+
tui/ ← PTY + hook infra
|
|
319
|
+
├── session.ts ← node-pty + @xterm/headless
|
|
320
|
+
└── hooks.ts ← Claude Code lifecycle events
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Design principles
|
|
324
|
+
|
|
325
|
+
| Principle | What it means |
|
|
326
|
+
|:---|:---|
|
|
327
|
+
| **Atomic worktree operations** | `setupWorktree()` and `teardownWorktree()` are the high-level entry points used by both the CLI and the TUI. Low-level `createSingleWorktree()` rolls back on partial failure. |
|
|
328
|
+
| **Resolver pattern** | One name (`api`, `fullstack`) is dispatched through `resolveProjectTarget()` to either a group or a single repo. Commands branch on `isGroup` once and delegate. |
|
|
329
|
+
| **Branch resolution priority** | Local exists → remote exists (tracking branch) → neither (new branch from base). |
|
|
330
|
+
| **Path normalisation** | `feature/login` → `feature-login` directory. Always. |
|
|
331
|
+
| **External binaries are external** | tsup bundles `src/bin.ts` as ESM with all dependencies marked `external` — they're resolved from `node_modules` at runtime. Adding a dep means `npm install` *and* rebuild. |
|
|
332
|
+
| **Color forcing for Windows** | `bin.ts` raises `chalk.level` to 1 when chalk detects 0 — Windows `.cmd` shims don't preserve TTY detection. `NO_COLOR` is respected. |
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## Tab Completion
|
|
337
|
+
|
|
338
|
+
Auto-installed during `work init`. Available standalone:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
work completion --install
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Detects PowerShell 7 / 5.1 on Windows (via `[Environment]::GetFolderPath('MyDocuments')`) and bash / zsh on Unix (via `$SHELL`). Idempotent — uses a `# work tab completions` marker to skip if already present. Manual fallback:
|
|
345
|
+
|
|
346
|
+
| Shell | Add to profile |
|
|
347
|
+
|:---|:---|
|
|
348
|
+
| **PowerShell** (`$PROFILE`) | `work completion --shell powershell \| Out-String \| Invoke-Expression` |
|
|
349
|
+
| **Bash** (`~/.bashrc`) | `eval "$(work completion)"` |
|
|
350
|
+
| **Zsh** (`~/.zshrc`) | `eval "$(work completion)"` |
|
|
351
|
+
|
|
352
|
+
Completions are dynamic — branch names come from the worktree directory listing for groups, and from each repo's worktree list for single repos.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Development
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
npm run build # Bundle with tsup → dist/bin.js
|
|
360
|
+
npm run dev # Run directly via tsx (no build)
|
|
361
|
+
npm test # Run all tests with vitest
|
|
362
|
+
npm run test:watch # Watch mode
|
|
363
|
+
npx vitest run tests/core/resolve.test.ts # Single test file
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
After building, `work` is available globally via `npm link`. Rebuild after source changes.
|
|
367
|
+
|
|
368
|
+
### Project layout
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
work-tree/
|
|
372
|
+
├── src/
|
|
373
|
+
│ ├── bin.ts # Entry point (chalk forcing, shebang)
|
|
374
|
+
│ ├── cli.ts # yargs router
|
|
375
|
+
│ ├── commands/ # CLI command handlers
|
|
376
|
+
│ ├── core/ # Shared operations (worktree, git, history, …)
|
|
377
|
+
│ ├── tui-ink/ # Ink/React TUI dashboard
|
|
378
|
+
│ ├── tui/ # PTY sessions and hook server
|
|
379
|
+
│ ├── completions/ # Dynamic tab-completion handler
|
|
380
|
+
│ └── utils/
|
|
381
|
+
├── tests/ # vitest suites
|
|
382
|
+
├── work.ps1 # PowerShell shim
|
|
383
|
+
├── work-completions.ps1 # PowerShell completion script
|
|
384
|
+
├── tsup.config.ts
|
|
385
|
+
└── package.json
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Unsafe Mode & Debug Logging
|
|
391
|
+
|
|
392
|
+
`--unsafe` on `work tree`, `work resume`, or `work dash` passes `--dangerously-skip-permissions` to the Claude CLI — useful in trusted, sandboxed worktrees, dangerous everywhere else. Use deliberately.
|
|
393
|
+
|
|
394
|
+
All CLI output and internal debug messages stream to `~/.work/debug.log` with timestamps. Auto-rotates at 5 MB. The first place to look when worktree creation, group CLAUDE.md generation, or hook delivery misbehaves.
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## FAQ
|
|
399
|
+
|
|
400
|
+
<details>
|
|
401
|
+
<summary><b>Why git worktrees instead of branches in one checkout?</b></summary>
|
|
402
|
+
|
|
403
|
+
Branches share a working directory. Worktrees give every branch its own isolated checkout — separate `node_modules`, separate `bin/obj`, separate dev-server processes, separate Claude Code sessions. You can run all of them concurrently without `git stash` gymnastics or losing your build cache.
|
|
404
|
+
</details>
|
|
405
|
+
|
|
406
|
+
<details>
|
|
407
|
+
<summary><b>Do I have to use Claude Code?</b></summary>
|
|
408
|
+
|
|
409
|
+
No — `work tree`, `work list`, `work status`, `work prune`, and the dashboard's session pane all work without Claude Code installed. You just lose auto-launch, group CLAUDE.md generation, and the embedded terminal in the dashboard. The CLI degrades gracefully when `claude` isn't on PATH.
|
|
410
|
+
</details>
|
|
411
|
+
|
|
412
|
+
<details>
|
|
413
|
+
<summary><b>Does the dashboard work on Windows?</b></summary>
|
|
414
|
+
|
|
415
|
+
Yes. Ink and node-pty support Windows; PowerShell completions are installed automatically. Mouse and keyboard handling work in Windows Terminal, ConEmu, and the new VS Code integrated terminal.
|
|
416
|
+
</details>
|
|
417
|
+
|
|
418
|
+
<details>
|
|
419
|
+
<summary><b>What happens when a worktree's branch is merged?</b></summary>
|
|
420
|
+
|
|
421
|
+
`work prune` lists every worktree whose branch is merged into `main` / `master` and offers to remove them interactively. `--force` skips the prompt. For groups, every sub-repo's branch must be merged before the group is offered.
|
|
422
|
+
</details>
|
|
423
|
+
|
|
424
|
+
<details>
|
|
425
|
+
<summary><b>Can I customize which files get copied into new worktrees?</b></summary>
|
|
426
|
+
|
|
427
|
+
Yes — edit `copyFiles` in `~/.work/config.json` (or run `work config edit`). Any glob pattern works. The default set covers `*.Development.json`, `*.Local.json`, and `.claude/settings.local.json` — the typical "gitignored but required to run" trio.
|
|
428
|
+
</details>
|
|
429
|
+
|
|
430
|
+
<details>
|
|
431
|
+
<summary><b>How does the Jira → branch flow work?</b></summary>
|
|
432
|
+
|
|
433
|
+
Pick a Jira issue in the dash, choose the target project, and Work invokes Claude Haiku with the issue title to generate a branch slug. It then runs `work tree <project> <slug>` in a PTY and pipes a structured planning prompt to Claude via `--prompt-file`. End result: a fresh worktree with Claude already thinking about your ticket.
|
|
434
|
+
</details>
|
|
435
|
+
|
|
436
|
+
<details>
|
|
437
|
+
<summary><b>Can I use my own AI assistant instead of Claude Code?</b></summary>
|
|
438
|
+
|
|
439
|
+
The auto-launch and the dashboard's embedded session both target Claude Code specifically. Other tools can still benefit from the worktree management, group CLAUDE.md generation, and session tracking — just don't pass `--prompt` flags or use the embedded terminal pane.
|
|
440
|
+
</details>
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
## License
|
|
445
|
+
|
|
446
|
+
MIT — see [LICENSE](LICENSE).
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
<div align="center">
|
|
451
|
+
|
|
452
|
+
**Work — Git Worktree Manager** v1.3.0 · [Moberg d.o.o.](https://www.moberg.hr)
|
|
453
|
+
|
|
454
|
+
Built for engineers who run more than one branch at a time.
|
|
455
|
+
|
|
456
|
+
</div>
|