worktree-launcher 1.4.0 → 1.4.2

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.
Files changed (2) hide show
  1. package/dist/index.js +81 -53
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -627,7 +627,10 @@ async function interactiveCommand() {
627
627
  const repoName = path8.basename(mainRepoPath);
628
628
  screen = blessed.screen({
629
629
  smartCSR: true,
630
- title: `wt - ${repoName}`
630
+ fullUnicode: true,
631
+ title: `wt - ${repoName}`,
632
+ terminal: "xterm-256color",
633
+ warnings: false
631
634
  });
632
635
  headerBox = blessed.box({
633
636
  parent: screen,
@@ -637,9 +640,8 @@ async function interactiveCommand() {
637
640
  height: 1,
638
641
  content: ` ${repoName} (${currentBranch})`,
639
642
  style: {
640
- fg: "white",
641
- bg: "blue",
642
- bold: true
643
+ fg: "black",
644
+ bg: "cyan"
643
645
  }
644
646
  });
645
647
  worktreeList = blessed.list({
@@ -653,16 +655,16 @@ async function interactiveCommand() {
653
655
  mouse: true,
654
656
  style: {
655
657
  selected: {
656
- bg: "blue",
657
- fg: "white"
658
+ bg: "cyan",
659
+ fg: "black"
658
660
  },
659
661
  item: {
660
- fg: "white"
662
+ fg: "default"
661
663
  }
662
664
  },
663
665
  scrollbar: {
664
666
  ch: " ",
665
- style: { bg: "grey" }
667
+ style: { bg: "cyan" }
666
668
  }
667
669
  });
668
670
  statusBar = blessed.box({
@@ -673,8 +675,7 @@ async function interactiveCommand() {
673
675
  height: 1,
674
676
  content: "",
675
677
  style: {
676
- fg: "yellow",
677
- bg: "black"
678
+ fg: "green"
678
679
  }
679
680
  });
680
681
  helpBar = blessed.box({
@@ -686,7 +687,7 @@ async function interactiveCommand() {
686
687
  content: " [n]ew [d]elete [c]laude [x]codex [Enter]cd [q]uit",
687
688
  style: {
688
689
  fg: "black",
689
- bg: "white"
690
+ bg: "cyan"
690
691
  }
691
692
  });
692
693
  await refreshWorktrees();
@@ -695,8 +696,7 @@ async function interactiveCommand() {
695
696
  showPath();
696
697
  });
697
698
  screen.key(["q", "C-c"], () => {
698
- screen.destroy();
699
- process.exit(0);
699
+ cleanExit();
700
700
  });
701
701
  screen.key(["n"], () => {
702
702
  startCreationWizard();
@@ -713,11 +713,9 @@ async function interactiveCommand() {
713
713
  screen.key(["enter"], () => {
714
714
  const wt = worktrees[selectedIndex];
715
715
  if (wt) {
716
- screen.destroy();
717
- console.log(`
716
+ cleanExit(`
718
717
  cd "${wt.path}"
719
718
  `);
720
- process.exit(0);
721
719
  }
722
720
  });
723
721
  screen.key(["r"], async () => {
@@ -753,6 +751,17 @@ function setStatus(msg) {
753
751
  statusBar.setContent(` ${msg}`);
754
752
  screen.render();
755
753
  }
754
+ function cleanExit(message) {
755
+ screen.program.clear();
756
+ screen.program.disableMouse();
757
+ screen.program.showCursor();
758
+ screen.program.normalBuffer();
759
+ screen.destroy();
760
+ if (message) {
761
+ console.log(message);
762
+ }
763
+ process.exit(0);
764
+ }
756
765
  function startCreationWizard() {
757
766
  const state = {
758
767
  branchName: "",
@@ -772,9 +781,8 @@ function askBranchName(state) {
772
781
  height: 12,
773
782
  border: { type: "line" },
774
783
  style: {
775
- fg: "white",
776
- bg: "black",
777
- border: { fg: "blue" }
784
+ fg: "default",
785
+ border: { fg: "cyan" }
778
786
  },
779
787
  label: " New Worktree "
780
788
  });
@@ -790,14 +798,14 @@ function askBranchName(state) {
790
798
  top: 2,
791
799
  left: 2,
792
800
  content: `Current branch: ${currentBranch}`,
793
- style: { fg: "grey" }
801
+ style: { fg: "default" }
794
802
  });
795
803
  blessed.text({
796
804
  parent: form,
797
805
  top: 4,
798
806
  left: 2,
799
807
  content: "Branch name:",
800
- style: { fg: "white" }
808
+ style: { fg: "default" }
801
809
  });
802
810
  const input = blessed.textbox({
803
811
  parent: form,
@@ -806,8 +814,8 @@ function askBranchName(state) {
806
814
  width: 54,
807
815
  height: 1,
808
816
  style: {
809
- fg: "white",
810
- bg: "grey"
817
+ fg: "black",
818
+ bg: "white"
811
819
  },
812
820
  inputOnFocus: true
813
821
  });
@@ -816,23 +824,27 @@ function askBranchName(state) {
816
824
  top: 7,
817
825
  left: 2,
818
826
  content: "[Enter] next [Esc] cancel",
819
- style: { fg: "grey" }
827
+ style: { fg: "cyan" }
820
828
  });
821
829
  input.focus();
822
830
  screen.render();
823
- input.on("submit", (value) => {
831
+ input.on("submit", () => {
832
+ const value = input.getValue();
824
833
  if (!value || !value.trim()) {
825
834
  form.destroy();
826
835
  screen.render();
836
+ worktreeList.focus();
827
837
  return;
828
838
  }
829
839
  try {
830
840
  validateBranchName(value.trim());
831
841
  state.branchName = value.trim();
832
842
  form.destroy();
843
+ screen.render();
833
844
  askBaseBranch(state);
834
845
  } catch (e) {
835
846
  setStatus(`Error: ${e.message}`);
847
+ input.clearValue();
836
848
  input.focus();
837
849
  screen.render();
838
850
  }
@@ -840,6 +852,7 @@ function askBranchName(state) {
840
852
  input.on("cancel", () => {
841
853
  form.destroy();
842
854
  screen.render();
855
+ worktreeList.focus();
843
856
  });
844
857
  input.readInput();
845
858
  }
@@ -852,9 +865,8 @@ function askBaseBranch(state) {
852
865
  height: 10,
853
866
  border: { type: "line" },
854
867
  style: {
855
- fg: "white",
856
- bg: "black",
857
- border: { fg: "blue" }
868
+ fg: "default",
869
+ border: { fg: "cyan" }
858
870
  },
859
871
  label: " Base Branch "
860
872
  });
@@ -863,7 +875,7 @@ function askBaseBranch(state) {
863
875
  top: 1,
864
876
  left: 2,
865
877
  content: "Create worktree from:",
866
- style: { fg: "white" }
878
+ style: { fg: "default" }
867
879
  });
868
880
  const list = blessed.list({
869
881
  parent: form,
@@ -874,8 +886,8 @@ function askBaseBranch(state) {
874
886
  keys: true,
875
887
  vi: true,
876
888
  style: {
877
- selected: { bg: "blue", fg: "white" },
878
- item: { fg: "white" }
889
+ selected: { bg: "cyan", fg: "black" },
890
+ item: { fg: "default" }
879
891
  },
880
892
  items: [
881
893
  ` Current branch (${currentBranch})`,
@@ -887,18 +899,20 @@ function askBaseBranch(state) {
887
899
  top: 7,
888
900
  left: 2,
889
901
  content: "[Enter] select [Esc] cancel",
890
- style: { fg: "grey" }
902
+ style: { fg: "cyan" }
891
903
  });
892
904
  list.focus();
893
905
  screen.render();
894
906
  list.on("select", (_item, index) => {
895
907
  state.baseBranch = index === 0 ? "current" : "default";
896
908
  form.destroy();
909
+ screen.render();
897
910
  askCopyEnv(state);
898
911
  });
899
912
  list.key(["escape"], () => {
900
913
  form.destroy();
901
914
  screen.render();
915
+ worktreeList.focus();
902
916
  });
903
917
  }
904
918
  function askCopyEnv(state) {
@@ -910,9 +924,8 @@ function askCopyEnv(state) {
910
924
  height: 8,
911
925
  border: { type: "line" },
912
926
  style: {
913
- fg: "white",
914
- bg: "black",
915
- border: { fg: "blue" }
927
+ fg: "default",
928
+ border: { fg: "cyan" }
916
929
  },
917
930
  label: " Environment Files "
918
931
  });
@@ -921,7 +934,7 @@ function askCopyEnv(state) {
921
934
  top: 1,
922
935
  left: 2,
923
936
  content: "Copy .env files to worktree?",
924
- style: { fg: "white" }
937
+ style: { fg: "default" }
925
938
  });
926
939
  const list = blessed.list({
927
940
  parent: form,
@@ -932,8 +945,8 @@ function askCopyEnv(state) {
932
945
  keys: true,
933
946
  vi: true,
934
947
  style: {
935
- selected: { bg: "blue", fg: "white" },
936
- item: { fg: "white" }
948
+ selected: { bg: "cyan", fg: "black" },
949
+ item: { fg: "default" }
937
950
  },
938
951
  items: [" Yes (recommended)", " No"]
939
952
  });
@@ -942,11 +955,13 @@ function askCopyEnv(state) {
942
955
  list.on("select", (_item, index) => {
943
956
  state.copyEnv = index === 0;
944
957
  form.destroy();
958
+ screen.render();
945
959
  askPushToRemote(state);
946
960
  });
947
961
  list.key(["escape"], () => {
948
962
  form.destroy();
949
963
  screen.render();
964
+ worktreeList.focus();
950
965
  });
951
966
  }
952
967
  function askPushToRemote(state) {
@@ -958,9 +973,8 @@ function askPushToRemote(state) {
958
973
  height: 8,
959
974
  border: { type: "line" },
960
975
  style: {
961
- fg: "white",
962
- bg: "black",
963
- border: { fg: "blue" }
976
+ fg: "default",
977
+ border: { fg: "cyan" }
964
978
  },
965
979
  label: " Push to Remote "
966
980
  });
@@ -969,7 +983,7 @@ function askPushToRemote(state) {
969
983
  top: 1,
970
984
  left: 2,
971
985
  content: "Push branch to GitHub immediately?",
972
- style: { fg: "white" }
986
+ style: { fg: "default" }
973
987
  });
974
988
  const list = blessed.list({
975
989
  parent: form,
@@ -980,8 +994,8 @@ function askPushToRemote(state) {
980
994
  keys: true,
981
995
  vi: true,
982
996
  style: {
983
- selected: { bg: "blue", fg: "white" },
984
- item: { fg: "white" }
997
+ selected: { bg: "cyan", fg: "black" },
998
+ item: { fg: "default" }
985
999
  },
986
1000
  items: [" No (push later)", " Yes (visible on GitHub now)"]
987
1001
  });
@@ -990,11 +1004,13 @@ function askPushToRemote(state) {
990
1004
  list.on("select", (_item, index) => {
991
1005
  state.pushToRemote = index === 1;
992
1006
  form.destroy();
1007
+ screen.render();
993
1008
  askAITool(state);
994
1009
  });
995
1010
  list.key(["escape"], () => {
996
1011
  form.destroy();
997
1012
  screen.render();
1013
+ worktreeList.focus();
998
1014
  });
999
1015
  }
1000
1016
  function askAITool(state) {
@@ -1006,9 +1022,8 @@ function askAITool(state) {
1006
1022
  height: 10,
1007
1023
  border: { type: "line" },
1008
1024
  style: {
1009
- fg: "white",
1010
- bg: "black",
1011
- border: { fg: "blue" }
1025
+ fg: "default",
1026
+ border: { fg: "cyan" }
1012
1027
  },
1013
1028
  label: " Launch AI Tool "
1014
1029
  });
@@ -1017,7 +1032,7 @@ function askAITool(state) {
1017
1032
  top: 1,
1018
1033
  left: 2,
1019
1034
  content: "Which AI assistant to launch?",
1020
- style: { fg: "white" }
1035
+ style: { fg: "default" }
1021
1036
  });
1022
1037
  const list = blessed.list({
1023
1038
  parent: form,
@@ -1028,8 +1043,8 @@ function askAITool(state) {
1028
1043
  keys: true,
1029
1044
  vi: true,
1030
1045
  style: {
1031
- selected: { bg: "blue", fg: "white" },
1032
- item: { fg: "white" }
1046
+ selected: { bg: "cyan", fg: "black" },
1047
+ item: { fg: "default" }
1033
1048
  },
1034
1049
  items: [" Claude Code", " Codex", " Skip (just create worktree)"]
1035
1050
  });
@@ -1038,11 +1053,13 @@ function askAITool(state) {
1038
1053
  list.on("select", (_item, index) => {
1039
1054
  state.aiTool = index === 0 ? "claude" : index === 1 ? "codex" : "skip";
1040
1055
  form.destroy();
1056
+ screen.render();
1041
1057
  executeCreation(state);
1042
1058
  });
1043
1059
  list.key(["escape"], () => {
1044
1060
  form.destroy();
1045
1061
  screen.render();
1062
+ worktreeList.focus();
1046
1063
  });
1047
1064
  }
1048
1065
  async function executeCreation(state) {
@@ -1064,6 +1081,7 @@ async function executeCreation(state) {
1064
1081
  }
1065
1082
  await refreshWorktrees();
1066
1083
  setStatus(`Created ${branchName}`);
1084
+ worktreeList.focus();
1067
1085
  if (aiTool !== "skip") {
1068
1086
  await launchInWorktree(worktreePath, aiTool);
1069
1087
  }
@@ -1079,12 +1097,15 @@ async function executeCreation(state) {
1079
1097
  }
1080
1098
  await refreshWorktrees();
1081
1099
  setStatus(`Created ${branchName}`);
1100
+ worktreeList.focus();
1082
1101
  if (aiTool !== "skip") {
1083
1102
  await launchInWorktree(worktreePath, aiTool);
1084
1103
  }
1085
1104
  }
1086
1105
  } catch (e) {
1087
1106
  setStatus(`Error: ${e.message}`);
1107
+ worktreeList.focus();
1108
+ screen.render();
1088
1109
  }
1089
1110
  }
1090
1111
  async function launchInWorktree(worktreePath, tool) {
@@ -1094,6 +1115,10 @@ async function launchInWorktree(worktreePath, tool) {
1094
1115
  return;
1095
1116
  }
1096
1117
  setStatus(`Launching ${tool}...`);
1118
+ screen.program.clear();
1119
+ screen.program.disableMouse();
1120
+ screen.program.showCursor();
1121
+ screen.program.normalBuffer();
1097
1122
  screen.destroy();
1098
1123
  launchAITool({ cwd: worktreePath, tool });
1099
1124
  console.log(`
@@ -1117,8 +1142,7 @@ async function deleteSelected() {
1117
1142
  height: 5,
1118
1143
  border: { type: "line" },
1119
1144
  style: {
1120
- fg: "white",
1121
- bg: "black",
1145
+ fg: "default",
1122
1146
  border: { fg: "red" }
1123
1147
  }
1124
1148
  });
@@ -1153,6 +1177,10 @@ async function launchAI(tool) {
1153
1177
  return;
1154
1178
  }
1155
1179
  setStatus(`Launching ${tool}...`);
1180
+ screen.program.clear();
1181
+ screen.program.disableMouse();
1182
+ screen.program.showCursor();
1183
+ screen.program.normalBuffer();
1156
1184
  screen.destroy();
1157
1185
  launchAITool({ cwd: wt.path, tool });
1158
1186
  console.log(`
@@ -1163,7 +1191,7 @@ ${tool} launched in: ${path8.basename(wt.path)}
1163
1191
 
1164
1192
  // src/index.ts
1165
1193
  var program = new Command();
1166
- program.name("wt").description("CLI tool to streamline git worktrees with AI coding assistants").version("1.4.0").action(async () => {
1194
+ program.name("wt").description("CLI tool to streamline git worktrees with AI coding assistants").version("1.4.2").action(async () => {
1167
1195
  await interactiveCommand();
1168
1196
  });
1169
1197
  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) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worktree-launcher",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "CLI tool for managing git worktrees with AI coding assistants",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",