@soprog_/cdwt 0.1.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/README.md +191 -0
- package/dist/cli.js +1787 -0
- package/dist/cli.js.map +1 -0
- package/package.json +71 -0
- package/shell/cdwt.zsh +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# cdwt
|
|
2
|
+
|
|
3
|
+
Interactive `git worktree` switcher for `zsh`. Pick an existing worktree, jump
|
|
4
|
+
back to the default branch worktree, create a new worktree from the default
|
|
5
|
+
branch, check out a GitHub PR into a worktree, or delete one — and `cd` into
|
|
6
|
+
the result.
|
|
7
|
+
|
|
8
|
+
Written in TypeScript, distributed as an `npx`-installable CLI plus a small
|
|
9
|
+
`zsh` function that performs the `cd`.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- Node.js 20+
|
|
14
|
+
- `git`
|
|
15
|
+
- `zsh`
|
|
16
|
+
- `fzf` recommended — without it the selector falls back to a numbered prompt
|
|
17
|
+
- `gh` optional — enables the `github pr` section
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
### From npm
|
|
22
|
+
|
|
23
|
+
Try it once:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npx @soprog_/cdwt --default-branch
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Install for daily use:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm i -g @soprog_/cdwt # or: pnpm add -g @soprog_/cdwt
|
|
33
|
+
cdwt install # writes shell function + sources it from ~/.zshrc
|
|
34
|
+
exec zsh -l
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### From source
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
git clone https://github.com/souta0104/cdworktree.git
|
|
41
|
+
cd cdworktree
|
|
42
|
+
pnpm install
|
|
43
|
+
pnpm build
|
|
44
|
+
pnpm link --global
|
|
45
|
+
cdwt install
|
|
46
|
+
exec zsh -l
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`cdwt install` writes `~/.local/share/cdwt/cdwt.zsh` and adds
|
|
50
|
+
`source "$HOME/.local/share/cdwt/cdwt.zsh"` to `~/.zshrc` (skipped if already
|
|
51
|
+
present). The shell function is required because a child process can't change
|
|
52
|
+
the parent shell's directory: `cdwt` prints the destination path on stdout
|
|
53
|
+
and the function `cd`s into it.
|
|
54
|
+
|
|
55
|
+
## Usage
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
cdwt
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Opens a single picker with rows tagged by section (in this order):
|
|
62
|
+
|
|
63
|
+
| Glyph + Tag | Action on `enter` |
|
|
64
|
+
| ---------------- | ----------------------------------------------------------- |
|
|
65
|
+
| `★ [main]` | `cd` into the main worktree |
|
|
66
|
+
| `● [worktree]` | `cd` into an existing linked worktree |
|
|
67
|
+
| `◆ [PR]` | `cd` into the PR's worktree (creates a detached one if new) |
|
|
68
|
+
| `○ [branch]` | runs `git worktree add` for that local branch and `cd`s in |
|
|
69
|
+
|
|
70
|
+
Filled glyphs (`★ ●`) mark rows whose worktree already exists on disk; open
|
|
71
|
+
glyphs (`○ ◆`) mark rows that will create a new worktree on `enter`. Each
|
|
72
|
+
section also has its own color so worktrees and branches are visually distinct.
|
|
73
|
+
|
|
74
|
+
`/new <branch>` creates a new worktree from the default branch; `ctrl-d` on
|
|
75
|
+
a `[worktree]` row deletes that worktree (with a confirmation prompt).
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
cdwt --default-branch # skip the picker, jump to the main worktree
|
|
79
|
+
cdwt -h # show help (bypasses the shell wrapper)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`--default-branch` jumps to the main worktree (the one that holds the
|
|
83
|
+
non-bare `.git` directory), not literally to a worktree of `origin/HEAD`.
|
|
84
|
+
In a typical setup these are the same; if you've checked out a different
|
|
85
|
+
branch in the main worktree, that's what you'll land on.
|
|
86
|
+
|
|
87
|
+
### New worktree paths
|
|
88
|
+
|
|
89
|
+
`new worktree` and `local branch` create the worktree at:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
<repo-parent>/<repo-name>-<branch-slug>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`<branch-slug>` replaces `/`, spaces, and any non-`[A-Za-z0-9._-]` character
|
|
96
|
+
with `-`, then trims leading/trailing dashes (e.g. `feature/awesome` →
|
|
97
|
+
`repo-feature-awesome`).
|
|
98
|
+
|
|
99
|
+
`github pr` for a branch without a local worktree creates:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
<repo-parent>/<repo-name>-pr-<pr-number>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
…then runs `gh pr checkout <pr-number>` inside it.
|
|
106
|
+
|
|
107
|
+
### Selector keys
|
|
108
|
+
|
|
109
|
+
With `fzf`:
|
|
110
|
+
|
|
111
|
+
- `enter` — `cd` into the highlighted entry
|
|
112
|
+
- `esc` — cancel
|
|
113
|
+
- `tab` / `shift-tab` — cycle the filter (all / worktree / branch / pr)
|
|
114
|
+
- `ctrl-d` — delete the highlighted worktree (confirmation prompt)
|
|
115
|
+
- `?` — show the help overlay (includes a row legend)
|
|
116
|
+
- `/` — slash commands (`/new <branch>`, `/main`, `/pr`, `/refresh`, `/help`)
|
|
117
|
+
|
|
118
|
+
Without `fzf`: numbered prompt; type a number to jump, `d <number>` to
|
|
119
|
+
delete that entry, or one of the slash commands above.
|
|
120
|
+
|
|
121
|
+
## Configuration
|
|
122
|
+
|
|
123
|
+
`.cdwt/settings.json` controls which Git-ignored files get copied into newly
|
|
124
|
+
created worktrees:
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"copyIgnored": {
|
|
129
|
+
"paths": [".claude/settings.local.json"],
|
|
130
|
+
"patterns": [".claude/**", "CLAUDE.md", "*.local.json"]
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- `paths` — repo-relative file or directory paths copied verbatim
|
|
136
|
+
- `patterns` — glob patterns matched against repo-relative paths
|
|
137
|
+
- a pattern containing `/` matches the whole path
|
|
138
|
+
- a pattern without `/` matches any file or directory of that name
|
|
139
|
+
|
|
140
|
+
Only files Git considers ignored are copied. Patterns and paths that escape
|
|
141
|
+
the worktree (`..`, absolute, …) are rejected.
|
|
142
|
+
|
|
143
|
+
### Config resolution order (weak → strong)
|
|
144
|
+
|
|
145
|
+
Later files override matching keys; missing keys leave earlier values intact.
|
|
146
|
+
An explicit empty array clears the inherited value.
|
|
147
|
+
|
|
148
|
+
1. `$HOME/.cdwt/settings.json`
|
|
149
|
+
2. `.cdwt/settings.json` walking from `/` down to the cwd (or to the main
|
|
150
|
+
worktree if cwd is outside it)
|
|
151
|
+
|
|
152
|
+
Set `CDWT_CONFIG=/path/to/settings.json` or pass `--config <file>` to read
|
|
153
|
+
only that file.
|
|
154
|
+
|
|
155
|
+
## Development
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
pnpm install
|
|
159
|
+
pnpm test # vitest
|
|
160
|
+
pnpm typecheck # tsc --noEmit
|
|
161
|
+
pnpm lint # eslint
|
|
162
|
+
pnpm format # prettier --write .
|
|
163
|
+
pnpm build # tsup → dist/cli.js
|
|
164
|
+
pnpm dev -- --default-branch
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Layout:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
src/
|
|
171
|
+
cli.ts commander entry
|
|
172
|
+
commands/ select / install / actions (confirm + git ops)
|
|
173
|
+
core/ pure functions (paths, config merge, sections, ...)
|
|
174
|
+
io/ git, gh, fs, repo context
|
|
175
|
+
ui/ fzf, prompts, selector flow
|
|
176
|
+
shell/cdwt.zsh zsh wrapper that cd's into stdout
|
|
177
|
+
tests/ vitest (pure + integration against a temp git repo)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Uninstall
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
npm rm -g cdwt # or: pnpm remove -g cdwt
|
|
184
|
+
rm -f ~/.local/share/cdwt/cdwt.zsh
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Then remove this line from `~/.zshrc`:
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
source "$HOME/.local/share/cdwt/cdwt.zsh"
|
|
191
|
+
```
|