@gw-tools/gw 0.12.23 → 0.12.26

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 (4) hide show
  1. package/README.md +136 -135
  2. package/bin/gw +0 -0
  3. package/install.js +34 -11
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -7,6 +7,10 @@ A command-line tool for managing git worktrees, built with Deno.
7
7
  - [gw - Git Worktree Tools](#gw---git-worktree-tools)
8
8
  - [Table of Contents](#table-of-contents)
9
9
  - [Quick Start](#quick-start)
10
+ - [Initial Setup: Secrets in the Default Branch](#initial-setup-secrets-in-the-default-branch)
11
+ - [First-Time Setup Flow](#first-time-setup-flow)
12
+ - [Why This Matters](#why-this-matters)
13
+ - [Keeping Secrets Updated](#keeping-secrets-updated)
10
14
  - [Features](#features)
11
15
  - [Installation](#installation)
12
16
  - [Via npm (Recommended)](#via-npm-recommended)
@@ -21,6 +25,7 @@ A command-line tool for managing git worktrees, built with Deno.
21
25
  - [Options](#options)
22
26
  - [Examples](#examples)
23
27
  - [Auto-Copy Configuration](#auto-copy-configuration)
28
+ - [Hooks](#hooks)
24
29
  - [cd](#cd)
25
30
  - [Arguments](#arguments-1)
26
31
  - [Examples](#examples-1)
@@ -38,18 +43,21 @@ A command-line tool for managing git worktrees, built with Deno.
38
43
  - [init](#init)
39
44
  - [Options](#options-3)
40
45
  - [Examples](#examples-5)
46
+ - [Hook Variables](#hook-variables)
47
+ - [Auto-Cleanup Configuration](#auto-cleanup-configuration)
41
48
  - [When to Use](#when-to-use)
42
49
  - [show-init](#show-init)
43
- - [Options](#options-6)
44
- - [Examples](#examples-8)
50
+ - [Options](#options-4)
51
+ - [Examples](#examples-6)
52
+ - [Output Example](#output-example)
45
53
  - [When to Use](#when-to-use-1)
46
54
  - [sync](#sync)
47
55
  - [Arguments](#arguments-2)
48
- - [Options](#options-4)
49
- - [Examples](#examples-6)
50
- - [clean](#clean)
51
56
  - [Options](#options-5)
52
57
  - [Examples](#examples-7)
58
+ - [clean](#clean)
59
+ - [Options](#options-6)
60
+ - [Examples](#examples-8)
53
61
  - [How It Works](#how-it-works-3)
54
62
  - [Git Worktree Proxy Commands](#git-worktree-proxy-commands)
55
63
  - [list (ls)](#list-ls)
@@ -63,11 +71,7 @@ A command-line tool for managing git worktrees, built with Deno.
63
71
  - [Typical Workflow](#typical-workflow)
64
72
  - [Development](#development)
65
73
  - [Local Development \& Testing](#local-development--testing)
66
- - [Method 1: Shell Alias (Recommended for Active Development)](#method-1-shell-alias-recommended-for-active-development)
67
- - [Method 2: Symlink to Compiled Binary (Faster Execution)](#method-2-symlink-to-compiled-binary-faster-execution)
68
- - [Method 3: Development Wrapper Script (Best of Both Worlds)](#method-3-development-wrapper-script-best-of-both-worlds)
69
- - [Method 4: npm link (For Testing Installation)](#method-4-npm-link-for-testing-installation)
70
- - [Watch Mode for Active Development](#watch-mode-for-active-development)
74
+ - [Shell Alias Method (Recommended)](#shell-alias-method-recommended)
71
75
  - [Available Scripts](#available-scripts)
72
76
  - [Publishing](#publishing)
73
77
  - [Automated Release (Recommended)](#automated-release-recommended)
@@ -76,6 +80,8 @@ A command-line tool for managing git worktrees, built with Deno.
76
80
  - [Version Management](#version-management)
77
81
  - [Project Structure](#project-structure)
78
82
  - [Adding New Commands](#adding-new-commands)
83
+ - [Custom Commands (like `add`, `copy`)](#custom-commands-like-add-copy)
84
+ - [Git Proxy Commands (like `list`, `remove`)](#git-proxy-commands-like-list-remove)
79
85
  - [License](#license)
80
86
 
81
87
  ## Quick Start
@@ -220,11 +226,7 @@ gw init --root /path/to/your/repo.git
220
226
  {
221
227
  "root": "/Users/username/Workspace/my-project.git",
222
228
  "defaultBranch": "main",
223
- "autoCopyFiles": [
224
- ".env",
225
- "components/agents/.env",
226
- "components/ui/.vercel/"
227
- ],
229
+ "autoCopyFiles": [".env", "components/agents/.env", "components/ui/.vercel/"],
228
230
  "hooks": {
229
231
  "add": {
230
232
  "pre": ["echo 'Creating worktree: {worktree}'"],
@@ -283,6 +285,7 @@ If you try to add a worktree that already exists, the command will prompt you to
283
285
  #### Options
284
286
 
285
287
  All `git worktree add` options are supported:
288
+
286
289
  - `-b <branch>`: Create a new branch
287
290
  - `-B <branch>`: Create or reset a branch
288
291
  - `--detach`: Detach HEAD in new worktree
@@ -323,6 +326,7 @@ gw init --auto-copy-files .env,secrets/,components/ui/.vercel/
323
326
  ```
324
327
 
325
328
  This creates:
329
+
326
330
  ```json
327
331
  {
328
332
  "root": "/path/to/repo.git",
@@ -336,6 +340,7 @@ Now every time you run `gw add`, these files will be automatically copied from y
336
340
  #### Hooks
337
341
 
338
342
  You can configure pre-add and post-add hooks to run commands before and after worktree creation. This is useful for:
343
+
339
344
  - **Pre-add hooks**: Running validation scripts, checking prerequisites
340
345
  - **Post-add hooks**: Installing dependencies, setting up the environment
341
346
 
@@ -350,12 +355,14 @@ gw init --pre-add "echo 'Creating: {worktree}'" --post-add "pnpm install" --post
350
355
  **Hook Variables:**
351
356
 
352
357
  Hooks support variable substitution:
358
+
353
359
  - `{worktree}` - The worktree name (e.g., "feat/new-feature")
354
360
  - `{worktreePath}` - Full absolute path to the worktree
355
361
  - `{gitRoot}` - The git repository root path
356
362
  - `{branch}` - The branch name
357
363
 
358
364
  **Hook Behavior:**
365
+
359
366
  - **Pre-add hooks** run before the worktree is created (in the git root directory). If any pre-add hook fails, the worktree creation is aborted.
360
367
  - **Post-add hooks** run after the worktree is created and files are copied (in the new worktree directory). If a post-add hook fails, a warning is shown but the worktree creation is considered successful.
361
368
 
@@ -454,6 +461,7 @@ gw pull --remote upstream
454
461
  3. Creates merge commit if histories have diverged
455
462
 
456
463
  **Safety checks:**
464
+
457
465
  - Blocks if you have uncommitted changes (use `--force` to override)
458
466
  - Blocks if you're in a detached HEAD state
459
467
  - Handles merge conflicts gracefully with clear guidance
@@ -463,6 +471,7 @@ gw pull --remote upstream
463
471
  **Configuration:**
464
472
 
465
473
  The default branch is read from `.gw/config.json`:
474
+
466
475
  ```json
467
476
  {
468
477
  "defaultBranch": "main"
@@ -473,7 +482,16 @@ If not configured, defaults to "main".
473
482
 
474
483
  ### install-shell
475
484
 
476
- Install or remove shell integration for the `gw cd` command. This is automatically run during `npm install`, but can be run manually if needed.
485
+ Install or remove shell integration for the `gw cd` command and enable real-time streaming output. This is automatically run during `npm install`, but can be run manually if needed.
486
+
487
+ The installation creates an integration script in `~/.gw/shell/` and adds a single line to your shell configuration to source it, keeping your shell config clean and minimal.
488
+
489
+ Shell integration provides:
490
+
491
+ - **Navigation support**: `gw cd <worktree>` navigates directly to worktrees
492
+ - **Real-time streaming**: Command output streams as it's generated (no buffering)
493
+ - **Auto-navigation**: Automatically navigate after `gw add` and `gw remove` operations
494
+ - **Multi-alias support**: Install for different command names (e.g., `gw-dev` for development)
477
495
 
478
496
  ```bash
479
497
  gw install-shell [options]
@@ -481,6 +499,8 @@ gw install-shell [options]
481
499
 
482
500
  #### Options
483
501
 
502
+ - `--name, -n NAME`: Install under a different command name (default: `gw`)
503
+ - `--command, -c CMD`: Actual command to run (use with `--name` for aliases/dev)
484
504
  - `--remove`: Remove shell integration
485
505
  - `--quiet, -q`: Suppress output messages
486
506
  - `-h, --help`: Show help message
@@ -491,19 +511,25 @@ gw install-shell [options]
491
511
  # Install shell integration (usually not needed - auto-installed)
492
512
  gw install-shell
493
513
 
494
- # Remove shell integration
495
- gw install-shell --remove
514
+ # Install for development (with Deno)
515
+ # Note: Remove any 'alias gw-dev=...' from .zshrc first!
516
+ gw install-shell --name gw-dev \
517
+ --command "deno run --allow-all ~/path/to/gw-tools/packages/gw-tool/src/main.ts"
518
+
519
+ # Remove shell integration for 'gw-dev'
520
+ gw install-shell --name gw-dev --remove
496
521
 
497
522
  # Install quietly (for automation)
498
523
  gw install-shell --quiet
499
524
  ```
500
525
 
501
526
  **Supported Shells:**
502
- - **Zsh** (~/.zshrc)
503
- - **Bash** (~/.bashrc)
504
- - **Fish** (~/.config/fish/functions/gw.fish)
505
527
 
506
- The command is idempotent - running it multiple times won't create duplicate entries.
528
+ - **Zsh** (~/.zshrc sources ~/.gw/shell/integration[-NAME].zsh)
529
+ - **Bash** (~/.bashrc sources ~/.gw/shell/integration[-NAME].bash)
530
+ - **Fish** (~/.config/fish/functions/[NAME].fish)
531
+
532
+ The command is idempotent - running it multiple times won't create duplicate entries. It will also automatically migrate old inline installations to the new format.
507
533
 
508
534
  ### root
509
535
 
@@ -604,6 +630,7 @@ gw init --help
604
630
  #### Hook Variables
605
631
 
606
632
  Hooks support variable substitution:
633
+
607
634
  - `{worktree}` - The worktree name (e.g., "feat/new-feature")
608
635
  - `{worktreePath}` - Full absolute path to the worktree
609
636
  - `{gitRoot}` - The git repository root path
@@ -625,6 +652,7 @@ gw init --auto-clean --auto-copy-files .env --post-add "pnpm install"
625
652
  ```
626
653
 
627
654
  **How it works:**
655
+
628
656
  - Runs automatically on `gw add` and `gw list` commands (in the background, non-blocking)
629
657
  - Only runs once per 24 hours (cooldown)
630
658
  - **Never removes the `defaultBranch` worktree** - it's protected as the source for file syncing
@@ -640,6 +668,7 @@ This is an opt-in feature. Use `gw clean` for manual, interactive cleanup with m
640
668
  #### When to Use
641
669
 
642
670
  Use `gw init` to:
671
+
643
672
  - Configure auto-copy files for automatic file copying on worktree creation
644
673
  - Set up pre-add and post-add hooks for automation
645
674
  - Configure the clean threshold for worktree age management
@@ -682,6 +711,7 @@ echo "## Setup\n\n\`\`\`bash\n$(gw show-init)\n\`\`\`" >> README.md
682
711
  #### Output Example
683
712
 
684
713
  If your `.gw/config.json` contains:
714
+
685
715
  ```json
686
716
  {
687
717
  "root": "/Users/username/Workspace/repo.git",
@@ -697,6 +727,7 @@ If your `.gw/config.json` contains:
697
727
  ```
698
728
 
699
729
  Then `gw show-init` will output:
730
+
700
731
  ```bash
701
732
  gw init --root /Users/username/Workspace/repo.git --auto-copy-files .env,secrets/ --post-add 'pnpm install'
702
733
  ```
@@ -704,6 +735,7 @@ gw init --root /Users/username/Workspace/repo.git --auto-copy-files .env,secrets
704
735
  #### When to Use
705
736
 
706
737
  Use `gw show-init` to:
738
+
707
739
  - Document your setup in README files or team wikis
708
740
  - Share configuration commands with team members
709
741
  - Recreate the same configuration in another repository
@@ -788,6 +820,7 @@ gw init --clean-threshold 14
788
820
  #### How It Works
789
821
 
790
822
  The clean command:
823
+
791
824
  1. Checks for worktrees older than the configured threshold (default: 7 days)
792
825
  2. Verifies they have no uncommitted changes (unless `--force`)
793
826
  3. Verifies they have no unpushed commits (unless `--force`)
@@ -795,6 +828,7 @@ The clean command:
795
828
  5. Never removes bare/main repository worktrees
796
829
 
797
830
  **Safety Features:**
831
+
798
832
  - By default, only removes worktrees with NO uncommitted changes
799
833
  - By default, only removes worktrees with NO unpushed commits
800
834
  - Always prompts for confirmation before deletion
@@ -811,6 +845,7 @@ gw init --clean-threshold 14
811
845
  ```
812
846
 
813
847
  This creates/updates the config:
848
+
814
849
  ```json
815
850
  {
816
851
  "root": "/path/to/repo.git",
@@ -834,6 +869,7 @@ gw ls
834
869
  ```
835
870
 
836
871
  **Examples:**
872
+
837
873
  ```bash
838
874
  gw list # List all worktrees
839
875
  gw list --porcelain # Machine-readable output
@@ -851,6 +887,7 @@ gw rm <worktree>
851
887
  ```
852
888
 
853
889
  **Examples:**
890
+
854
891
  ```bash
855
892
  gw remove feat-branch # Remove a worktree
856
893
  gw remove --force feat-branch # Force remove even if dirty
@@ -868,6 +905,7 @@ gw mv <worktree> <new-path>
868
905
  ```
869
906
 
870
907
  **Examples:**
908
+
871
909
  ```bash
872
910
  gw move feat-branch ../new-location
873
911
  gw mv feat-branch ../new-location
@@ -875,19 +913,56 @@ gw mv feat-branch ../new-location
875
913
 
876
914
  #### prune
877
915
 
878
- Clean up worktree information for deleted worktrees.
916
+ Clean up worktree administrative data and optionally remove clean worktrees.
917
+
918
+ **Standard Mode** (without `--clean`):
919
+ Wraps `git worktree prune` to clean up administrative files for deleted worktrees.
920
+
921
+ **Clean Mode** (with `--clean`):
922
+ First runs `git worktree prune`, then removes ALL worktrees that have no uncommitted changes, no staged files, and no unpushed commits. Unlike `gw clean` (which is age-based), `gw prune --clean` removes worktrees regardless of age.
879
923
 
880
924
  ```bash
881
- gw prune
925
+ gw prune [options]
882
926
  ```
883
927
 
928
+ **Options:**
929
+
930
+ - `--clean` - Enable clean mode (remove clean worktrees)
931
+ - `-n, --dry-run` - Preview what would be removed
932
+ - `-f, --force` - Skip confirmation prompt
933
+ - `-v, --verbose` - Show detailed output
934
+ - `-h, --help` - Show help
935
+
936
+ **Safety Features** (in clean mode):
937
+
938
+ - Default branch is protected (configured in `.gw/config.json`)
939
+ - Current worktree cannot be removed
940
+ - Bare repository is never removed
941
+ - Confirmation prompt before removal (defaults to yes, just press Enter to confirm)
942
+
884
943
  **Examples:**
944
+
885
945
  ```bash
886
- gw prune # Clean up stale worktree information
887
- gw prune --dry-run # Preview what would be pruned
888
- gw prune --verbose # Show detailed output
946
+ # Standard prune (cleanup administrative data)
947
+ gw prune
948
+ gw prune --verbose
949
+
950
+ # Clean mode (remove clean worktrees)
951
+ gw prune --clean # Remove all clean worktrees (with prompt)
952
+ gw prune --clean --dry-run # Preview what would be removed
953
+ gw prune --clean --force # Remove without confirmation
954
+ gw prune --clean --verbose # Show detailed output
889
955
  ```
890
956
 
957
+ **Comparison with `gw clean`:**
958
+ | Feature | `gw clean` | `gw prune --clean` |
959
+ |---------|-----------|-------------------|
960
+ | Age-based | Yes (configurable threshold) | No (removes all clean) |
961
+ | Safety checks | Yes | Yes |
962
+ | Protects default branch | No | Yes |
963
+ | Runs `git worktree prune` | No | Yes |
964
+ | Use case | Regular maintenance | Aggressive cleanup |
965
+
891
966
  #### lock
892
967
 
893
968
  Lock a worktree to prevent removal.
@@ -897,6 +972,7 @@ gw lock <worktree>
897
972
  ```
898
973
 
899
974
  **Examples:**
975
+
900
976
  ```bash
901
977
  gw lock feat-branch
902
978
  gw lock --reason "Work in progress" feat-branch
@@ -911,6 +987,7 @@ gw unlock <worktree>
911
987
  ```
912
988
 
913
989
  **Examples:**
990
+
914
991
  ```bash
915
992
  gw unlock feat-branch
916
993
  ```
@@ -924,6 +1001,7 @@ gw repair [<path>]
924
1001
  ```
925
1002
 
926
1003
  **Examples:**
1004
+
927
1005
  ```bash
928
1006
  gw repair # Repair all worktrees
929
1007
  gw repair /path/to/worktree # Repair specific worktree
@@ -964,117 +1042,36 @@ gw cd feat-manual
964
1042
 
965
1043
  ### Local Development & Testing
966
1044
 
967
- When developing the tool, you can test changes locally without publishing by creating a global symlink. This allows you to use the `gw` command with live code updates.
1045
+ When developing the tool, you can test changes locally without publishing by using a shell alias. This allows you to use the `gw-dev` command with live code updates and full shell integration.
968
1046
 
969
- #### Method 1: Shell Alias (Recommended for Active Development)
1047
+ #### Shell Alias Method (Recommended)
970
1048
 
971
- Create a shell alias that runs the Deno version directly with watch mode:
1049
+ Create a shell alias that runs the Deno version directly for instant feedback:
972
1050
 
973
1051
  ```bash
974
- # Add to your ~/.zshrc or ~/.bashrc
975
- alias gw-dev='deno run --allow-all ~/path/to/gw-tools/packages/gw-tool/src/main.ts'
1052
+ # Install shell integration for gw-dev
1053
+ # IMPORTANT: Don't create an alias yourself - the install-shell command creates a function for you
1054
+ # Make sure to use your actual path to gw-tools
1055
+ deno run --allow-all ~/path/to/gw-tools/packages/gw-tool/src/main.ts install-shell \
1056
+ --name gw-dev \
1057
+ --command "deno run --allow-all ~/path/to/gw-tools/packages/gw-tool/src/main.ts"
976
1058
 
977
1059
  # Reload your shell
978
1060
  source ~/.zshrc # or ~/.bashrc
979
1061
 
980
- # Now you can use it anywhere
1062
+ # Now you can use it anywhere with full shell integration
981
1063
  cd ~/some-project
1064
+ gw-dev add feat-branch # Output streams in real-time!
1065
+ gw-dev cd feat-branch # Navigates to the worktree
982
1066
  gw-dev copy feat-branch .env
983
1067
  ```
984
1068
 
985
- This gives you instant feedback - just edit the TypeScript files and run the command again.
986
-
987
- #### Method 2: Symlink to Compiled Binary (Faster Execution)
988
-
989
- Create a symlink to the compiled binary and recompile when needed:
990
-
991
- ```bash
992
- # From the workspace root
993
- nx run gw-tool:compile
994
-
995
- # Create global symlink (one-time setup)
996
- sudo ln -sf ~/path/to/gw-tools/dist/packages/gw-tool/gw /usr/local/bin/gw
997
-
998
- # Now you can use `gw` globally
999
- cd ~/some-project
1000
- gw sync feat-branch .env
1001
-
1002
- # When you make changes, recompile
1003
- nx run gw-tool:compile
1004
- # The symlink automatically points to the new binary
1005
- ```
1006
-
1007
- #### Method 3: Development Wrapper Script (Best of Both Worlds)
1008
-
1009
- Create a wrapper script that provides both speed and live updates:
1010
-
1011
- ```bash
1012
- # Create ~/bin/gw (make sure ~/bin is in your PATH)
1013
- cat > ~/bin/gw << 'EOF'
1014
- #!/bin/bash
1015
- # Check if we're in development mode (set GW_DEV=1 to use source)
1016
- if [ "$GW_DEV" = "1" ]; then
1017
- exec deno run --allow-all ~/path/to/gw-tools/packages/gw-tool/src/main.ts "$@"
1018
- else
1019
- exec ~/path/to/gw-tools/dist/packages/gw-tool/gw "$@"
1020
- fi
1021
- EOF
1022
-
1023
- chmod +x ~/bin/gw
1024
-
1025
- # Use compiled version (fast)
1026
- gw sync feat-branch .env
1027
-
1028
- # Use development version with live updates
1029
- GW_DEV=1 gw sync feat-branch .env
1030
-
1031
- # Or set it for your entire session
1032
- export GW_DEV=1
1033
- gw sync feat-branch .env
1034
- ```
1035
-
1036
- #### Method 4: npm link (For Testing Installation)
1069
+ This gives you instant feedback - just edit the TypeScript files and run the command again. The shell integration provides the same experience as the installed version:
1037
1070
 
1038
- Test the npm package installation flow locally:
1039
-
1040
- ```bash
1041
- # Compile binaries
1042
- nx run gw-tool:compile-all
1043
-
1044
- # Prepare npm package
1045
- nx run gw-tool:npm-pack
1046
-
1047
- # Link the package globally
1048
- cd dist/packages/gw-tool/npm
1049
- npm link
1050
-
1051
- # Now `gw` is available globally via npm
1052
- gw sync feat-branch .env
1053
-
1054
- # When you make changes
1055
- cd ~/path/to/gw-tools
1056
- nx run gw-tool:compile-all
1057
- nx run gw-tool:npm-pack
1058
- # The link automatically uses the updated binaries
1059
-
1060
- # To unlink when done
1061
- npm unlink -g @gw-tools/gw
1062
- ```
1063
-
1064
- #### Watch Mode for Active Development
1065
-
1066
- Use the watch mode to automatically restart when files change:
1067
-
1068
- ```bash
1069
- # Terminal 1: Run in watch mode
1070
- nx run gw-tool:dev
1071
-
1072
- # Terminal 2: Test in another project
1073
- cd ~/some-project
1074
- ~/path/to/gw-tools/dist/packages/gw-tool/gw sync feat-branch .env
1075
- ```
1076
-
1077
- **Pro tip**: Combine Method 3 (wrapper script) with watch mode by setting `GW_DEV=1` in your development shell.
1071
+ - Real-time streaming output (no buffering)
1072
+ - `gw-dev cd` navigation support
1073
+ - Auto-navigation after `gw-dev add`
1074
+ - Auto-navigation to repo root after `gw-dev remove`
1078
1075
 
1079
1076
  ### Available Scripts
1080
1077
 
@@ -1190,6 +1187,7 @@ npm publish --access public
1190
1187
  For users who prefer Deno's native package manager.
1191
1188
 
1192
1189
  1. **Add JSR configuration to `deno.json`:**
1190
+
1193
1191
  ```json
1194
1192
  {
1195
1193
  "name": "@your-scope/gw",
@@ -1281,15 +1279,16 @@ There are two types of commands you can add:
1281
1279
  For commands with custom logic, follow the pattern used by existing commands:
1282
1280
 
1283
1281
  1. **Create a new file** in `src/commands/` (e.g., `list.ts`):
1282
+
1284
1283
  ```typescript
1285
1284
  // src/commands/list.ts
1286
1285
  export async function executeList(args: string[]): Promise<void> {
1287
1286
  // Check for help flag
1288
- if (args.includes("--help") || args.includes("-h")) {
1287
+ if (args.includes('--help') || args.includes('-h')) {
1289
1288
  console.log(`Usage: gw list
1290
-
1289
+
1291
1290
  List all git worktrees in the current repository.
1292
-
1291
+
1293
1292
  Options:
1294
1293
  -h, --help Show this help message
1295
1294
  `);
@@ -1302,8 +1301,9 @@ For commands with custom logic, follow the pattern used by existing commands:
1302
1301
  ```
1303
1302
 
1304
1303
  2. **Import and register** the command in `src/main.ts`:
1304
+
1305
1305
  ```typescript
1306
- import { executeList } from "./commands/list.ts";
1306
+ import { executeList } from './commands/list.ts';
1307
1307
 
1308
1308
  const COMMANDS = {
1309
1309
  add: executeAdd,
@@ -1333,18 +1333,18 @@ For commands with custom logic, follow the pattern used by existing commands:
1333
1333
  For simple pass-through commands that wrap git worktree operations, use the `git-proxy` utility:
1334
1334
 
1335
1335
  1. **Create a new file** in `src/commands/` (e.g., `list.ts`):
1336
+
1336
1337
  ```typescript
1337
1338
  // src/commands/list.ts
1338
1339
  import { executeGitWorktree, showProxyHelp } from '../lib/git-proxy.ts';
1339
1340
 
1340
1341
  export async function executeList(args: string[]): Promise<void> {
1341
1342
  if (args.includes('--help') || args.includes('-h')) {
1342
- showProxyHelp(
1343
- 'list',
1344
- 'list',
1345
- 'List all worktrees in the repository',
1346
- ['gw list', 'gw list --porcelain', 'gw list -v'],
1347
- );
1343
+ showProxyHelp('list', 'list', 'List all worktrees in the repository', [
1344
+ 'gw list',
1345
+ 'gw list --porcelain',
1346
+ 'gw list -v',
1347
+ ]);
1348
1348
  Deno.exit(0);
1349
1349
  }
1350
1350
 
@@ -1359,6 +1359,7 @@ For simple pass-through commands that wrap git worktree operations, use the `git
1359
1359
  This approach requires minimal maintenance as it simply forwards all arguments to git.
1360
1360
 
1361
1361
  **Tips**:
1362
+
1362
1363
  - Look at [src/commands/root.ts](src/commands/root.ts) for a simple custom command
1363
1364
  - Look at [src/commands/copy.ts](src/commands/copy.ts) for a complex command with argument parsing
1364
1365
  - Look at [src/commands/list.ts](src/commands/list.ts) for a simple proxy command
package/bin/gw ADDED
Binary file
package/install.js CHANGED
@@ -176,12 +176,28 @@ async function install() {
176
176
  async function installShellIntegration(binaryPath, retries = 3) {
177
177
  const { spawn } = require('child_process');
178
178
 
179
+ // Check environment before attempting shell integration
180
+ const hasRequiredEnv = process.env.HOME || process.env.USERPROFILE;
181
+ const hasShell = process.env.SHELL;
182
+
183
+ if (!hasRequiredEnv) {
184
+ console.log(' Skipping shell integration: HOME environment variable not set');
185
+ console.log(' Run "gw install-shell" manually after installation');
186
+ return;
187
+ }
188
+
189
+ if (!hasShell) {
190
+ console.log(' Skipping shell integration: SHELL environment variable not set');
191
+ console.log(' Run "gw install-shell" manually after installation');
192
+ return;
193
+ }
194
+
179
195
  return new Promise((resolve) => {
180
196
  let child;
181
197
 
182
198
  try {
183
- child = spawn(binaryPath, ['install-shell', '--quiet'], {
184
- stdio: 'inherit',
199
+ child = spawn(binaryPath, ['install-shell'], {
200
+ stdio: ['inherit', 'inherit', 'pipe'], // stdin, stdout, stderr
185
201
  });
186
202
  } catch (err) {
187
203
  // Catch synchronous spawn errors (e.g., ETXTBSY thrown immediately)
@@ -191,20 +207,28 @@ async function installShellIntegration(binaryPath, retries = 3) {
191
207
  }, 200);
192
208
  return;
193
209
  }
194
- console.log(
195
- ' (Shell integration can be installed later with: gw install-shell)',
196
- );
210
+ console.log(' Shell integration setup encountered an issue.');
211
+ console.log(' You can install it manually later with: gw install-shell');
197
212
  resolve();
198
213
  return;
199
214
  }
200
215
 
216
+ let stderrOutput = '';
217
+ child.stderr.on('data', (data) => {
218
+ stderrOutput += data.toString();
219
+ // Also display it immediately
220
+ process.stderr.write(data);
221
+ });
222
+
201
223
  child.on('close', (code) => {
202
224
  if (code === 0) {
203
225
  console.log('✓ Shell integration installed!');
204
226
  } else {
205
- console.log(
206
- ' (Shell integration can be installed later with: gw install-shell)',
207
- );
227
+ console.log(' Shell integration failed with exit code:', code);
228
+ if (stderrOutput) {
229
+ console.log(' Error:', stderrOutput.trim());
230
+ }
231
+ console.log(' You can install it manually later with: gw install-shell');
208
232
  }
209
233
  resolve();
210
234
  });
@@ -215,9 +239,8 @@ async function installShellIntegration(binaryPath, retries = 3) {
215
239
  await new Promise((r) => setTimeout(r, 200));
216
240
  return installShellIntegration(binaryPath, retries - 1).then(resolve);
217
241
  }
218
- console.log(
219
- ' (Shell integration can be installed later with: gw install-shell)',
220
- );
242
+ console.log(' Shell integration setup encountered an issue.');
243
+ console.log(' You can install it manually later with: gw install-shell');
221
244
  resolve();
222
245
  });
223
246
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gw-tools/gw",
3
- "version": "0.12.23",
3
+ "version": "0.12.26",
4
4
  "description": "A command-line tool for managing git worktrees - copy files between worktrees with ease",
5
5
  "keywords": [
6
6
  "git",