@outlit/cli 1.0.0 → 1.0.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 (2) hide show
  1. package/dist/cli.js +451 -82
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -104,7 +104,7 @@ var package_default;
104
104
  var init_package = __esm(() => {
105
105
  package_default = {
106
106
  name: "@outlit/cli",
107
- version: "1.0.0",
107
+ version: "1.0.1",
108
108
  description: "CLI for Outlit customer intelligence platform",
109
109
  license: "Apache-2.0",
110
110
  repository: {
@@ -157,6 +157,10 @@ function isInteractive() {
157
157
  return false;
158
158
  return true;
159
159
  }
160
+ var isUnicodeSupported;
161
+ var init_tty = __esm(() => {
162
+ isUnicodeSupported = process.platform !== "win32" || Boolean(process.env.WT_SESSION) || process.env.TERM_PROGRAM === "vscode";
163
+ });
160
164
 
161
165
  // src/lib/output.ts
162
166
  function isJsonMode(json) {
@@ -181,7 +185,9 @@ function outputError(error, json) {
181
185
  function errorMessage(err, fallback) {
182
186
  return err instanceof Error ? err.message : fallback;
183
187
  }
184
- var init_output = () => {};
188
+ var init_output = __esm(() => {
189
+ init_tty();
190
+ });
185
191
 
186
192
  // ../../node_modules/.bun/citty@0.2.1/node_modules/citty/dist/index.mjs
187
193
  function defineCommand2(def) {
@@ -1305,6 +1311,7 @@ var init_signup = __esm(() => {
1305
1311
  init_dist();
1306
1312
  init_output2();
1307
1313
  init_output();
1314
+ init_tty();
1308
1315
  signup_default = defineCommand2({
1309
1316
  meta: {
1310
1317
  name: "signup",
@@ -1326,7 +1333,7 @@ var init_signup = __esm(() => {
1326
1333
  return outputResult({ url: OUTLIT_SIGNUP_URL });
1327
1334
  }
1328
1335
  if (isInteractive()) {
1329
- We("Outlit CLI Sign Up");
1336
+ We("Outlit CLI -- Sign Up");
1330
1337
  }
1331
1338
  try {
1332
1339
  if (process.platform === "win32") {
@@ -1437,11 +1444,13 @@ function storeApiKey(apiKey) {
1437
1444
  writeFileSync(credPath, JSON.stringify({ apiKey }, null, 2), { mode: 384 });
1438
1445
  return credPath;
1439
1446
  }
1440
- var CLI_VERSION2, DEFAULT_MCP_URL = "https://mcp.outlit.ai/mcp", DEFAULT_API_URL = "https://app.outlit.ai", OUTLIT_DASHBOARD_URL = "https://app.outlit.ai/workspace-profile", TICK = "\x1B[32m✓\x1B[0m";
1447
+ var CLI_VERSION2, DEFAULT_MCP_URL = "https://mcp.outlit.ai/mcp", DEFAULT_API_URL = "https://app.outlit.ai", OUTLIT_DASHBOARD_URL = "https://app.outlit.ai/workspace-profile", TICK2;
1441
1448
  var init_config = __esm(() => {
1442
1449
  init_package();
1443
1450
  init_output();
1451
+ init_tty();
1444
1452
  CLI_VERSION2 = package_default.version;
1453
+ TICK2 = `\x1B[32m${isUnicodeSupported ? String.fromCodePoint(10003) : String.fromCodePoint(8730)}\x1B[0m`;
1445
1454
  });
1446
1455
 
1447
1456
  // src/lib/client.ts
@@ -1523,30 +1532,62 @@ function createSpinner(message) {
1523
1532
  }
1524
1533
  let frameIndex = 0;
1525
1534
  let text = message;
1535
+ let stopped = false;
1536
+ process.stderr.write(HIDE_CURSOR);
1537
+ const removeSignalHandlers = () => {
1538
+ process.off("SIGINT", onSigint);
1539
+ process.off("SIGTERM", onSigterm);
1540
+ };
1541
+ const cleanup = () => {
1542
+ if (stopped)
1543
+ return;
1544
+ stopped = true;
1545
+ clearInterval(timer);
1546
+ removeSignalHandlers();
1547
+ process.stderr.write(SHOW_CURSOR);
1548
+ };
1549
+ const onSigint = () => {
1550
+ cleanup();
1551
+ process.exit(130);
1552
+ };
1553
+ const onSigterm = () => {
1554
+ cleanup();
1555
+ process.exit(143);
1556
+ };
1557
+ process.on("SIGINT", onSigint);
1558
+ process.on("SIGTERM", onSigterm);
1526
1559
  const timer = setInterval(() => {
1527
1560
  const frame = FRAMES[frameIndex % FRAMES.length];
1528
1561
  process.stderr.write(`\r\x1B[2K ${frame} ${text}`);
1529
1562
  frameIndex++;
1530
1563
  }, INTERVAL_MS);
1564
+ const finish = (symbol, color, msg) => {
1565
+ if (stopped)
1566
+ return;
1567
+ cleanup();
1568
+ process.stderr.write(`\r\x1B[2K ${color}${symbol}\x1B[0m ${msg}
1569
+ `);
1570
+ };
1531
1571
  return {
1532
1572
  update(msg) {
1533
1573
  text = msg;
1534
1574
  },
1535
1575
  stop(msg) {
1536
- clearInterval(timer);
1537
- process.stderr.write(`\r\x1B[2K \x1B[32m✔\x1B[0m ${msg}
1538
- `);
1576
+ finish(SUCCESS_SYMBOL, "\x1B[32m", msg);
1539
1577
  },
1540
1578
  fail(msg) {
1541
- clearInterval(timer);
1542
- process.stderr.write(`\r\x1B[2K \x1B[31m✗\x1B[0m ${msg}
1543
- `);
1579
+ finish(FAIL_SYMBOL, "\x1B[31m", msg);
1544
1580
  }
1545
1581
  };
1546
1582
  }
1547
- var FRAMES, INTERVAL_MS = 80;
1583
+ var UNICODE_FRAMES, ASCII_FRAMES, FRAMES, INTERVAL_MS = 80, SUCCESS_SYMBOL, FAIL_SYMBOL, HIDE_CURSOR = "\x1B[?25l", SHOW_CURSOR = "\x1B[?25h";
1548
1584
  var init_spinner = __esm(() => {
1549
- FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
1585
+ init_tty();
1586
+ UNICODE_FRAMES = [10251, 10265, 10297, 10296, 10300, 10292, 10278, 10279, 10247, 10255].map((cp) => String.fromCodePoint(cp));
1587
+ ASCII_FRAMES = ["-", "\\", "|", "/"];
1588
+ FRAMES = isUnicodeSupported ? UNICODE_FRAMES : ASCII_FRAMES;
1589
+ SUCCESS_SYMBOL = isUnicodeSupported ? String.fromCodePoint(10003) : String.fromCodePoint(8730);
1590
+ FAIL_SYMBOL = isUnicodeSupported ? String.fromCodePoint(10007) : "x";
1550
1591
  });
1551
1592
 
1552
1593
  // src/lib/table.ts
@@ -1554,14 +1595,14 @@ function renderTable(headers, rows, emptyMessage = "(no results)") {
1554
1595
  if (rows.length === 0)
1555
1596
  return emptyMessage;
1556
1597
  const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length)));
1557
- const border = (left, mid, right) => `${left}${widths.map((w) => "─".repeat(w + 2)).join(mid)}${right}`;
1558
- const formatRow = (cells) => `│${cells.map((c, i) => ` ${(c ?? "").padEnd(widths[i] ?? 0)} `).join("│")}│`;
1598
+ const border = (left, mid, right) => `${left}${widths.map((w) => BOX.h.repeat(w + 2)).join(mid)}${right}`;
1599
+ const formatRow = (cells) => `${BOX.v}${cells.map((c, i) => ` ${(c ?? "").padEnd(widths[i] ?? 0)} `).join(BOX.v)}${BOX.v}`;
1559
1600
  return [
1560
- border("┌", "┬", "┐"),
1601
+ border(BOX.tl, BOX.tt, BOX.tr),
1561
1602
  formatRow(headers),
1562
- border("├", "┼", "┤"),
1603
+ border(BOX.lt, BOX.cr, BOX.rt),
1563
1604
  ...rows.map(formatRow),
1564
- border("└", "┴", "┘")
1605
+ border(BOX.bl, BOX.bt, BOX.br)
1565
1606
  ].join(`
1566
1607
  `);
1567
1608
  }
@@ -1573,6 +1614,35 @@ function renderPaginationHint(pagination, itemCount) {
1573
1614
  }
1574
1615
  return `Showing all ${pagination.total} results.`;
1575
1616
  }
1617
+ var BOX;
1618
+ var init_table = __esm(() => {
1619
+ init_tty();
1620
+ BOX = isUnicodeSupported ? {
1621
+ h: String.fromCodePoint(9472),
1622
+ v: String.fromCodePoint(9474),
1623
+ tl: String.fromCodePoint(9484),
1624
+ tr: String.fromCodePoint(9488),
1625
+ bl: String.fromCodePoint(9492),
1626
+ br: String.fromCodePoint(9496),
1627
+ lt: String.fromCodePoint(9500),
1628
+ rt: String.fromCodePoint(9508),
1629
+ tt: String.fromCodePoint(9516),
1630
+ bt: String.fromCodePoint(9524),
1631
+ cr: String.fromCodePoint(9532)
1632
+ } : {
1633
+ h: "-",
1634
+ v: "|",
1635
+ tl: "+",
1636
+ tr: "+",
1637
+ bl: "+",
1638
+ br: "+",
1639
+ lt: "+",
1640
+ rt: "+",
1641
+ tt: "+",
1642
+ bt: "+",
1643
+ cr: "+"
1644
+ };
1645
+ });
1576
1646
 
1577
1647
  // src/lib/api.ts
1578
1648
  async function getClientOrExit(flagApiKey, json) {
@@ -1634,6 +1704,7 @@ var init_api = __esm(() => {
1634
1704
  init_client();
1635
1705
  init_output();
1636
1706
  init_spinner();
1707
+ init_table();
1637
1708
  });
1638
1709
 
1639
1710
  // src/commands/auth/login.ts
@@ -1650,6 +1721,7 @@ var init_login = __esm(() => {
1650
1721
  init_api();
1651
1722
  init_config();
1652
1723
  init_output();
1724
+ init_tty();
1653
1725
  login_default = defineCommand2({
1654
1726
  meta: {
1655
1727
  name: "login",
@@ -1682,7 +1754,7 @@ Format: ok_ followed by 32+ alphanumeric characters.`
1682
1754
  if (!isInteractive()) {
1683
1755
  return outputError({ message: "--key <apiKey> is required in non-interactive mode", code: "missing_key" }, json);
1684
1756
  }
1685
- We("Outlit CLI Login");
1757
+ We("Outlit CLI -- Login");
1686
1758
  const existing = resolveApiKey();
1687
1759
  if (existing) {
1688
1760
  R2.info(`A key from ${existing.source} is already active. Enter a new key to replace it.`);
@@ -1781,7 +1853,7 @@ var init_logout = __esm(() => {
1781
1853
  "Remove the stored Outlit API key.",
1782
1854
  "",
1783
1855
  "Deletes ~/.config/outlit/credentials.json.",
1784
- "Idempotent safe to run even if not logged in.",
1856
+ "Idempotent -- safe to run even if not logged in.",
1785
1857
  "",
1786
1858
  "Note: If OUTLIT_API_KEY env var is set, it continues to work after logout."
1787
1859
  ].join(`
@@ -1808,7 +1880,7 @@ var init_logout = __esm(() => {
1808
1880
  if (isJsonMode(json)) {
1809
1881
  return outputResult({ success: true });
1810
1882
  }
1811
- process.stdout.write(`${TICK} Logged out. Credentials removed from ${credPath}
1883
+ process.stdout.write(`${TICK2} Logged out. Credentials removed from ${credPath}
1812
1884
  `);
1813
1885
  }
1814
1886
  });
@@ -1867,7 +1939,7 @@ var init_status = __esm(() => {
1867
1939
  if (isJsonMode(json)) {
1868
1940
  return outputResult({ authenticated: true, source: credential.source, key: masked });
1869
1941
  }
1870
- console.log(`${TICK} Authenticated
1942
+ console.log(`${TICK2} Authenticated
1871
1943
  Key: ${masked}
1872
1944
  Source: ${credential.source}`);
1873
1945
  }
@@ -1894,7 +1966,7 @@ var init_whoami = __esm(() => {
1894
1966
  "Print the active API key (masked) and its source.",
1895
1967
  "",
1896
1968
  "Validates the key against the Outlit API.",
1897
- "Designed for shell scripting outputs a single line in TTY mode.",
1969
+ "Designed for shell scripting -- outputs a single line in TTY mode.",
1898
1970
  "",
1899
1971
  "Examples:",
1900
1972
  " outlit auth whoami",
@@ -1935,11 +2007,11 @@ var init_auth2 = __esm(() => {
1935
2007
  "Manage Outlit CLI authentication.",
1936
2008
  "",
1937
2009
  "Subcommands:",
1938
- " signup create an Outlit account",
1939
- " login store API key",
1940
- " logout remove stored key",
1941
- " status check current auth state",
1942
- " whoami print masked key for scripting"
2010
+ " signup -- create an Outlit account",
2011
+ " login -- store API key",
2012
+ " logout -- remove stored key",
2013
+ " status -- check current auth state",
2014
+ " whoami -- print masked key for scripting"
1943
2015
  ].join(`
1944
2016
  `)
1945
2017
  },
@@ -2014,7 +2086,7 @@ var init_pagination = __esm(() => {
2014
2086
  paginationArgs = {
2015
2087
  limit: {
2016
2088
  type: "string",
2017
- description: "Max results to return (1100). Default: 20.",
2089
+ description: "Max results to return (1-100). Default: 20.",
2018
2090
  default: "20"
2019
2091
  },
2020
2092
  cursor: {
@@ -2061,7 +2133,9 @@ function truncate(value, maxLen) {
2061
2133
  const str = String(value);
2062
2134
  if (str.length <= maxLen)
2063
2135
  return str;
2064
- return `${str.slice(0, maxLen - 1)}…`;
2136
+ if (maxLen <= 3)
2137
+ return "...".slice(0, maxLen);
2138
+ return `${str.slice(0, maxLen - 3)}...`;
2065
2139
  }
2066
2140
 
2067
2141
  // src/commands/customers/list.ts
@@ -2356,9 +2430,9 @@ var init_customers = __esm(() => {
2356
2430
  "Query and filter your customer base.",
2357
2431
  "",
2358
2432
  "Subcommands:",
2359
- " list list customers with filters",
2360
- " get get a specific customer by ID or domain",
2361
- " timeline show activity timeline for a customer",
2433
+ " list -- list customers with filters",
2434
+ " get -- get a specific customer by ID or domain",
2435
+ " timeline -- show activity timeline for a customer",
2362
2436
  "",
2363
2437
  AGENT_JSON_HINT
2364
2438
  ].join(`
@@ -2467,7 +2541,7 @@ var init_users = __esm(() => {
2467
2541
  "Query and filter users across your customer base.",
2468
2542
  "",
2469
2543
  "Subcommands:",
2470
- " list list users with filters",
2544
+ " list -- list users with filters",
2471
2545
  "",
2472
2546
  AGENT_JSON_HINT
2473
2547
  ].join(`
@@ -2508,7 +2582,7 @@ function runMcpCliSetup(key, json, opts, exitOnError = true) {
2508
2582
  outputResult({ success: true, agent: opts.agentId });
2509
2583
  return { success: true };
2510
2584
  }
2511
- console.log(`${TICK} ${opts.successMessage}`);
2585
+ console.log(`${TICK2} ${opts.successMessage}`);
2512
2586
  }
2513
2587
  return { success: true };
2514
2588
  }
@@ -2530,7 +2604,7 @@ function runMcpFileSetup(key, json, opts, exitOnError = true) {
2530
2604
  outputResult({ success: true, path: opts.configPath, agent: opts.agentId });
2531
2605
  return { success: true };
2532
2606
  }
2533
- console.log(`${TICK} ${opts.successMessage}`);
2607
+ console.log(`${TICK2} ${opts.successMessage}`);
2534
2608
  }
2535
2609
  return { success: true };
2536
2610
  }
@@ -2821,7 +2895,7 @@ var init_openclaw = __esm(() => {
2821
2895
  if (isJsonMode(json)) {
2822
2896
  return outputResult({ success: true, path: skillPath, agent: "openclaw" });
2823
2897
  }
2824
- console.log(`${TICK} Outlit skill written to ${skillPath}. OpenClaw will load it automatically.`);
2898
+ console.log(`${TICK2} Outlit skill written to ${skillPath}. OpenClaw will load it automatically.`);
2825
2899
  }
2826
2900
  });
2827
2901
  });
@@ -2965,7 +3039,7 @@ var init_setup2 = __esm(() => {
2965
3039
  console.log("Detected agents:");
2966
3040
  for (const agentId of detected) {
2967
3041
  const { label, hint } = agentLabels[agentId];
2968
- console.log(` ${TICK} ${label.padEnd(14)} ${hint}`);
3042
+ console.log(` ${TICK2} ${label.padEnd(14)} -- ${hint}`);
2969
3043
  }
2970
3044
  console.log(`
2971
3045
  Configuring...`);
@@ -3041,7 +3115,7 @@ function checkApiKeyPresence(credential) {
3041
3115
  return {
3042
3116
  name: "API key",
3043
3117
  status: "fail",
3044
- message: `Invalid format expected ok_ prefix, got "${credential.key.slice(0, 3)}..."`,
3118
+ message: `Invalid format -- expected ok_ prefix, got "${credential.key.slice(0, 3)}..."`,
3045
3119
  detail: `Get a valid key at ${OUTLIT_DASHBOARD_URL}`
3046
3120
  };
3047
3121
  }
@@ -3150,7 +3224,7 @@ function printChecks(checks) {
3150
3224
  }
3151
3225
  console.log("");
3152
3226
  }
3153
- var STATUS_ICONS, doctor_default, agentChecks;
3227
+ var FAIL_SYMBOL2, STATUS_ICONS, doctor_default, agentChecks;
3154
3228
  var init_doctor = __esm(() => {
3155
3229
  init_dist();
3156
3230
  init_auth();
@@ -3159,10 +3233,12 @@ var init_doctor = __esm(() => {
3159
3233
  init_config();
3160
3234
  init_output();
3161
3235
  init_setup2();
3236
+ init_tty();
3237
+ FAIL_SYMBOL2 = isUnicodeSupported ? String.fromCodePoint(10007) : "x";
3162
3238
  STATUS_ICONS = {
3163
- pass: TICK,
3239
+ pass: TICK2,
3164
3240
  warn: "\x1B[33m!\x1B[0m",
3165
- fail: "\x1B[31m✗\x1B[0m"
3241
+ fail: `\x1B[31m${FAIL_SYMBOL2}\x1B[0m`
3166
3242
  };
3167
3243
  doctor_default = defineCommand2({
3168
3244
  meta: {
@@ -3171,10 +3247,10 @@ var init_doctor = __esm(() => {
3171
3247
  "Check CLI version, API key, connectivity, and agent detection.",
3172
3248
  "",
3173
3249
  "Runs four checks in sequence:",
3174
- " 1. CLI version compares against npm registry",
3175
- " 2. API key checks presence and format (ok_ prefix)",
3176
- " 3. API validation makes a live test call to verify the key works",
3177
- " 4. Agent detection detects OpenClaw, Cursor, Claude Desktop, VS Code",
3250
+ " 1. CLI version -- compares against npm registry",
3251
+ " 2. API key -- checks presence and format (ok_ prefix)",
3252
+ " 3. API validation -- makes a live test call to verify the key works",
3253
+ " 4. Agent detection -- detects OpenClaw, Cursor, Claude Desktop, VS Code",
3178
3254
  "",
3179
3255
  "Exit code: 0 if all checks pass or warn, 1 if any check fails.",
3180
3256
  "",
@@ -3200,7 +3276,7 @@ var init_doctor = __esm(() => {
3200
3276
  if (credential) {
3201
3277
  checks.push(await validateApiKey(credential.key));
3202
3278
  } else {
3203
- checks.push({ name: "API validation", status: "fail", message: "Skipped no API key found" });
3279
+ checks.push({ name: "API validation", status: "fail", message: "Skipped -- no API key found" });
3204
3280
  }
3205
3281
  checks.push(...detectAgents2());
3206
3282
  const hasFail = checks.some((c) => c.status === "fail");
@@ -3502,47 +3578,334 @@ var exports_completions = {};
3502
3578
  __export(exports_completions, {
3503
3579
  default: () => completions_default
3504
3580
  });
3505
- var COMMANDS, cmdNames, BASH_SCRIPT, zshCommands, ZSH_SCRIPT, FISH_SCRIPT, SCRIPTS, completions_default;
3506
- var init_completions = __esm(() => {
3507
- init_dist();
3508
- init_output2();
3509
- init_output();
3510
- COMMANDS = [
3511
- { name: "auth", desc: "Manage authentication" },
3512
- { name: "customers", desc: "Customer operations" },
3513
- { name: "users", desc: "User operations" },
3514
- { name: "facts", desc: "Get customer facts" },
3515
- { name: "search", desc: "Search customer context" },
3516
- { name: "sql", desc: "Execute SQL queries" },
3517
- { name: "schema", desc: "Discover table schemas" },
3518
- { name: "setup", desc: "Configure AI agent tools" },
3519
- { name: "doctor", desc: "Diagnose environment" },
3520
- { name: "completions", desc: "Generate shell completions" }
3521
- ];
3522
- cmdNames = COMMANDS.map((c) => c.name).join(" ");
3523
- BASH_SCRIPT = `_outlit_completions() {
3581
+ function escZsh(s) {
3582
+ return s.replace(/'/g, "'\\''");
3583
+ }
3584
+ function flagNames(flags) {
3585
+ return flags.map((f) => f.name).join(" ");
3586
+ }
3587
+ function generateBash() {
3588
+ const cmdNames = COMMANDS.map((c) => c.name).join(" ");
3589
+ const subCases = cmdsWithSubs.map((c) => {
3590
+ const names = c.subs.map((s) => s.name).join(" ");
3591
+ const parentFlags = c.flags?.length ? ` ${flagNames(c.flags)}` : "";
3592
+ return ` ${c.name}) COMPREPLY=($(compgen -W "${names}${parentFlags}" -- "$cur")) ;;`;
3593
+ }).join(`
3594
+ `);
3595
+ const flagEntries = [];
3596
+ for (const cmd of leafCmds) {
3597
+ flagEntries.push(` ${cmd.name}) COMPREPLY=($(compgen -W "${flagNames(cmd.flags)}" -- "$cur")) ;;`);
3598
+ }
3599
+ for (const cmd of cmdsWithSubs) {
3600
+ for (const sub of cmd.subs) {
3601
+ if (sub.flags?.length) {
3602
+ flagEntries.push(` ${cmd.name}.${sub.name}) COMPREPLY=($(compgen -W "${flagNames(sub.flags)}" -- "$cur")) ;;`);
3603
+ }
3604
+ }
3605
+ }
3606
+ const flagCases = flagEntries.join(`
3607
+ `);
3608
+ return `_outlit_completions() {
3524
3609
  local cur="\${COMP_WORDS[COMP_CWORD]}"
3525
- COMPREPLY=($(compgen -W "${cmdNames}" -- "$cur"))
3610
+ local cmd="\${COMP_WORDS[1]}"
3611
+ local key
3612
+
3613
+ if [[ $COMP_CWORD -eq 1 ]]; then
3614
+ COMPREPLY=($(compgen -W "${cmdNames}" -- "$cur"))
3615
+ return
3616
+ fi
3617
+
3618
+ case $cmd in
3619
+ ${cmdsWithSubs.map((c) => c.name).join("|")})
3620
+ if [[ $COMP_CWORD -eq 2 ]]; then
3621
+ case $cmd in
3622
+ ${subCases}
3623
+ esac
3624
+ return
3625
+ fi
3626
+ key="\${cmd}.\${COMP_WORDS[2]}"
3627
+ ;;
3628
+ *)
3629
+ key=$cmd
3630
+ ;;
3631
+ esac
3632
+
3633
+ case $key in
3634
+ ${flagCases}
3635
+ esac
3526
3636
  }
3527
3637
  complete -F _outlit_completions outlit
3528
3638
  `;
3529
- zshCommands = COMMANDS.map((c) => `'${c.name}:${c.desc.replace(/:/g, "")}'`).join(" ");
3530
- ZSH_SCRIPT = `#compdef outlit
3639
+ }
3640
+ function zshDescribe(items) {
3641
+ return items.map((c) => `'${escZsh(c.name)}:${escZsh(c.desc)}'`).join(" ");
3642
+ }
3643
+ function generateZsh() {
3644
+ const topLevel = zshDescribe(COMMANDS);
3645
+ const subCases = cmdsWithSubs.map((c) => {
3646
+ const items = [...c.subs.map((s) => ({ name: s.name, desc: s.desc })), ...(c.flags ?? []).map((f) => ({ name: f.name, desc: f.desc }))];
3647
+ return ` ${c.name})
3648
+ completions=(${zshDescribe(items)})
3649
+ _describe 'subcommand' completions
3650
+ ;;`;
3651
+ }).join(`
3652
+ `);
3653
+ const flagEntries = [];
3654
+ for (const cmd of leafCmds) {
3655
+ flagEntries.push(` ${cmd.name})
3656
+ completions=(${zshDescribe(cmd.flags)})
3657
+ _describe 'option' completions
3658
+ ;;`);
3659
+ }
3660
+ for (const cmd of cmdsWithSubs) {
3661
+ for (const sub of cmd.subs) {
3662
+ if (sub.flags?.length) {
3663
+ flagEntries.push(` ${cmd.name}.${sub.name})
3664
+ completions=(${zshDescribe(sub.flags)})
3665
+ _describe 'option' completions
3666
+ ;;`);
3667
+ }
3668
+ }
3669
+ }
3670
+ const flagCases = flagEntries.join(`
3671
+ `);
3672
+ return `#compdef outlit
3531
3673
  _outlit() {
3532
- local -a commands
3533
- commands=(${zshCommands})
3534
- _describe 'command' commands
3674
+ local -a completions
3675
+ local cmd=$words[2]
3676
+ local key
3677
+
3678
+ if (( CURRENT == 2 )); then
3679
+ completions=(${topLevel})
3680
+ _describe 'command' completions
3681
+ return
3682
+ fi
3683
+
3684
+ case $cmd in
3685
+ ${cmdsWithSubs.map((c) => c.name).join("|")})
3686
+ if (( CURRENT == 3 )); then
3687
+ case $cmd in
3688
+ ${subCases}
3689
+ esac
3690
+ return
3691
+ fi
3692
+ key="\${cmd}.$words[3]"
3693
+ ;;
3694
+ *)
3695
+ key=$cmd
3696
+ ;;
3697
+ esac
3698
+
3699
+ case $key in
3700
+ ${flagCases}
3701
+ esac
3535
3702
  }
3536
3703
  compdef _outlit outlit
3537
3704
  `;
3538
- FISH_SCRIPT = `# outlit completions for fish shell
3539
- ${COMMANDS.map((c) => `complete -c outlit -f -a ${c.name} -d "${c.desc.replace(/"/g, "\\\"")}"`).join(`
3540
- `)}
3705
+ }
3706
+ function esc(s) {
3707
+ return s.replace(/"/g, "\\\"");
3708
+ }
3709
+ function generateFish() {
3710
+ const lines = [
3711
+ "# outlit completions for fish shell",
3712
+ "",
3713
+ "# Helper: true when commandline starts with the given subcommand path",
3714
+ "function __outlit_using_cmd",
3715
+ " set -l tokens (commandline -opc)",
3716
+ " set -l n (count $argv)",
3717
+ " if test (count $tokens) -le $n",
3718
+ " return 1",
3719
+ " end",
3720
+ " for i in (seq $n)",
3721
+ ' if test "$tokens[(math $i + 1)]" != "$argv[$i]"',
3722
+ " return 1",
3723
+ " end",
3724
+ " end",
3725
+ " return 0",
3726
+ "end",
3727
+ "",
3728
+ "# Top-level commands"
3729
+ ];
3730
+ for (const c of COMMANDS) {
3731
+ lines.push(`complete -c outlit -f -n '__fish_use_subcommand' -a ${c.name} -d "${esc(c.desc)}"`);
3732
+ }
3733
+ for (const cmd of cmdsWithSubs) {
3734
+ lines.push("");
3735
+ lines.push(`# ${cmd.name} subcommands`);
3736
+ for (const sub of cmd.subs) {
3737
+ lines.push(`complete -c outlit -f -n '__outlit_using_cmd ${cmd.name}' -a ${sub.name} -d "${esc(sub.desc)}"`);
3738
+ }
3739
+ }
3740
+ for (const cmd of leafCmds) {
3741
+ lines.push("");
3742
+ lines.push(`# ${cmd.name} flags`);
3743
+ for (const f of cmd.flags) {
3744
+ const long = f.name.replace(/^--/, "");
3745
+ lines.push(`complete -c outlit -n '__outlit_using_cmd ${cmd.name}' -l ${long} -d "${esc(f.desc)}"`);
3746
+ }
3747
+ }
3748
+ for (const cmd of cmdsWithSubs) {
3749
+ if (cmd.flags?.length) {
3750
+ lines.push("");
3751
+ lines.push(`# ${cmd.name} flags`);
3752
+ for (const f of cmd.flags) {
3753
+ const long = f.name.replace(/^--/, "");
3754
+ lines.push(`complete -c outlit -n '__outlit_using_cmd ${cmd.name}' -l ${long} -d "${esc(f.desc)}"`);
3755
+ }
3756
+ }
3757
+ }
3758
+ for (const cmd of cmdsWithSubs) {
3759
+ for (const sub of cmd.subs) {
3760
+ if (sub.flags?.length) {
3761
+ lines.push("");
3762
+ lines.push(`# ${cmd.name} ${sub.name} flags`);
3763
+ for (const f of sub.flags) {
3764
+ const long = f.name.replace(/^--/, "");
3765
+ lines.push(`complete -c outlit -n '__outlit_using_cmd ${cmd.name} ${sub.name}' -l ${long} -d "${esc(f.desc)}"`);
3766
+ }
3767
+ }
3768
+ }
3769
+ }
3770
+ return lines.join(`
3771
+ `) + `
3541
3772
  `;
3773
+ }
3774
+ var JSON_F, API_KEY_F, LIMIT_F, CURSOR_F, COMMON, PAGINATED, ACTIVITY_ORDER, COMMANDS, cmdsWithSubs, leafCmds, SCRIPTS, completions_default;
3775
+ var init_completions = __esm(() => {
3776
+ init_dist();
3777
+ init_output2();
3778
+ init_output();
3779
+ JSON_F = { name: "--json", desc: "Force JSON output" };
3780
+ API_KEY_F = { name: "--api-key", desc: "Outlit API key" };
3781
+ LIMIT_F = { name: "--limit", desc: "Max results (1-100)" };
3782
+ CURSOR_F = { name: "--cursor", desc: "Pagination cursor" };
3783
+ COMMON = [API_KEY_F, JSON_F];
3784
+ PAGINATED = [...COMMON, LIMIT_F, CURSOR_F];
3785
+ ACTIVITY_ORDER = [
3786
+ { name: "--no-activity-in", desc: "No activity in period" },
3787
+ { name: "--has-activity-in", desc: "Activity in period" },
3788
+ { name: "--order-by", desc: "Sort field" },
3789
+ { name: "--order-direction", desc: "Sort direction (asc, desc)" }
3790
+ ];
3791
+ COMMANDS = [
3792
+ {
3793
+ name: "auth",
3794
+ desc: "Manage authentication",
3795
+ subs: [
3796
+ { name: "signup", desc: "Create an Outlit account", flags: [JSON_F] },
3797
+ { name: "login", desc: "Store API key", flags: [JSON_F, { name: "--key", desc: "API key to store" }] },
3798
+ { name: "logout", desc: "Remove stored key", flags: [JSON_F] },
3799
+ { name: "status", desc: "Check auth state", flags: [...COMMON] },
3800
+ { name: "whoami", desc: "Print masked key", flags: [...COMMON] }
3801
+ ]
3802
+ },
3803
+ {
3804
+ name: "customers",
3805
+ desc: "Customer operations",
3806
+ subs: [
3807
+ {
3808
+ name: "list",
3809
+ desc: "List and filter customers",
3810
+ flags: [
3811
+ ...PAGINATED,
3812
+ ...ACTIVITY_ORDER,
3813
+ { name: "--billing-status", desc: "Filter by billing status" },
3814
+ { name: "--mrr-above", desc: "MRR above threshold (cents)" },
3815
+ { name: "--mrr-below", desc: "MRR below threshold (cents)" },
3816
+ { name: "--search", desc: "Search name or domain" },
3817
+ { name: "--status", desc: "Customer status filter" },
3818
+ { name: "--type", desc: "Customer type filter" }
3819
+ ]
3820
+ },
3821
+ {
3822
+ name: "get",
3823
+ desc: "Get customer by ID or domain",
3824
+ flags: [
3825
+ ...COMMON,
3826
+ { name: "--include", desc: "Sections to include" },
3827
+ { name: "--timeframe", desc: "Metrics timeframe" }
3828
+ ]
3829
+ },
3830
+ {
3831
+ name: "timeline",
3832
+ desc: "Show activity timeline",
3833
+ flags: [
3834
+ ...PAGINATED,
3835
+ { name: "--channels", desc: "Filter by channels" },
3836
+ { name: "--event-types", desc: "Filter by event types" },
3837
+ { name: "--timeframe", desc: "Event timeframe" },
3838
+ { name: "--start-date", desc: "Start date (ISO 8601)" },
3839
+ { name: "--end-date", desc: "End date (ISO 8601)" }
3840
+ ]
3841
+ }
3842
+ ]
3843
+ },
3844
+ {
3845
+ name: "users",
3846
+ desc: "User operations",
3847
+ subs: [
3848
+ {
3849
+ name: "list",
3850
+ desc: "List and filter users",
3851
+ flags: [
3852
+ ...PAGINATED,
3853
+ ...ACTIVITY_ORDER,
3854
+ { name: "--journey-stage", desc: "Filter by journey stage" },
3855
+ { name: "--customer-id", desc: "Filter by customer UUID" },
3856
+ { name: "--search", desc: "Search name or email" }
3857
+ ]
3858
+ }
3859
+ ]
3860
+ },
3861
+ {
3862
+ name: "facts",
3863
+ desc: "Get customer facts",
3864
+ flags: [...PAGINATED, { name: "--timeframe", desc: "Lookback window (7d, 30d, 90d)" }]
3865
+ },
3866
+ {
3867
+ name: "search",
3868
+ desc: "Search customer context",
3869
+ flags: [
3870
+ ...COMMON,
3871
+ { name: "--customer", desc: "Scope to customer (UUID or domain)" },
3872
+ { name: "--top-k", desc: "Max results" },
3873
+ { name: "--after", desc: "Events after date (ISO 8601)" },
3874
+ { name: "--before", desc: "Events before date (ISO 8601)" }
3875
+ ]
3876
+ },
3877
+ {
3878
+ name: "sql",
3879
+ desc: "Execute SQL queries",
3880
+ flags: [
3881
+ ...COMMON,
3882
+ { name: "--query-file", desc: "Path to .sql file" },
3883
+ { name: "--limit", desc: "Max rows to return" }
3884
+ ]
3885
+ },
3886
+ { name: "schema", desc: "Discover table schemas", flags: [...COMMON] },
3887
+ {
3888
+ name: "setup",
3889
+ desc: "Configure AI agent tools",
3890
+ flags: [...COMMON, { name: "--yes", desc: "Skip prompts" }],
3891
+ subs: [
3892
+ { name: "cursor", desc: "Configure Cursor", flags: [...COMMON] },
3893
+ { name: "claude-code", desc: "Configure Claude Code", flags: [...COMMON] },
3894
+ { name: "claude-desktop", desc: "Configure Claude Desktop", flags: [...COMMON] },
3895
+ { name: "vscode", desc: "Configure VS Code", flags: [...COMMON] },
3896
+ { name: "gemini", desc: "Configure Gemini CLI", flags: [...COMMON] },
3897
+ { name: "openclaw", desc: "Configure OpenClaw", flags: [...COMMON] }
3898
+ ]
3899
+ },
3900
+ { name: "doctor", desc: "Diagnose environment", flags: [...COMMON] },
3901
+ { name: "completions", desc: "Generate shell completions", flags: [JSON_F] }
3902
+ ];
3903
+ cmdsWithSubs = COMMANDS.filter((c) => c.subs?.length);
3904
+ leafCmds = COMMANDS.filter((c) => !c.subs?.length && c.flags?.length);
3542
3905
  SCRIPTS = {
3543
- bash: BASH_SCRIPT,
3544
- zsh: ZSH_SCRIPT,
3545
- fish: FISH_SCRIPT
3906
+ bash: generateBash,
3907
+ zsh: generateZsh,
3908
+ fish: generateFish
3546
3909
  };
3547
3910
  completions_default = defineCommand2({
3548
3911
  meta: {
@@ -3572,14 +3935,14 @@ ${COMMANDS.map((c) => `complete -c outlit -f -a ${c.name} -d "${c.desc.replace(/
3572
3935
  run({ args }) {
3573
3936
  const json = !!args.json;
3574
3937
  const shell = args.shell;
3575
- const script = SCRIPTS[shell];
3576
- if (!script) {
3938
+ const generate = SCRIPTS[shell];
3939
+ if (!generate) {
3577
3940
  return outputError({
3578
3941
  message: `Unknown shell: ${shell}. Supported: bash, zsh, fish`,
3579
3942
  code: "unknown_shell"
3580
3943
  }, json);
3581
3944
  }
3582
- process.stdout.write(script);
3945
+ process.stdout.write(generate());
3583
3946
  }
3584
3947
  });
3585
3948
  });
@@ -3692,7 +4055,7 @@ var init_setup3 = __esm(() => {
3692
4055
  console.log("Detected agents:");
3693
4056
  for (const agentId of detected) {
3694
4057
  const { label, hint } = agentLabels2[agentId];
3695
- console.log(` ${TICK} ${label.padEnd(14)} ${hint}`);
4058
+ console.log(` ${TICK2} ${label.padEnd(14)} -- ${hint}`);
3696
4059
  }
3697
4060
  console.log(`
3698
4061
  Configuring...`);
@@ -4068,14 +4431,20 @@ async function runMain(cmd, opts = {}) {
4068
4431
  // src/lib/config.ts
4069
4432
  init_package();
4070
4433
  init_output();
4434
+ init_tty();
4071
4435
  var CLI_VERSION = package_default.version;
4436
+ var TICK = `\x1B[32m${isUnicodeSupported ? String.fromCodePoint(10003) : String.fromCodePoint(8730)}\x1B[0m`;
4072
4437
 
4073
4438
  // src/cli.ts
4439
+ if (process.argv.includes("-v")) {
4440
+ console.log(CLI_VERSION);
4441
+ process.exit(0);
4442
+ }
4074
4443
  var main = defineCommand({
4075
4444
  meta: {
4076
4445
  name: "outlit",
4077
4446
  version: CLI_VERSION,
4078
- description: `Outlit CLI \u2014 customer intelligence from the terminal.
4447
+ description: `Outlit CLI -- customer intelligence from the terminal.
4079
4448
 
4080
4449
  Usage examples:
4081
4450
  outlit customers list --billing-status PAYING --no-activity-in 30d
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outlit/cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "CLI for Outlit customer intelligence platform",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {