@fatdoge/wtree 0.1.9 → 0.2.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.
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.fixed{position:fixed}.inset-0{top:0;right:0;bottom:0;left:0}.z-50{z-index:50}.order-1{order:1}.order-2{order:2}.col-span-12{grid-column:span 12 / span 12}.col-span-2{grid-column:span 2 / span 2}.col-span-3{grid-column:span 3 / span 3}.col-span-5{grid-column:span 5 / span 5}.mx-auto{margin-left:auto;margin-right:auto}.mb-0\.5{margin-bottom:.125rem}.mb-4{margin-bottom:1rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-4{height:1rem}.h-full{height:100%}.max-h-\[520px\]{max-height:520px}.w-4{width:1rem}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-md{max-width:28rem}.max-w-screen-xl{max-width:1280px}.shrink-0{flex-shrink:0}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-slate-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-slate-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.bg-rose-100{--tw-bg-opacity: 1;background-color:rgb(255 228 230 / var(--tw-bg-opacity, 1))}.bg-rose-600{--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity, 1))}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-slate-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-slate-900\/50{background-color:#0f172a80}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pt-2{padding-top:.5rem}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.text-emerald-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-rose-600{--tw-text-opacity: 1;color:rgb(225 29 72 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Noto Sans,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";line-height:1.5;font-weight:400;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}html,body,#root{height:100%}body{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}body:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(2 6 23 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.placeholder\:text-slate-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.placeholder\:text-slate-400::placeholder{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.hover\:bg-indigo-700:hover{--tw-bg-opacity: 1;background-color:rgb(67 56 202 / var(--tw-bg-opacity, 1))}.hover\:bg-rose-700:hover{--tw-bg-opacity: 1;background-color:rgb(190 18 60 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-200:hover{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-50:hover{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.hover\:text-slate-600:hover{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.hover\:text-slate-900:hover{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.focus\:border-indigo-500:focus{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-indigo-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1))}.focus\:ring-slate-400:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(148 163 184 / var(--tw-ring-opacity, 1))}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.dark\:border-slate-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.dark\:border-slate-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(30 41 59 / var(--tw-border-opacity, 1))}.dark\:border-slate-800\/50:is(.dark *){border-color:#1e293b80}.dark\:bg-black\/50:is(.dark *){background-color:#00000080}.dark\:bg-indigo-500:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity, 1))}.dark\:bg-rose-500:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity, 1))}.dark\:bg-rose-500\/10:is(.dark *){background-color:#f43f5e1a}.dark\:bg-slate-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-900\/60:is(.dark *){background-color:#0f172a99}.dark\:bg-slate-950:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(2 6 23 / var(--tw-bg-opacity, 1))}.dark\:text-emerald-400:is(.dark *){--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.dark\:text-rose-400:is(.dark *){--tw-text-opacity: 1;color:rgb(251 113 133 / var(--tw-text-opacity, 1))}.dark\:text-slate-100:is(.dark *){--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity, 1))}.dark\:text-slate-200:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.dark\:text-slate-300:is(.dark *){--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.dark\:text-slate-400:is(.dark *){--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.dark\:text-slate-500:is(.dark *){--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.dark\:placeholder\:text-slate-500:is(.dark *)::-moz-placeholder{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.dark\:placeholder\:text-slate-500:is(.dark *)::placeholder{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.dark\:hover\:bg-indigo-600:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-rose-600:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(225 29 72 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-slate-700:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-slate-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-slate-900\/40:hover:is(.dark *){background-color:#0f172a66}.dark\:hover\:text-slate-100:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity, 1))}.dark\:hover\:text-slate-200:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.dark\:focus\:border-indigo-500:focus:is(.dark *){--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.dark\:focus\:ring-indigo-500:focus:is(.dark *){--tw-ring-opacity: 1;--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1))}.dark\:focus\:ring-slate-700:focus:is(.dark *){--tw-ring-opacity: 1;--tw-ring-color: rgb(51 65 85 / var(--tw-ring-opacity, 1))}@media(min-width:640px){.sm\:w-auto{width:auto}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}}@media(min-width:768px){.md\:mt-0{margin-top:0}.md\:block{display:block}.md\:inline{display:inline}.md\:grid{display:grid}.md\:hidden{display:none}.md\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:justify-end{justify-content:flex-end}.md\:border-b-0{border-bottom-width:0px}.md\:py-2{padding-top:.5rem;padding-bottom:.5rem}}@media(min-width:1024px){.lg\:order-1{order:1}.lg\:order-2{order:2}.lg\:col-span-3{grid-column:span 3 / span 3}.lg\:col-span-5{grid-column:span 5 / span 5}.lg\:col-span-6{grid-column:span 6 / span 6}.lg\:col-span-7{grid-column:span 7 / span 7}.lg\:col-span-9{grid-column:span 9 / span 9}.lg\:mb-0{margin-bottom:0}}
package/dist/index.html CHANGED
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>TreeLab - Git Worktree Manager</title>
8
- <script type="module" crossorigin src="/assets/index-AspflbWf.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-DXiZ6dVD.css">
8
+ <script type="module" crossorigin src="/assets/index-C78PMV-C.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-CR9jga1C.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
@@ -21,6 +21,14 @@ function parseArgs(argv) {
21
21
  noOpen: false,
22
22
  repo: '',
23
23
  port: undefined,
24
+ json: false,
25
+ yes: false,
26
+ force: false,
27
+ dir: '',
28
+ base: '',
29
+ editor: undefined,
30
+ noEditor: false,
31
+ noInstall: false,
24
32
  };
25
33
  const positional = [];
26
34
  while (args.length) {
@@ -43,6 +51,38 @@ function parseArgs(argv) {
43
51
  flags.port = v;
44
52
  continue;
45
53
  }
54
+ if (a === '--json') {
55
+ flags.json = true;
56
+ continue;
57
+ }
58
+ if (a === '--yes' || a === '-y') {
59
+ flags.yes = true;
60
+ continue;
61
+ }
62
+ if (a === '--force' || a === '-f') {
63
+ flags.force = true;
64
+ continue;
65
+ }
66
+ if (a === '--dir') {
67
+ flags.dir = String(args.shift() || '');
68
+ continue;
69
+ }
70
+ if (a === '--base') {
71
+ flags.base = String(args.shift() || '');
72
+ continue;
73
+ }
74
+ if (a === '--editor') {
75
+ flags.editor = String(args.shift() || '');
76
+ continue;
77
+ }
78
+ if (a === '--no-editor') {
79
+ flags.noEditor = true;
80
+ continue;
81
+ }
82
+ if (a === '--no-install') {
83
+ flags.noInstall = true;
84
+ continue;
85
+ }
46
86
  if (a.startsWith('--'))
47
87
  continue;
48
88
  positional.push(a);
@@ -80,8 +120,12 @@ function parseCommand(positional) {
80
120
  }
81
121
  return { command: 'interactive', rest: positional };
82
122
  }
83
- function printWorktreeList(rootDir) {
123
+ function printWorktreeList(rootDir, json = false) {
84
124
  const items = listWorktrees(rootDir);
125
+ if (json) {
126
+ console.info(JSON.stringify(items, null, 2));
127
+ return;
128
+ }
85
129
  if (items.length === 0) {
86
130
  console.info('未读取到 worktree。');
87
131
  return;
@@ -98,7 +142,7 @@ function printHelp() {
98
142
  console.info(' wtree');
99
143
  console.info(' wtree list');
100
144
  console.info(' wtree create [branch]');
101
- console.info(' wtree delete');
145
+ console.info(' wtree delete [branch|path ...]');
102
146
  console.info(' wtree open [path|branch]');
103
147
  console.info(' wtree lock [path|branch]');
104
148
  console.info(' wtree unlock [path|branch]');
@@ -108,7 +152,23 @@ function printHelp() {
108
152
  console.info(' wtree config set <key> <value>');
109
153
  console.info(' wtree --ui [--repo <path>] [--no-open] [--port <number>]');
110
154
  console.info('');
155
+ console.info('选项:');
156
+ console.info(' --json 以 JSON 格式输出 (适合脚本/agent 使用)');
157
+ console.info(' --yes, -y 自动确认所有提示');
158
+ console.info(' --force, -f 强制操作 (如强制删除有未提交更改的 worktree)');
159
+ console.info(' --dir <path> 指定 worktree 目录路径 (相对于 git 根目录)');
160
+ console.info(' --base <ref> 创建新分支时的基准引用 (如 main, origin/main)');
161
+ console.info(' --editor <name> 创建后使用指定编辑器打开 (trae, cursor, code, none)');
162
+ console.info(' --no-editor 创建后不打开编辑器');
163
+ console.info(' --no-install 创建后不自动安装依赖');
164
+ console.info('');
111
165
  console.info('可用配置 key: baseDir, openCommand, editorCommand');
166
+ console.info('');
167
+ console.info('非交互示例:');
168
+ console.info(' wtree list --json');
169
+ console.info(' wtree create feat/x --yes --no-editor --no-install --json');
170
+ console.info(' wtree create feat/new --base main --yes --dir worktrees/feat-new --json');
171
+ console.info(' wtree delete feat/old --yes --force --json');
112
172
  }
113
173
  function resolveWorktree(rootDir, key) {
114
174
  const items = listWorktrees(rootDir);
@@ -276,18 +336,20 @@ async function main() {
276
336
  process.on('SIGTERM', close);
277
337
  return;
278
338
  }
279
- console.info(chalk.blue(`检测到git repo根目录 ${rootDir},将在这里运行git命令`));
339
+ if (!flags.json) {
340
+ console.info(chalk.blue(`检测到git repo根目录 ${rootDir},将在这里运行git命令`));
341
+ }
280
342
  const { command, rest } = parseCommand(positional);
281
343
  if (command === 'list') {
282
- printWorktreeList(rootDir);
344
+ printWorktreeList(rootDir, flags.json);
283
345
  return;
284
346
  }
285
347
  if (command === 'create') {
286
- await createWorktree({ rootDir }, rest[0]);
348
+ await createWorktree({ rootDir, flags }, rest[0]);
287
349
  return;
288
350
  }
289
351
  if (command === 'delete') {
290
- await deleteWorktree({ rootDir });
352
+ await deleteWorktree({ rootDir, flags }, rest);
291
353
  return;
292
354
  }
293
355
  if (command === 'open') {
@@ -329,7 +391,7 @@ async function main() {
329
391
  }
330
392
  const directBranch = rest[0];
331
393
  const action = await getUserAction(directBranch);
332
- const ctx = { rootDir };
394
+ const ctx = { rootDir, flags };
333
395
  if (action === 'create') {
334
396
  await createWorktree(ctx, directBranch);
335
397
  }
@@ -374,21 +436,28 @@ async function getUserAction(directBranch) {
374
436
  return action;
375
437
  }
376
438
  async function createWorktree(ctx, directBranch) {
377
- const { rootDir } = ctx;
439
+ const { rootDir, flags } = ctx;
378
440
  const defaultBranch = git(rootDir, ['symbolic-ref', '--short', 'refs/remotes/origin/HEAD']).stdout
379
441
  .replace(/^origin\//, '')
380
442
  .trim() || 'master';
381
443
  const { sourceType, selection } = await selectSource(rootDir, directBranch, defaultBranch);
382
- const { targetBranch, baseRef, isNewBranch } = await resolveBranchInfo(rootDir, sourceType, selection, directBranch, defaultBranch);
383
- const { targetDir, dirName } = await selectTargetDir(rootDir, targetBranch);
384
- console.info(chalk.green(`\n准备创建 Worktree:`));
385
- console.info(` 分支: ${targetBranch}`);
386
- console.info(` 目录: ${targetDir}`);
387
- console.info(` 来源: ${baseRef || 'Existing Local'}`);
444
+ const { targetBranch, baseRef, isNewBranch } = await resolveBranchInfo(rootDir, sourceType, selection, directBranch, defaultBranch, flags);
445
+ const { targetDir, dirName } = await selectTargetDir(rootDir, targetBranch, flags);
446
+ if (!flags.json) {
447
+ console.info(chalk.green(`\n准备创建 Worktree:`));
448
+ console.info(` 分支: ${targetBranch}`);
449
+ console.info(` 目录: ${targetDir}`);
450
+ console.info(` 来源: ${baseRef || 'Existing Local'}`);
451
+ }
388
452
  await createGitWorktree(rootDir, targetDir, targetBranch, baseRef, isNewBranch, sourceType, defaultBranch);
389
453
  await setupWorktreeEnv(rootDir, targetDir, dirName);
390
- await installDependencies(targetDir);
391
- await openInIDE(targetDir);
454
+ await installDependencies(targetDir, flags.noInstall);
455
+ await openInIDE(targetDir, flags);
456
+ if (flags.json) {
457
+ const items = listWorktrees(rootDir);
458
+ const created = items.find(x => path.resolve(x.path) === path.resolve(targetDir));
459
+ console.info(JSON.stringify({ ok: true, data: created || null }));
460
+ }
392
461
  }
393
462
  async function selectSource(rootDir, directBranch, defaultBranch) {
394
463
  let sourceType;
@@ -430,7 +499,7 @@ async function selectSource(rootDir, directBranch, defaultBranch) {
430
499
  }
431
500
  return { sourceType, selection };
432
501
  }
433
- async function resolveBranchInfo(rootDir, sourceType, selection, directBranch, defaultBranch) {
502
+ async function resolveBranchInfo(rootDir, sourceType, selection, directBranch, defaultBranch, flags) {
434
503
  let targetBranch = '';
435
504
  let baseRef = '';
436
505
  let isNewBranch = false;
@@ -470,20 +539,26 @@ async function resolveBranchInfo(rootDir, sourceType, selection, directBranch, d
470
539
  isNewBranch = true;
471
540
  }
472
541
  else {
473
- const { createNew } = await inquirer.prompt([
474
- {
475
- type: 'confirm',
476
- name: 'createNew',
477
- message: `分支 ${targetBranch} 不存在。是否基于 ${defaultBranch} 创建新分支?`,
478
- default: true,
479
- },
480
- ]);
481
- if (createNew) {
482
- baseRef = defaultBranch;
542
+ if (flags.yes) {
543
+ baseRef = flags.base || defaultBranch;
483
544
  isNewBranch = true;
484
545
  }
485
546
  else {
486
- process.exit(1);
547
+ const { createNew } = await inquirer.prompt([
548
+ {
549
+ type: 'confirm',
550
+ name: 'createNew',
551
+ message: `分支 ${targetBranch} 不存在。是否基于 ${defaultBranch} 创建新分支?`,
552
+ default: true,
553
+ },
554
+ ]);
555
+ if (createNew) {
556
+ baseRef = defaultBranch;
557
+ isNewBranch = true;
558
+ }
559
+ else {
560
+ process.exit(1);
561
+ }
487
562
  }
488
563
  }
489
564
  }
@@ -539,16 +614,26 @@ async function resolveBranchInfo(rootDir, sourceType, selection, directBranch, d
539
614
  }
540
615
  return { targetBranch, baseRef, isNewBranch };
541
616
  }
542
- async function selectTargetDir(rootDir, targetBranch) {
617
+ async function selectTargetDir(rootDir, targetBranch, flags) {
543
618
  const defaultDirName = `worktrees/${targetBranch.split('/').join('-')}`;
544
- const { dirName } = await inquirer.prompt([
545
- {
546
- type: 'input',
547
- name: 'dirName',
548
- message: `请输入 Worktree 目录路径 (相对于 Git 根目录, 默认: ${defaultDirName}):`,
549
- default: defaultDirName,
550
- },
551
- ]);
619
+ let dirName;
620
+ if (flags.dir) {
621
+ dirName = flags.dir;
622
+ }
623
+ else if (flags.yes) {
624
+ dirName = defaultDirName;
625
+ }
626
+ else {
627
+ const result = await inquirer.prompt([
628
+ {
629
+ type: 'input',
630
+ name: 'dirName',
631
+ message: `请输入 Worktree 目录路径 (相对于 Git 根目录, 默认: ${defaultDirName}):`,
632
+ default: defaultDirName,
633
+ },
634
+ ]);
635
+ dirName = result.dirName;
636
+ }
552
637
  const targetDir = path.resolve(rootDir, dirName);
553
638
  if (fs.existsSync(targetDir)) {
554
639
  console.error(chalk.red(`目录 ${targetDir} 已存在!`));
@@ -594,7 +679,9 @@ async function setupWorktreeEnv(rootDir, targetDir, dirName) {
594
679
  }
595
680
  }
596
681
  }
597
- async function installDependencies(targetDir) {
682
+ async function installDependencies(targetDir, skip = false) {
683
+ if (skip)
684
+ return;
598
685
  if (!fs.existsSync(path.join(targetDir, 'package.json')))
599
686
  return;
600
687
  try {
@@ -615,7 +702,20 @@ function hasCommand(cmd) {
615
702
  return false;
616
703
  }
617
704
  }
618
- async function openInIDE(targetDir) {
705
+ async function openInIDE(targetDir, flags) {
706
+ if (flags.noEditor)
707
+ return;
708
+ if (flags.editor !== undefined) {
709
+ if (flags.editor === 'none' || flags.editor === '')
710
+ return;
711
+ try {
712
+ execSync(`${flags.editor} "${targetDir}"`, { stdio: 'ignore' });
713
+ }
714
+ catch (e) {
715
+ void e;
716
+ }
717
+ return;
718
+ }
619
719
  const editors = [];
620
720
  if (hasCommand('trae'))
621
721
  editors.push({ name: `在 Trae 中打开 (trae ${targetDir})`, value: 'trae' });
@@ -644,34 +744,63 @@ async function openInIDE(targetDir) {
644
744
  void e;
645
745
  }
646
746
  }
647
- async function deleteWorktree(ctx) {
648
- const worktrees = getWorktreeList(ctx.rootDir);
649
- const choices = getDeletableWorktrees(ctx.rootDir, worktrees);
747
+ async function deleteWorktree(ctx, targets = []) {
748
+ const { rootDir, flags } = ctx;
749
+ const worktrees = getWorktreeList(rootDir);
750
+ const choices = getDeletableWorktrees(rootDir, worktrees);
650
751
  if (choices.length === 0) {
651
- console.warn(chalk.yellow('没有可删除的 Worktree (除了主 Worktree)'));
752
+ if (flags.json) {
753
+ console.info(JSON.stringify({ ok: true, data: [], message: 'No deletable worktrees' }));
754
+ }
755
+ else {
756
+ console.warn(chalk.yellow('没有可删除的 Worktree (除了主 Worktree)'));
757
+ }
652
758
  return;
653
759
  }
654
- const { targetPaths } = await inquirer.prompt([
655
- {
656
- type: 'checkbox',
657
- name: 'targetPaths',
658
- message: '请选择要删除的 Worktree:',
659
- choices,
660
- validate: (answer) => (answer.length > 0 ? true : '请至少选择一个'),
661
- },
662
- ]);
663
- const { confirmDelete } = await inquirer.prompt([
664
- {
665
- type: 'confirm',
666
- name: 'confirmDelete',
667
- message: `确定要删除这 ${targetPaths.length} 个 Worktree 吗?`,
668
- default: false,
669
- },
670
- ]);
671
- if (!confirmDelete)
672
- return;
760
+ let targetPaths;
761
+ if (targets.length > 0) {
762
+ // Non-interactive: resolve each target to a worktree path
763
+ targetPaths = [];
764
+ for (const key of targets) {
765
+ const wt = resolveWorktree(rootDir, key);
766
+ if (!wt) {
767
+ console.error(chalk.red(`未找到 worktree: ${key}`));
768
+ process.exit(1);
769
+ }
770
+ if (path.resolve(wt.path) === path.resolve(rootDir)) {
771
+ console.error(chalk.red(`不能删除主 worktree: ${key}`));
772
+ process.exit(1);
773
+ }
774
+ targetPaths.push(wt.path);
775
+ }
776
+ }
777
+ else {
778
+ // Interactive: checkbox prompt
779
+ const result = await inquirer.prompt([
780
+ {
781
+ type: 'checkbox',
782
+ name: 'targetPaths',
783
+ message: '请选择要删除的 Worktree:',
784
+ choices,
785
+ validate: (answer) => (answer.length > 0 ? true : '请至少选择一个'),
786
+ },
787
+ ]);
788
+ targetPaths = result.targetPaths;
789
+ }
790
+ if (!flags.yes) {
791
+ const { confirmDelete } = await inquirer.prompt([
792
+ {
793
+ type: 'confirm',
794
+ name: 'confirmDelete',
795
+ message: `确定要删除这 ${targetPaths.length} 个 Worktree 吗?`,
796
+ default: false,
797
+ },
798
+ ]);
799
+ if (!confirmDelete)
800
+ return;
801
+ }
673
802
  for (const targetPath of targetPaths) {
674
- await deleteSingleWorktree(ctx.rootDir, targetPath);
803
+ await deleteSingleWorktree(rootDir, targetPath, flags);
675
804
  }
676
805
  }
677
806
  function getWorktreeList(rootDir) {
@@ -690,29 +819,55 @@ function getDeletableWorktrees(rootDir, worktrees) {
690
819
  return { name: `${wt.branch || 'HEAD'} (${relativePath})`, value: wt.path };
691
820
  });
692
821
  }
693
- async function deleteSingleWorktree(rootDir, targetPath) {
822
+ async function deleteSingleWorktree(rootDir, targetPath, flags) {
694
823
  try {
695
824
  gitOrThrow(rootDir, ['worktree', 'remove', targetPath], 'WORKTREE_REMOVE');
696
- console.info(chalk.green(`成功删除: ${targetPath}`));
825
+ if (flags.json) {
826
+ console.info(JSON.stringify({ ok: true, removed: targetPath }));
827
+ }
828
+ else {
829
+ console.info(chalk.green(`成功删除: ${targetPath}`));
830
+ }
697
831
  }
698
832
  catch (e) {
699
- console.error(chalk.red(`删除失败: ${errMsg(e)}`));
700
- const { force } = await inquirer.prompt([
701
- {
702
- type: 'confirm',
703
- name: 'force',
704
- message: '删除失败 (可能有未提交的更改). 强制删除吗?',
705
- default: false,
706
- },
707
- ]);
708
- if (!force)
709
- return;
710
- try {
711
- gitOrThrow(rootDir, ['worktree', 'remove', '--force', targetPath], 'WORKTREE_REMOVE_FORCE');
712
- console.info(chalk.green(`成功强制删除: ${targetPath}`));
833
+ if (flags.force) {
834
+ try {
835
+ gitOrThrow(rootDir, ['worktree', 'remove', '--force', targetPath], 'WORKTREE_REMOVE_FORCE');
836
+ if (flags.json) {
837
+ console.info(JSON.stringify({ ok: true, removed: targetPath, forced: true }));
838
+ }
839
+ else {
840
+ console.info(chalk.green(`成功强制删除: ${targetPath}`));
841
+ }
842
+ }
843
+ catch (forceErr) {
844
+ if (flags.json) {
845
+ console.error(JSON.stringify({ ok: false, error: errMsg(forceErr), path: targetPath }));
846
+ }
847
+ else {
848
+ console.error(chalk.red(`强制删除也失败了: ${errMsg(forceErr)}`));
849
+ }
850
+ }
713
851
  }
714
- catch (forceErr) {
715
- console.error(chalk.red(`强制删除也失败了: ${errMsg(forceErr)}`));
852
+ else {
853
+ console.error(chalk.red(`删除失败: ${errMsg(e)}`));
854
+ const { force } = await inquirer.prompt([
855
+ {
856
+ type: 'confirm',
857
+ name: 'force',
858
+ message: '删除失败 (可能有未提交的更改). 强制删除吗?',
859
+ default: false,
860
+ },
861
+ ]);
862
+ if (!force)
863
+ return;
864
+ try {
865
+ gitOrThrow(rootDir, ['worktree', 'remove', '--force', targetPath], 'WORKTREE_REMOVE_FORCE');
866
+ console.info(chalk.green(`成功强制删除: ${targetPath}`));
867
+ }
868
+ catch (forceErr) {
869
+ console.error(chalk.red(`强制删除也失败了: ${errMsg(forceErr)}`));
870
+ }
716
871
  }
717
872
  }
718
873
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fatdoge/wtree",
3
3
  "private": false,
4
- "version": "0.1.9",
4
+ "version": "0.2.0",
5
5
  "description": "CLI + UI tool for managing git worktrees",
6
6
  "keywords": [
7
7
  "git",
@@ -30,6 +30,7 @@
30
30
  "api",
31
31
  "src",
32
32
  "shared",
33
+ "skills",
33
34
  "index.html",
34
35
  "vite.config.ts",
35
36
  "tailwind.config.js",
@@ -68,6 +69,7 @@
68
69
  "react-i18next": "^16.5.7",
69
70
  "react-router-dom": "^7.3.0",
70
71
  "serve-static": "^2.2.1",
72
+ "sonner": "^2.0.7",
71
73
  "tailwind-merge": "^3.0.2",
72
74
  "tailwindcss": "^3.4.17",
73
75
  "vite": "^6.3.5",