@gw-tools/gw 0.20.5 → 0.20.8
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 +117 -12
- package/install.js +25 -42
- package/package.json +1 -1
- package/uninstall.js +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ 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
|
+
- [🎓 AI Skills (for Claude Code, Copilot, Cursor, etc.)](#-ai-skills-for-claude-code-copilot-cursor-etc)
|
|
10
11
|
- [Initial Setup: Secrets in the Default Branch](#initial-setup-secrets-in-the-default-branch)
|
|
11
12
|
- [First-Time Setup Flow](#first-time-setup-flow)
|
|
12
13
|
- [Why This Matters](#why-this-matters)
|
|
@@ -35,36 +36,42 @@ A command-line tool for managing git worktrees, built with Deno.
|
|
|
35
36
|
- [Arguments](#arguments-2)
|
|
36
37
|
- [Examples](#examples-2)
|
|
37
38
|
- [How It Works](#how-it-works-1)
|
|
38
|
-
- [
|
|
39
|
+
- [pr](#pr)
|
|
40
|
+
- [Arguments](#arguments-3)
|
|
39
41
|
- [Options](#options-1)
|
|
40
42
|
- [Examples](#examples-3)
|
|
43
|
+
- [Requirements](#requirements)
|
|
41
44
|
- [How It Works](#how-it-works-2)
|
|
42
|
-
- [
|
|
45
|
+
- [update](#update)
|
|
43
46
|
- [Options](#options-2)
|
|
44
47
|
- [Examples](#examples-4)
|
|
45
|
-
- [root](#root)
|
|
46
|
-
- [Examples](#examples-5)
|
|
47
48
|
- [How It Works](#how-it-works-3)
|
|
48
|
-
- [
|
|
49
|
+
- [install-shell](#install-shell)
|
|
49
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)
|
|
50
57
|
- [Clone Examples](#clone-examples)
|
|
51
58
|
- [Existing Repository Examples](#existing-repository-examples)
|
|
52
59
|
- [Hook Variables](#hook-variables)
|
|
53
60
|
- [Auto-Cleanup Configuration](#auto-cleanup-configuration)
|
|
54
61
|
- [When to Use](#when-to-use)
|
|
55
62
|
- [show-init](#show-init)
|
|
56
|
-
- [Options](#options-
|
|
57
|
-
- [Examples](#examples-
|
|
63
|
+
- [Options](#options-5)
|
|
64
|
+
- [Examples](#examples-7)
|
|
58
65
|
- [Output Example](#output-example)
|
|
59
66
|
- [When to Use](#when-to-use-1)
|
|
60
67
|
- [sync](#sync)
|
|
61
|
-
- [Arguments](#arguments-
|
|
62
|
-
- [Options](#options-5)
|
|
63
|
-
- [Examples](#examples-7)
|
|
64
|
-
- [clean](#clean)
|
|
68
|
+
- [Arguments](#arguments-4)
|
|
65
69
|
- [Options](#options-6)
|
|
66
70
|
- [Examples](#examples-8)
|
|
67
|
-
|
|
71
|
+
- [clean](#clean)
|
|
72
|
+
- [Options](#options-7)
|
|
73
|
+
- [Examples](#examples-9)
|
|
74
|
+
- [How It Works](#how-it-works-5)
|
|
68
75
|
- [Git Worktree Proxy Commands](#git-worktree-proxy-commands)
|
|
69
76
|
- [list (ls)](#list-ls)
|
|
70
77
|
- [remove (rm)](#remove-rm)
|
|
@@ -127,6 +134,35 @@ gw cd feat/another-feature
|
|
|
127
134
|
gw checkout main
|
|
128
135
|
```
|
|
129
136
|
|
|
137
|
+
## 🎓 AI Skills (for Claude Code, Copilot, Cursor, etc.)
|
|
138
|
+
|
|
139
|
+
Enhance your AI agent with gw-tools knowledge using [skills.sh](https://skills.sh):
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npx skills add https://github.com/mthines/gw-tools --skill @gw-git-worktree-workflows @gw-config-management @gw-autonomous-workflow # installs all skills
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Autonomous feature development workflow
|
|
147
|
+
npx skills add https://github.com/mthines/gw-tools --skill @gw-autonomous-workflow
|
|
148
|
+
|
|
149
|
+
# Master Git worktrees and gw workflows
|
|
150
|
+
npx skills add https://github.com/mthines/gw-tools --skill @gw-git-worktree-workflows
|
|
151
|
+
|
|
152
|
+
# Configure gw for your project type (Next.js, monorepos, etc.)
|
|
153
|
+
npx skills add https://github.com/mthines/gw-tools --skill @gw-config-management
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Once installed, your AI agent can:
|
|
157
|
+
|
|
158
|
+
- Execute complete feature development cycles autonomously
|
|
159
|
+
- Create worktrees for bug fixes and features automatically
|
|
160
|
+
- Configure gw for your specific project type
|
|
161
|
+
- Navigate between worktrees and manage files
|
|
162
|
+
- Create tested PRs from isolated worktrees
|
|
163
|
+
|
|
164
|
+
📖 **Skill documentation:** [skills/README.md](../../skills/README.md)
|
|
165
|
+
|
|
130
166
|
## Initial Setup: Secrets in the Default Branch
|
|
131
167
|
|
|
132
168
|
**Important:** Before using `gw add` with auto-copy, ensure your secrets and environment files exist in your `defaultBranch` worktree (typically `main`). This worktree is the **source** from which files are copied to new worktrees.
|
|
@@ -581,6 +617,75 @@ The `checkout` command intelligently handles four scenarios:
|
|
|
581
617
|
|
|
582
618
|
**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.
|
|
583
619
|
|
|
620
|
+
### pr
|
|
621
|
+
|
|
622
|
+
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.
|
|
623
|
+
|
|
624
|
+
```bash
|
|
625
|
+
gw pr <pr-number|pr-url>
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
When you want to review or test a pull request, you typically need to:
|
|
629
|
+
|
|
630
|
+
1. Find the PR's branch name
|
|
631
|
+
2. Fetch the branch (especially for forks)
|
|
632
|
+
3. Create a worktree for it
|
|
633
|
+
4. Navigate to the worktree
|
|
634
|
+
|
|
635
|
+
The `gw pr` command does all of this in a single step.
|
|
636
|
+
|
|
637
|
+
#### Arguments
|
|
638
|
+
|
|
639
|
+
- `<pr-number|pr-url>`: PR number (e.g., 42) or GitHub PR URL
|
|
640
|
+
|
|
641
|
+
#### Options
|
|
642
|
+
|
|
643
|
+
- `--name <name>`: Custom name for the worktree directory (defaults to PR's branch name)
|
|
644
|
+
- `--no-cd`: Don't navigate to the new worktree after creation
|
|
645
|
+
- `-h, --help`: Show help message
|
|
646
|
+
|
|
647
|
+
#### Examples
|
|
648
|
+
|
|
649
|
+
```bash
|
|
650
|
+
# Check out PR #42
|
|
651
|
+
gw pr 42
|
|
652
|
+
|
|
653
|
+
# Check out PR by URL
|
|
654
|
+
gw pr https://github.com/user/repo/pull/42
|
|
655
|
+
|
|
656
|
+
# Use custom worktree name
|
|
657
|
+
gw pr 42 --name review-feature
|
|
658
|
+
|
|
659
|
+
# Check out without auto-navigation
|
|
660
|
+
gw pr 42 --no-cd
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
#### Requirements
|
|
664
|
+
|
|
665
|
+
- **GitHub CLI (gh)** must be installed and authenticated
|
|
666
|
+
- Install from: https://cli.github.com/
|
|
667
|
+
- After installation, authenticate with: `gh auth login`
|
|
668
|
+
|
|
669
|
+
#### How It Works
|
|
670
|
+
|
|
671
|
+
1. **Resolves PR info**: Uses `gh pr view` to get the PR's branch name and fork information
|
|
672
|
+
2. **Validates URL** (if provided): Ensures the PR URL matches the current repository
|
|
673
|
+
3. **Checks for existing worktree**: If the branch is already checked out, offers to navigate there
|
|
674
|
+
4. **Fetches PR branch**: Uses `git fetch origin pull/<number>/head:<branch>` pattern which works for both same-repo and fork PRs
|
|
675
|
+
5. **Creates worktree**: Creates a new worktree with the PR's branch
|
|
676
|
+
6. **Copies files**: Auto-copies files from `autoCopyFiles` config (same as `gw add`)
|
|
677
|
+
7. **Runs hooks**: Executes pre-add and post-add hooks (same as `gw add`)
|
|
678
|
+
8. **Navigates**: Automatically navigates to the new worktree
|
|
679
|
+
|
|
680
|
+
**Fork Handling:**
|
|
681
|
+
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.
|
|
682
|
+
|
|
683
|
+
**Error Handling:**
|
|
684
|
+
|
|
685
|
+
- If `gh` is not installed, shows installation instructions
|
|
686
|
+
- If PR is not found, shows helpful error with authentication hint
|
|
687
|
+
- If PR URL is for a different repository, shows clear error message
|
|
688
|
+
|
|
584
689
|
### update
|
|
585
690
|
|
|
586
691
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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'],
|
|
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
package/uninstall.js
CHANGED