ultracontext 1.4.13 → 1.6.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.
Files changed (41) hide show
  1. package/dist/cli/entry.mjs +9 -3
  2. package/dist/cli/entry.mjs.map +1 -1
  3. package/dist/cli/onboarding.mjs +268 -111
  4. package/dist/cli/onboarding.mjs.map +1 -1
  5. package/dist/cli/sdk-sync.mjs +199 -939
  6. package/dist/cli/sdk-sync.mjs.map +1 -1
  7. package/dist/cli/switch.mjs +168 -0
  8. package/dist/cli/switch.mjs.map +1 -0
  9. package/dist/{ctl-CXfNEPN8.mjs → ctl-DTQZxn3N.mjs} +2 -2
  10. package/dist/{ctl-CXfNEPN8.mjs.map → ctl-DTQZxn3N.mjs.map} +1 -1
  11. package/dist/hero-art-C03HmDXN.mjs +46 -0
  12. package/dist/hero-art-C03HmDXN.mjs.map +1 -0
  13. package/dist/index.d.mts +21 -1
  14. package/dist/index.d.mts.map +1 -1
  15. package/dist/index.mjs +25 -3
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/{launcher-BMMjzr5k.mjs → launcher-ZylswrpR.mjs} +3 -3
  18. package/dist/{launcher-BMMjzr5k.mjs.map → launcher-ZylswrpR.mjs.map} +1 -1
  19. package/dist/{lock-5aJnda81.mjs → lock-BhZX2aF3.mjs} +2 -2
  20. package/dist/{lock-5aJnda81.mjs.map → lock-BhZX2aF3.mjs.map} +1 -1
  21. package/dist/onboarding-preferences-Alhblobi.mjs +76 -0
  22. package/dist/onboarding-preferences-Alhblobi.mjs.map +1 -0
  23. package/dist/src-Bovo1ukU.mjs +1200 -0
  24. package/dist/src-Bovo1ukU.mjs.map +1 -0
  25. package/dist/{tui-DZ1SDOH2.mjs → tui-DLEjew3K.mjs} +334 -115
  26. package/dist/tui-DLEjew3K.mjs.map +1 -0
  27. package/dist/utils-BTfShW0g.mjs +36 -0
  28. package/dist/utils-BTfShW0g.mjs.map +1 -0
  29. package/dist/{utils-CmuIYHtm.mjs → utils-D9CKnbke.mjs} +26 -34
  30. package/dist/utils-D9CKnbke.mjs.map +1 -0
  31. package/lib/register-skills.mjs +96 -0
  32. package/package.json +8 -3
  33. package/plugin/.claude-plugin/plugin.json +6 -0
  34. package/plugin/README.md +112 -0
  35. package/plugin/marketplace.json +17 -0
  36. package/plugin/skills/switch/SKILL.md +27 -0
  37. package/postinstall.mjs +35 -2
  38. package/dist/Spinner-CwBjkXHv.mjs +0 -153
  39. package/dist/Spinner-CwBjkXHv.mjs.map +0 -1
  40. package/dist/tui-DZ1SDOH2.mjs.map +0 -1
  41. package/dist/utils-CmuIYHtm.mjs.map +0 -1
@@ -1,39 +1,118 @@
1
- import { c as heroArtForWidth, i as UC_BRAND_BLUE, r as UC_BLUE_LIGHT, t as Spinner } from "../Spinner-CwBjkXHv.mjs";
2
- import process from "node:process";
1
+ import { t as heroArtForWidth } from "../hero-art-C03HmDXN.mjs";
2
+ import { i as buildOnboardingConfigPatch, n as ONBOARDING_AGENT_OPTIONS, r as ONBOARDING_CAPTURE_OPTIONS, t as ONBOARDING_AGENT_ALL_OPTION } from "../onboarding-preferences-Alhblobi.mjs";
3
+ import process$1 from "node:process";
3
4
  import path from "node:path";
4
5
  import fs from "node:fs";
5
- import { spawn } from "node:child_process";
6
6
  import React from "react";
7
7
  import { Box, Text, render, useInput, useStdout } from "ink";
8
8
  import { TitledBox } from "@mishieck/ink-titled-box";
9
9
 
10
+ //#region ../sync/src/recent-projects.mjs
11
+ function safeStat(p) {
12
+ try {
13
+ return fs.statSync(p);
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+ function safeReaddir(dir) {
19
+ try {
20
+ return fs.readdirSync(dir, { withFileTypes: true });
21
+ } catch {
22
+ return [];
23
+ }
24
+ }
25
+ function firstJsonlFile(dir) {
26
+ return safeReaddir(dir).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
27
+ const full = path.join(dir, e.name);
28
+ const stat = safeStat(full);
29
+ return {
30
+ full,
31
+ mtime: stat ? stat.mtimeMs : 0
32
+ };
33
+ }).sort((a, b) => b.mtime - a.mtime)[0]?.full ?? null;
34
+ }
35
+ function readCwdFromJsonl(file, maxLines = 10) {
36
+ try {
37
+ const lines = fs.readFileSync(file, "utf8").split("\n", maxLines + 1).slice(0, maxLines);
38
+ for (const line of lines) {
39
+ if (!line) continue;
40
+ try {
41
+ const obj = JSON.parse(line);
42
+ if (typeof obj.cwd === "string" && obj.cwd) return obj.cwd;
43
+ if (obj.payload && typeof obj.payload.cwd === "string" && obj.payload.cwd) return obj.payload.cwd;
44
+ } catch {}
45
+ }
46
+ } catch {}
47
+ return null;
48
+ }
49
+ function decodeDirNameWithLeadingSlash(name) {
50
+ return "/" + name.replace(/^-/, "").replace(/-/g, "/");
51
+ }
52
+ function decodeCursorDirName(name) {
53
+ return "/" + name.replace(/-/g, "/");
54
+ }
55
+ function collect(rootDir, decode) {
56
+ return safeReaddir(rootDir).filter((entry) => entry.isDirectory()).map((entry) => {
57
+ const dir = path.join(rootDir, entry.name);
58
+ const stat = safeStat(dir);
59
+ const mtime = stat ? stat.mtimeMs : 0;
60
+ const jsonl = firstJsonlFile(dir);
61
+ return {
62
+ path: (jsonl ? readCwdFromJsonl(jsonl) : null) || decode(entry.name),
63
+ mtime
64
+ };
65
+ });
66
+ }
67
+ function discoverRecentProjects({ home = process.env.HOME } = {}) {
68
+ if (!home) return [];
69
+ const candidates = [...collect(path.join(home, ".claude", "projects"), decodeDirNameWithLeadingSlash), ...collect(path.join(home, ".cursor", "projects"), decodeCursorDirName)];
70
+ const best = /* @__PURE__ */ new Map();
71
+ for (const c of candidates) {
72
+ if (!c.path || !c.path.startsWith("/")) continue;
73
+ const stat = safeStat(c.path);
74
+ if (!stat || !stat.isDirectory()) continue;
75
+ const prev = best.get(c.path);
76
+ if (!prev || prev.mtime < c.mtime) best.set(c.path, c);
77
+ }
78
+ return [...best.values()].sort((a, b) => b.mtime - a.mtime).map((c) => c.path);
79
+ }
80
+
81
+ //#endregion
10
82
  //#region src/cli/onboarding.mjs
11
- const CONFIG_DIR = path.join(process.env.HOME || process.env.USERPROFILE || "~", ".ultracontext");
12
- const CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
83
+ const AGENT_ROWS = [ONBOARDING_AGENT_ALL_OPTION, ...ONBOARDING_AGENT_OPTIONS];
84
+ function ListRow({ focused, checked, label, multi = false, keyProp }) {
85
+ const line = `${focused ? "❯ " : " "}${multi ? checked ? "✓ " : " " : ""}${label}`;
86
+ return React.createElement(Text, {
87
+ key: keyProp,
88
+ color: focused ? "white" : "gray",
89
+ bold: focused
90
+ }, line);
91
+ }
92
+ function configPaths() {
93
+ const home = process$1.env.ULTRACONTEXT_CONFIG_HOME || process$1.env.HOME || process$1.env.USERPROFILE || "~";
94
+ const dir = path.join(home, ".ultracontext");
95
+ return {
96
+ dir,
97
+ path: path.join(dir, "config.json")
98
+ };
99
+ }
13
100
  function readConfig() {
14
101
  try {
15
- return JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
102
+ return JSON.parse(fs.readFileSync(configPaths().path, "utf8"));
16
103
  } catch {
17
104
  return {};
18
105
  }
19
106
  }
20
107
  function writeConfig(patch) {
21
108
  const existing = readConfig();
22
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
23
- fs.writeFileSync(CONFIG_PATH, JSON.stringify({
109
+ const { dir, path: file } = configPaths();
110
+ fs.mkdirSync(dir, { recursive: true });
111
+ fs.writeFileSync(file, JSON.stringify({
24
112
  ...existing,
25
113
  ...patch
26
114
  }, null, 2) + "\n", "utf8");
27
115
  }
28
- function openUrl(url) {
29
- const cmd = process.platform === "darwin" ? "open" : "xdg-open";
30
- try {
31
- spawn(cmd, [url], {
32
- detached: true,
33
- stdio: "ignore"
34
- }).unref();
35
- } catch {}
36
- }
37
116
  function isValidKey(key) {
38
117
  return /^uc_(live|test)_/.test(key);
39
118
  }
@@ -44,20 +123,6 @@ const MODE_OPTIONS = [{
44
123
  label: "Self-host",
45
124
  value: "selfhost"
46
125
  }];
47
- const BOOTSTRAP_OPTIONS = [
48
- {
49
- label: "New only (recommended)",
50
- value: "new_only"
51
- },
52
- {
53
- label: "Last 24h",
54
- value: "last_24h"
55
- },
56
- {
57
- label: "All",
58
- value: "all"
59
- }
60
- ];
61
126
  const LAUNCH_OPTIONS = [{
62
127
  label: "Yes, open the TUI (recommended)",
63
128
  value: true
@@ -69,42 +134,70 @@ function stepNumber(step) {
69
134
  if (step === "welcome") return 1;
70
135
  if (step === "mode") return 2;
71
136
  if (step === "url" || step === "key") return 3;
72
- if (step === "bootstrap") return 4;
73
- if (step === "launch") return 5;
74
- return 5;
137
+ if (step === "agents") return 4;
138
+ if (step === "projects") return 5;
139
+ if (step === "capture") return 6;
140
+ if (step === "launch") return 7;
141
+ return 7;
75
142
  }
76
- const TOTAL_STEPS = 5;
143
+ const TOTAL_STEPS = 7;
77
144
  function Onboarding({ onDone }) {
78
145
  const { stdout } = useStdout();
79
- const cols = stdout?.columns ?? process.stdout.columns ?? 80;
146
+ const cols = stdout?.columns ?? process$1.stdout.columns ?? 80;
80
147
  const [step, setStep] = React.useState("welcome");
148
+ const [history, setHistory] = React.useState([]);
81
149
  const [hosting, setHosting] = React.useState("cloud");
82
150
  const [baseUrl, setBaseUrl] = React.useState("https://api.ultracontext.ai");
83
151
  const [apiKey, setApiKey] = React.useState("");
84
- const [bootstrapMode, setBootstrapMode] = React.useState("new_only");
152
+ const [captureAgents, setCaptureAgents] = React.useState(ONBOARDING_AGENT_OPTIONS.map((o) => o.id));
153
+ const [projectPaths, setProjectPaths] = React.useState([]);
154
+ const [autoCaptureMode, setAutoCaptureMode] = React.useState("all");
85
155
  const [selectedIndex, setSelectedIndex] = React.useState(0);
86
156
  const [keyInput, setKeyInput] = React.useState("");
87
157
  const [urlInput, setUrlInput] = React.useState("https://");
88
158
  const [error, setError] = React.useState("");
89
- const [launchTui, setLaunchTui] = React.useState(false);
90
- const finish = React.useCallback((finalKey, finalUrl, finalBootstrap) => {
159
+ const inferredProjects = React.useMemo(() => discoverRecentProjects(), []);
160
+ const ALL_PROJECTS = "__all__";
161
+ const projectRows = React.useMemo(() => [ALL_PROJECTS, ...inferredProjects], [inferredProjects]);
162
+ const [pickedProjects, setPickedProjects] = React.useState([ALL_PROJECTS]);
163
+ const pushStep = React.useCallback((nextStep) => {
164
+ setHistory((h) => [...h, step]);
165
+ setStep(nextStep);
166
+ setSelectedIndex(0);
167
+ setError("");
168
+ }, [step]);
169
+ const goBack = React.useCallback(() => {
170
+ setHistory((h) => {
171
+ if (h.length === 0) return h;
172
+ setStep(h[h.length - 1]);
173
+ setSelectedIndex(0);
174
+ setError("");
175
+ return h.slice(0, -1);
176
+ });
177
+ }, []);
178
+ const finish = React.useCallback((finalKey, finalUrl, preferences) => {
91
179
  writeConfig({
92
180
  apiKey: finalKey,
93
181
  baseUrl: finalUrl,
94
- bootstrapMode: finalBootstrap
182
+ ...buildOnboardingConfigPatch(preferences)
95
183
  });
96
- process.env.ULTRACONTEXT_API_KEY = finalKey;
97
- process.env.ULTRACONTEXT_BASE_URL = finalUrl;
98
- setStep("launch");
99
- setSelectedIndex(0);
100
- }, []);
184
+ process$1.env.ULTRACONTEXT_API_KEY = finalKey;
185
+ process$1.env.ULTRACONTEXT_BASE_URL = finalUrl;
186
+ pushStep("launch");
187
+ }, [pushStep]);
101
188
  useInput((input, key) => {
102
- if (key.escape || input === "c" && key.ctrl) process.exit(0);
189
+ if (input === "c" && key.ctrl) process$1.exit(0);
190
+ if (key.escape) {
191
+ if (step === "welcome") process$1.exit(0);
192
+ goBack();
193
+ return;
194
+ }
195
+ if (key.leftArrow && step !== "welcome") {
196
+ goBack();
197
+ return;
198
+ }
103
199
  if (step === "welcome") {
104
- if (key.return) {
105
- setStep("mode");
106
- setSelectedIndex(0);
107
- }
200
+ if (key.return) pushStep("mode");
108
201
  return;
109
202
  }
110
203
  if (step === "mode") {
@@ -115,18 +208,11 @@ function Onboarding({ onDone }) {
115
208
  if (key.return || input === " ") {
116
209
  const chosen = MODE_OPTIONS[selectedIndex].value;
117
210
  setHosting(chosen);
118
- if (chosen === "selfhost") {
119
- setStep("url");
120
- setUrlInput("https://");
121
- setError("");
122
- } else {
211
+ if (chosen === "selfhost") pushStep("url");
212
+ else {
123
213
  setBaseUrl("https://api.ultracontext.ai");
124
- openUrl("https://ultracontext.ai");
125
- setStep("key");
126
- setKeyInput("");
127
- setError("");
214
+ pushStep("key");
128
215
  }
129
- setSelectedIndex(0);
130
216
  }
131
217
  return;
132
218
  }
@@ -138,9 +224,7 @@ function Onboarding({ onDone }) {
138
224
  return;
139
225
  }
140
226
  setBaseUrl(trimmed);
141
- setStep("key");
142
- setKeyInput("");
143
- setError("");
227
+ pushStep("key");
144
228
  return;
145
229
  }
146
230
  if (key.backspace || key.delete) {
@@ -166,9 +250,7 @@ function Onboarding({ onDone }) {
166
250
  return;
167
251
  }
168
252
  setApiKey(trimmed);
169
- setStep("bootstrap");
170
- setSelectedIndex(0);
171
- setError("");
253
+ pushStep("agents");
172
254
  return;
173
255
  }
174
256
  if (key.backspace || key.delete) {
@@ -182,16 +264,63 @@ function Onboarding({ onDone }) {
182
264
  }
183
265
  return;
184
266
  }
185
- if (step === "bootstrap") {
267
+ if (step === "agents") {
268
+ if (key.upArrow) setSelectedIndex((i) => Math.max(i - 1, 0));
269
+ if (key.downArrow) setSelectedIndex((i) => Math.min(i + 1, AGENT_ROWS.length - 1));
270
+ if (input === " ") {
271
+ setError("");
272
+ const row = AGENT_ROWS[selectedIndex];
273
+ if (row.id === "all") {
274
+ const allIds = ONBOARDING_AGENT_OPTIONS.map((o) => o.id);
275
+ setCaptureAgents((current) => current.length === allIds.length ? [] : allIds);
276
+ } else setCaptureAgents((current) => current.includes(row.id) ? current.filter((x) => x !== row.id) : [...current, row.id]);
277
+ return;
278
+ }
279
+ if (key.return) {
280
+ if (captureAgents.length === 0) {
281
+ setError("Select at least one agent");
282
+ return;
283
+ }
284
+ pushStep("projects");
285
+ }
286
+ return;
287
+ }
288
+ if (step === "projects") {
186
289
  if (key.upArrow) setSelectedIndex((i) => Math.max(i - 1, 0));
187
- if (key.downArrow) setSelectedIndex((i) => Math.min(i + 1, BOOTSTRAP_OPTIONS.length - 1));
290
+ if (key.downArrow) setSelectedIndex((i) => Math.min(i + 1, projectRows.length - 1));
291
+ if (input === " ") {
292
+ const row = projectRows[selectedIndex];
293
+ setPickedProjects((current) => {
294
+ if (row === ALL_PROJECTS) return current.includes(ALL_PROJECTS) ? [] : [ALL_PROJECTS];
295
+ const without = current.filter((p) => p !== ALL_PROJECTS && p !== row);
296
+ return current.includes(row) ? without : [...without, row];
297
+ });
298
+ setError("");
299
+ return;
300
+ }
301
+ if (key.return) {
302
+ if (pickedProjects.length === 0) {
303
+ setError("Select at least one project (or 'All projects')");
304
+ return;
305
+ }
306
+ setProjectPaths(pickedProjects.includes(ALL_PROJECTS) ? [] : pickedProjects.slice());
307
+ pushStep("capture");
308
+ }
309
+ return;
310
+ }
311
+ if (step === "capture") {
312
+ if (key.upArrow) setSelectedIndex((i) => Math.max(i - 1, 0));
313
+ if (key.downArrow) setSelectedIndex((i) => Math.min(i + 1, ONBOARDING_CAPTURE_OPTIONS.length - 1));
188
314
  if (input === "1") setSelectedIndex(0);
189
315
  if (input === "2") setSelectedIndex(1);
190
- if (input === "3") setSelectedIndex(2);
191
316
  if (key.return || input === " ") {
192
- const chosen = BOOTSTRAP_OPTIONS[selectedIndex].value;
193
- setBootstrapMode(chosen);
194
- finish(apiKey, baseUrl, chosen);
317
+ const chosen = ONBOARDING_CAPTURE_OPTIONS[selectedIndex].id;
318
+ setAutoCaptureMode(chosen);
319
+ finish(apiKey, baseUrl, {
320
+ captureAgents,
321
+ projectPaths,
322
+ autoCaptureMode: chosen
323
+ });
195
324
  }
196
325
  return;
197
326
  }
@@ -202,8 +331,7 @@ function Onboarding({ onDone }) {
202
331
  if (input === "2") setSelectedIndex(1);
203
332
  if (key.return || input === " ") {
204
333
  const chosen = LAUNCH_OPTIONS[selectedIndex].value;
205
- setLaunchTui(chosen);
206
- setStep("done");
334
+ pushStep("done");
207
335
  setTimeout(() => onDone(chosen), 80);
208
336
  }
209
337
  return;
@@ -212,67 +340,93 @@ function Onboarding({ onDone }) {
212
340
  const heroLines = heroArtForWidth(cols - 4);
213
341
  const stepNum = stepNumber(step);
214
342
  const hero = React.createElement(Box, {
215
- flexDirection: "row",
216
- justifyContent: "center",
217
- width: "100%"
218
- }, React.createElement(Spinner, { color: UC_BLUE_LIGHT }), React.createElement(Box, { width: 3 }), React.createElement(Box, {
219
343
  flexDirection: "column",
220
- justifyContent: "center"
344
+ alignItems: "center",
345
+ width: "100%"
221
346
  }, ...heroLines.map((line, i) => React.createElement(Text, {
222
347
  key: `h${i}`,
223
348
  color: "white",
224
349
  bold: true
225
- }, line))));
350
+ }, line)));
226
351
  let content = null;
227
352
  if (step === "welcome") content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
228
353
  color: "white",
229
354
  bold: true
230
- }, "Welcome to UltraContext"), React.createElement(Text, { color: "gray" }, "Context engineering for AI coding agents."), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: UC_BLUE_LIGHT }, "Press Enter to begin setup..."));
355
+ }, "Welcome to UltraContext"), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "white" }, "Press Enter to begin setup..."));
231
356
  if (step === "mode") content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
232
357
  color: "white",
233
358
  bold: true
234
- }, "How do you want to connect?"), React.createElement(Box, { height: 1 }), ...MODE_OPTIONS.map((opt, i) => {
235
- const sel = i === selectedIndex;
236
- return React.createElement(Text, {
237
- key: `m${i}`,
238
- color: sel ? UC_BLUE_LIGHT : "white"
239
- }, sel ? "[•]" : "[ ]", ` ${i + 1}. ${opt.label}`);
240
- }), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "Navigate: up/down, 1/2 | Confirm: Enter"));
359
+ }, "How do you want to connect?"), React.createElement(Box, { height: 1 }), ...MODE_OPTIONS.map((opt, i) => ListRow({
360
+ keyProp: `m${i}`,
361
+ focused: i === selectedIndex,
362
+ label: opt.label
363
+ })), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "↑↓ navigate · enter select"));
241
364
  if (step === "url") content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
242
365
  color: "white",
243
366
  bold: true
244
- }, "Enter your API base URL:"), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: UC_BLUE_LIGHT }, `> ${urlInput}_`), error ? React.createElement(Text, { color: "red" }, error) : null, React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "Enter to confirm | Esc to quit"));
367
+ }, "Enter your API base URL:"), React.createElement(Box, { height: 1 }), React.createElement(Text, {
368
+ color: "white",
369
+ bold: true
370
+ }, `> ${urlInput}_`), error ? React.createElement(Text, { color: "red" }, error) : null, React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "Enter to confirm | Esc to go back"));
245
371
  if (step === "key") {
246
- const keyPrompt = hosting === "cloud" ? "Paste your API key (browser opened for you):" : "Enter your API key:";
372
+ const keyPrompt = hosting === "cloud" ? "Paste your API key from ultracontext.ai:" : "Enter your API key:";
247
373
  content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
248
374
  color: "white",
249
375
  bold: true
250
- }, keyPrompt), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: UC_BLUE_LIGHT }, `> ${keyInput}_`), error ? React.createElement(Text, { color: "red" }, error) : null, React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "Format: uc_live_... or uc_test_... | Enter to confirm"));
376
+ }, keyPrompt), React.createElement(Box, { height: 1 }), React.createElement(Text, {
377
+ color: "white",
378
+ bold: true
379
+ }, `> ${keyInput}_`), error ? React.createElement(Text, { color: "red" }, error) : null, React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "Format: uc_live_... or uc_test_... | Enter to confirm"));
251
380
  }
252
- if (step === "bootstrap") content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
381
+ if (step === "agents") {
382
+ const allChecked = ONBOARDING_AGENT_OPTIONS.every((o) => captureAgents.includes(o.id));
383
+ const selectedCount = captureAgents.length;
384
+ const totalCount = ONBOARDING_AGENT_OPTIONS.length;
385
+ content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
386
+ color: "white",
387
+ bold: true
388
+ }, "Which agents should UltraContext watch?"), React.createElement(Text, { color: "gray" }, `${selectedCount} of ${totalCount} selected`), React.createElement(Box, { height: 1 }), ...AGENT_ROWS.map((opt, i) => ListRow({
389
+ keyProp: `a${i}`,
390
+ focused: i === selectedIndex,
391
+ checked: opt.id === "all" ? allChecked : captureAgents.includes(opt.id),
392
+ label: opt.label,
393
+ multi: true
394
+ })), error ? React.createElement(Text, { color: "red" }, error) : null, React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "↑↓ navigate · space toggle · enter confirm"));
395
+ }
396
+ if (step === "projects") {
397
+ const specificsPicked = pickedProjects.filter((p) => p !== ALL_PROJECTS).length;
398
+ const summary = pickedProjects.includes(ALL_PROJECTS) ? "all projects" : `${specificsPicked} of ${inferredProjects.length} selected`;
399
+ content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
400
+ color: "white",
401
+ bold: true
402
+ }, "Which projects should UltraContext auto-capture?"), React.createElement(Text, { color: "gray" }, `${summary} \u00B7 their agent sessions will be ingested`), React.createElement(Box, { height: 1 }), ...projectRows.map((row, i) => ListRow({
403
+ keyProp: `pr${i}`,
404
+ focused: i === selectedIndex,
405
+ checked: pickedProjects.includes(row),
406
+ label: row === ALL_PROJECTS ? "All projects (recommended)" : row,
407
+ multi: true
408
+ })), inferredProjects.length === 0 ? React.createElement(Text, { color: "gray" }, "(no recent Claude/Cursor projects found — all will be captured)") : null, error ? React.createElement(Text, { color: "red" }, error) : null, React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "↑↓ navigate · space toggle · enter confirm"));
409
+ }
410
+ if (step === "capture") content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
253
411
  color: "white",
254
412
  bold: true
255
- }, "Initial sync mode:"), React.createElement(Box, { height: 1 }), ...BOOTSTRAP_OPTIONS.map((opt, i) => {
256
- const sel = i === selectedIndex;
257
- return React.createElement(Text, {
258
- key: `b${i}`,
259
- color: sel ? UC_BLUE_LIGHT : "white"
260
- }, sel ? "[•]" : "[ ]", ` ${i + 1}. ${opt.label}`);
261
- }), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "Navigate: up/down, 1/2/3 | Confirm: Enter"));
413
+ }, "Auto-capture mode:"), React.createElement(Box, { height: 1 }), ...ONBOARDING_CAPTURE_OPTIONS.map((opt, i) => ListRow({
414
+ keyProp: `c${i}`,
415
+ focused: i === selectedIndex,
416
+ label: opt.label
417
+ })), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "↑↓ navigate · enter select"));
262
418
  if (step === "launch") content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
263
419
  color: "white",
264
420
  bold: true
265
- }, "Launch the TUI dashboard?"), React.createElement(Box, { height: 1 }), ...LAUNCH_OPTIONS.map((opt, i) => {
266
- const sel = i === selectedIndex;
267
- return React.createElement(Text, {
268
- key: `l${i}`,
269
- color: sel ? UC_BLUE_LIGHT : "white"
270
- }, sel ? "[•]" : "[ ]", ` ${i + 1}. ${opt.label}`);
271
- }), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "Navigate: up/down, 1/2 | Confirm: Enter"));
421
+ }, "Launch the TUI dashboard?"), React.createElement(Box, { height: 1 }), ...LAUNCH_OPTIONS.map((opt, i) => ListRow({
422
+ keyProp: `l${i}`,
423
+ focused: i === selectedIndex,
424
+ label: opt.label
425
+ })), React.createElement(Box, { height: 1 }), React.createElement(Text, { color: "gray" }, "↑↓ navigate · enter select"));
272
426
  if (step === "done") content = React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, {
273
427
  color: "green",
274
428
  bold: true
275
- }, "Setup complete!"), React.createElement(Text, { color: "gray" }, `Config saved to ${CONFIG_PATH}`));
429
+ }, "Setup complete!"), React.createElement(Text, { color: "gray" }, `Config saved to ${configPaths().path}`));
276
430
  const boxWidth = Math.min(cols - 2, 60);
277
431
  return React.createElement(Box, {
278
432
  flexDirection: "column",
@@ -281,13 +435,13 @@ function Onboarding({ onDone }) {
281
435
  paddingY: 1,
282
436
  width: cols
283
437
  }, hero, React.createElement(Text, {
284
- color: UC_BLUE_LIGHT,
438
+ color: "white",
285
439
  bold: true
286
- }, "[ The Context Hub for AI Agents ]"), React.createElement(Box, { height: 1 }), React.createElement(TitledBox, {
440
+ }, "[ Same context, everywhere ]"), React.createElement(Box, { height: 1 }), React.createElement(TitledBox, {
287
441
  borderStyle: "single",
288
442
  titles: ["Setup"],
289
443
  titleJustify: "flex-start",
290
- borderColor: UC_BRAND_BLUE,
444
+ borderColor: "white",
291
445
  flexDirection: "column",
292
446
  paddingX: 2,
293
447
  paddingY: 1,
@@ -295,7 +449,10 @@ function Onboarding({ onDone }) {
295
449
  }, React.createElement(Text, {
296
450
  color: "gray",
297
451
  dimColor: true
298
- }, step !== "done" ? `Step ${stepNum} of ${TOTAL_STEPS}` : "Done"), React.createElement(Box, { height: 1 }), content));
452
+ }, step !== "done" ? `Step ${stepNum} of ${TOTAL_STEPS}` : "Done"), step !== "done" && step !== "welcome" ? React.createElement(Text, {
453
+ color: "gray",
454
+ dimColor: true
455
+ }, "← / Esc: back · Ctrl+C: quit") : null, React.createElement(Box, { height: 1 }), content));
299
456
  }
300
457
  function onboard() {
301
458
  return new Promise((resolve) => {