workshell 0.0.2 → 0.0.3
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 +41 -41
- package/dist/index.js +83 -103
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -27,16 +27,16 @@ $ npm i -g workshell
|
|
|
27
27
|
|
|
28
28
|
## How `workshell` works
|
|
29
29
|
|
|
30
|
-
There have been many attempts to nail a DX for parallel work in the agentic coding era. Most are thin wrappers over `git worktree`. Instead `
|
|
30
|
+
There have been many attempts to nail a DX for parallel work in the agentic coding era. Most are thin wrappers over `git worktree`. Instead `wksh` introduces a new paradigm: the *workshell*.
|
|
31
31
|
|
|
32
32
|
**A _workshell_ is an ephemeral worktree whose lifecycle is bound to a subshell.**
|
|
33
33
|
|
|
34
34
|
Here's how it works (key points in **bold**).
|
|
35
35
|
|
|
36
|
-
- You open a Git branch with `
|
|
37
|
-
- An ephemeral worktree is created for this branch (in `.git/
|
|
36
|
+
- You open a Git branch with `wksh open <branch>` or create a new one with `wksh new <branch>`.
|
|
37
|
+
- An ephemeral worktree is created for this branch (in `.git/workshell/worktrees`) and **opened in a fresh subshell**.
|
|
38
38
|
- You are now in an fresh checkout of your repo that is isolated on disk. Make changes with your agent/editor of choice and commit them.
|
|
39
|
-
- You close the subshell with `
|
|
39
|
+
- You close the subshell with `wksh close`. **The associated worktree is auto-pruned**.
|
|
40
40
|
- Your changes still exist on the associated branch, as Git commits/branches are shared among all worktrees. The worktree is destroyed—but your commits aren't.
|
|
41
41
|
|
|
42
42
|
<!-- That's it. **Ephemeral worktrees whose lifecycle is bound to a subshell.** When the subshell exits, the worktree is destroyed—but your commits aren't. -->
|
|
@@ -44,14 +44,14 @@ Here's how it works (key points in **bold**).
|
|
|
44
44
|
<!--
|
|
45
45
|
## How does it work
|
|
46
46
|
|
|
47
|
-
There have been many attempts to nail a DX for parallel work in the agentic coding era. Most are thin wrappers over `git worktree`. That's not what `
|
|
47
|
+
There have been many attempts to nail a DX for parallel work in the agentic coding era. Most are thin wrappers over `git worktree`. That's not what `wksh` is (though worktrees are used internally).
|
|
48
48
|
|
|
49
49
|
Here's how it works (key points in **bold**).
|
|
50
50
|
|
|
51
|
-
- **A fresh worktree is created** — The `
|
|
51
|
+
- **A fresh worktree is created** — The `wksh` utility a) creates a new worktree in `.git/workshell/worktrees` and b) opens it in a *subshell*.
|
|
52
52
|
- **Make edits and commit** — From the worksh your preferred IDE/agent.
|
|
53
53
|
- **Commit your changes** — Though your file system is isolated, Git commit history (including branches) is still shared among all worktrees.
|
|
54
|
-
- **Exit the subshell** — Run `
|
|
54
|
+
- **Exit the subshell** — Run `wksh close` to exit the subshell. As with `git switch`, `wksh close` won't let you close the subshell if you have unstaged/uncommitted changes.
|
|
55
55
|
- **The worktree is auto-pruned** — This is key. The lifecycle of the worktree is tied to the subshell. When the subshell is closed, the worktree is destroyed. But *the commits you made inside the subshell* still exist.
|
|
56
56
|
- **Merge in your changes** — Merge/rebase your branch as you normally would, or push to GitHub to open a PR. -->
|
|
57
57
|
|
|
@@ -63,15 +63,15 @@ This approach has some nice properties.
|
|
|
63
63
|
|
|
64
64
|
- 🖥️ **Tab-local workspaces** — Normally a `git checkout`/`git switch` changes your active branch for all terminals. With workshells, you can functionality open branches *in the current tab only*.
|
|
65
65
|
- 🌳 **Full isolation** — Each workshell is isolated on disk, so the changes you make don't interfere anything else you're doing.
|
|
66
|
-
- 🙅♂️ **Never stash again** — You can `
|
|
67
|
-
- **Consistent with branch semantics** — As with regular `git switch`, `
|
|
66
|
+
- 🙅♂️ **Never stash again** — You can `wksh open` a branch even with uncommitted changes. When you exit the subshell, things will be exactly the same as they were. ☕️
|
|
67
|
+
- **Consistent with branch semantics** — As with regular `git switch`, `wksh close` won't let you close the subshell if you have unstaged/uncommitted changes. This is a feature, not a bug! Regular worktrees make it easy to lose your work in a forgotten corner of your file system.
|
|
68
68
|
- 🤖 **Agent-ready** — Spin up parallel workshells so multiple agents can work simultaneously without conflicts.
|
|
69
69
|
|
|
70
70
|
<br/>
|
|
71
71
|
|
|
72
72
|
## Quickstart
|
|
73
73
|
|
|
74
|
-
This section is entirely linear and self-contained. Try running all these commands in order to get a feel for how `
|
|
74
|
+
This section is entirely linear and self-contained. Try running all these commands in order to get a feel for how `wksh` works. First, install `wksh`.
|
|
75
75
|
|
|
76
76
|
```bash
|
|
77
77
|
$ npm i -g workshell
|
|
@@ -91,11 +91,11 @@ $ cd zod
|
|
|
91
91
|
After cloning, the `main` branch is checked out. Let's say we want to start work on a new feature:
|
|
92
92
|
|
|
93
93
|
```bash
|
|
94
|
-
$
|
|
94
|
+
$ wksh new feat-1
|
|
95
95
|
|
|
96
96
|
✓ feat-1 (from main)
|
|
97
|
-
Opened branch in ephemeral subshell at .git/
|
|
98
|
-
Type '
|
|
97
|
+
Opened branch in ephemeral subshell at .git/workshell/worktrees/zod@feat-1
|
|
98
|
+
Type 'wksh close' to return.
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
<br/>
|
|
@@ -104,7 +104,7 @@ You're now in a workshell. Check where you are:
|
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
106
|
$ pwd
|
|
107
|
-
/Users/colinmcd94/Documents/repos/zod/.git/
|
|
107
|
+
/Users/colinmcd94/Documents/repos/zod/.git/workshell/worktrees/zod@feat-1
|
|
108
108
|
|
|
109
109
|
$ git branch --show-current
|
|
110
110
|
feat-1
|
|
@@ -123,10 +123,10 @@ $ touch a.txt
|
|
|
123
123
|
Now let's try to close the workshell.
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
|
-
$
|
|
126
|
+
$ wksh close
|
|
127
127
|
⚠ Uncommitted changes found. Commit, stash, or reset your changes first.
|
|
128
128
|
Or use --force/-f to discard changes
|
|
129
|
-
|
|
129
|
+
wksh close -f
|
|
130
130
|
```
|
|
131
131
|
|
|
132
132
|
<br/>
|
|
@@ -139,10 +139,10 @@ $ git add -A && git commit -am "Add a.txt"
|
|
|
139
139
|
|
|
140
140
|
<br/>
|
|
141
141
|
|
|
142
|
-
Now we can try closing again. Since our changes can be fast-forwarded from the base branch, `
|
|
142
|
+
Now we can try closing again. Since our changes can be fast-forwarded from the base branch, `wksh` offers to auto-merge the changes.
|
|
143
143
|
|
|
144
144
|
```bash
|
|
145
|
-
$
|
|
145
|
+
$ wksh close
|
|
146
146
|
✓ Back in main
|
|
147
147
|
Pruned worktree. Your changes are still in the 'feat-1' branch.
|
|
148
148
|
To merge your changes:
|
|
@@ -158,9 +158,9 @@ $ wsh close
|
|
|
158
158
|
## CLI
|
|
159
159
|
|
|
160
160
|
```sh
|
|
161
|
-
|
|
161
|
+
wksh v0.x.y - Human- and agent-friendly Git multitasking
|
|
162
162
|
|
|
163
|
-
Usage:
|
|
163
|
+
Usage: wksh <command> [options]
|
|
164
164
|
|
|
165
165
|
Commands:
|
|
166
166
|
new [branch] Create a branch and open it [--from <branch>]
|
|
@@ -180,10 +180,10 @@ Options:
|
|
|
180
180
|
|
|
181
181
|
### List orphaned worktrees
|
|
182
182
|
|
|
183
|
-
Normally the worktree will be auto-pruned when you close its associated workshell. If a worktree is left behind for some reason, you can list them with `
|
|
183
|
+
Normally the worktree will be auto-pruned when you close its associated workshell. If a worktree is left behind for some reason, you can list them with `wksh ls`.
|
|
184
184
|
|
|
185
185
|
```sh
|
|
186
|
-
$
|
|
186
|
+
$ wksh ls
|
|
187
187
|
┌────────┬───────────┬───────────────┐
|
|
188
188
|
│ branch │ status │ created │
|
|
189
189
|
├────────┼───────────┼───────────────┤
|
|
@@ -200,10 +200,10 @@ $ wsh ls
|
|
|
200
200
|
You can open any existing Git branch in a workshell.
|
|
201
201
|
|
|
202
202
|
```sh
|
|
203
|
-
$
|
|
203
|
+
$ wksh open feat-1
|
|
204
204
|
|
|
205
205
|
✓ feat-1 (existing worktree)
|
|
206
|
-
Type '
|
|
206
|
+
Type 'wksh close' to return.
|
|
207
207
|
```
|
|
208
208
|
|
|
209
209
|
<br />
|
|
@@ -211,7 +211,7 @@ Type 'wsh close' to return.
|
|
|
211
211
|
### Show current branch status
|
|
212
212
|
|
|
213
213
|
```sh
|
|
214
|
-
$
|
|
214
|
+
$ wksh status
|
|
215
215
|
branch: main (root)
|
|
216
216
|
worktree: /path/to/zod
|
|
217
217
|
status: clean
|
|
@@ -224,7 +224,7 @@ status: clean
|
|
|
224
224
|
Remove the worktree for a branch (the branch itself is kept):
|
|
225
225
|
|
|
226
226
|
```sh
|
|
227
|
-
$
|
|
227
|
+
$ wksh rm feat-1
|
|
228
228
|
|
|
229
229
|
✓ Pruned worktree for feat-1
|
|
230
230
|
```
|
|
@@ -236,7 +236,7 @@ $ wsh rm feat-1
|
|
|
236
236
|
This closes the current workshell and auto-prunes the associated worktree. Your changes survive in your branch commits.
|
|
237
237
|
|
|
238
238
|
```sh
|
|
239
|
-
$
|
|
239
|
+
$ wksh close
|
|
240
240
|
✓ Back in main
|
|
241
241
|
Pruned worktree. Your changes are still in the 'feat-1' branch.
|
|
242
242
|
To merge your changes:
|
|
@@ -256,19 +256,19 @@ If the branch hasn't been pushed to a remote, you'll be prompted to auto-merge:
|
|
|
256
256
|
That command will fail if you have unstaged/uncommited changes. Use the `--force`/`-f` flag to force close the workshell; **this will discard uncommitted changes**.
|
|
257
257
|
|
|
258
258
|
```sh
|
|
259
|
-
$
|
|
259
|
+
$ wksh close --force
|
|
260
260
|
```
|
|
261
261
|
|
|
262
262
|
<br />
|
|
263
263
|
|
|
264
|
-
### Print or create a `
|
|
264
|
+
### Print or create a `workshell.toml`
|
|
265
265
|
|
|
266
266
|
To print or create a config file:
|
|
267
267
|
|
|
268
268
|
```sh
|
|
269
|
-
$
|
|
269
|
+
$ wksh config
|
|
270
270
|
|
|
271
|
-
✓ Config file: /path/to/repo/.git/
|
|
271
|
+
✓ Config file: /path/to/repo/.git/workshell.toml
|
|
272
272
|
|
|
273
273
|
────────────────────────────────────────────────────────────
|
|
274
274
|
setup = "npm install"
|
|
@@ -278,31 +278,31 @@ setup = "npm install"
|
|
|
278
278
|
If no config exists, you'll be prompted to create one.
|
|
279
279
|
|
|
280
280
|
```sh
|
|
281
|
-
$
|
|
281
|
+
$ wksh config
|
|
282
282
|
|
|
283
283
|
No config file found.
|
|
284
284
|
|
|
285
285
|
Where would you like to create one?
|
|
286
|
-
1. .git/
|
|
287
|
-
2.
|
|
286
|
+
1. .git/workshell.toml (local only, not committed)
|
|
287
|
+
2. workshell.toml (project root, can be committed)
|
|
288
288
|
|
|
289
289
|
Choice (1/2): 1
|
|
290
290
|
|
|
291
|
-
✓ Created /path/to/repo/.git/
|
|
291
|
+
✓ Created /path/to/repo/.git/workshell.toml
|
|
292
292
|
```
|
|
293
293
|
|
|
294
294
|
<br />
|
|
295
295
|
|
|
296
|
-
## `
|
|
296
|
+
## `workshell.toml`
|
|
297
297
|
|
|
298
|
-
You can configure `
|
|
298
|
+
You can configure `wksh` with a `workshell.toml` file. This is useful for running setup scripts when opening a workshell (e.g., `npm install`).
|
|
299
299
|
|
|
300
|
-
`
|
|
300
|
+
`wksh` looks for config files in the following order:
|
|
301
301
|
|
|
302
302
|
| Path | Description |
|
|
303
303
|
|------|-------------|
|
|
304
|
-
| `.git/
|
|
305
|
-
| `
|
|
304
|
+
| `.git/workshell.toml` | Local only, not committed (highest precedence) |
|
|
305
|
+
| `workshell.toml` | Project root, can be committed |
|
|
306
306
|
|
|
307
307
|
<br />
|
|
308
308
|
|
|
@@ -317,5 +317,5 @@ The following variable substitutions are supported in `setup`.
|
|
|
317
317
|
|----------|-------------|---------|
|
|
318
318
|
| `{{ branch }}` | Branch name | `feature/auth` |
|
|
319
319
|
| `{{ repo_path }}` | Absolute path to main repo | `/path/to/repo` |
|
|
320
|
-
| `{{ worktree_path }}` | Absolute path to worktree | `/path/to/repo/.git/
|
|
320
|
+
| `{{ worktree_path }}` | Absolute path to worktree | `/path/to/repo/.git/workshell/worktrees/repo@feat` |
|
|
321
321
|
|
package/dist/index.js
CHANGED
|
@@ -6494,10 +6494,10 @@ function getMainWorktree() {
|
|
|
6494
6494
|
return dirname(getGitCommonDir());
|
|
6495
6495
|
}
|
|
6496
6496
|
function getWorktreesDir() {
|
|
6497
|
-
return join(getGitCommonDir(), "
|
|
6497
|
+
return join(getGitCommonDir(), "workshell", "worktrees");
|
|
6498
6498
|
}
|
|
6499
6499
|
function getStorePath() {
|
|
6500
|
-
return join(getGitCommonDir(), "
|
|
6500
|
+
return join(getGitCommonDir(), "workshell");
|
|
6501
6501
|
}
|
|
6502
6502
|
function loadStore() {
|
|
6503
6503
|
const storePath = getStorePath();
|
|
@@ -6537,7 +6537,7 @@ function getWorktreeId(path) {
|
|
|
6537
6537
|
function getWorktreePath(id) {
|
|
6538
6538
|
return join(getWorktreesDir(), id);
|
|
6539
6539
|
}
|
|
6540
|
-
var CONFIG_FILENAME = "
|
|
6540
|
+
var CONFIG_FILENAME = "workshell.toml";
|
|
6541
6541
|
function getConfigPath() {
|
|
6542
6542
|
const gitConfigPath = join(getGitCommonDir(), CONFIG_FILENAME);
|
|
6543
6543
|
if (existsSync(gitConfigPath)) {
|
|
@@ -6594,7 +6594,7 @@ function getCommandName() {
|
|
|
6594
6594
|
}
|
|
6595
6595
|
const scriptName = basename2(scriptPath, ".js");
|
|
6596
6596
|
if (scriptName === "index" || scriptName === "dist") {
|
|
6597
|
-
return "
|
|
6597
|
+
return "wksh";
|
|
6598
6598
|
}
|
|
6599
6599
|
return scriptName;
|
|
6600
6600
|
}
|
|
@@ -6760,22 +6760,11 @@ function canFastForward(baseBranch, targetBranch) {
|
|
|
6760
6760
|
return false;
|
|
6761
6761
|
}
|
|
6762
6762
|
}
|
|
6763
|
-
function inferBaseBranch(branch) {
|
|
6764
|
-
const candidates = ["main", "master"];
|
|
6765
|
-
for (const candidate of candidates) {
|
|
6766
|
-
try {
|
|
6767
|
-
execSync2(`git show-ref --verify --quiet refs/heads/${candidate}`);
|
|
6768
|
-
return candidate;
|
|
6769
|
-
} catch {
|
|
6770
|
-
}
|
|
6771
|
-
}
|
|
6772
|
-
return "HEAD";
|
|
6773
|
-
}
|
|
6774
6763
|
function generateName() {
|
|
6775
6764
|
const bytes = new Uint8Array(4);
|
|
6776
6765
|
crypto.getRandomValues(bytes);
|
|
6777
6766
|
const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
6778
|
-
return `
|
|
6767
|
+
return `wksh-${hex}`;
|
|
6779
6768
|
}
|
|
6780
6769
|
function slugify(name) {
|
|
6781
6770
|
return name.replace(/[^a-zA-Z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
@@ -6802,9 +6791,9 @@ exit() {
|
|
|
6802
6791
|
builtin exit "$@"
|
|
6803
6792
|
fi
|
|
6804
6793
|
# Support: exit -f / exit --force (strip before calling builtin exit)
|
|
6805
|
-
local
|
|
6794
|
+
local wksh_force=""
|
|
6806
6795
|
if [[ "\${1:-}" == "-f" || "\${1:-}" == "--force" ]]; then
|
|
6807
|
-
|
|
6796
|
+
wksh_force="\${1:-}"
|
|
6808
6797
|
shift
|
|
6809
6798
|
fi
|
|
6810
6799
|
# Fail open if ${cmd2} not in PATH
|
|
@@ -6812,30 +6801,30 @@ exit() {
|
|
|
6812
6801
|
builtin exit "$@"
|
|
6813
6802
|
fi
|
|
6814
6803
|
# Run preclose - exit code 1 means dirty, block exit
|
|
6815
|
-
command ${cmd2} __preclose $
|
|
6804
|
+
command ${cmd2} __preclose $wksh_force
|
|
6816
6805
|
if [[ $? -eq 1 ]]; then
|
|
6817
6806
|
return
|
|
6818
6807
|
fi
|
|
6819
6808
|
builtin exit "$@"
|
|
6820
6809
|
}
|
|
6821
6810
|
|
|
6822
|
-
|
|
6811
|
+
__wksh_wrapper() {
|
|
6823
6812
|
case "$1" in
|
|
6824
6813
|
close) shift; exit "$@" ;;
|
|
6825
6814
|
*) command ${cmd2} "$@" ;;
|
|
6826
6815
|
esac
|
|
6827
6816
|
}
|
|
6828
|
-
alias
|
|
6829
|
-
${cmd2.endsWith("-dev") ? `alias
|
|
6817
|
+
alias wksh='__wksh_wrapper'
|
|
6818
|
+
${cmd2.endsWith("-dev") ? `alias wksh-dev='__wksh_wrapper'` : ""}
|
|
6830
6819
|
`;
|
|
6831
6820
|
const zshScript = `
|
|
6832
6821
|
exit() {
|
|
6833
6822
|
if [[ \${ZSH_SUBSHELL:-0} -gt 0 ]]; then
|
|
6834
6823
|
builtin exit "$@"
|
|
6835
6824
|
fi
|
|
6836
|
-
local
|
|
6825
|
+
local wksh_force=""
|
|
6837
6826
|
if [[ "\${1:-}" == "-f" || "\${1:-}" == "--force" ]]; then
|
|
6838
|
-
|
|
6827
|
+
wksh_force="\${1:-}"
|
|
6839
6828
|
shift
|
|
6840
6829
|
fi
|
|
6841
6830
|
# Fail open if ${cmd2} not in PATH
|
|
@@ -6843,21 +6832,21 @@ exit() {
|
|
|
6843
6832
|
builtin exit "$@"
|
|
6844
6833
|
fi
|
|
6845
6834
|
# Run preclose - exit code 1 means dirty, block exit
|
|
6846
|
-
command ${cmd2} __preclose $
|
|
6835
|
+
command ${cmd2} __preclose $wksh_force
|
|
6847
6836
|
if [[ $? -eq 1 ]]; then
|
|
6848
6837
|
return
|
|
6849
6838
|
fi
|
|
6850
6839
|
builtin exit "$@"
|
|
6851
6840
|
}
|
|
6852
6841
|
|
|
6853
|
-
|
|
6842
|
+
__wksh_wrapper() {
|
|
6854
6843
|
case "$1" in
|
|
6855
6844
|
close) shift; exit "$@" ;;
|
|
6856
6845
|
*) command ${cmd2} "$@" ;;
|
|
6857
6846
|
esac
|
|
6858
6847
|
}
|
|
6859
|
-
alias
|
|
6860
|
-
${cmd2.endsWith("-dev") ? `alias
|
|
6848
|
+
alias wksh='__wksh_wrapper'
|
|
6849
|
+
${cmd2.endsWith("-dev") ? `alias wksh-dev='__wksh_wrapper'` : ""}
|
|
6861
6850
|
`;
|
|
6862
6851
|
const fishScript = `
|
|
6863
6852
|
function exit --wraps=exit
|
|
@@ -6865,11 +6854,11 @@ function exit --wraps=exit
|
|
|
6865
6854
|
if not status is-interactive
|
|
6866
6855
|
builtin exit $argv
|
|
6867
6856
|
end
|
|
6868
|
-
set
|
|
6857
|
+
set wksh_force
|
|
6869
6858
|
set args $argv
|
|
6870
6859
|
if test (count $args) -gt 0
|
|
6871
6860
|
if test "$args[1]" = "-f"; or test "$args[1]" = "--force"
|
|
6872
|
-
set
|
|
6861
|
+
set wksh_force $args[1]
|
|
6873
6862
|
set -e args[1]
|
|
6874
6863
|
end
|
|
6875
6864
|
end
|
|
@@ -6878,14 +6867,14 @@ function exit --wraps=exit
|
|
|
6878
6867
|
builtin exit $args
|
|
6879
6868
|
end
|
|
6880
6869
|
# Run preclose - exit code 1 means dirty, block exit
|
|
6881
|
-
command ${cmd2} __preclose $
|
|
6870
|
+
command ${cmd2} __preclose $wksh_force
|
|
6882
6871
|
if test $status -eq 1
|
|
6883
6872
|
return
|
|
6884
6873
|
end
|
|
6885
6874
|
builtin exit $args
|
|
6886
6875
|
end
|
|
6887
6876
|
|
|
6888
|
-
function
|
|
6877
|
+
function __wksh_wrapper
|
|
6889
6878
|
if test "$argv[1]" = "close"
|
|
6890
6879
|
set args $argv
|
|
6891
6880
|
set -e args[1]
|
|
@@ -6895,21 +6884,21 @@ function __wsh_wrapper
|
|
|
6895
6884
|
end
|
|
6896
6885
|
end
|
|
6897
6886
|
|
|
6898
|
-
function
|
|
6899
|
-
|
|
6887
|
+
function wksh --wraps=${cmd2}
|
|
6888
|
+
__wksh_wrapper $argv
|
|
6900
6889
|
end
|
|
6901
6890
|
${cmd2.endsWith("-dev") ? `
|
|
6902
|
-
function
|
|
6903
|
-
|
|
6891
|
+
function wksh-dev --wraps=${cmd2}
|
|
6892
|
+
__wksh_wrapper $argv
|
|
6904
6893
|
end
|
|
6905
6894
|
` : ""}
|
|
6906
6895
|
`;
|
|
6907
6896
|
const setupSection = setupCommand ? `
|
|
6908
|
-
#
|
|
6897
|
+
# wksh setup script
|
|
6909
6898
|
${setupCommand}
|
|
6910
6899
|
` : "";
|
|
6911
6900
|
if (shell.endsWith("zsh")) {
|
|
6912
|
-
const tmpDir = join2(tmpdir(), `
|
|
6901
|
+
const tmpDir = join2(tmpdir(), `wksh-${process.pid}`);
|
|
6913
6902
|
mkdirSync2(tmpDir, { recursive: true });
|
|
6914
6903
|
try {
|
|
6915
6904
|
writeFileSync2(join2(tmpDir, ".zshrc"), `[[ -f "$HOME/.zshrc" ]] && source "$HOME/.zshrc"
|
|
@@ -6919,7 +6908,7 @@ ${zshScript}${setupSection}`);
|
|
|
6919
6908
|
rmSync(tmpDir, { recursive: true, force: true });
|
|
6920
6909
|
}
|
|
6921
6910
|
} else if (shell.endsWith("bash")) {
|
|
6922
|
-
const tmpDir = join2(tmpdir(), `
|
|
6911
|
+
const tmpDir = join2(tmpdir(), `wksh-${process.pid}`);
|
|
6923
6912
|
mkdirSync2(tmpDir, { recursive: true });
|
|
6924
6913
|
try {
|
|
6925
6914
|
const rcFile = join2(tmpDir, ".bashrc");
|
|
@@ -6931,12 +6920,12 @@ ${bashScript}${setupSection}`);
|
|
|
6931
6920
|
}
|
|
6932
6921
|
} else if (shell.endsWith("fish")) {
|
|
6933
6922
|
const fishInit = setupCommand ? `${fishScript}
|
|
6934
|
-
#
|
|
6923
|
+
# wksh setup script
|
|
6935
6924
|
${setupCommand}` : fishScript;
|
|
6936
6925
|
spawnSync(shell, ["--init-command", fishInit], { cwd, stdio: "inherit" });
|
|
6937
6926
|
} else {
|
|
6938
6927
|
console.error(`Error: Unsupported shell '${shell}'`);
|
|
6939
|
-
console.error("
|
|
6928
|
+
console.error("wksh requires bash, zsh, or fish.");
|
|
6940
6929
|
process.exit(1);
|
|
6941
6930
|
}
|
|
6942
6931
|
}
|
|
@@ -6954,20 +6943,19 @@ function autoCleanupWorktree(worktreeId, path, store, saveStore2) {
|
|
|
6954
6943
|
const status = getWorktreeStatus(path);
|
|
6955
6944
|
if (status !== "clean") {
|
|
6956
6945
|
console.log(" " + warn(`Branch '${branch}' has uncommitted changes. Worktree kept.`));
|
|
6957
|
-
console.log(dim(` To reopen: `) + cyan(`
|
|
6946
|
+
console.log(dim(` To reopen: `) + cyan(`wksh open ${branch}`));
|
|
6958
6947
|
return;
|
|
6959
6948
|
}
|
|
6960
|
-
const
|
|
6961
|
-
|
|
6949
|
+
const currentBranch = getCurrentBranch();
|
|
6950
|
+
console.log(" Pruning worktree...");
|
|
6962
6951
|
try {
|
|
6963
6952
|
removeGitWorktree(path);
|
|
6964
6953
|
} catch {
|
|
6965
6954
|
}
|
|
6966
|
-
console.log(" Pruning worktree...");
|
|
6967
6955
|
pruneWorktrees();
|
|
6968
6956
|
removeWorktreeMeta(store, worktreeId);
|
|
6969
6957
|
saveStore2(store);
|
|
6970
|
-
const canMergeBranch = branch !== "[missing]" && branch !== "[detached]" &&
|
|
6958
|
+
const canMergeBranch = branch !== "[missing]" && branch !== "[detached]" && currentBranch !== "HEAD";
|
|
6971
6959
|
if (!canMergeBranch) {
|
|
6972
6960
|
console.log(` Pruned '${branch}' worktree`);
|
|
6973
6961
|
return;
|
|
@@ -6976,19 +6964,14 @@ function autoCleanupWorktree(worktreeId, path, store, saveStore2) {
|
|
|
6976
6964
|
console.log(` Changes have been pushed to a remote.`);
|
|
6977
6965
|
console.log(` Pruned worktree. Your changes are still in the '${cyan(branch)}' branch.`);
|
|
6978
6966
|
console.log(` To check it out again later:`);
|
|
6979
|
-
console.log(dim(` `) + cyan(`
|
|
6967
|
+
console.log(dim(` `) + cyan(`wksh open ${branch}`));
|
|
6980
6968
|
return;
|
|
6981
6969
|
}
|
|
6982
6970
|
console.log(` Pruned worktree. Your changes are still in the '${cyan(branch)}' branch.`);
|
|
6983
6971
|
console.log(` To merge your changes:`);
|
|
6984
|
-
|
|
6985
|
-
if (currentBranch === baseBranch) {
|
|
6986
|
-
console.log(dim(` git merge ${cyan(branch)}`));
|
|
6987
|
-
} else {
|
|
6988
|
-
console.log(dim(` git checkout ${cyan(baseBranch)} && git merge ${cyan(branch)}`));
|
|
6989
|
-
}
|
|
6972
|
+
console.log(dim(` git merge ${cyan(branch)}`));
|
|
6990
6973
|
console.log();
|
|
6991
|
-
if (!canFastForward(
|
|
6974
|
+
if (!canFastForward(currentBranch, branch)) {
|
|
6992
6975
|
return;
|
|
6993
6976
|
}
|
|
6994
6977
|
if (store.auto_merge_prompt === false) {
|
|
@@ -7005,7 +6988,7 @@ function autoCleanupWorktree(worktreeId, path, store, saveStore2) {
|
|
|
7005
6988
|
execSync2(`git merge "${branch}"`, { stdio: "inherit" });
|
|
7006
6989
|
deleteBranch(branch);
|
|
7007
6990
|
console.log();
|
|
7008
|
-
console.log(success(`Merged '${cyan(branch)}' into '${cyan(
|
|
6991
|
+
console.log(success(`Merged '${cyan(branch)}' into '${cyan(currentBranch)}'`));
|
|
7009
6992
|
} catch {
|
|
7010
6993
|
console.log();
|
|
7011
6994
|
console.log(warn(`Merge failed. Resolve conflicts manually, then delete branch with:`));
|
|
@@ -7031,12 +7014,12 @@ function newCommand(branchName, fromBranch) {
|
|
|
7031
7014
|
const existingWorktree = getWorktreeForBranch(branch);
|
|
7032
7015
|
if (existingWorktree) {
|
|
7033
7016
|
console.error(`Error: branch '${branch}' already has an active worktree`);
|
|
7034
|
-
console.error(dim(` Try: `) + cyan(`
|
|
7017
|
+
console.error(dim(` Try: `) + cyan(`wksh open ${branch}`));
|
|
7035
7018
|
process.exit(1);
|
|
7036
7019
|
}
|
|
7037
7020
|
if (branchExists(branch)) {
|
|
7038
7021
|
console.error(`Error: branch '${branch}' already exists`);
|
|
7039
|
-
console.error(dim(` Try: `) + cyan(`
|
|
7022
|
+
console.error(dim(` Try: `) + cyan(`wksh open ${branch}`));
|
|
7040
7023
|
process.exit(1);
|
|
7041
7024
|
}
|
|
7042
7025
|
const store = loadStore();
|
|
@@ -7047,7 +7030,6 @@ function newCommand(branchName, fromBranch) {
|
|
|
7047
7030
|
mkdirSync3(dirname3(worktreePath), { recursive: true });
|
|
7048
7031
|
createWorktree(branch, worktreePath, fromBranch);
|
|
7049
7032
|
setWorktreeMeta(store, worktreeId, {
|
|
7050
|
-
base_branch: baseBranch,
|
|
7051
7033
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
7052
7034
|
});
|
|
7053
7035
|
saveStore(store);
|
|
@@ -7055,7 +7037,7 @@ function newCommand(branchName, fromBranch) {
|
|
|
7055
7037
|
console.log();
|
|
7056
7038
|
console.log(success(bold(branch)), dim(`(from ${cyan(baseBranch)})`));
|
|
7057
7039
|
console.log(dim(`Opened branch in ephemeral subshell at ${relative(mainWorktree, worktreePath)}`));
|
|
7058
|
-
console.log(dim("Type '
|
|
7040
|
+
console.log(dim("Type 'wksh close' to return."));
|
|
7059
7041
|
console.log();
|
|
7060
7042
|
spawnShell(worktreePath, {
|
|
7061
7043
|
branch,
|
|
@@ -7095,7 +7077,7 @@ function openCommand(branch) {
|
|
|
7095
7077
|
const mainWorktree2 = getMainWorktree();
|
|
7096
7078
|
console.log();
|
|
7097
7079
|
console.log(success(bold(branch)), dim(`(existing worktree)`));
|
|
7098
|
-
console.log(dim("Type '
|
|
7080
|
+
console.log(dim("Type 'wksh close' to return."));
|
|
7099
7081
|
console.log();
|
|
7100
7082
|
spawnShell(existingWorktreePath, {
|
|
7101
7083
|
branch,
|
|
@@ -7116,16 +7098,14 @@ function openCommand(branch) {
|
|
|
7116
7098
|
const worktreePath = join4(getWorktreesDir(), worktreeId);
|
|
7117
7099
|
mkdirSync4(dirname4(worktreePath), { recursive: true });
|
|
7118
7100
|
createWorktreeForExistingBranch(branch, worktreePath);
|
|
7119
|
-
const baseBranch = inferBaseBranch(branch);
|
|
7120
7101
|
setWorktreeMeta(store, worktreeId, {
|
|
7121
|
-
base_branch: baseBranch,
|
|
7122
7102
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
7123
7103
|
});
|
|
7124
7104
|
saveStore(store);
|
|
7125
7105
|
console.log();
|
|
7126
7106
|
console.log(success(bold(branch)));
|
|
7127
7107
|
console.log(dim(`Opened branch in ephemeral subshell at ${relative2(mainWorktree, worktreePath)}`));
|
|
7128
|
-
console.log(dim("Type 'exit' or '
|
|
7108
|
+
console.log(dim("Type 'exit' or 'wksh close' to return."));
|
|
7129
7109
|
console.log();
|
|
7130
7110
|
spawnShell(worktreePath, {
|
|
7131
7111
|
branch,
|
|
@@ -8007,14 +7987,14 @@ function rmCommand(branch, force = false) {
|
|
|
8007
7987
|
const absCwd = resolve2(cwd);
|
|
8008
7988
|
if (absCwd === absWtPath || absCwd.startsWith(absWtPath + "/")) {
|
|
8009
7989
|
console.error("Error: cannot remove current worktree");
|
|
8010
|
-
console.error(dim(` Try: `) + cyan(`
|
|
7990
|
+
console.error(dim(` Try: `) + cyan(`wksh close`));
|
|
8011
7991
|
process.exit(1);
|
|
8012
7992
|
}
|
|
8013
7993
|
const status = getWorktreeStatus(worktreePath);
|
|
8014
7994
|
const isDirty = status !== "clean" && status !== "";
|
|
8015
7995
|
if (isDirty && !force) {
|
|
8016
7996
|
console.error(warn("Uncommitted changes found. Commit, stash, or reset your changes first."));
|
|
8017
|
-
console.error(dim(` Or run: `) + cyan(`
|
|
7997
|
+
console.error(dim(` Or run: `) + cyan(`wksh rm ${branch} -f`));
|
|
8018
7998
|
process.exit(1);
|
|
8019
7999
|
}
|
|
8020
8000
|
if (isDirty && force) {
|
|
@@ -8127,7 +8107,7 @@ function precloseCommand(force) {
|
|
|
8127
8107
|
}
|
|
8128
8108
|
console.error(warn("Uncommitted changes found. Commit, stash, or reset your changes first."));
|
|
8129
8109
|
console.error(dim(" Or use --force/-f to discard changes"));
|
|
8130
|
-
console.error(" " + cyan("
|
|
8110
|
+
console.error(" " + cyan("wksh close -f"));
|
|
8131
8111
|
process.exit(1);
|
|
8132
8112
|
}
|
|
8133
8113
|
|
|
@@ -8135,7 +8115,7 @@ function precloseCommand(force) {
|
|
|
8135
8115
|
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
8136
8116
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync3, openSync as openSync2, readSync as readSync2 } from "fs";
|
|
8137
8117
|
import { join as join5 } from "path";
|
|
8138
|
-
var CONFIG_TEMPLATE = `#
|
|
8118
|
+
var CONFIG_TEMPLATE = `# workshell configuration
|
|
8139
8119
|
# https://github.com/colinhacks/workshell
|
|
8140
8120
|
|
|
8141
8121
|
# Initialization script to run when opening a worktree.
|
|
@@ -8165,15 +8145,15 @@ function configCommand() {
|
|
|
8165
8145
|
console.log("No config file found.");
|
|
8166
8146
|
console.log();
|
|
8167
8147
|
console.log("Where would you like to create one?");
|
|
8168
|
-
console.log(` ${import_picocolors3.default.bold("1.")} ${cyan(".git/
|
|
8169
|
-
console.log(` ${import_picocolors3.default.bold("2.")} ${cyan("
|
|
8148
|
+
console.log(` ${import_picocolors3.default.bold("1.")} ${cyan(".git/workshell.toml")} ${dim("(local only, not committed)")}`);
|
|
8149
|
+
console.log(` ${import_picocolors3.default.bold("2.")} ${cyan("workshell.toml")} ${dim("(project root, can be committed)")}`);
|
|
8170
8150
|
console.log();
|
|
8171
8151
|
const choice = promptChoice();
|
|
8172
8152
|
if (!choice) {
|
|
8173
8153
|
console.log(dim("Cancelled."));
|
|
8174
8154
|
return;
|
|
8175
8155
|
}
|
|
8176
|
-
const targetPath = choice === 1 ? join5(getGitCommonDir(), "
|
|
8156
|
+
const targetPath = choice === 1 ? join5(getGitCommonDir(), "workshell.toml") : join5(getMainWorktree(), "workshell.toml");
|
|
8177
8157
|
writeFileSync3(targetPath, CONFIG_TEMPLATE);
|
|
8178
8158
|
console.log();
|
|
8179
8159
|
console.log(success(`Created ${cyan(targetPath)}`));
|
|
@@ -8193,14 +8173,14 @@ function promptChoice() {
|
|
|
8193
8173
|
}
|
|
8194
8174
|
|
|
8195
8175
|
// index.ts
|
|
8196
|
-
var VERSION = "0.0.
|
|
8176
|
+
var VERSION = "0.0.3";
|
|
8197
8177
|
function printHelp() {
|
|
8198
8178
|
const dim2 = import_picocolors4.default.dim;
|
|
8199
8179
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8200
8180
|
const green2 = import_picocolors4.default.green;
|
|
8201
|
-
console.log(`${import_picocolors4.default.bold("
|
|
8181
|
+
console.log(`${import_picocolors4.default.bold("wksh")} ${dim2(`v${VERSION}`)} - Open branches in ephemeral subshells
|
|
8202
8182
|
|
|
8203
|
-
${import_picocolors4.default.bold("Usage:")} ${cyan2("
|
|
8183
|
+
${import_picocolors4.default.bold("Usage:")} ${cyan2("wksh")} ${dim2("<command>")} ${dim2("[options]")}
|
|
8204
8184
|
|
|
8205
8185
|
${import_picocolors4.default.bold("Commands:")}
|
|
8206
8186
|
${green2("new")} ${dim2("[branch]")} Create a branch and open it ${dim2("[--from <branch>]")}
|
|
@@ -8217,15 +8197,15 @@ ${import_picocolors4.default.bold("Options:")}
|
|
|
8217
8197
|
|
|
8218
8198
|
${dim2("\u2500".repeat(60))}
|
|
8219
8199
|
|
|
8220
|
-
${import_picocolors4.default.bold("Why
|
|
8200
|
+
${import_picocolors4.default.bold("Why wksh?")}
|
|
8221
8201
|
|
|
8222
8202
|
In agentic development, you often want to spin up isolated workspaces for
|
|
8223
|
-
specific tasks\u2014without stashing or committing your current changes.
|
|
8203
|
+
specific tasks\u2014without stashing or committing your current changes. wksh makes
|
|
8224
8204
|
this effortless.
|
|
8225
8205
|
|
|
8226
8206
|
Open a new branch in an ephemeral subshell:
|
|
8227
8207
|
|
|
8228
|
-
${dim2("$")} ${cyan2("
|
|
8208
|
+
${dim2("$")} ${cyan2("wksh new add-login-button")}
|
|
8229
8209
|
|
|
8230
8210
|
This creates a branch and worktree, then drops you into a subshell. Open it
|
|
8231
8211
|
in your editor or point an AI coding agent at it. Your changes are completely
|
|
@@ -8239,24 +8219,24 @@ Or merge directly back into main:
|
|
|
8239
8219
|
|
|
8240
8220
|
${dim2("$")} ${cyan2("git checkout main && git merge add-login-button")}
|
|
8241
8221
|
|
|
8242
|
-
Then just ${cyan2("
|
|
8222
|
+
Then just ${cyan2("wksh close")} to return to your main repo. The worktree is ephemeral\u2014
|
|
8243
8223
|
it gets cleaned up automatically.
|
|
8244
8224
|
|
|
8245
|
-
Use ${cyan2("
|
|
8225
|
+
Use ${cyan2("wksh ls")} to see branches with open worktrees, and ${cyan2("wksh open <branch>")} to
|
|
8246
8226
|
reopen one later.`);
|
|
8247
8227
|
}
|
|
8248
8228
|
function printVersion() {
|
|
8249
|
-
console.log(`
|
|
8229
|
+
console.log(`wksh v${VERSION}`);
|
|
8250
8230
|
}
|
|
8251
8231
|
function printNewHelp() {
|
|
8252
8232
|
const dim2 = import_picocolors4.default.dim;
|
|
8253
8233
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8254
|
-
console.log(`${import_picocolors4.default.bold("
|
|
8234
|
+
console.log(`${import_picocolors4.default.bold("wksh new")} - Create a branch and open it in an ephemeral subshell
|
|
8255
8235
|
|
|
8256
|
-
${import_picocolors4.default.bold("Usage:")} ${cyan2("
|
|
8236
|
+
${import_picocolors4.default.bold("Usage:")} ${cyan2("wksh new")} ${dim2("[branch]")} ${dim2("[--from <branch>]")}
|
|
8257
8237
|
|
|
8258
8238
|
${import_picocolors4.default.bold("Arguments:")}
|
|
8259
|
-
${dim2("[branch]")} Branch name ${dim2('(default: "
|
|
8239
|
+
${dim2("[branch]")} Branch name ${dim2('(default: "wksh-[hash]")')}
|
|
8260
8240
|
|
|
8261
8241
|
${import_picocolors4.default.bold("Options:")}
|
|
8262
8242
|
${cyan2("--from")} ${dim2("<branch>")} Base branch to fork from ${dim2("(default: current branch)")}
|
|
@@ -8264,14 +8244,14 @@ ${import_picocolors4.default.bold("Options:")}
|
|
|
8264
8244
|
${import_picocolors4.default.bold("Description:")}
|
|
8265
8245
|
Creates a new Git branch (forked from current or specified branch) and opens
|
|
8266
8246
|
it in an ephemeral subshell with its own worktree.
|
|
8267
|
-
Type '
|
|
8247
|
+
Type 'wksh close' to return.`);
|
|
8268
8248
|
}
|
|
8269
8249
|
function printOpenHelp() {
|
|
8270
8250
|
const dim2 = import_picocolors4.default.dim;
|
|
8271
8251
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8272
|
-
console.log(`${import_picocolors4.default.bold("
|
|
8252
|
+
console.log(`${import_picocolors4.default.bold("wksh open")} - Open a branch in an ephemeral subshell
|
|
8273
8253
|
|
|
8274
|
-
${import_picocolors4.default.bold("Usage:")} ${cyan2("
|
|
8254
|
+
${import_picocolors4.default.bold("Usage:")} ${cyan2("wksh open")} ${dim2("<branch>")}
|
|
8275
8255
|
|
|
8276
8256
|
${import_picocolors4.default.bold("Arguments:")}
|
|
8277
8257
|
${dim2("<branch>")} Branch name ${dim2("(required)")}
|
|
@@ -8280,14 +8260,14 @@ ${import_picocolors4.default.bold("Description:")}
|
|
|
8280
8260
|
Opens the specified branch in an ephemeral subshell.
|
|
8281
8261
|
If a worktree already exists for the branch, uses that.
|
|
8282
8262
|
Otherwise, creates a new worktree automatically.
|
|
8283
|
-
Type '
|
|
8263
|
+
Type 'wksh close' to return.`);
|
|
8284
8264
|
}
|
|
8285
8265
|
function printLsHelp() {
|
|
8286
8266
|
const dim2 = import_picocolors4.default.dim;
|
|
8287
8267
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8288
|
-
console.log(`${import_picocolors4.default.bold("
|
|
8268
|
+
console.log(`${import_picocolors4.default.bold("wksh ls")} - List branches with open worktrees
|
|
8289
8269
|
|
|
8290
|
-
${import_picocolors4.default.bold("Usage:")} ${cyan2("
|
|
8270
|
+
${import_picocolors4.default.bold("Usage:")} ${cyan2("wksh ls")} ${dim2("[options]")}
|
|
8291
8271
|
|
|
8292
8272
|
${import_picocolors4.default.bold("Options:")}
|
|
8293
8273
|
${cyan2("--plain")} Output in plain tab-separated format
|
|
@@ -8300,9 +8280,9 @@ ${import_picocolors4.default.bold("Description:")}
|
|
|
8300
8280
|
function printRmHelp() {
|
|
8301
8281
|
const dim2 = import_picocolors4.default.dim;
|
|
8302
8282
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8303
|
-
console.log(`${import_picocolors4.default.bold("
|
|
8283
|
+
console.log(`${import_picocolors4.default.bold("wksh rm")} - Remove a branch's worktree
|
|
8304
8284
|
|
|
8305
|
-
${import_picocolors4.default.bold("Usage:")} ${cyan2("
|
|
8285
|
+
${import_picocolors4.default.bold("Usage:")} ${cyan2("wksh rm")} ${dim2("<branch>")} ${dim2("[options]")}
|
|
8306
8286
|
|
|
8307
8287
|
${import_picocolors4.default.bold("Arguments:")}
|
|
8308
8288
|
${dim2("<branch>")} Branch whose worktree to remove ${dim2("(required)")}
|
|
@@ -8317,9 +8297,9 @@ ${import_picocolors4.default.bold("Description:")}
|
|
|
8317
8297
|
}
|
|
8318
8298
|
function printStatusHelp() {
|
|
8319
8299
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8320
|
-
console.log(`${import_picocolors4.default.bold("
|
|
8300
|
+
console.log(`${import_picocolors4.default.bold("wksh status")} - Show current branch status
|
|
8321
8301
|
|
|
8322
|
-
${import_picocolors4.default.bold("Usage:")} ${cyan2("
|
|
8302
|
+
${import_picocolors4.default.bold("Usage:")} ${cyan2("wksh status")}
|
|
8323
8303
|
|
|
8324
8304
|
${import_picocolors4.default.bold("Description:")}
|
|
8325
8305
|
Shows the current branch, worktree path, and git status.`);
|
|
@@ -8327,9 +8307,9 @@ ${import_picocolors4.default.bold("Description:")}
|
|
|
8327
8307
|
function printCloseHelp() {
|
|
8328
8308
|
const dim2 = import_picocolors4.default.dim;
|
|
8329
8309
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8330
|
-
console.log(`${import_picocolors4.default.bold("
|
|
8310
|
+
console.log(`${import_picocolors4.default.bold("wksh close")} - Exit current subshell
|
|
8331
8311
|
|
|
8332
|
-
${import_picocolors4.default.bold("Usage:")} ${cyan2("
|
|
8312
|
+
${import_picocolors4.default.bold("Usage:")} ${cyan2("wksh close")} ${dim2("[options]")}
|
|
8333
8313
|
|
|
8334
8314
|
${import_picocolors4.default.bold("Options:")}
|
|
8335
8315
|
${cyan2("-f")}, ${cyan2("--force")} Discard uncommitted changes and exit
|
|
@@ -8348,17 +8328,17 @@ ${import_picocolors4.default.bold("Description:")}
|
|
|
8348
8328
|
function printConfigHelp() {
|
|
8349
8329
|
const dim2 = import_picocolors4.default.dim;
|
|
8350
8330
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8351
|
-
console.log(`${import_picocolors4.default.bold("
|
|
8331
|
+
console.log(`${import_picocolors4.default.bold("wksh config")} - Show or create config file
|
|
8352
8332
|
|
|
8353
|
-
${import_picocolors4.default.bold("Usage:")} ${cyan2("
|
|
8333
|
+
${import_picocolors4.default.bold("Usage:")} ${cyan2("wksh config")}
|
|
8354
8334
|
|
|
8355
8335
|
${import_picocolors4.default.bold("Description:")}
|
|
8356
|
-
Shows the path and contents of your
|
|
8336
|
+
Shows the path and contents of your workshell config file.
|
|
8357
8337
|
If no config exists, prompts to create one.
|
|
8358
8338
|
|
|
8359
8339
|
${import_picocolors4.default.bold("Config locations")} ${dim2("(in precedence order)")}${import_picocolors4.default.bold(":")}
|
|
8360
|
-
${cyan2(".git/
|
|
8361
|
-
${cyan2("
|
|
8340
|
+
${cyan2(".git/workshell.toml")} Local only, not committed
|
|
8341
|
+
${cyan2("workshell.toml")} Project root, can be committed`);
|
|
8362
8342
|
}
|
|
8363
8343
|
function isHelp(arg) {
|
|
8364
8344
|
return arg === "--help" || arg === "-h";
|
|
@@ -8401,7 +8381,7 @@ switch (cmd) {
|
|
|
8401
8381
|
process.exit(0);
|
|
8402
8382
|
}
|
|
8403
8383
|
if (!args[1]) {
|
|
8404
|
-
console.error("Usage:
|
|
8384
|
+
console.error("Usage: wksh open <branch>");
|
|
8405
8385
|
process.exit(1);
|
|
8406
8386
|
}
|
|
8407
8387
|
openCommand(args[1]);
|
|
@@ -8426,7 +8406,7 @@ switch (cmd) {
|
|
|
8426
8406
|
process.exit(0);
|
|
8427
8407
|
}
|
|
8428
8408
|
if (!args[1]) {
|
|
8429
|
-
console.error("Usage:
|
|
8409
|
+
console.error("Usage: wksh rm <branch>");
|
|
8430
8410
|
process.exit(1);
|
|
8431
8411
|
}
|
|
8432
8412
|
rmCommand(args[1], args.includes("-f") || args.includes("--force"));
|
|
@@ -8443,7 +8423,7 @@ switch (cmd) {
|
|
|
8443
8423
|
printCloseHelp();
|
|
8444
8424
|
process.exit(0);
|
|
8445
8425
|
}
|
|
8446
|
-
console.error(fail("'
|
|
8426
|
+
console.error(fail("'wksh close' only works inside a wksh subshell."));
|
|
8447
8427
|
process.exit(1);
|
|
8448
8428
|
break;
|
|
8449
8429
|
case "__preclose":
|
|
@@ -8451,7 +8431,7 @@ switch (cmd) {
|
|
|
8451
8431
|
break;
|
|
8452
8432
|
default:
|
|
8453
8433
|
console.error(`Unknown command: ${cmd}`);
|
|
8454
|
-
console.error("Run '
|
|
8434
|
+
console.error("Run 'wksh --help' for usage.");
|
|
8455
8435
|
process.exit(1);
|
|
8456
8436
|
}
|
|
8457
8437
|
/*! Bundled license information:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workshell",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Agent- and human-friendly Git multitasking, powered by worktrees",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"isolation"
|
|
23
23
|
],
|
|
24
24
|
"bin": {
|
|
25
|
-
"
|
|
25
|
+
"wksh": "dist/index.js",
|
|
26
26
|
"workshell": "dist/index.js",
|
|
27
27
|
"git-workshell": "dist/index.js"
|
|
28
28
|
},
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"sideEffects": false,
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "tsc && node build.ts",
|
|
35
|
-
"postbuild": "ln -sf $(pwd)/dist/index.js /usr/local/bin/
|
|
35
|
+
"postbuild": "ln -sf $(pwd)/dist/index.js /usr/local/bin/wksh-dev",
|
|
36
36
|
"dev": "node build.ts --watch",
|
|
37
37
|
"prepare": "husky && node build.ts",
|
|
38
38
|
"typecheck": "tsc",
|