worktree-launcher 1.3.0 → 1.4.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/README.md +14 -5
- package/dist/index.js +349 -49
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,26 +38,35 @@ Requires Node.js 18+ and git.
|
|
|
38
38
|
|
|
39
39
|
## Interactive Mode (TUI)
|
|
40
40
|
|
|
41
|
-
Run `wt` with no arguments to open a terminal UI
|
|
41
|
+
Run `wt` with no arguments to open a terminal UI:
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
wt
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
The TUI
|
|
47
|
+
The TUI shows your repo name, current branch, and all existing worktrees. Use keyboard shortcuts to manage them:
|
|
48
48
|
|
|
49
49
|
| Key | Action |
|
|
50
50
|
|-----|--------|
|
|
51
|
-
| `n` | Create new worktree |
|
|
51
|
+
| `n` | Create new worktree (guided wizard) |
|
|
52
52
|
| `d` | Delete selected worktree |
|
|
53
53
|
| `c` | Launch Claude Code in selected worktree |
|
|
54
54
|
| `x` | Launch Codex in selected worktree |
|
|
55
|
-
| `p` | Push branch to remote |
|
|
56
55
|
| `Enter` | Print cd command for selected worktree |
|
|
57
56
|
| `r` | Refresh worktree list |
|
|
58
57
|
| `q` | Quit |
|
|
59
58
|
|
|
60
|
-
Navigate with arrow keys or vim-style `j`/`k`.
|
|
59
|
+
Navigate with arrow keys or vim-style `j`/`k`.
|
|
60
|
+
|
|
61
|
+
### Creating a New Worktree
|
|
62
|
+
|
|
63
|
+
Press `n` to start the guided creation wizard:
|
|
64
|
+
|
|
65
|
+
1. **Branch name** - Enter the name for your new branch
|
|
66
|
+
2. **Base branch** - Create from current branch or default branch (main/master)
|
|
67
|
+
3. **Copy .env files** - Copy environment files to the new worktree
|
|
68
|
+
4. **Push to remote** - Push branch to GitHub immediately
|
|
69
|
+
5. **Launch AI tool** - Choose Claude Code, Codex, or skip
|
|
61
70
|
|
|
62
71
|
## Commands
|
|
63
72
|
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,14 @@ async function remoteBranchExists(branchName) {
|
|
|
44
44
|
return false;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
async function getCurrentBranch() {
|
|
48
|
+
try {
|
|
49
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
50
|
+
return stdout.trim();
|
|
51
|
+
} catch {
|
|
52
|
+
return "HEAD";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
47
55
|
async function getDefaultBranch() {
|
|
48
56
|
try {
|
|
49
57
|
const { stdout } = await execFileAsync("git", ["symbolic-ref", "refs/remotes/origin/HEAD"]);
|
|
@@ -103,8 +111,8 @@ async function pruneWorktrees() {
|
|
|
103
111
|
}
|
|
104
112
|
async function isBranchMerged(branchName) {
|
|
105
113
|
try {
|
|
106
|
-
const
|
|
107
|
-
const { stdout } = await execFileAsync("git", ["branch", "--merged",
|
|
114
|
+
const defaultBranch2 = await getDefaultBranch();
|
|
115
|
+
const { stdout } = await execFileAsync("git", ["branch", "--merged", defaultBranch2]);
|
|
108
116
|
const mergedBranches = stdout.split("\n").map((b) => b.trim().replace("* ", ""));
|
|
109
117
|
return mergedBranches.includes(branchName);
|
|
110
118
|
} catch {
|
|
@@ -602,7 +610,10 @@ var screen;
|
|
|
602
610
|
var worktreeList;
|
|
603
611
|
var statusBar;
|
|
604
612
|
var helpBar;
|
|
613
|
+
var headerBox;
|
|
605
614
|
var mainRepoPath;
|
|
615
|
+
var currentBranch;
|
|
616
|
+
var defaultBranch;
|
|
606
617
|
var worktrees = [];
|
|
607
618
|
var selectedIndex = 0;
|
|
608
619
|
async function interactiveCommand() {
|
|
@@ -611,18 +622,20 @@ async function interactiveCommand() {
|
|
|
611
622
|
process.exit(1);
|
|
612
623
|
}
|
|
613
624
|
mainRepoPath = await getGitRoot();
|
|
625
|
+
currentBranch = await getCurrentBranch();
|
|
626
|
+
defaultBranch = await getDefaultBranch();
|
|
614
627
|
const repoName = path8.basename(mainRepoPath);
|
|
615
628
|
screen = blessed.screen({
|
|
616
629
|
smartCSR: true,
|
|
617
630
|
title: `wt - ${repoName}`
|
|
618
631
|
});
|
|
619
|
-
blessed.box({
|
|
632
|
+
headerBox = blessed.box({
|
|
620
633
|
parent: screen,
|
|
621
634
|
top: 0,
|
|
622
635
|
left: 0,
|
|
623
636
|
width: "100%",
|
|
624
637
|
height: 1,
|
|
625
|
-
content: `
|
|
638
|
+
content: ` ${repoName} (${currentBranch})`,
|
|
626
639
|
style: {
|
|
627
640
|
fg: "white",
|
|
628
641
|
bg: "blue",
|
|
@@ -670,7 +683,7 @@ async function interactiveCommand() {
|
|
|
670
683
|
left: 0,
|
|
671
684
|
width: "100%",
|
|
672
685
|
height: 1,
|
|
673
|
-
content: " [n]ew [d]elete [c]laude [x]codex [
|
|
686
|
+
content: " [n]ew [d]elete [c]laude [x]codex [Enter]cd [q]uit",
|
|
674
687
|
style: {
|
|
675
688
|
fg: "black",
|
|
676
689
|
bg: "white"
|
|
@@ -685,8 +698,8 @@ async function interactiveCommand() {
|
|
|
685
698
|
screen.destroy();
|
|
686
699
|
process.exit(0);
|
|
687
700
|
});
|
|
688
|
-
screen.key(["n"],
|
|
689
|
-
|
|
701
|
+
screen.key(["n"], () => {
|
|
702
|
+
startCreationWizard();
|
|
690
703
|
});
|
|
691
704
|
screen.key(["d"], async () => {
|
|
692
705
|
await deleteSelected();
|
|
@@ -697,9 +710,6 @@ async function interactiveCommand() {
|
|
|
697
710
|
screen.key(["x"], async () => {
|
|
698
711
|
await launchAI("codex");
|
|
699
712
|
});
|
|
700
|
-
screen.key(["p"], async () => {
|
|
701
|
-
await pushSelected();
|
|
702
|
-
});
|
|
703
713
|
screen.key(["enter"], () => {
|
|
704
714
|
const wt = worktrees[selectedIndex];
|
|
705
715
|
if (wt) {
|
|
@@ -743,54 +753,354 @@ function setStatus(msg) {
|
|
|
743
753
|
statusBar.setContent(` ${msg}`);
|
|
744
754
|
screen.render();
|
|
745
755
|
}
|
|
746
|
-
|
|
747
|
-
const
|
|
756
|
+
function startCreationWizard() {
|
|
757
|
+
const state = {
|
|
758
|
+
branchName: "",
|
|
759
|
+
baseBranch: "current",
|
|
760
|
+
copyEnv: true,
|
|
761
|
+
pushToRemote: false,
|
|
762
|
+
aiTool: "claude"
|
|
763
|
+
};
|
|
764
|
+
askBranchName(state);
|
|
765
|
+
}
|
|
766
|
+
function askBranchName(state) {
|
|
767
|
+
const form = blessed.box({
|
|
748
768
|
parent: screen,
|
|
749
769
|
top: "center",
|
|
750
770
|
left: "center",
|
|
751
|
-
width:
|
|
752
|
-
height:
|
|
771
|
+
width: 60,
|
|
772
|
+
height: 12,
|
|
753
773
|
border: { type: "line" },
|
|
754
774
|
style: {
|
|
755
775
|
fg: "white",
|
|
756
776
|
bg: "black",
|
|
757
777
|
border: { fg: "blue" }
|
|
758
778
|
},
|
|
759
|
-
label: "
|
|
779
|
+
label: " New Worktree "
|
|
780
|
+
});
|
|
781
|
+
blessed.text({
|
|
782
|
+
parent: form,
|
|
783
|
+
top: 1,
|
|
784
|
+
left: 2,
|
|
785
|
+
content: `Repository: ${path8.basename(mainRepoPath)}`,
|
|
786
|
+
style: { fg: "cyan" }
|
|
787
|
+
});
|
|
788
|
+
blessed.text({
|
|
789
|
+
parent: form,
|
|
790
|
+
top: 2,
|
|
791
|
+
left: 2,
|
|
792
|
+
content: `Current branch: ${currentBranch}`,
|
|
793
|
+
style: { fg: "grey" }
|
|
794
|
+
});
|
|
795
|
+
blessed.text({
|
|
796
|
+
parent: form,
|
|
797
|
+
top: 4,
|
|
798
|
+
left: 2,
|
|
799
|
+
content: "Branch name:",
|
|
800
|
+
style: { fg: "white" }
|
|
801
|
+
});
|
|
802
|
+
const input = blessed.textbox({
|
|
803
|
+
parent: form,
|
|
804
|
+
top: 5,
|
|
805
|
+
left: 2,
|
|
806
|
+
width: 54,
|
|
807
|
+
height: 1,
|
|
808
|
+
style: {
|
|
809
|
+
fg: "white",
|
|
810
|
+
bg: "grey"
|
|
811
|
+
},
|
|
760
812
|
inputOnFocus: true
|
|
761
813
|
});
|
|
814
|
+
blessed.text({
|
|
815
|
+
parent: form,
|
|
816
|
+
top: 7,
|
|
817
|
+
left: 2,
|
|
818
|
+
content: "[Enter] next [Esc] cancel",
|
|
819
|
+
style: { fg: "grey" }
|
|
820
|
+
});
|
|
762
821
|
input.focus();
|
|
763
822
|
screen.render();
|
|
764
|
-
input.on("submit",
|
|
765
|
-
input.destroy();
|
|
823
|
+
input.on("submit", (value) => {
|
|
766
824
|
if (!value || !value.trim()) {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
}
|
|
770
|
-
const branchName = value.trim();
|
|
771
|
-
try {
|
|
772
|
-
validateBranchName(branchName);
|
|
773
|
-
} catch (e) {
|
|
774
|
-
setStatus(`Error: ${e.message}`);
|
|
825
|
+
form.destroy();
|
|
826
|
+
screen.render();
|
|
775
827
|
return;
|
|
776
828
|
}
|
|
777
|
-
setStatus(`Creating ${branchName}...`);
|
|
778
829
|
try {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
await refreshWorktrees();
|
|
830
|
+
validateBranchName(value.trim());
|
|
831
|
+
state.branchName = value.trim();
|
|
832
|
+
form.destroy();
|
|
833
|
+
askBaseBranch(state);
|
|
784
834
|
} catch (e) {
|
|
785
835
|
setStatus(`Error: ${e.message}`);
|
|
836
|
+
input.focus();
|
|
837
|
+
screen.render();
|
|
786
838
|
}
|
|
787
839
|
});
|
|
788
840
|
input.on("cancel", () => {
|
|
789
|
-
|
|
790
|
-
|
|
841
|
+
form.destroy();
|
|
842
|
+
screen.render();
|
|
791
843
|
});
|
|
792
844
|
input.readInput();
|
|
793
845
|
}
|
|
846
|
+
function askBaseBranch(state) {
|
|
847
|
+
const form = blessed.box({
|
|
848
|
+
parent: screen,
|
|
849
|
+
top: "center",
|
|
850
|
+
left: "center",
|
|
851
|
+
width: 50,
|
|
852
|
+
height: 10,
|
|
853
|
+
border: { type: "line" },
|
|
854
|
+
style: {
|
|
855
|
+
fg: "white",
|
|
856
|
+
bg: "black",
|
|
857
|
+
border: { fg: "blue" }
|
|
858
|
+
},
|
|
859
|
+
label: " Base Branch "
|
|
860
|
+
});
|
|
861
|
+
blessed.text({
|
|
862
|
+
parent: form,
|
|
863
|
+
top: 1,
|
|
864
|
+
left: 2,
|
|
865
|
+
content: "Create worktree from:",
|
|
866
|
+
style: { fg: "white" }
|
|
867
|
+
});
|
|
868
|
+
const list = blessed.list({
|
|
869
|
+
parent: form,
|
|
870
|
+
top: 3,
|
|
871
|
+
left: 2,
|
|
872
|
+
width: 44,
|
|
873
|
+
height: 3,
|
|
874
|
+
keys: true,
|
|
875
|
+
vi: true,
|
|
876
|
+
style: {
|
|
877
|
+
selected: { bg: "blue", fg: "white" },
|
|
878
|
+
item: { fg: "white" }
|
|
879
|
+
},
|
|
880
|
+
items: [
|
|
881
|
+
` Current branch (${currentBranch})`,
|
|
882
|
+
` Default branch (${defaultBranch})`
|
|
883
|
+
]
|
|
884
|
+
});
|
|
885
|
+
blessed.text({
|
|
886
|
+
parent: form,
|
|
887
|
+
top: 7,
|
|
888
|
+
left: 2,
|
|
889
|
+
content: "[Enter] select [Esc] cancel",
|
|
890
|
+
style: { fg: "grey" }
|
|
891
|
+
});
|
|
892
|
+
list.focus();
|
|
893
|
+
screen.render();
|
|
894
|
+
list.on("select", (_item, index) => {
|
|
895
|
+
state.baseBranch = index === 0 ? "current" : "default";
|
|
896
|
+
form.destroy();
|
|
897
|
+
askCopyEnv(state);
|
|
898
|
+
});
|
|
899
|
+
list.key(["escape"], () => {
|
|
900
|
+
form.destroy();
|
|
901
|
+
screen.render();
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
function askCopyEnv(state) {
|
|
905
|
+
const form = blessed.box({
|
|
906
|
+
parent: screen,
|
|
907
|
+
top: "center",
|
|
908
|
+
left: "center",
|
|
909
|
+
width: 40,
|
|
910
|
+
height: 8,
|
|
911
|
+
border: { type: "line" },
|
|
912
|
+
style: {
|
|
913
|
+
fg: "white",
|
|
914
|
+
bg: "black",
|
|
915
|
+
border: { fg: "blue" }
|
|
916
|
+
},
|
|
917
|
+
label: " Environment Files "
|
|
918
|
+
});
|
|
919
|
+
blessed.text({
|
|
920
|
+
parent: form,
|
|
921
|
+
top: 1,
|
|
922
|
+
left: 2,
|
|
923
|
+
content: "Copy .env files to worktree?",
|
|
924
|
+
style: { fg: "white" }
|
|
925
|
+
});
|
|
926
|
+
const list = blessed.list({
|
|
927
|
+
parent: form,
|
|
928
|
+
top: 3,
|
|
929
|
+
left: 2,
|
|
930
|
+
width: 34,
|
|
931
|
+
height: 2,
|
|
932
|
+
keys: true,
|
|
933
|
+
vi: true,
|
|
934
|
+
style: {
|
|
935
|
+
selected: { bg: "blue", fg: "white" },
|
|
936
|
+
item: { fg: "white" }
|
|
937
|
+
},
|
|
938
|
+
items: [" Yes (recommended)", " No"]
|
|
939
|
+
});
|
|
940
|
+
list.focus();
|
|
941
|
+
screen.render();
|
|
942
|
+
list.on("select", (_item, index) => {
|
|
943
|
+
state.copyEnv = index === 0;
|
|
944
|
+
form.destroy();
|
|
945
|
+
askPushToRemote(state);
|
|
946
|
+
});
|
|
947
|
+
list.key(["escape"], () => {
|
|
948
|
+
form.destroy();
|
|
949
|
+
screen.render();
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
function askPushToRemote(state) {
|
|
953
|
+
const form = blessed.box({
|
|
954
|
+
parent: screen,
|
|
955
|
+
top: "center",
|
|
956
|
+
left: "center",
|
|
957
|
+
width: 45,
|
|
958
|
+
height: 8,
|
|
959
|
+
border: { type: "line" },
|
|
960
|
+
style: {
|
|
961
|
+
fg: "white",
|
|
962
|
+
bg: "black",
|
|
963
|
+
border: { fg: "blue" }
|
|
964
|
+
},
|
|
965
|
+
label: " Push to Remote "
|
|
966
|
+
});
|
|
967
|
+
blessed.text({
|
|
968
|
+
parent: form,
|
|
969
|
+
top: 1,
|
|
970
|
+
left: 2,
|
|
971
|
+
content: "Push branch to GitHub immediately?",
|
|
972
|
+
style: { fg: "white" }
|
|
973
|
+
});
|
|
974
|
+
const list = blessed.list({
|
|
975
|
+
parent: form,
|
|
976
|
+
top: 3,
|
|
977
|
+
left: 2,
|
|
978
|
+
width: 39,
|
|
979
|
+
height: 2,
|
|
980
|
+
keys: true,
|
|
981
|
+
vi: true,
|
|
982
|
+
style: {
|
|
983
|
+
selected: { bg: "blue", fg: "white" },
|
|
984
|
+
item: { fg: "white" }
|
|
985
|
+
},
|
|
986
|
+
items: [" No (push later)", " Yes (visible on GitHub now)"]
|
|
987
|
+
});
|
|
988
|
+
list.focus();
|
|
989
|
+
screen.render();
|
|
990
|
+
list.on("select", (_item, index) => {
|
|
991
|
+
state.pushToRemote = index === 1;
|
|
992
|
+
form.destroy();
|
|
993
|
+
askAITool(state);
|
|
994
|
+
});
|
|
995
|
+
list.key(["escape"], () => {
|
|
996
|
+
form.destroy();
|
|
997
|
+
screen.render();
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
function askAITool(state) {
|
|
1001
|
+
const form = blessed.box({
|
|
1002
|
+
parent: screen,
|
|
1003
|
+
top: "center",
|
|
1004
|
+
left: "center",
|
|
1005
|
+
width: 40,
|
|
1006
|
+
height: 10,
|
|
1007
|
+
border: { type: "line" },
|
|
1008
|
+
style: {
|
|
1009
|
+
fg: "white",
|
|
1010
|
+
bg: "black",
|
|
1011
|
+
border: { fg: "blue" }
|
|
1012
|
+
},
|
|
1013
|
+
label: " Launch AI Tool "
|
|
1014
|
+
});
|
|
1015
|
+
blessed.text({
|
|
1016
|
+
parent: form,
|
|
1017
|
+
top: 1,
|
|
1018
|
+
left: 2,
|
|
1019
|
+
content: "Which AI assistant to launch?",
|
|
1020
|
+
style: { fg: "white" }
|
|
1021
|
+
});
|
|
1022
|
+
const list = blessed.list({
|
|
1023
|
+
parent: form,
|
|
1024
|
+
top: 3,
|
|
1025
|
+
left: 2,
|
|
1026
|
+
width: 34,
|
|
1027
|
+
height: 3,
|
|
1028
|
+
keys: true,
|
|
1029
|
+
vi: true,
|
|
1030
|
+
style: {
|
|
1031
|
+
selected: { bg: "blue", fg: "white" },
|
|
1032
|
+
item: { fg: "white" }
|
|
1033
|
+
},
|
|
1034
|
+
items: [" Claude Code", " Codex", " Skip (just create worktree)"]
|
|
1035
|
+
});
|
|
1036
|
+
list.focus();
|
|
1037
|
+
screen.render();
|
|
1038
|
+
list.on("select", (_item, index) => {
|
|
1039
|
+
state.aiTool = index === 0 ? "claude" : index === 1 ? "codex" : "skip";
|
|
1040
|
+
form.destroy();
|
|
1041
|
+
executeCreation(state);
|
|
1042
|
+
});
|
|
1043
|
+
list.key(["escape"], () => {
|
|
1044
|
+
form.destroy();
|
|
1045
|
+
screen.render();
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
async function executeCreation(state) {
|
|
1049
|
+
const { branchName, baseBranch, copyEnv, pushToRemote, aiTool } = state;
|
|
1050
|
+
setStatus(`Creating ${branchName}...`);
|
|
1051
|
+
try {
|
|
1052
|
+
if (baseBranch === "default" && currentBranch !== defaultBranch) {
|
|
1053
|
+
const worktreePath = getWorktreePath(mainRepoPath, branchName);
|
|
1054
|
+
const { execFile: execFile2 } = await import("child_process");
|
|
1055
|
+
const { promisify: promisify2 } = await import("util");
|
|
1056
|
+
const execFileAsync2 = promisify2(execFile2);
|
|
1057
|
+
await execFileAsync2("git", ["worktree", "add", "-b", branchName, "--", worktreePath, defaultBranch]);
|
|
1058
|
+
if (copyEnv) {
|
|
1059
|
+
await copyEnvFiles(mainRepoPath, worktreePath);
|
|
1060
|
+
}
|
|
1061
|
+
if (pushToRemote) {
|
|
1062
|
+
setStatus(`Pushing ${branchName}...`);
|
|
1063
|
+
await pushBranch(branchName, worktreePath);
|
|
1064
|
+
}
|
|
1065
|
+
await refreshWorktrees();
|
|
1066
|
+
setStatus(`Created ${branchName}`);
|
|
1067
|
+
if (aiTool !== "skip") {
|
|
1068
|
+
await launchInWorktree(worktreePath, aiTool);
|
|
1069
|
+
}
|
|
1070
|
+
} else {
|
|
1071
|
+
const worktreePath = getWorktreePath(mainRepoPath, branchName);
|
|
1072
|
+
await createWorktree(worktreePath, branchName);
|
|
1073
|
+
if (copyEnv) {
|
|
1074
|
+
await copyEnvFiles(mainRepoPath, worktreePath);
|
|
1075
|
+
}
|
|
1076
|
+
if (pushToRemote) {
|
|
1077
|
+
setStatus(`Pushing ${branchName}...`);
|
|
1078
|
+
await pushBranch(branchName, worktreePath);
|
|
1079
|
+
}
|
|
1080
|
+
await refreshWorktrees();
|
|
1081
|
+
setStatus(`Created ${branchName}`);
|
|
1082
|
+
if (aiTool !== "skip") {
|
|
1083
|
+
await launchInWorktree(worktreePath, aiTool);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
} catch (e) {
|
|
1087
|
+
setStatus(`Error: ${e.message}`);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
async function launchInWorktree(worktreePath, tool) {
|
|
1091
|
+
const available = await isToolAvailable(tool);
|
|
1092
|
+
if (!available) {
|
|
1093
|
+
setStatus(`${tool} is not installed`);
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
setStatus(`Launching ${tool}...`);
|
|
1097
|
+
screen.destroy();
|
|
1098
|
+
launchAITool({ cwd: worktreePath, tool });
|
|
1099
|
+
console.log(`
|
|
1100
|
+
${tool} launched in: ${worktreePath}
|
|
1101
|
+
`);
|
|
1102
|
+
process.exit(0);
|
|
1103
|
+
}
|
|
794
1104
|
async function deleteSelected() {
|
|
795
1105
|
const wt = worktrees[selectedIndex];
|
|
796
1106
|
if (!wt) return;
|
|
@@ -843,27 +1153,17 @@ async function launchAI(tool) {
|
|
|
843
1153
|
return;
|
|
844
1154
|
}
|
|
845
1155
|
setStatus(`Launching ${tool}...`);
|
|
1156
|
+
screen.destroy();
|
|
846
1157
|
launchAITool({ cwd: wt.path, tool });
|
|
847
|
-
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
if (!wt || !wt.branch) {
|
|
852
|
-
setStatus("No branch to push");
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
setStatus(`Pushing ${wt.branch}...`);
|
|
856
|
-
try {
|
|
857
|
-
await pushBranch(wt.branch, wt.path);
|
|
858
|
-
setStatus(`Pushed ${wt.branch} to origin`);
|
|
859
|
-
} catch (e) {
|
|
860
|
-
setStatus(`Error: ${e.message}`);
|
|
861
|
-
}
|
|
1158
|
+
console.log(`
|
|
1159
|
+
${tool} launched in: ${path8.basename(wt.path)}
|
|
1160
|
+
`);
|
|
1161
|
+
process.exit(0);
|
|
862
1162
|
}
|
|
863
1163
|
|
|
864
1164
|
// src/index.ts
|
|
865
1165
|
var program = new Command();
|
|
866
|
-
program.name("wt").description("CLI tool to streamline git worktrees with AI coding assistants").version("1.
|
|
1166
|
+
program.name("wt").description("CLI tool to streamline git worktrees with AI coding assistants").version("1.4.0").action(async () => {
|
|
867
1167
|
await interactiveCommand();
|
|
868
1168
|
});
|
|
869
1169
|
program.command("new <branch-name>").description("Create a new worktree and launch AI assistant").option("-i, --install", "Run package manager install after creating worktree").option("-s, --skip-launch", "Create worktree without launching AI assistant").option("-p, --push", "Push branch to remote (visible on GitHub)").action(async (branchName, options) => {
|