@shivanshshrivas/gwit 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/LICENSE +21 -0
- package/README.md +240 -0
- package/dist/index.cjs +1224 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 shivanshshrivas
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# gwit
|
|
2
|
+
|
|
3
|
+
Fully isolated git worktrees, in one command.
|
|
4
|
+
|
|
5
|
+
gwit wraps `git worktree` to turn a fresh checkout into a fully working environment - gitignored files copied, unique port assigned, per-worktree env vars injected, and setup scripts run automatically.
|
|
6
|
+
|
|
7
|
+
Built for parallel development with multiple branches and AI coding agents - no database collisions, no port conflicts, no manual setup.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install -g gwit
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires **Node.js >= 20** and **git >= 2.5**.
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
# Set up gwit for this repo (run once, commit the output)
|
|
21
|
+
gwit init
|
|
22
|
+
|
|
23
|
+
# Create an isolated worktree
|
|
24
|
+
gwit feature/auth # existing branch
|
|
25
|
+
gwit -b fix/login-page # create a new branch from HEAD
|
|
26
|
+
|
|
27
|
+
# Day-to-day
|
|
28
|
+
gwit list # show all active worktrees
|
|
29
|
+
gwit sync feature/auth # re-copy files after .env changes
|
|
30
|
+
gwit open feature/auth # re-open editor for an existing worktree
|
|
31
|
+
gwit remove feature/auth # run cleanup hooks and remove worktree
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## How it works
|
|
35
|
+
|
|
36
|
+
gwit adds three layers on top of `git worktree add`:
|
|
37
|
+
|
|
38
|
+
1. **Files** - copies gitignored files listed in `.gwitinclude` (`.env`, `node_modules/`, certs) so the new worktree starts complete instead of broken.
|
|
39
|
+
|
|
40
|
+
2. **Isolation** - assigns a unique port and injects `$GWIT_*` env vars into your setup scripts, so each worktree can create its own database, Docker project, Redis namespace, and anything else your stack needs.
|
|
41
|
+
|
|
42
|
+
3. **Automation** - runs `.gwitcommand` after creation and `.gwitcleanup` before removal, giving your team a shared, repeatable isolation setup committed to the repo.
|
|
43
|
+
|
|
44
|
+
## Commands
|
|
45
|
+
|
|
46
|
+
### `gwit <branch>`
|
|
47
|
+
|
|
48
|
+
Create an isolated worktree for `branch` (local or remote).
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
gwit feature/auth # check out existing branch
|
|
52
|
+
gwit -b fix/login-page # create a new branch from HEAD
|
|
53
|
+
gwit feature/auth --editor cursor # override editor for this run
|
|
54
|
+
gwit feature/auth --no-editor # skip opening editor
|
|
55
|
+
gwit feature/auth --no-commands # skip .gwitcommand
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
What it does, in order:
|
|
59
|
+
|
|
60
|
+
1. Resolves the branch (local -> remote tracking -> error)
|
|
61
|
+
2. Runs `git worktree add`
|
|
62
|
+
3. Copies files listed in `.gwitinclude` from the main worktree
|
|
63
|
+
4. Allocates a unique port (scans from `basePort`, up to 100 ports)
|
|
64
|
+
5. Injects `$GWIT_*` variables and runs `.gwitcommand` inside the new worktree
|
|
65
|
+
6. Writes the registry entry to `~/.gwit/worktrees.json`
|
|
66
|
+
7. Opens the editor
|
|
67
|
+
|
|
68
|
+
### `gwit init`
|
|
69
|
+
|
|
70
|
+
Interactive wizard that scaffolds the three per-repo hook files. Run once per repo and commit the output so every teammate gets the same isolation setup automatically.
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
gwit init # creates .gwitinclude, .gwitcommand, .gwitcleanup
|
|
74
|
+
gwit init --force # overwrite existing files
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The wizard:
|
|
78
|
+
|
|
79
|
+
- Shows a checklist of gitignored files/directories to copy (pre-selects `.env*`)
|
|
80
|
+
- Asks about your package manager, database, Redis, Docker Compose
|
|
81
|
+
- Asks for any extra setup and teardown commands
|
|
82
|
+
- Generates ready-to-edit hook files
|
|
83
|
+
|
|
84
|
+
### `gwit list`
|
|
85
|
+
|
|
86
|
+
Show all active worktrees for this repo.
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
Branch Path Port Index Created
|
|
90
|
+
feature/auth ../myapp-feature_auth 3001 1 2026-01-15
|
|
91
|
+
fix/login-page ../myapp-fix_login_page 3002 2 2026-01-16
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `gwit remove <branch>`
|
|
95
|
+
|
|
96
|
+
Run cleanup hooks, remove the worktree, and free the port from the registry.
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
gwit remove feature/auth
|
|
100
|
+
gwit remove feature/auth --force # skip uncommitted-changes check
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### `gwit sync [branch]`
|
|
104
|
+
|
|
105
|
+
Re-copy `.gwitinclude` files into an existing worktree. Use this when your `.env` gains a new key, certs rotate, or `node_modules` is updated.
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
gwit sync feature/auth # sync a specific branch
|
|
109
|
+
gwit sync # auto-detect from current directory (when inside a worktree)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `gwit open <branch>`
|
|
113
|
+
|
|
114
|
+
Re-open the editor for an existing worktree. Useful when the editor window was closed.
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
gwit open feature/auth
|
|
118
|
+
gwit open feature/auth --editor cursor
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### `gwit config`
|
|
122
|
+
|
|
123
|
+
Show or update global configuration stored in `~/.gwitrc`.
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
gwit config # show all settings
|
|
127
|
+
gwit config get editor # get one setting
|
|
128
|
+
gwit config set editor cursor # change editor
|
|
129
|
+
gwit config set location sibling # or: subdirectory
|
|
130
|
+
gwit config set basePort 4000 # starting port for auto-assignment
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
| Key | Values | Default |
|
|
134
|
+
| --- | --- | --- |
|
|
135
|
+
| `editor` | any editor command | `code` |
|
|
136
|
+
| `location` | `sibling`, `subdirectory` | `sibling` |
|
|
137
|
+
| `basePort` | 1-65535 | `3001` |
|
|
138
|
+
|
|
139
|
+
`location` controls where worktrees are placed:
|
|
140
|
+
|
|
141
|
+
- `sibling` - next to the repo: `../myapp-feature_auth`
|
|
142
|
+
- `subdirectory` - inside the repo: `myapp/.worktrees/feature_auth`
|
|
143
|
+
|
|
144
|
+
## File formats
|
|
145
|
+
|
|
146
|
+
### `.gwitinclude`
|
|
147
|
+
|
|
148
|
+
List of gitignored files and directories to copy into every new worktree. One entry per line, comments with `#` ignored.
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
# .gwitinclude - files to copy into each new worktree
|
|
152
|
+
.env
|
|
153
|
+
.env.local
|
|
154
|
+
certs/
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Only gitignored files are eligible to copy. Tracked files are silently skipped - gwit is an allowlist for files that must be present but cannot be committed.
|
|
158
|
+
|
|
159
|
+
### `.gwitcommand`
|
|
160
|
+
|
|
161
|
+
Shell commands run inside the worktree after creation. One command per line.
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
# .gwitcommand - setup commands
|
|
165
|
+
# $GWIT_* variables are available here
|
|
166
|
+
npm install
|
|
167
|
+
createdb myapp$GWIT_DB_SUFFIX
|
|
168
|
+
npm run db:migrate
|
|
169
|
+
echo "PORT=$GWIT_PORT" >> .env
|
|
170
|
+
echo "DATABASE_URL=postgres://localhost/myapp$GWIT_DB_SUFFIX" >> .env
|
|
171
|
+
echo "REDIS_URL=redis://localhost:6379/$GWIT_INDEX" >> .env
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Commands run sequentially. If any command fails, the rest are skipped and gwit exits with an error.
|
|
175
|
+
|
|
176
|
+
### `.gwitcleanup`
|
|
177
|
+
|
|
178
|
+
Shell commands run inside the worktree before removal. Mirrors `.gwitcommand`.
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
# .gwitcleanup - teardown commands
|
|
182
|
+
dropdb --if-exists myapp$GWIT_DB_SUFFIX
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Commands run sequentially. Errors are printed as warnings and execution continues - cleanup is best-effort.
|
|
186
|
+
|
|
187
|
+
## Environment variables
|
|
188
|
+
|
|
189
|
+
All `$GWIT_*` variables are available inside `.gwitcommand` and `.gwitcleanup`:
|
|
190
|
+
|
|
191
|
+
| Variable | Example value | Description |
|
|
192
|
+
| --- | --- | --- |
|
|
193
|
+
| `$GWIT_BRANCH` | `feature/auth` | Raw branch name |
|
|
194
|
+
| `$GWIT_SLUG` | `feature_auth` | Filesystem/DB-safe slug |
|
|
195
|
+
| `$GWIT_PORT` | `3001` | Auto-assigned unique port |
|
|
196
|
+
| `$GWIT_DB_SUFFIX` | `_feature_auth` | Underscore-prefixed slug for DB names |
|
|
197
|
+
| `$GWIT_WORKTREE_PATH` | `/home/user/myapp-feature_auth` | Absolute path to this worktree |
|
|
198
|
+
| `$GWIT_MAIN_PATH` | `/home/user/myapp` | Absolute path to the main repo |
|
|
199
|
+
| `$GWIT_INDEX` | `1` | Stable, never-reused index per repo |
|
|
200
|
+
|
|
201
|
+
`$GWIT_INDEX` is monotonically increasing and never reused after removal - safe to use as a Redis DB number, a Docker Compose project suffix, or any resource that must survive across separate worktree sessions.
|
|
202
|
+
|
|
203
|
+
## Example: full-stack isolation
|
|
204
|
+
|
|
205
|
+
A complete setup for a Node.js app with Postgres and Redis:
|
|
206
|
+
|
|
207
|
+
**`.gwitinclude`**
|
|
208
|
+
```
|
|
209
|
+
.env
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**`.gwitcommand`**
|
|
213
|
+
```sh
|
|
214
|
+
npm install
|
|
215
|
+
createdb myapp$GWIT_DB_SUFFIX
|
|
216
|
+
npm run db:migrate
|
|
217
|
+
echo "PORT=$GWIT_PORT" >> .env
|
|
218
|
+
echo "DATABASE_URL=postgres://localhost/myapp$GWIT_DB_SUFFIX" >> .env
|
|
219
|
+
echo "REDIS_URL=redis://localhost:6379/$GWIT_INDEX" >> .env
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**`.gwitcleanup`**
|
|
223
|
+
```sh
|
|
224
|
+
dropdb --if-exists myapp$GWIT_DB_SUFFIX
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
With this setup, `gwit feature/auth` spins up a worktree with its own database (`myapp_feature_auth`), its own Redis DB (`redis://.../1`), and its own port (`3001`) - no collisions, no manual steps.
|
|
228
|
+
|
|
229
|
+
## Registry and config files
|
|
230
|
+
|
|
231
|
+
| File | Purpose |
|
|
232
|
+
| --- | --- |
|
|
233
|
+
| `~/.gwitrc` | Global config (editor, location, basePort) |
|
|
234
|
+
| `~/.gwit/worktrees.json` | Active worktrees registry (paths, ports, indices) |
|
|
235
|
+
|
|
236
|
+
Both files are user-owned and never shared. The registry is written atomically using a write-and-rename strategy to handle concurrent `gwit` runs safely.
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
MIT
|