wtcode 0.2.0__tar.gz → 0.4.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.
- {wtcode-0.2.0/wtcode.egg-info → wtcode-0.4.0}/PKG-INFO +5 -3
- {wtcode-0.2.0 → wtcode-0.4.0}/README.md +4 -2
- {wtcode-0.2.0 → wtcode-0.4.0}/pyproject.toml +1 -1
- {wtcode-0.2.0 → wtcode-0.4.0}/wtcode/__init__.py +1 -1
- {wtcode-0.2.0 → wtcode-0.4.0}/wtcode/wtcode.sh +222 -34
- {wtcode-0.2.0 → wtcode-0.4.0/wtcode.egg-info}/PKG-INFO +5 -3
- {wtcode-0.2.0 → wtcode-0.4.0}/LICENSE +0 -0
- {wtcode-0.2.0 → wtcode-0.4.0}/setup.cfg +0 -0
- {wtcode-0.2.0 → wtcode-0.4.0}/wtcode/__main__.py +0 -0
- {wtcode-0.2.0 → wtcode-0.4.0}/wtcode.egg-info/SOURCES.txt +0 -0
- {wtcode-0.2.0 → wtcode-0.4.0}/wtcode.egg-info/dependency_links.txt +0 -0
- {wtcode-0.2.0 → wtcode-0.4.0}/wtcode.egg-info/entry_points.txt +0 -0
- {wtcode-0.2.0 → wtcode-0.4.0}/wtcode.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wtcode
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Launch your favorite code tool in a git worktree
|
|
5
5
|
Author-email: Jaeho Shin <netj@sparcs.org>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -61,6 +61,7 @@ wtcode --exec CMD [CMD-ARGS...]
|
|
|
61
61
|
|
|
62
62
|
- **`BRANCH`** -- Git branch or worktree name. If omitted and [fzf](https://github.com/junegunn/fzf) is available, interactively select one. Surround with `:` to create a new branch (use `:::name` or `name:::` to avoid fzf matching the colons).
|
|
63
63
|
- **`CMD`** -- Command to launch in the worktree. Defaults to `$WTCODE_CMD`, or the first available of: `claude`, `aider`, `codex`, `$SHELL`.
|
|
64
|
+
When `CMD` resolves to plain `claude` (no extra args) in a worktree that already existed, wtcode launches `claude /resume` so it opens straight into your last session there. Press `Esc` in the picker to start a new session instead.
|
|
64
65
|
- **`--exec`** -- Skip the branch argument; select interactively via fzf, then launch `CMD`.
|
|
65
66
|
- **`--help`** / **`--version`** -- Show help or version info.
|
|
66
67
|
|
|
@@ -88,13 +89,14 @@ WTCODE_CMD=cursor wtcode feature # use cursor as default tool
|
|
|
88
89
|
|
|
89
90
|
1. **Select/specify a branch** -- pass as argument or pick interactively with fzf
|
|
90
91
|
2. **Create or switch to the worktree** -- worktrees are organized under `$GIT_WORKTREE_ROOT` (defaults to `../<repo>.worktrees/`)
|
|
91
|
-
3. **
|
|
92
|
+
3. **Provision Claude Code, if that's what you're launching** -- when the resolved tool is `claude`, the worktree is auto-trusted (skips the "do you trust this folder" dialog) and `.claude/settings.json` / `.claude/settings.local.json` are symlinked in from the main repo if not already present -- never for other tools, never clobbering a file that's already there
|
|
93
|
+
4. **Launch the tool** -- runs the specified command (or smart default) inside the worktree
|
|
92
94
|
|
|
93
95
|
## Dependencies
|
|
94
96
|
|
|
95
97
|
- **git** -- required
|
|
96
98
|
- **[fzf](https://github.com/junegunn/fzf)** -- recommended, for interactive branch selection
|
|
97
|
-
- **[jq](https://jqlang.github.io/jq/)** -- optional, for Claude Code auto-trust setup
|
|
99
|
+
- **[jq](https://jqlang.github.io/jq/)** -- optional, for Claude Code auto-trust setup (no dependency needed for the settings symlinking itself)
|
|
98
100
|
|
|
99
101
|
## License
|
|
100
102
|
|
|
@@ -43,6 +43,7 @@ wtcode --exec CMD [CMD-ARGS...]
|
|
|
43
43
|
|
|
44
44
|
- **`BRANCH`** -- Git branch or worktree name. If omitted and [fzf](https://github.com/junegunn/fzf) is available, interactively select one. Surround with `:` to create a new branch (use `:::name` or `name:::` to avoid fzf matching the colons).
|
|
45
45
|
- **`CMD`** -- Command to launch in the worktree. Defaults to `$WTCODE_CMD`, or the first available of: `claude`, `aider`, `codex`, `$SHELL`.
|
|
46
|
+
When `CMD` resolves to plain `claude` (no extra args) in a worktree that already existed, wtcode launches `claude /resume` so it opens straight into your last session there. Press `Esc` in the picker to start a new session instead.
|
|
46
47
|
- **`--exec`** -- Skip the branch argument; select interactively via fzf, then launch `CMD`.
|
|
47
48
|
- **`--help`** / **`--version`** -- Show help or version info.
|
|
48
49
|
|
|
@@ -70,13 +71,14 @@ WTCODE_CMD=cursor wtcode feature # use cursor as default tool
|
|
|
70
71
|
|
|
71
72
|
1. **Select/specify a branch** -- pass as argument or pick interactively with fzf
|
|
72
73
|
2. **Create or switch to the worktree** -- worktrees are organized under `$GIT_WORKTREE_ROOT` (defaults to `../<repo>.worktrees/`)
|
|
73
|
-
3. **
|
|
74
|
+
3. **Provision Claude Code, if that's what you're launching** -- when the resolved tool is `claude`, the worktree is auto-trusted (skips the "do you trust this folder" dialog) and `.claude/settings.json` / `.claude/settings.local.json` are symlinked in from the main repo if not already present -- never for other tools, never clobbering a file that's already there
|
|
75
|
+
4. **Launch the tool** -- runs the specified command (or smart default) inside the worktree
|
|
74
76
|
|
|
75
77
|
## Dependencies
|
|
76
78
|
|
|
77
79
|
- **git** -- required
|
|
78
80
|
- **[fzf](https://github.com/junegunn/fzf)** -- recommended, for interactive branch selection
|
|
79
|
-
- **[jq](https://jqlang.github.io/jq/)** -- optional, for Claude Code auto-trust setup
|
|
81
|
+
- **[jq](https://jqlang.github.io/jq/)** -- optional, for Claude Code auto-trust setup (no dependency needed for the settings symlinking itself)
|
|
80
82
|
|
|
81
83
|
## License
|
|
82
84
|
|
|
@@ -8,6 +8,10 @@ shopt -s extglob
|
|
|
8
8
|
${WTCODE_DEBUG:+set -x}
|
|
9
9
|
|
|
10
10
|
--msg() { echo "wtcode: $*" >&2; }
|
|
11
|
+
@q() {
|
|
12
|
+
local quoted=$({ set +x; } 2>/dev/null; exec 2>&1; PS4=; set -x; : "$@")
|
|
13
|
+
echo "${quoted:2}" # lstrip the ': ' prefix to get the compact bash-quoted form
|
|
14
|
+
}
|
|
11
15
|
--sanitize-branch-name() {
|
|
12
16
|
printf '%s' "$1" |
|
|
13
17
|
tr '[:upper:]' '[:lower:]' | # lowercase
|
|
@@ -16,7 +20,7 @@ ${WTCODE_DEBUG:+set -x}
|
|
|
16
20
|
sed 's/^-//; s/-$//' # trim leading/trailing hyphens
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
WTCODE_VERSION=0.
|
|
23
|
+
WTCODE_VERSION=0.4.0
|
|
20
24
|
--version() { echo "wtcode $WTCODE_VERSION"; }
|
|
21
25
|
--help() {
|
|
22
26
|
cat <<USAGE
|
|
@@ -43,6 +47,12 @@ Environment variables:
|
|
|
43
47
|
split-window - create split pane with send-keys
|
|
44
48
|
new-window - create new window with send-keys
|
|
45
49
|
exec - exec the tool directly (opt out of send-keys)
|
|
50
|
+
WTCODE_TERMINAL_MODE Outside tmux, control how the tool is launched:
|
|
51
|
+
send-keys - reuse the current tab/window via AppleScript
|
|
52
|
+
(default; macOS only). Terminal.app and Ghostty
|
|
53
|
+
1.3+ use their own scripting support; any other
|
|
54
|
+
terminal falls back to simulated keystrokes
|
|
55
|
+
exec - exec the tool directly (opt out of send-keys)
|
|
46
56
|
WTCODE_DEBUG Enable debug tracing when set
|
|
47
57
|
GIT_WORKTREE_ROOT Override the directory where worktrees are created
|
|
48
58
|
|
|
@@ -69,6 +79,7 @@ WTCODE_CMDS_TO_TRY=(
|
|
|
69
79
|
###############################################################################
|
|
70
80
|
--enter-git-worktree() {
|
|
71
81
|
local branch_name=
|
|
82
|
+
WTCODE_WORKTREE_EXISTED=false
|
|
72
83
|
|
|
73
84
|
# 1. determine which branch/worktree to use
|
|
74
85
|
if [[ $# -gt 0 ]]; then
|
|
@@ -172,6 +183,7 @@ WTCODE_CMDS_TO_TRY=(
|
|
|
172
183
|
if [[ -n $existing_worktree ]]; then
|
|
173
184
|
--msg "branch '$branch_name' is checked out at: $existing_worktree"
|
|
174
185
|
cd "$existing_worktree"
|
|
186
|
+
WTCODE_WORKTREE_EXISTED=true
|
|
175
187
|
return 0
|
|
176
188
|
fi
|
|
177
189
|
fi
|
|
@@ -207,6 +219,7 @@ WTCODE_CMDS_TO_TRY=(
|
|
|
207
219
|
|
|
208
220
|
if [[ -e "$worktree_path"/.git ]]; then
|
|
209
221
|
--msg "using existing worktree: $worktree_path"
|
|
222
|
+
WTCODE_WORKTREE_EXISTED=true
|
|
210
223
|
elif [[ -n ${remote_branch-} ]] && ! git rev-parse --verify "refs/heads/$branch_name" &>/dev/null; then
|
|
211
224
|
# remote branch: create local tracking branch in a new worktree
|
|
212
225
|
--msg "creating worktree for remote branch: $remote_branch"
|
|
@@ -228,6 +241,183 @@ WTCODE_CMDS_TO_TRY=(
|
|
|
228
241
|
git checkout "$branch_name" --
|
|
229
242
|
}
|
|
230
243
|
|
|
244
|
+
###############################################################################
|
|
245
|
+
## --provision-claude-settings -- Claude Code setup, only when launching claude
|
|
246
|
+
###############################################################################
|
|
247
|
+
# Everything Claude-Code-specific lives here so it runs once, synchronously,
|
|
248
|
+
# before dispatch -- regardless of tmux mode -- and only when the resolved
|
|
249
|
+
# tool is actually `claude`. See the call site in --launch-code-tool.
|
|
250
|
+
--provision-claude-settings() {
|
|
251
|
+
# auto-trust this worktree in Claude Code's global config. Newer Claude
|
|
252
|
+
# Code versions also gate a separate "pre-approves N tool permissions"
|
|
253
|
+
# onboarding screen (shown when .claude/settings.local.json grants
|
|
254
|
+
# auto-approve rules) that hasTrustDialogAccepted alone doesn't suppress --
|
|
255
|
+
# hasCompletedProjectOnboarding is needed too.
|
|
256
|
+
if type jq &>/dev/null && [[ -f ~/.claude.json ]]; then
|
|
257
|
+
(
|
|
258
|
+
export worktree_path="$PWD"
|
|
259
|
+
jq -e '.projects[env.worktree_path]' ~/.claude.json &>/dev/null || {
|
|
260
|
+
jq '.projects[env.worktree_path] = ({} | .hasTrustDialogAccepted = true | .hasCompletedProjectOnboarding = true)' \
|
|
261
|
+
~/.claude.json >~/.claude.json.wtcode.$$
|
|
262
|
+
mv -f ~/.claude.json.wtcode.$$ ~/.claude.json
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
fi
|
|
266
|
+
|
|
267
|
+
# symlink project-local settings from the main worktree, if not already
|
|
268
|
+
# present here -- never clobber a file that's git-tracked, hook-provisioned,
|
|
269
|
+
# or already customized in this worktree (including from a prior run: a
|
|
270
|
+
# dangling/previously-created symlink also counts as "already present").
|
|
271
|
+
local main_root
|
|
272
|
+
main_root=$(
|
|
273
|
+
git_common_dir=$(git rev-parse --git-common-dir)
|
|
274
|
+
cd "$git_common_dir"
|
|
275
|
+
cd ..
|
|
276
|
+
pwd
|
|
277
|
+
)
|
|
278
|
+
[[ -d "$main_root/.claude" ]] || return 0 # nothing to provision from
|
|
279
|
+
[[ "$main_root" == "$PWD" ]] && return 0 # already in the main worktree
|
|
280
|
+
|
|
281
|
+
local name created_names=()
|
|
282
|
+
for name in settings.json settings.local.json; do
|
|
283
|
+
local src="$main_root/.claude/$name" dst="$PWD/.claude/$name"
|
|
284
|
+
[[ -e "$src" ]] || continue # nothing to link
|
|
285
|
+
[[ -e "$dst" || -L "$dst" ]] && continue # don't clobber existing/broken link
|
|
286
|
+
mkdir -p "$PWD/.claude" # safe no-op if .claude/ (with other content) already exists
|
|
287
|
+
ln -s "$src" "$dst"
|
|
288
|
+
--msg "symlinked .claude/$name from main worktree"
|
|
289
|
+
created_names+=("$name")
|
|
290
|
+
done
|
|
291
|
+
|
|
292
|
+
(( ${#created_names[@]} > 0 )) || return 0
|
|
293
|
+
|
|
294
|
+
local gi="$PWD/.claude/.gitignore"
|
|
295
|
+
[[ -e $gi ]] && return 0 # respect a pre-existing, possibly customized file
|
|
296
|
+
|
|
297
|
+
local already_ignored=true
|
|
298
|
+
for name in "${created_names[@]}"; do
|
|
299
|
+
git check-ignore -q ".claude/$name" || already_ignored=false
|
|
300
|
+
done
|
|
301
|
+
$already_ignored && return 0
|
|
302
|
+
|
|
303
|
+
{
|
|
304
|
+
echo '# wtcode: symlinked from the main worktree; never commit these here'
|
|
305
|
+
echo 'settings.json'
|
|
306
|
+
echo 'settings.local.json'
|
|
307
|
+
} >"$gi"
|
|
308
|
+
--msg "created .claude/.gitignore"
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
###############################################################################
|
|
312
|
+
## --terminal-send-keys -- tmux-like send-keys for GUI terminal apps
|
|
313
|
+
###############################################################################
|
|
314
|
+
# Reuses the current tab/window in the surrounding terminal app, outside
|
|
315
|
+
# tmux. cd_cmd/run_cmd are sent as two separate lines rather than one
|
|
316
|
+
# `cd X && cmd` line, since the shell's PROMPT_COMMAND (what updates the
|
|
317
|
+
# tab/window title via OSC 7/6) only fires between commands, at the next
|
|
318
|
+
# prompt -- a single `&&` line never shows one, so the title would stay
|
|
319
|
+
# stale for as long as cmd runs.
|
|
320
|
+
#
|
|
321
|
+
# macOS-only: dispatches on $TERM_PROGRAM by looking for a matching
|
|
322
|
+
# --terminal-send-keys--macos--$TERM_PROGRAM function -- add support for
|
|
323
|
+
# another terminal app by just defining one, named to match its
|
|
324
|
+
# $TERM_PROGRAM value exactly. `type osascript` fails (and this returns 1)
|
|
325
|
+
# on any other platform, so this whole mechanism is a no-op there and
|
|
326
|
+
# callers just fall back to exec. Also returns 1 if there's no terminal
|
|
327
|
+
# emulator signal (TERM_PROGRAM/TERMINAL_EMULATOR, as in ~/.zprofile) at all.
|
|
328
|
+
--terminal-send-keys() {
|
|
329
|
+
local worktree_path="$PWD"
|
|
330
|
+
local cd_cmd="cd $(@q "$worktree_path")"
|
|
331
|
+
local run_cmd="$(@q "$@")"
|
|
332
|
+
|
|
333
|
+
# TODO: support Linux/general-unix terminals (and SSH sessions) too --
|
|
334
|
+
# e.g. terminals with OSC 7/6 + a way to inject text (wezterm cli,
|
|
335
|
+
# kitty @ send-text, iterm2's escape sequences, etc). For now this whole
|
|
336
|
+
# mechanism is macOS-only and returns 1 (falls back to exec) elsewhere.
|
|
337
|
+
type osascript &>/dev/null || return 1
|
|
338
|
+
|
|
339
|
+
local termprog=${TERM_PROGRAM-${TERMINAL_EMULATOR-}}
|
|
340
|
+
[[ -n $termprog ]] || return 1
|
|
341
|
+
if type -- "--terminal-send-keys--macos--$termprog" &>/dev/null; then
|
|
342
|
+
"--terminal-send-keys--macos--$termprog" "$cd_cmd" "$run_cmd"
|
|
343
|
+
else
|
|
344
|
+
--terminal-send-keys--macos--system-events "$cd_cmd" "$run_cmd"
|
|
345
|
+
fi
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
# `do script ... in front window`: reuses Terminal's front window via a real
|
|
349
|
+
# Apple Event, not a keystroke. `osascript -` reads the script from stdin;
|
|
350
|
+
# without it, osascript treats argv[0] as a script *file* path.
|
|
351
|
+
--terminal-send-keys--macos--Apple_Terminal() {
|
|
352
|
+
local result
|
|
353
|
+
result=$(osascript - "$@" <<'APPLESCRIPT'
|
|
354
|
+
on run argv
|
|
355
|
+
tell application "Terminal"
|
|
356
|
+
try
|
|
357
|
+
repeat with line_cmd in argv
|
|
358
|
+
do script (line_cmd as text) in front window
|
|
359
|
+
end repeat
|
|
360
|
+
set frontmost of front window to true
|
|
361
|
+
return "OK"
|
|
362
|
+
on error
|
|
363
|
+
return "NOTFOUND"
|
|
364
|
+
end try
|
|
365
|
+
end tell
|
|
366
|
+
end run
|
|
367
|
+
APPLESCRIPT
|
|
368
|
+
) || return 1
|
|
369
|
+
[[ $result == OK ]]
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
# Ghostty 1.3+ ships a real AppleScript dictionary: `input text ... to
|
|
373
|
+
# term` targets the terminal focused in the front window's selected tab.
|
|
374
|
+
# Falls back to --macos--system-events since this is still a young feature.
|
|
375
|
+
--terminal-send-keys--macos--ghostty() {
|
|
376
|
+
local result rc
|
|
377
|
+
result=$(osascript - "$@" <<'APPLESCRIPT'
|
|
378
|
+
on run argv
|
|
379
|
+
tell application "Ghostty"
|
|
380
|
+
try
|
|
381
|
+
set term to focused terminal of selected tab of front window
|
|
382
|
+
repeat with line_cmd in argv
|
|
383
|
+
input text ((line_cmd as text) & "\n") to term
|
|
384
|
+
end repeat
|
|
385
|
+
return "OK"
|
|
386
|
+
on error
|
|
387
|
+
return "NOTFOUND"
|
|
388
|
+
end try
|
|
389
|
+
end tell
|
|
390
|
+
end run
|
|
391
|
+
APPLESCRIPT
|
|
392
|
+
); rc=$?
|
|
393
|
+
[[ $rc -eq 0 && $result == OK ]] || --terminal-send-keys--macos--system-events "$@"
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
# Last resort: fake keystrokes via System Events (needs Accessibility
|
|
397
|
+
# permission). No `activate` call -- $TERM_PROGRAM isn't always a real app
|
|
398
|
+
# name, so this relies on the calling terminal still being frontmost.
|
|
399
|
+
--terminal-send-keys--macos--system-events() {
|
|
400
|
+
local result
|
|
401
|
+
result=$(osascript - "$@" <<'APPLESCRIPT'
|
|
402
|
+
on run argv
|
|
403
|
+
tell application "System Events"
|
|
404
|
+
try
|
|
405
|
+
repeat with line_cmd in argv
|
|
406
|
+
keystroke (line_cmd as text)
|
|
407
|
+
key code 36 -- Return
|
|
408
|
+
delay 0.05
|
|
409
|
+
end repeat
|
|
410
|
+
return "OK"
|
|
411
|
+
on error
|
|
412
|
+
return "NOTFOUND"
|
|
413
|
+
end try
|
|
414
|
+
end tell
|
|
415
|
+
end run
|
|
416
|
+
APPLESCRIPT
|
|
417
|
+
) || return 1
|
|
418
|
+
[[ $result == OK ]]
|
|
419
|
+
}
|
|
420
|
+
|
|
231
421
|
###############################################################################
|
|
232
422
|
## --launch-code-tool -- resolve and exec the tool in the worktree
|
|
233
423
|
###############################################################################
|
|
@@ -241,6 +431,16 @@ WTCODE_CMDS_TO_TRY=(
|
|
|
241
431
|
[[ $# -gt 0 ]] || set -- "${SHELL:-bash}"
|
|
242
432
|
fi
|
|
243
433
|
|
|
434
|
+
# default to resuming the last session when relaunching claude in a
|
|
435
|
+
# worktree that already existed; press Esc in the picker to start fresh
|
|
436
|
+
# instead. only kicks in when no CMD-ARGS were given, so explicit flags
|
|
437
|
+
# (e.g. `claude --resume`) are never overridden.
|
|
438
|
+
if [[ $1 == claude && $# -eq 1 && ${WTCODE_WORKTREE_EXISTED:-false} == true ]]; then
|
|
439
|
+
set -- "$1" /resume
|
|
440
|
+
fi
|
|
441
|
+
|
|
442
|
+
[[ $1 == claude ]] && --provision-claude-settings
|
|
443
|
+
|
|
244
444
|
--msg "launching: $*"
|
|
245
445
|
|
|
246
446
|
# when inside tmux, default to send-keys for command history access
|
|
@@ -251,12 +451,7 @@ WTCODE_CMDS_TO_TRY=(
|
|
|
251
451
|
case $mode in
|
|
252
452
|
send-keys|split-window|new-window)
|
|
253
453
|
local worktree_path="$PWD"
|
|
254
|
-
|
|
255
|
-
local quoted_args=()
|
|
256
|
-
for arg in "$@"; do
|
|
257
|
-
quoted_args+=("$(printf '%q' "$arg")")
|
|
258
|
-
done
|
|
259
|
-
local cmd="cd $(printf '%q' "$worktree_path") && ${quoted_args[*]}"
|
|
454
|
+
local cmd="cd $(@q "$worktree_path") && $(@q "$@")"
|
|
260
455
|
|
|
261
456
|
case $mode in
|
|
262
457
|
send-keys)
|
|
@@ -287,35 +482,28 @@ WTCODE_CMDS_TO_TRY=(
|
|
|
287
482
|
esac
|
|
288
483
|
fi
|
|
289
484
|
|
|
290
|
-
# outside tmux
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
485
|
+
# outside tmux: reuse the current tab/window if the terminal app supports
|
|
486
|
+
# it (see --terminal-send-keys). set WTCODE_TERMINAL_MODE=exec to opt out
|
|
487
|
+
if [[ -z ${TMUX:-} ]]; then
|
|
488
|
+
local mode=${WTCODE_TERMINAL_MODE:-send-keys}
|
|
489
|
+
case $mode in
|
|
490
|
+
send-keys)
|
|
491
|
+
if --terminal-send-keys "$@"; then
|
|
492
|
+
return 0
|
|
493
|
+
fi
|
|
494
|
+
--msg "could not reuse the current tab/window; falling back to exec"
|
|
495
|
+
;;
|
|
496
|
+
exec)
|
|
497
|
+
# explicitly opt out of send-keys, fall through to exec
|
|
498
|
+
;;
|
|
499
|
+
*)
|
|
500
|
+
--msg "unknown WTCODE_TERMINAL_MODE: $mode (expected: send-keys, exec)"
|
|
501
|
+
;;
|
|
502
|
+
esac
|
|
295
503
|
fi
|
|
296
|
-
}
|
|
297
504
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
## Define a function with the tool's name to add custom behavior.
|
|
301
|
-
###############################################################################
|
|
302
|
-
|
|
303
|
-
# claude: auto-trust the worktree in Claude Code's config
|
|
304
|
-
claude() {
|
|
305
|
-
if type jq &>/dev/null && [[ -f ~/.claude.json ]]; then
|
|
306
|
-
(
|
|
307
|
-
export worktree_path="$PWD"
|
|
308
|
-
jq -e '.projects[env.worktree_path]' ~/.claude.json &>/dev/null || {
|
|
309
|
-
jq '
|
|
310
|
-
.projects[env.worktree_path] = ({}
|
|
311
|
-
| .hasTrustDialogAccepted = true
|
|
312
|
-
)
|
|
313
|
-
' ~/.claude.json >~/.claude.json.wtcode.$$
|
|
314
|
-
mv -f ~/.claude.json.wtcode.$$ ~/.claude.json
|
|
315
|
-
}
|
|
316
|
-
)
|
|
317
|
-
fi
|
|
318
|
-
exec claude "$@"
|
|
505
|
+
# outside tmux, WTCODE_TMUX_MODE=exec, unsupported terminal, or unknown mode: exec directly
|
|
506
|
+
exec "$@"
|
|
319
507
|
}
|
|
320
508
|
|
|
321
509
|
###############################################################################
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wtcode
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Launch your favorite code tool in a git worktree
|
|
5
5
|
Author-email: Jaeho Shin <netj@sparcs.org>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -61,6 +61,7 @@ wtcode --exec CMD [CMD-ARGS...]
|
|
|
61
61
|
|
|
62
62
|
- **`BRANCH`** -- Git branch or worktree name. If omitted and [fzf](https://github.com/junegunn/fzf) is available, interactively select one. Surround with `:` to create a new branch (use `:::name` or `name:::` to avoid fzf matching the colons).
|
|
63
63
|
- **`CMD`** -- Command to launch in the worktree. Defaults to `$WTCODE_CMD`, or the first available of: `claude`, `aider`, `codex`, `$SHELL`.
|
|
64
|
+
When `CMD` resolves to plain `claude` (no extra args) in a worktree that already existed, wtcode launches `claude /resume` so it opens straight into your last session there. Press `Esc` in the picker to start a new session instead.
|
|
64
65
|
- **`--exec`** -- Skip the branch argument; select interactively via fzf, then launch `CMD`.
|
|
65
66
|
- **`--help`** / **`--version`** -- Show help or version info.
|
|
66
67
|
|
|
@@ -88,13 +89,14 @@ WTCODE_CMD=cursor wtcode feature # use cursor as default tool
|
|
|
88
89
|
|
|
89
90
|
1. **Select/specify a branch** -- pass as argument or pick interactively with fzf
|
|
90
91
|
2. **Create or switch to the worktree** -- worktrees are organized under `$GIT_WORKTREE_ROOT` (defaults to `../<repo>.worktrees/`)
|
|
91
|
-
3. **
|
|
92
|
+
3. **Provision Claude Code, if that's what you're launching** -- when the resolved tool is `claude`, the worktree is auto-trusted (skips the "do you trust this folder" dialog) and `.claude/settings.json` / `.claude/settings.local.json` are symlinked in from the main repo if not already present -- never for other tools, never clobbering a file that's already there
|
|
93
|
+
4. **Launch the tool** -- runs the specified command (or smart default) inside the worktree
|
|
92
94
|
|
|
93
95
|
## Dependencies
|
|
94
96
|
|
|
95
97
|
- **git** -- required
|
|
96
98
|
- **[fzf](https://github.com/junegunn/fzf)** -- recommended, for interactive branch selection
|
|
97
|
-
- **[jq](https://jqlang.github.io/jq/)** -- optional, for Claude Code auto-trust setup
|
|
99
|
+
- **[jq](https://jqlang.github.io/jq/)** -- optional, for Claude Code auto-trust setup (no dependency needed for the settings symlinking itself)
|
|
98
100
|
|
|
99
101
|
## License
|
|
100
102
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|