@gw-tools/gw 0.20.7 → 0.20.9-beta.1

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 CHANGED
@@ -36,36 +36,42 @@ A command-line tool for managing git worktrees, built with Deno.
36
36
  - [Arguments](#arguments-2)
37
37
  - [Examples](#examples-2)
38
38
  - [How It Works](#how-it-works-1)
39
- - [update](#update)
39
+ - [pr](#pr)
40
+ - [Arguments](#arguments-3)
40
41
  - [Options](#options-1)
41
42
  - [Examples](#examples-3)
43
+ - [Requirements](#requirements)
42
44
  - [How It Works](#how-it-works-2)
43
- - [install-shell](#install-shell)
45
+ - [update](#update)
44
46
  - [Options](#options-2)
45
47
  - [Examples](#examples-4)
46
- - [root](#root)
47
- - [Examples](#examples-5)
48
48
  - [How It Works](#how-it-works-3)
49
- - [init](#init)
49
+ - [install-shell](#install-shell)
50
50
  - [Options](#options-3)
51
+ - [Examples](#examples-5)
52
+ - [root](#root)
53
+ - [Examples](#examples-6)
54
+ - [How It Works](#how-it-works-4)
55
+ - [init](#init)
56
+ - [Options](#options-4)
51
57
  - [Clone Examples](#clone-examples)
52
58
  - [Existing Repository Examples](#existing-repository-examples)
53
59
  - [Hook Variables](#hook-variables)
54
60
  - [Auto-Cleanup Configuration](#auto-cleanup-configuration)
55
61
  - [When to Use](#when-to-use)
56
62
  - [show-init](#show-init)
57
- - [Options](#options-4)
58
- - [Examples](#examples-6)
63
+ - [Options](#options-5)
64
+ - [Examples](#examples-7)
59
65
  - [Output Example](#output-example)
60
66
  - [When to Use](#when-to-use-1)
61
67
  - [sync](#sync)
62
- - [Arguments](#arguments-3)
63
- - [Options](#options-5)
64
- - [Examples](#examples-7)
65
- - [clean](#clean)
68
+ - [Arguments](#arguments-4)
66
69
  - [Options](#options-6)
67
70
  - [Examples](#examples-8)
68
- - [How It Works](#how-it-works-4)
71
+ - [clean](#clean)
72
+ - [Options](#options-7)
73
+ - [Examples](#examples-9)
74
+ - [How It Works](#how-it-works-5)
69
75
  - [Git Worktree Proxy Commands](#git-worktree-proxy-commands)
70
76
  - [list (ls)](#list-ls)
71
77
  - [remove (rm)](#remove-rm)
@@ -137,14 +143,14 @@ npx skills add https://github.com/mthines/gw-tools --skill @gw-git-worktree-work
137
143
  ```
138
144
 
139
145
  ```bash
146
+ # Autonomous feature development workflow
147
+ npx skills add https://github.com/mthines/gw-tools --skill @gw-autonomous-workflow
148
+
140
149
  # Master Git worktrees and gw workflows
141
150
  npx skills add https://github.com/mthines/gw-tools --skill @gw-git-worktree-workflows
142
151
 
143
152
  # Configure gw for your project type (Next.js, monorepos, etc.)
144
153
  npx skills add https://github.com/mthines/gw-tools --skill @gw-config-management
145
-
146
- # Autonomous feature development workflow
147
- npx skills add https://github.com/mthines/gw-tools --skill @gw-autonomous-workflow
148
154
  ```
149
155
 
150
156
  Once installed, your AI agent can:
@@ -300,10 +306,11 @@ gw init --root /path/to/your/repo.git
300
306
 
301
307
  ### Example Configuration
302
308
 
303
- ```json
309
+ ```jsonc
304
310
  {
305
311
  "root": "/Users/username/Workspace/my-project.git",
306
312
  "defaultBranch": "main",
313
+ // Auto-copy these files when creating new worktrees
307
314
  "autoCopyFiles": [".env", "components/agents/.env", "components/ui/.vercel/"],
308
315
  "hooks": {
309
316
  "add": {
@@ -314,10 +321,12 @@ gw init --root /path/to/your/repo.git
314
321
  "cleanThreshold": 7,
315
322
  "autoClean": true,
316
323
  "updateStrategy": "merge",
317
- "lastAutoCleanTime": 1706371200000
324
+ "lastAutoCleanTime": 1706371200000, // trailing comma OK
318
325
  }
319
326
  ```
320
327
 
328
+ **JSONC Support**: Configuration files support JSONC (JSON with Comments) with `//` single-line comments, `/* */` multi-line comments, and trailing commas. When you run `gw init`, it generates a comprehensive self-documenting template with inline documentation for all available options. Active features are shown uncommented while inactive features appear as commented examples with usage patterns.
329
+
321
330
  **More Examples**: See the [examples/](./examples/) directory for configuration templates for various project types (Next.js, Node.js API, monorepos, CI/CD, etc.).
322
331
 
323
332
  ### Configuration Options
@@ -611,6 +620,75 @@ The `checkout` command intelligently handles four scenarios:
611
620
 
612
621
  **Use case:** When updating your feature branch with latest changes, you might instinctively try `git checkout main && git pull`. With worktrees, this fails because main is checked out elsewhere. Instead, use `gw update` to update your current branch with main, or use `gw checkout main` to navigate to the main worktree.
613
622
 
623
+ ### pr
624
+
625
+ Check out a pull request into a new worktree. This command fetches a PR's branch and creates a worktree for it in one step, making it easy to review, test, or contribute to pull requests.
626
+
627
+ ```bash
628
+ gw pr <pr-number|pr-url>
629
+ ```
630
+
631
+ When you want to review or test a pull request, you typically need to:
632
+
633
+ 1. Find the PR's branch name
634
+ 2. Fetch the branch (especially for forks)
635
+ 3. Create a worktree for it
636
+ 4. Navigate to the worktree
637
+
638
+ The `gw pr` command does all of this in a single step.
639
+
640
+ #### Arguments
641
+
642
+ - `<pr-number|pr-url>`: PR number (e.g., 42) or GitHub PR URL
643
+
644
+ #### Options
645
+
646
+ - `--name <name>`: Custom name for the worktree directory (defaults to PR's branch name)
647
+ - `--no-cd`: Don't navigate to the new worktree after creation
648
+ - `-h, --help`: Show help message
649
+
650
+ #### Examples
651
+
652
+ ```bash
653
+ # Check out PR #42
654
+ gw pr 42
655
+
656
+ # Check out PR by URL
657
+ gw pr https://github.com/user/repo/pull/42
658
+
659
+ # Use custom worktree name
660
+ gw pr 42 --name review-feature
661
+
662
+ # Check out without auto-navigation
663
+ gw pr 42 --no-cd
664
+ ```
665
+
666
+ #### Requirements
667
+
668
+ - **GitHub CLI (gh)** must be installed and authenticated
669
+ - Install from: https://cli.github.com/
670
+ - After installation, authenticate with: `gh auth login`
671
+
672
+ #### How It Works
673
+
674
+ 1. **Resolves PR info**: Uses `gh pr view` to get the PR's branch name and fork information
675
+ 2. **Validates URL** (if provided): Ensures the PR URL matches the current repository
676
+ 3. **Checks for existing worktree**: If the branch is already checked out, offers to navigate there
677
+ 4. **Fetches PR branch**: Uses `git fetch origin pull/<number>/head:<branch>` pattern which works for both same-repo and fork PRs
678
+ 5. **Creates worktree**: Creates a new worktree with the PR's branch
679
+ 6. **Copies files**: Auto-copies files from `autoCopyFiles` config (same as `gw add`)
680
+ 7. **Runs hooks**: Executes pre-add and post-add hooks (same as `gw add`)
681
+ 8. **Navigates**: Automatically navigates to the new worktree
682
+
683
+ **Fork Handling:**
684
+ The command automatically handles PRs from forks by using GitHub's `pull/<number>/head` ref pattern. This fetches the PR branch without needing to add the fork as a remote.
685
+
686
+ **Error Handling:**
687
+
688
+ - If `gh` is not installed, shows installation instructions
689
+ - If PR is not found, shows helpful error with authentication hint
690
+ - If PR URL is for a different repository, shows clear error message
691
+
614
692
  ### update
615
693
 
616
694
  Update your current worktree with the latest changes from the default branch (or specified branch) using either merge or rebase strategy. This is useful when you want to update your feature branch with the latest changes from main without having to switch worktrees.
package/install.js CHANGED
@@ -5,14 +5,7 @@
5
5
  * Downloads the appropriate binary for the current platform
6
6
  */
7
7
 
8
- const {
9
- existsSync,
10
- mkdirSync,
11
- chmodSync,
12
- openSync,
13
- fsyncSync,
14
- closeSync,
15
- } = require('fs');
8
+ const { existsSync, mkdirSync, chmodSync, openSync, fsyncSync, closeSync } = require('fs');
16
9
  const { join } = require('path');
17
10
  const { arch, platform } = require('os');
18
11
  const https = require('https');
@@ -46,7 +39,7 @@ function getBinaryName() {
46
39
  if (!os || !cpu) {
47
40
  console.error(
48
41
  `Unsupported platform: ${platform()}-${arch()}\n` +
49
- 'Supported platforms: macOS (x64, arm64), Linux (x64, arm64), Windows (x64, arm64)',
42
+ 'Supported platforms: macOS (x64, arm64), Linux (x64, arm64), Windows (x64, arm64)'
50
43
  );
51
44
  process.exit(1);
52
45
  }
@@ -63,39 +56,29 @@ function download(url, dest) {
63
56
  const file = createWriteStream(dest);
64
57
 
65
58
  https
66
- .get(
67
- url,
68
- { headers: { 'User-Agent': 'gw-npm-installer' } },
69
- (response) => {
70
- // Handle redirects
71
- if (response.statusCode === 302 || response.statusCode === 301) {
72
- return download(response.headers.location, dest)
73
- .then(resolve)
74
- .catch(reject);
75
- }
76
-
77
- if (response.statusCode !== 200) {
78
- reject(
79
- new Error(
80
- `Failed to download: ${response.statusCode} ${response.statusMessage}`,
81
- ),
82
- );
83
- return;
84
- }
85
-
86
- response.pipe(file);
87
-
88
- file.on('finish', () => {
89
- file.close((err) => {
90
- if (err) {
91
- reject(err);
92
- } else {
93
- resolve();
94
- }
95
- });
59
+ .get(url, { headers: { 'User-Agent': 'gw-npm-installer' } }, (response) => {
60
+ // Handle redirects
61
+ if (response.statusCode === 302 || response.statusCode === 301) {
62
+ return download(response.headers.location, dest).then(resolve).catch(reject);
63
+ }
64
+
65
+ if (response.statusCode !== 200) {
66
+ reject(new Error(`Failed to download: ${response.statusCode} ${response.statusMessage}`));
67
+ return;
68
+ }
69
+
70
+ response.pipe(file);
71
+
72
+ file.on('finish', () => {
73
+ file.close((err) => {
74
+ if (err) {
75
+ reject(err);
76
+ } else {
77
+ resolve();
78
+ }
96
79
  });
97
- },
98
- )
80
+ });
81
+ })
99
82
  .on('error', (err) => {
100
83
  reject(err);
101
84
  });
@@ -197,7 +180,7 @@ async function installShellIntegration(binaryPath, retries = 3) {
197
180
 
198
181
  try {
199
182
  child = spawn(binaryPath, ['install-shell'], {
200
- stdio: ['inherit', 'inherit', 'pipe'], // stdin, stdout, stderr
183
+ stdio: ['inherit', 'inherit', 'pipe'], // stdin, stdout, stderr
201
184
  });
202
185
  } catch (err) {
203
186
  // Catch synchronous spawn errors (e.g., ETXTBSY thrown immediately)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gw-tools/gw",
3
- "version": "0.20.7",
3
+ "version": "0.20.9-beta.1",
4
4
  "description": "A command-line tool for managing git worktrees - copy files between worktrees with ease",
5
5
  "keywords": [
6
6
  "git",
package/uninstall.js CHANGED
@@ -119,7 +119,7 @@ function uninstall() {
119
119
  const result = spawnSync(binaryPath, ['install-shell', '--remove'], {
120
120
  stdio: ['inherit', 'pipe', 'pipe'],
121
121
  timeout: 5000,
122
- encoding: 'utf8'
122
+ encoding: 'utf8',
123
123
  });
124
124
 
125
125
  if (result.status === 0) {