@glrs-dev/cli 0.0.1 → 0.1.1

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 (173) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +14 -15
  3. package/dist/chunk-3RG5ZIWI.js +10 -0
  4. package/dist/chunk-6RHN2EDH.js +93 -0
  5. package/dist/chunk-DEODG2LC.js +55 -0
  6. package/dist/chunk-FSAGM22T.js +17 -0
  7. package/dist/chunk-GQBZREK5.js +136 -0
  8. package/dist/chunk-HWMRY35D.js +139 -0
  9. package/dist/chunk-LMRDQ4GW.js +129 -0
  10. package/dist/chunk-NLPX2KOF.js +149 -0
  11. package/dist/chunk-P7PRH4I3.js +177 -0
  12. package/dist/chunk-VCN7RNLU.js +60 -0
  13. package/dist/chunk-VJFNIKQJ.js +120 -0
  14. package/dist/chunk-W37UX3U2.js +35 -0
  15. package/dist/chunk-YBCA3IP6.js +25 -0
  16. package/dist/chunk-YGNDPKIW.js +99 -0
  17. package/dist/cli.d.ts +1 -1
  18. package/dist/cli.js +89 -36
  19. package/dist/commands/cleanup.d.ts +19 -0
  20. package/dist/commands/cleanup.js +11 -0
  21. package/dist/commands/create.d.ts +17 -0
  22. package/dist/commands/create.js +12 -0
  23. package/dist/commands/delete.d.ts +17 -0
  24. package/dist/commands/delete.js +12 -0
  25. package/dist/commands/go.d.ts +4 -0
  26. package/dist/commands/go.js +11 -0
  27. package/dist/commands/list.d.ts +15 -0
  28. package/dist/commands/list.js +12 -0
  29. package/dist/commands/switch.d.ts +11 -0
  30. package/dist/commands/switch.js +12 -0
  31. package/dist/commands/types.d.ts +10 -0
  32. package/dist/commands/types.js +0 -0
  33. package/dist/index.d.ts +16 -19
  34. package/dist/index.js +4 -1
  35. package/dist/lib/config.d.ts +14 -0
  36. package/dist/lib/config.js +14 -0
  37. package/dist/lib/fmt.d.ts +12 -0
  38. package/dist/lib/fmt.js +25 -0
  39. package/dist/lib/git.d.ts +26 -0
  40. package/dist/lib/git.js +25 -0
  41. package/dist/lib/registry.d.ts +14 -0
  42. package/dist/lib/registry.js +13 -0
  43. package/dist/lib/select.d.ts +21 -0
  44. package/dist/lib/select.js +10 -0
  45. package/dist/lib/worktree.d.ts +35 -0
  46. package/dist/lib/worktree.js +17 -0
  47. package/dist/vendor/harness-opencode/dist/agents/prompts/agents-md-writer.md +89 -0
  48. package/dist/vendor/harness-opencode/dist/agents/prompts/architecture-advisor.md +46 -0
  49. package/dist/vendor/harness-opencode/dist/agents/prompts/build.md +93 -0
  50. package/dist/vendor/harness-opencode/dist/agents/prompts/code-searcher.md +54 -0
  51. package/dist/vendor/harness-opencode/dist/agents/prompts/docs-maintainer.md +128 -0
  52. package/dist/vendor/harness-opencode/dist/agents/prompts/gap-analyzer.md +44 -0
  53. package/dist/vendor/harness-opencode/dist/agents/prompts/lib-reader.md +39 -0
  54. package/dist/vendor/harness-opencode/dist/agents/prompts/pilot-builder.md +107 -0
  55. package/dist/vendor/harness-opencode/dist/agents/prompts/pilot-planner.md +153 -0
  56. package/dist/vendor/harness-opencode/dist/agents/prompts/plan-reviewer.md +49 -0
  57. package/dist/vendor/harness-opencode/dist/agents/prompts/plan.md +144 -0
  58. package/dist/vendor/harness-opencode/dist/agents/prompts/prime.md +374 -0
  59. package/dist/vendor/harness-opencode/dist/agents/prompts/qa-reviewer.md +68 -0
  60. package/dist/vendor/harness-opencode/dist/agents/prompts/qa-thorough.md +63 -0
  61. package/dist/vendor/harness-opencode/dist/agents/prompts/research.md +138 -0
  62. package/dist/vendor/harness-opencode/dist/agents/shared/index.ts +26 -0
  63. package/dist/vendor/harness-opencode/dist/agents/shared/workflow-mechanics.md +32 -0
  64. package/dist/vendor/harness-opencode/dist/bin/memory-mcp-launcher.sh +145 -0
  65. package/dist/vendor/harness-opencode/dist/bin/plan-check.sh +255 -0
  66. package/dist/vendor/harness-opencode/dist/chunk-VJUETC6A.js +205 -0
  67. package/dist/vendor/harness-opencode/dist/chunk-VVMP6QWS.js +731 -0
  68. package/dist/vendor/harness-opencode/dist/chunk-XCZ3NOXR.js +703 -0
  69. package/dist/vendor/harness-opencode/dist/cli.d.ts +1 -0
  70. package/dist/vendor/harness-opencode/dist/cli.js +5096 -0
  71. package/dist/vendor/harness-opencode/dist/commands/prompts/autopilot.md +96 -0
  72. package/dist/vendor/harness-opencode/dist/commands/prompts/costs.md +94 -0
  73. package/dist/vendor/harness-opencode/dist/commands/prompts/fresh.md +382 -0
  74. package/dist/vendor/harness-opencode/dist/commands/prompts/init-deep.md +196 -0
  75. package/dist/vendor/harness-opencode/dist/commands/prompts/research.md +27 -0
  76. package/dist/vendor/harness-opencode/dist/commands/prompts/review.md +96 -0
  77. package/dist/vendor/harness-opencode/dist/commands/prompts/ship.md +104 -0
  78. package/dist/vendor/harness-opencode/dist/index.d.ts +21 -0
  79. package/dist/vendor/harness-opencode/dist/index.js +2092 -0
  80. package/dist/vendor/harness-opencode/dist/install-4EYR56OR.js +9 -0
  81. package/dist/vendor/harness-opencode/dist/skills/agent-estimation/SKILL.md +159 -0
  82. package/dist/vendor/harness-opencode/dist/skills/paths.ts +18 -0
  83. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/SKILL.md +49 -0
  84. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/dag-shape.md +47 -0
  85. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/decomposition.md +36 -0
  86. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/first-principles.md +29 -0
  87. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/milestones.md +57 -0
  88. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/self-review.md +46 -0
  89. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/task-context.md +47 -0
  90. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/touches-scope.md +47 -0
  91. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/verify-design.md +53 -0
  92. package/dist/vendor/harness-opencode/dist/skills/research/SKILL.md +350 -0
  93. package/dist/vendor/harness-opencode/dist/skills/research-auto/SKILL.md +283 -0
  94. package/dist/vendor/harness-opencode/dist/skills/research-local/SKILL.md +268 -0
  95. package/dist/vendor/harness-opencode/dist/skills/research-web/SKILL.md +119 -0
  96. package/dist/vendor/harness-opencode/dist/skills/review-plan/SKILL.md +32 -0
  97. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/AGENTS.md +946 -0
  98. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/README.md +60 -0
  99. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/SKILL.md +89 -0
  100. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  101. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/architecture-compound-components.md +112 -0
  102. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  103. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -0
  104. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
  105. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
  106. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -0
  107. package/dist/vendor/harness-opencode/dist/skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
  108. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/AGENTS.md +2975 -0
  109. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/README.md +123 -0
  110. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/SKILL.md +137 -0
  111. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  112. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  113. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  114. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  115. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  116. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  117. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  118. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  119. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  120. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  121. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  122. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  123. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  124. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  125. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  126. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  127. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  128. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  129. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  130. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  131. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  132. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  133. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  134. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  135. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  136. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  137. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  138. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  139. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  140. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  141. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  142. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  143. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  144. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  145. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  146. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  147. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  148. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  149. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  150. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  151. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  152. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  153. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  154. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  155. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  156. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  157. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  158. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  159. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  160. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  161. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  162. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  163. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  164. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  165. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  166. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +142 -0
  167. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  168. package/dist/vendor/harness-opencode/dist/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  169. package/dist/vendor/harness-opencode/dist/skills/web-design-guidelines/SKILL.md +39 -0
  170. package/dist/vendor/harness-opencode/package.json +11 -0
  171. package/package.json +20 -15
  172. package/LICENSE +0 -21
  173. package/dist/chunk-TU23AE2F.js +0 -69
@@ -0,0 +1,149 @@
1
+ import {
2
+ worktreePath
3
+ } from "./chunk-W37UX3U2.js";
4
+ import {
5
+ multiSelect
6
+ } from "./chunk-P7PRH4I3.js";
7
+ import {
8
+ gitIn,
9
+ gitInSafe,
10
+ gitRoot,
11
+ listWorktrees
12
+ } from "./chunk-LMRDQ4GW.js";
13
+ import {
14
+ loadRegistry,
15
+ unregisterWorktree
16
+ } from "./chunk-VCN7RNLU.js";
17
+ import {
18
+ bold,
19
+ dim,
20
+ ok,
21
+ red,
22
+ warn
23
+ } from "./chunk-YBCA3IP6.js";
24
+
25
+ // src/commands/delete.ts
26
+ import * as readline from "readline";
27
+ import { command, positional, flag, optional, string } from "cmd-ts";
28
+ var del = command({
29
+ name: "delete",
30
+ aliases: ["rm"],
31
+ description: "Remove worktrees and their branches",
32
+ args: {
33
+ name: positional({
34
+ type: optional(string),
35
+ displayName: "name",
36
+ description: "Worktree name. Omit for interactive multi-select."
37
+ }),
38
+ force: flag({
39
+ long: "force",
40
+ short: "f",
41
+ description: "Remove even if there are uncommitted changes"
42
+ })
43
+ },
44
+ handler: async ({ name, force }) => {
45
+ if (!name) {
46
+ await interactiveDelete();
47
+ return;
48
+ }
49
+ const registry = loadRegistry();
50
+ const match = registry.find((e) => e.branch === name);
51
+ if (match) {
52
+ removeWorktree(match.repoPath, match.wtPath, match.branch, force);
53
+ unregisterWorktree(match.wtPath);
54
+ return;
55
+ }
56
+ let wtPath;
57
+ try {
58
+ wtPath = worktreePath(name);
59
+ } catch {
60
+ throw new Error(`Worktree '${name}' not found`);
61
+ }
62
+ const entries = listWorktrees();
63
+ const entry = entries.find((e) => e.path === wtPath);
64
+ if (!entry) {
65
+ throw new Error(`Worktree '${name}' not found at ${wtPath}`);
66
+ }
67
+ removeWorktree(gitRoot(), wtPath, name, force);
68
+ unregisterWorktree(wtPath);
69
+ }
70
+ });
71
+ function removeWorktree(repoPath, wtPath, branch, force) {
72
+ if (force) {
73
+ gitIn(repoPath, "worktree", "remove", "--force", wtPath);
74
+ } else {
75
+ try {
76
+ gitIn(repoPath, "worktree", "remove", wtPath);
77
+ } catch {
78
+ throw new Error(
79
+ "Worktree has uncommitted changes. Use --force to override."
80
+ );
81
+ }
82
+ }
83
+ gitInSafe(repoPath, "branch", "-d", branch);
84
+ ok(`deleted worktree ${bold(branch)}`);
85
+ }
86
+ async function interactiveDelete() {
87
+ const entries = loadRegistry();
88
+ if (entries.length === 0) {
89
+ warn("no worktrees registered");
90
+ return;
91
+ }
92
+ const byRepo = /* @__PURE__ */ new Map();
93
+ for (const entry of entries) {
94
+ const list = byRepo.get(entry.repo) ?? [];
95
+ list.push(entry);
96
+ byRepo.set(entry.repo, list);
97
+ }
98
+ const groups = [];
99
+ for (const [repo, repoEntries] of byRepo) {
100
+ groups.push({
101
+ title: repo,
102
+ choices: repoEntries.map((e) => ({
103
+ label: e.branch,
104
+ value: e,
105
+ hint: e.wtPath
106
+ }))
107
+ });
108
+ }
109
+ const selected = await multiSelect({
110
+ message: "Select worktrees to delete",
111
+ groups
112
+ });
113
+ if (selected.length === 0) return;
114
+ console.log();
115
+ for (const entry of selected) {
116
+ console.log(` ${red("\u2715")} ${entry.branch} ${dim(entry.wtPath)}`);
117
+ }
118
+ console.log();
119
+ const confirmed = await confirm(
120
+ `Delete ${selected.length} worktree(s)? [y/N] `
121
+ );
122
+ if (!confirmed) return;
123
+ for (const entry of selected) {
124
+ try {
125
+ gitIn(entry.repoPath, "worktree", "remove", entry.wtPath);
126
+ gitInSafe(entry.repoPath, "branch", "-d", entry.branch);
127
+ unregisterWorktree(entry.wtPath);
128
+ ok(`deleted ${entry.branch}`);
129
+ } catch {
130
+ warn(`failed to delete ${entry.branch} \u2014 may have uncommitted changes`);
131
+ }
132
+ }
133
+ }
134
+ function confirm(prompt) {
135
+ const rl = readline.createInterface({
136
+ input: process.stdin,
137
+ output: process.stdout
138
+ });
139
+ return new Promise((resolve) => {
140
+ rl.question(prompt, (answer) => {
141
+ rl.close();
142
+ resolve(/^[Yy]$/.test(answer.trim()));
143
+ });
144
+ });
145
+ }
146
+
147
+ export {
148
+ del
149
+ };
@@ -0,0 +1,177 @@
1
+ import {
2
+ bold,
3
+ cyan,
4
+ dim,
5
+ green
6
+ } from "./chunk-YBCA3IP6.js";
7
+
8
+ // src/lib/select.ts
9
+ function flatten(groups) {
10
+ const items = [];
11
+ for (const group of groups) {
12
+ items.push({ type: "header", label: group.title });
13
+ for (const choice of group.choices) {
14
+ items.push({
15
+ type: "choice",
16
+ label: choice.label,
17
+ hint: choice.hint,
18
+ value: choice.value
19
+ });
20
+ }
21
+ }
22
+ return items;
23
+ }
24
+ function selectableIndices(items) {
25
+ return items.reduce((acc, item, i) => {
26
+ if (item.type === "choice") acc.push(i);
27
+ return acc;
28
+ }, []);
29
+ }
30
+ function select(opts) {
31
+ const items = flatten(opts.groups);
32
+ const selectable = selectableIndices(items);
33
+ if (selectable.length === 0) return Promise.resolve(null);
34
+ let cursor = 0;
35
+ return new Promise((resolve) => {
36
+ const { stdin, stdout } = process;
37
+ if (!stdin.isTTY) {
38
+ resolve(null);
39
+ return;
40
+ }
41
+ stdin.setRawMode(true);
42
+ stdin.resume();
43
+ stdin.setEncoding("utf8");
44
+ stdout.write("\x1B[?25l");
45
+ let lineCount = 0;
46
+ function render() {
47
+ let out = "";
48
+ if (lineCount > 0) out += `\x1B[${lineCount}A`;
49
+ const lines = [];
50
+ lines.push(`${cyan("?")} ${bold(opts.message)}`);
51
+ lines.push("");
52
+ for (let i = 0; i < items.length; i++) {
53
+ const item = items[i];
54
+ if (item.type === "header") {
55
+ lines.push(` ${bold(item.label)}`);
56
+ } else {
57
+ const active = selectable[cursor] === i;
58
+ const prefix = active ? cyan("> ") : " ";
59
+ const label = active ? item.label : dim(item.label);
60
+ const hint = item.hint ? ` ${dim(item.hint)}` : "";
61
+ lines.push(`${prefix}${label}${hint}`);
62
+ }
63
+ }
64
+ out += lines.map((l) => `\x1B[2K${l}`).join("\n") + "\n";
65
+ stdout.write(out);
66
+ lineCount = lines.length;
67
+ }
68
+ function cleanup() {
69
+ stdin.removeListener("data", onKey);
70
+ stdin.setRawMode(false);
71
+ stdin.pause();
72
+ stdout.write("\x1B[?25h");
73
+ }
74
+ function onKey(data) {
75
+ if (data === "") {
76
+ cleanup();
77
+ process.exit(130);
78
+ return;
79
+ }
80
+ if (data === "\r" || data === "\n") {
81
+ cleanup();
82
+ resolve(items[selectable[cursor]].value);
83
+ return;
84
+ }
85
+ if (data === "\x1B[A" || data === "k") {
86
+ cursor = Math.max(0, cursor - 1);
87
+ render();
88
+ } else if (data === "\x1B[B" || data === "j") {
89
+ cursor = Math.min(selectable.length - 1, cursor + 1);
90
+ render();
91
+ }
92
+ }
93
+ stdin.on("data", onKey);
94
+ render();
95
+ });
96
+ }
97
+ function multiSelect(opts) {
98
+ const items = flatten(opts.groups);
99
+ const selectable = selectableIndices(items);
100
+ if (selectable.length === 0) return Promise.resolve([]);
101
+ let cursor = 0;
102
+ const selected = /* @__PURE__ */ new Set();
103
+ return new Promise((resolve) => {
104
+ const { stdin, stdout } = process;
105
+ if (!stdin.isTTY) {
106
+ resolve([]);
107
+ return;
108
+ }
109
+ stdin.setRawMode(true);
110
+ stdin.resume();
111
+ stdin.setEncoding("utf8");
112
+ stdout.write("\x1B[?25l");
113
+ let lineCount = 0;
114
+ function render() {
115
+ let out = "";
116
+ if (lineCount > 0) out += `\x1B[${lineCount}A`;
117
+ const lines = [];
118
+ lines.push(
119
+ `${cyan("?")} ${bold(opts.message)} ${dim("(space = toggle, enter = confirm)")}`
120
+ );
121
+ lines.push("");
122
+ for (let i = 0; i < items.length; i++) {
123
+ const item = items[i];
124
+ if (item.type === "header") {
125
+ lines.push(` ${bold(item.label)}`);
126
+ } else {
127
+ const idx = selectable.indexOf(i);
128
+ const active = cursor === idx;
129
+ const checked = selected.has(idx);
130
+ const box = checked ? green("[x]") : dim("[ ]");
131
+ const prefix = active ? cyan("> ") : " ";
132
+ const hint = item.hint ? ` ${dim(item.hint)}` : "";
133
+ lines.push(`${prefix}${box} ${item.label}${hint}`);
134
+ }
135
+ }
136
+ out += lines.map((l) => `\x1B[2K${l}`).join("\n") + "\n";
137
+ stdout.write(out);
138
+ lineCount = lines.length;
139
+ }
140
+ function cleanup() {
141
+ stdin.removeListener("data", onKey);
142
+ stdin.setRawMode(false);
143
+ stdin.pause();
144
+ stdout.write("\x1B[?25h");
145
+ }
146
+ function onKey(data) {
147
+ if (data === "") {
148
+ cleanup();
149
+ process.exit(130);
150
+ return;
151
+ }
152
+ if (data === "\r" || data === "\n") {
153
+ cleanup();
154
+ resolve([...selected].map((idx) => items[selectable[idx]].value));
155
+ return;
156
+ }
157
+ if (data === " ") {
158
+ if (selected.has(cursor)) selected.delete(cursor);
159
+ else selected.add(cursor);
160
+ render();
161
+ } else if (data === "\x1B[A" || data === "k") {
162
+ cursor = Math.max(0, cursor - 1);
163
+ render();
164
+ } else if (data === "\x1B[B" || data === "j") {
165
+ cursor = Math.min(selectable.length - 1, cursor + 1);
166
+ render();
167
+ }
168
+ }
169
+ stdin.on("data", onKey);
170
+ render();
171
+ });
172
+ }
173
+
174
+ export {
175
+ select,
176
+ multiSelect
177
+ };
@@ -0,0 +1,60 @@
1
+ // src/lib/registry.ts
2
+ import * as path from "path";
3
+ import * as os from "os";
4
+ var REGISTRY_DIR = path.join(os.homedir(), ".glorious");
5
+ var REGISTRY_FILE = path.join(REGISTRY_DIR, "worktrees.json");
6
+ function ensureDir() {
7
+ Bun.mkdir(REGISTRY_DIR, { recursive: true });
8
+ }
9
+ function existsSync(filePath) {
10
+ return Bun.file(filePath).existsSync();
11
+ }
12
+ function readTextSync(filePath) {
13
+ try {
14
+ return Bun.file(filePath).textSync();
15
+ } catch {
16
+ return null;
17
+ }
18
+ }
19
+ function writeTextSync(filePath, content) {
20
+ Bun.file(filePath).writer().write(content);
21
+ }
22
+ function loadRegistry() {
23
+ if (!existsSync(REGISTRY_FILE)) return [];
24
+ try {
25
+ const raw = readTextSync(REGISTRY_FILE);
26
+ if (!raw) return [];
27
+ const entries = JSON.parse(raw);
28
+ const valid = entries.filter((e) => existsSync(e.wtPath));
29
+ if (valid.length !== entries.length) {
30
+ saveRegistry(valid);
31
+ }
32
+ return valid;
33
+ } catch {
34
+ return [];
35
+ }
36
+ }
37
+ function saveRegistry(entries) {
38
+ ensureDir();
39
+ writeTextSync(REGISTRY_FILE, JSON.stringify(entries, null, 2) + "\n");
40
+ }
41
+ function registerWorktree(entry) {
42
+ const entries = loadRegistry();
43
+ const filtered = entries.filter((e) => e.wtPath !== entry.wtPath);
44
+ filtered.push(entry);
45
+ saveRegistry(filtered);
46
+ }
47
+ function unregisterWorktree(wtPath) {
48
+ const entries = loadRegistry();
49
+ const filtered = entries.filter((e) => e.wtPath !== wtPath);
50
+ if (filtered.length !== entries.length) {
51
+ saveRegistry(filtered);
52
+ }
53
+ }
54
+
55
+ export {
56
+ loadRegistry,
57
+ saveRegistry,
58
+ registerWorktree,
59
+ unregisterWorktree
60
+ };
@@ -0,0 +1,120 @@
1
+ import {
2
+ repoName,
3
+ worktreePath
4
+ } from "./chunk-W37UX3U2.js";
5
+ import {
6
+ defaultBranchIn,
7
+ gitIn,
8
+ gitInSafe,
9
+ gitRoot
10
+ } from "./chunk-LMRDQ4GW.js";
11
+ import {
12
+ registerWorktree
13
+ } from "./chunk-VCN7RNLU.js";
14
+ import {
15
+ bold,
16
+ info,
17
+ ok,
18
+ warn
19
+ } from "./chunk-YBCA3IP6.js";
20
+
21
+ // src/lib/worktree.ts
22
+ import * as path from "path";
23
+ function existsSync(filePath) {
24
+ return Bun.file(filePath).existsSync();
25
+ }
26
+ function mkdirSync(dirPath, opts) {
27
+ Bun.mkdir(dirPath, opts);
28
+ }
29
+ function autoName(now = /* @__PURE__ */ new Date(), suffix = randomSuffix()) {
30
+ const pad = (n) => n.toString().padStart(2, "0");
31
+ const yy = now.getFullYear().toString().slice(2);
32
+ const mm = pad(now.getMonth() + 1);
33
+ const dd = pad(now.getDate());
34
+ const hh = pad(now.getHours());
35
+ const mi = pad(now.getMinutes());
36
+ const ss = pad(now.getSeconds());
37
+ return `wt-${yy}${mm}${dd}-${hh}${mi}${ss}-${suffix}`;
38
+ }
39
+ function randomSuffix() {
40
+ return Math.random().toString(36).slice(2, 5).padEnd(3, "0");
41
+ }
42
+ function assertPrimaryClone(srcRepo) {
43
+ const commonDir = gitInSafe(srcRepo, "rev-parse", "--git-common-dir");
44
+ if (!commonDir) return;
45
+ if (!path.isAbsolute(commonDir)) return;
46
+ const primary = path.dirname(commonDir);
47
+ if (path.resolve(primary) === path.resolve(srcRepo)) return;
48
+ throw new Error(
49
+ `Refusing to create a nested worktree.
50
+ '${srcRepo}' is itself a worktree of '${primary}'.
51
+ Create worktrees from the primary clone, or pass a repo name:
52
+ glrs wt new <repo>`
53
+ );
54
+ }
55
+ function createWorktree(opts = {}) {
56
+ const srcRepo = opts.repoPath ?? gitRoot();
57
+ assertPrimaryClone(srcRepo);
58
+ const repo = opts.repo ?? path.basename(srcRepo);
59
+ const name = opts.name ?? autoName();
60
+ const wtPath = worktreePath(name, repo);
61
+ if (existsSync(wtPath)) {
62
+ throw new Error(`Worktree already exists: ${wtPath}`);
63
+ }
64
+ mkdirSync(path.dirname(wtPath), { recursive: true });
65
+ const base = opts.from ?? defaultBranchIn(srcRepo);
66
+ info(`fetching origin/${base}...`);
67
+ gitIn(srcRepo, "fetch", "origin", base, "--quiet");
68
+ const branchExists = gitInSafe(srcRepo, "show-ref", "--verify", `refs/heads/${name}`) !== null;
69
+ if (branchExists) {
70
+ warn(`branch ${bold(name)} already exists, resetting to origin/${base}`);
71
+ gitIn(srcRepo, "branch", "-D", name);
72
+ }
73
+ info(`creating worktree ${bold(name)} from origin/${base}...`);
74
+ gitIn(
75
+ srcRepo,
76
+ "worktree",
77
+ "add",
78
+ "-b",
79
+ name,
80
+ wtPath,
81
+ `origin/${base}`,
82
+ "--quiet"
83
+ );
84
+ try {
85
+ gitIn(wtPath, "branch", "--set-upstream-to", `origin/${base}`, name);
86
+ } catch {
87
+ }
88
+ registerWorktree({
89
+ repo,
90
+ repoPath: srcRepo,
91
+ wtPath,
92
+ branch: name,
93
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
94
+ });
95
+ ok(`worktree created at ${bold(wtPath)}`);
96
+ return { wtPath, name, base };
97
+ }
98
+ function ensureWorktree(name, from) {
99
+ const repo = repoName();
100
+ const wtPath = worktreePath(name, repo);
101
+ if (existsSync(wtPath)) {
102
+ info(`worktree already exists at ${bold(wtPath)}, reusing...`);
103
+ registerWorktree({
104
+ repo,
105
+ repoPath: gitRoot(),
106
+ wtPath,
107
+ branch: name,
108
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
109
+ });
110
+ return wtPath;
111
+ }
112
+ return createWorktree({ name, from }).wtPath;
113
+ }
114
+
115
+ export {
116
+ autoName,
117
+ assertPrimaryClone,
118
+ createWorktree,
119
+ ensureWorktree
120
+ };
@@ -0,0 +1,35 @@
1
+ import {
2
+ gitRoot
3
+ } from "./chunk-LMRDQ4GW.js";
4
+
5
+ // src/lib/config.ts
6
+ import * as path from "path";
7
+ import * as os from "os";
8
+ var PROTECTED_BRANCHES = /* @__PURE__ */ new Set([
9
+ "main",
10
+ "master",
11
+ "next",
12
+ "prerelease"
13
+ ]);
14
+ function isProtected(branch) {
15
+ return PROTECTED_BRANCHES.has(branch);
16
+ }
17
+ function repoName() {
18
+ return path.basename(gitRoot());
19
+ }
20
+ function worktreesRoot(repo) {
21
+ const override = process.env.GLORIOUS_DIR;
22
+ if (override) return path.resolve(override, repo);
23
+ return path.join(os.homedir(), ".glorious", "worktrees", repo);
24
+ }
25
+ function worktreePath(name, repo) {
26
+ const repoKey = repo ?? repoName();
27
+ return path.join(worktreesRoot(repoKey), name);
28
+ }
29
+
30
+ export {
31
+ isProtected,
32
+ repoName,
33
+ worktreesRoot,
34
+ worktreePath
35
+ };
@@ -0,0 +1,25 @@
1
+ // src/lib/fmt.ts
2
+ var isTTY = process.stdout.isTTY;
3
+ var bold = (s) => isTTY ? `\x1B[1m${s}\x1B[0m` : s;
4
+ var dim = (s) => isTTY ? `\x1B[2m${s}\x1B[0m` : s;
5
+ var red = (s) => isTTY ? `\x1B[31m${s}\x1B[0m` : s;
6
+ var green = (s) => isTTY ? `\x1B[32m${s}\x1B[0m` : s;
7
+ var yellow = (s) => isTTY ? `\x1B[33m${s}\x1B[0m` : s;
8
+ var cyan = (s) => isTTY ? `\x1B[36m${s}\x1B[0m` : s;
9
+ var ok = (msg) => console.log(`${green("\u2713")} ${msg}`);
10
+ var okErr = (msg) => console.error(`${green("\u2713")} ${msg}`);
11
+ var info = (msg) => console.log(`${cyan("\u25B8")} ${msg}`);
12
+ var warn = (msg) => console.error(`${yellow("warning:")} ${msg}`);
13
+
14
+ export {
15
+ bold,
16
+ dim,
17
+ red,
18
+ green,
19
+ yellow,
20
+ cyan,
21
+ ok,
22
+ okErr,
23
+ info,
24
+ warn
25
+ };
@@ -0,0 +1,99 @@
1
+ // src/index.ts
2
+ import { readFileSync } from "fs";
3
+ import { dirname, resolve as pathResolve } from "path";
4
+ import { fileURLToPath } from "url";
5
+ function resolveVendoredHarness(binKey) {
6
+ const here = dirname(fileURLToPath(import.meta.url));
7
+ const vendorPkgJson = pathResolve(here, "vendor", "harness-opencode", "package.json");
8
+ let pkgJsonPath;
9
+ try {
10
+ readFileSync(vendorPkgJson, "utf8");
11
+ pkgJsonPath = vendorPkgJson;
12
+ } catch {
13
+ throw new Error(
14
+ `[@glrs-dev/cli] Vendored harness-opencode not found at ${vendorPkgJson}.
15
+ This means the cli package was built incorrectly or the tarball is incomplete.
16
+ Report at https://github.com/iceglober/glrs/issues.`
17
+ );
18
+ }
19
+ const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf8"));
20
+ const bin = pkgJson.bin;
21
+ let relative;
22
+ if (typeof bin === "string") {
23
+ relative = bin;
24
+ } else if (bin && typeof bin === "object" && typeof bin[binKey] === "string") {
25
+ relative = bin[binKey];
26
+ } else {
27
+ throw new Error(
28
+ `[@glrs-dev/cli] Vendored harness-opencode has no bin entry for '${binKey}'. This shouldn't happen \u2014 report at https://github.com/iceglober/glrs/issues.`
29
+ );
30
+ }
31
+ const binPath = pathResolve(dirname(pkgJsonPath), relative);
32
+ return { executable: "bun", preArgs: [binPath] };
33
+ }
34
+ function resolveSubcommand(sub) {
35
+ switch (sub) {
36
+ case "oc":
37
+ return resolveVendoredHarness("harness-opencode");
38
+ case "wt":
39
+ throw new Error("Worktree commands should be handled natively");
40
+ default: {
41
+ const exhaustive = sub;
42
+ throw new Error(`Unknown subcommand: ${exhaustive}`);
43
+ }
44
+ }
45
+ }
46
+ var SUBCOMMANDS = ["oc", "wt"];
47
+ var HELP_TEXT = `glrs \u2014 unified CLI for the @glrs-dev ecosystem
48
+
49
+ USAGE
50
+ glrs <subcommand> [args...]
51
+
52
+ SUBCOMMANDS
53
+ oc OpenCode agent harness (install, pilot, etc.)
54
+ wt Worktree management (create, list, switch, delete, cleanup)
55
+
56
+ Run 'glrs <subcommand> --help' for per-command help.
57
+
58
+ EXAMPLES
59
+ glrs oc install
60
+ glrs wt new
61
+ glrs wt list
62
+ glrs wt switch
63
+
64
+ REQUIREMENTS
65
+ Bun >= 1.2.0 on PATH (install: https://bun.sh)
66
+
67
+ DOCS https://glrs.dev
68
+ ISSUES https://github.com/iceglober/glrs/issues
69
+ `;
70
+ var WORKTREE_HELP_TEXT = `glrs wt \u2014 worktree management
71
+
72
+ USAGE
73
+ glrs wt <command> [args...]
74
+
75
+ COMMANDS
76
+ new Create a new worktree (auto-named from origin/default)
77
+ list, ls List all worktrees across repos
78
+ switch, sw Interactively select and switch to a worktree
79
+ delete, rm Remove worktrees (interactive or by name)
80
+ cleanup Delete merged/stale worktrees
81
+
82
+ EXAMPLES
83
+ glrs wt new # Create worktree in current repo
84
+ glrs wt new myrepo # Create worktree for named repo
85
+ glrs wt list # Show all worktrees
86
+ glrs wt list -i # Interactive picker
87
+ glrs wt switch # Interactive switcher
88
+ glrs wt delete my-branch # Delete specific worktree
89
+ glrs wt cleanup # Clean up merged worktrees
90
+
91
+ Worktrees are stored in ~/.glorious/worktrees/<repo>/<name>/
92
+ `;
93
+
94
+ export {
95
+ resolveSubcommand,
96
+ SUBCOMMANDS,
97
+ HELP_TEXT,
98
+ WORKTREE_HELP_TEXT
99
+ };
package/dist/cli.d.ts CHANGED
@@ -1 +1 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun