@claudetools/cli 0.13.13 → 0.13.15

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 (368) hide show
  1. package/dist/__tests__/factories.d.ts +173 -0
  2. package/dist/__tests__/factories.d.ts.map +1 -0
  3. package/dist/__tests__/factories.js +150 -0
  4. package/dist/__tests__/factories.js.map +1 -0
  5. package/dist/__tests__/helpers.d.ts +36 -0
  6. package/dist/__tests__/helpers.d.ts.map +1 -0
  7. package/dist/__tests__/helpers.js +52 -0
  8. package/dist/__tests__/helpers.js.map +1 -0
  9. package/dist/analytics/index.d.ts +14 -0
  10. package/dist/analytics/index.d.ts.map +1 -0
  11. package/dist/analytics/index.js +259 -0
  12. package/dist/analytics/index.js.map +1 -0
  13. package/dist/analytics/session.d.ts +17 -0
  14. package/dist/analytics/session.d.ts.map +1 -0
  15. package/dist/analytics/session.js +130 -0
  16. package/dist/analytics/session.js.map +1 -0
  17. package/dist/analytics/token-tracker.d.ts +48 -0
  18. package/dist/analytics/token-tracker.d.ts.map +1 -0
  19. package/dist/analytics/token-tracker.js +269 -0
  20. package/dist/analytics/token-tracker.js.map +1 -0
  21. package/dist/analytics/tracker.d.ts +33 -0
  22. package/dist/analytics/tracker.d.ts.map +1 -0
  23. package/dist/analytics/tracker.js +210 -0
  24. package/dist/analytics/tracker.js.map +1 -0
  25. package/dist/api-keys/index.d.ts +15 -0
  26. package/dist/api-keys/index.d.ts.map +1 -0
  27. package/dist/api-keys/index.js +228 -0
  28. package/dist/api-keys/index.js.map +1 -0
  29. package/dist/auth/config.d.ts +15 -0
  30. package/dist/auth/config.d.ts.map +1 -0
  31. package/dist/auth/config.js +67 -0
  32. package/dist/auth/config.js.map +1 -0
  33. package/dist/auth/index.d.ts +8 -0
  34. package/dist/auth/index.d.ts.map +1 -0
  35. package/dist/auth/index.js +299 -0
  36. package/dist/auth/index.js.map +1 -0
  37. package/dist/auth/keychain.d.ts +21 -0
  38. package/dist/auth/keychain.d.ts.map +1 -0
  39. package/dist/auth/keychain.js +256 -0
  40. package/dist/auth/keychain.js.map +1 -0
  41. package/dist/billing/index.d.ts +7 -0
  42. package/dist/billing/index.d.ts.map +1 -0
  43. package/dist/billing/index.js +233 -0
  44. package/dist/billing/index.js.map +1 -0
  45. package/dist/cli.js +291 -43
  46. package/dist/cli.js.map +1 -1
  47. package/dist/commands/hook.d.ts +12 -0
  48. package/dist/commands/hook.d.ts.map +1 -0
  49. package/dist/commands/hook.js +190 -0
  50. package/dist/commands/hook.js.map +1 -0
  51. package/dist/commands/keys.d.ts +4 -0
  52. package/dist/commands/keys.d.ts.map +1 -0
  53. package/dist/commands/keys.js +43 -0
  54. package/dist/commands/keys.js.map +1 -0
  55. package/dist/commands/mcp.d.ts +4 -0
  56. package/dist/commands/mcp.d.ts.map +1 -0
  57. package/dist/commands/mcp.js +43 -0
  58. package/dist/commands/mcp.js.map +1 -0
  59. package/dist/commands/project.d.ts +4 -0
  60. package/dist/commands/project.d.ts.map +1 -0
  61. package/dist/commands/project.js +68 -0
  62. package/dist/commands/project.js.map +1 -0
  63. package/dist/commands/skill.d.ts +4 -0
  64. package/dist/commands/skill.d.ts.map +1 -0
  65. package/dist/commands/skill.js +37 -0
  66. package/dist/commands/skill.js.map +1 -0
  67. package/dist/commands/stacks.d.ts +4 -0
  68. package/dist/commands/stacks.d.ts.map +1 -0
  69. package/dist/commands/stacks.js +103 -0
  70. package/dist/commands/stacks.js.map +1 -0
  71. package/dist/commands/stats.d.ts +4 -0
  72. package/dist/commands/stats.d.ts.map +1 -0
  73. package/dist/commands/stats.js +6 -0
  74. package/dist/commands/stats.js.map +1 -0
  75. package/dist/commands/sync.d.ts +4 -0
  76. package/dist/commands/sync.d.ts.map +1 -0
  77. package/dist/commands/sync.js +60 -0
  78. package/dist/commands/sync.js.map +1 -0
  79. package/dist/commands/update.d.ts +4 -0
  80. package/dist/commands/update.d.ts.map +1 -0
  81. package/dist/commands/update.js +63 -0
  82. package/dist/commands/update.js.map +1 -0
  83. package/dist/daemon/client.d.ts +107 -0
  84. package/dist/daemon/client.d.ts.map +1 -0
  85. package/dist/daemon/client.js +250 -0
  86. package/dist/daemon/client.js.map +1 -0
  87. package/dist/daemon/health.d.ts +38 -0
  88. package/dist/daemon/health.d.ts.map +1 -0
  89. package/dist/daemon/health.js +212 -0
  90. package/dist/daemon/health.js.map +1 -0
  91. package/dist/daemon/index.d.ts +34 -0
  92. package/dist/daemon/index.d.ts.map +1 -0
  93. package/dist/daemon/index.js +197 -0
  94. package/dist/daemon/index.js.map +1 -0
  95. package/dist/daemon/protocol.d.ts +144 -0
  96. package/dist/daemon/protocol.d.ts.map +1 -0
  97. package/dist/daemon/protocol.js +5 -0
  98. package/dist/daemon/protocol.js.map +1 -0
  99. package/dist/gamification/index.d.ts +13 -0
  100. package/dist/gamification/index.d.ts.map +1 -0
  101. package/dist/gamification/index.js +120 -0
  102. package/dist/gamification/index.js.map +1 -0
  103. package/dist/gamification/types.d.ts +34 -0
  104. package/dist/gamification/types.d.ts.map +1 -0
  105. package/dist/gamification/types.js +5 -0
  106. package/dist/gamification/types.js.map +1 -0
  107. package/dist/hooks/index.d.ts +65 -0
  108. package/dist/hooks/index.d.ts.map +1 -0
  109. package/dist/hooks/index.js +403 -0
  110. package/dist/hooks/index.js.map +1 -0
  111. package/dist/lib/api.d.ts +29 -0
  112. package/dist/lib/api.d.ts.map +1 -0
  113. package/dist/lib/api.js +213 -0
  114. package/dist/lib/api.js.map +1 -0
  115. package/dist/lib/browser.d.ts +6 -0
  116. package/dist/lib/browser.d.ts.map +1 -0
  117. package/dist/lib/browser.js +14 -0
  118. package/dist/lib/browser.js.map +1 -0
  119. package/dist/lib/channel-config.d.ts +10 -0
  120. package/dist/lib/channel-config.d.ts.map +1 -0
  121. package/dist/lib/channel-config.js +48 -0
  122. package/dist/lib/channel-config.js.map +1 -0
  123. package/dist/lib/command-runner.d.ts +16 -0
  124. package/dist/lib/command-runner.d.ts.map +1 -0
  125. package/dist/lib/command-runner.js +59 -0
  126. package/dist/lib/command-runner.js.map +1 -0
  127. package/dist/lib/command-utils.d.ts +22 -0
  128. package/dist/lib/command-utils.d.ts.map +1 -0
  129. package/dist/lib/command-utils.js +88 -0
  130. package/dist/lib/command-utils.js.map +1 -0
  131. package/dist/lib/error-handler.d.ts +13 -0
  132. package/dist/lib/error-handler.d.ts.map +1 -0
  133. package/dist/lib/error-handler.js +70 -0
  134. package/dist/lib/error-handler.js.map +1 -0
  135. package/dist/lib/errors.d.ts +35 -0
  136. package/dist/lib/errors.d.ts.map +1 -0
  137. package/dist/lib/errors.js +70 -0
  138. package/dist/lib/errors.js.map +1 -0
  139. package/dist/lib/exit.d.ts +10 -0
  140. package/dist/lib/exit.d.ts.map +1 -0
  141. package/dist/lib/exit.js +21 -0
  142. package/dist/lib/exit.js.map +1 -0
  143. package/dist/lib/formatters.d.ts +65 -0
  144. package/dist/lib/formatters.d.ts.map +1 -0
  145. package/dist/lib/formatters.js +180 -0
  146. package/dist/lib/formatters.js.map +1 -0
  147. package/dist/lib/hybrid-data.d.ts +47 -0
  148. package/dist/lib/hybrid-data.d.ts.map +1 -0
  149. package/dist/lib/hybrid-data.js +326 -0
  150. package/dist/lib/hybrid-data.js.map +1 -0
  151. package/dist/lib/local-store.d.ts +113 -0
  152. package/dist/lib/local-store.d.ts.map +1 -0
  153. package/dist/lib/local-store.js +220 -0
  154. package/dist/lib/local-store.js.map +1 -0
  155. package/dist/lib/machine-id.d.ts +8 -0
  156. package/dist/lib/machine-id.d.ts.map +1 -0
  157. package/dist/lib/machine-id.js +39 -0
  158. package/dist/lib/machine-id.js.map +1 -0
  159. package/dist/lib/network.d.ts +15 -0
  160. package/dist/lib/network.d.ts.map +1 -0
  161. package/dist/lib/network.js +46 -0
  162. package/dist/lib/network.js.map +1 -0
  163. package/dist/lib/theme.d.ts +77 -0
  164. package/dist/lib/theme.d.ts.map +1 -0
  165. package/dist/lib/theme.js +137 -0
  166. package/dist/lib/theme.js.map +1 -0
  167. package/dist/lib/tool-availability.d.ts +13 -0
  168. package/dist/lib/tool-availability.d.ts.map +1 -0
  169. package/dist/lib/tool-availability.js +48 -0
  170. package/dist/lib/tool-availability.js.map +1 -0
  171. package/dist/lib/update-checker.d.ts +21 -0
  172. package/dist/lib/update-checker.d.ts.map +1 -0
  173. package/dist/lib/update-checker.js +110 -0
  174. package/dist/lib/update-checker.js.map +1 -0
  175. package/dist/lib/validation.d.ts +30 -0
  176. package/dist/lib/validation.d.ts.map +1 -0
  177. package/dist/lib/validation.js +82 -0
  178. package/dist/lib/validation.js.map +1 -0
  179. package/dist/lib/validators.d.ts +18 -0
  180. package/dist/lib/validators.d.ts.map +1 -0
  181. package/dist/lib/validators.js +30 -0
  182. package/dist/lib/validators.js.map +1 -0
  183. package/dist/marketplace/api.d.ts +24 -0
  184. package/dist/marketplace/api.d.ts.map +1 -0
  185. package/dist/marketplace/api.js +92 -0
  186. package/dist/marketplace/api.js.map +1 -0
  187. package/dist/marketplace/index.d.ts +13 -0
  188. package/dist/marketplace/index.d.ts.map +1 -0
  189. package/dist/marketplace/index.js +155 -0
  190. package/dist/marketplace/index.js.map +1 -0
  191. package/dist/marketplace/installer.d.ts +18 -0
  192. package/dist/marketplace/installer.d.ts.map +1 -0
  193. package/dist/marketplace/installer.js +184 -0
  194. package/dist/marketplace/installer.js.map +1 -0
  195. package/dist/mcp/api.d.ts +93 -0
  196. package/dist/mcp/api.d.ts.map +1 -0
  197. package/dist/mcp/api.js +106 -0
  198. package/dist/mcp/api.js.map +1 -0
  199. package/dist/mcp/config.d.ts +72 -0
  200. package/dist/mcp/config.d.ts.map +1 -0
  201. package/dist/mcp/config.js +156 -0
  202. package/dist/mcp/config.js.map +1 -0
  203. package/dist/mcp/index.d.ts +54 -0
  204. package/dist/mcp/index.d.ts.map +1 -0
  205. package/dist/mcp/index.js +381 -0
  206. package/dist/mcp/index.js.map +1 -0
  207. package/dist/mcp/prompt.clean.d.ts +25 -0
  208. package/dist/mcp/prompt.clean.d.ts.map +1 -0
  209. package/dist/mcp/prompt.clean.js +206 -0
  210. package/dist/mcp/prompt.clean.js.map +1 -0
  211. package/dist/mcp/prompt.d.ts +52 -0
  212. package/dist/mcp/prompt.d.ts.map +1 -0
  213. package/dist/mcp/prompt.js +210 -0
  214. package/dist/mcp/prompt.js.map +1 -0
  215. package/dist/mcp/secrets.clean.d.ts +18 -0
  216. package/dist/mcp/secrets.clean.d.ts.map +1 -0
  217. package/dist/mcp/secrets.clean.js +357 -0
  218. package/dist/mcp/secrets.clean.js.map +1 -0
  219. package/dist/mcp/secrets.d.ts +46 -0
  220. package/dist/mcp/secrets.d.ts.map +1 -0
  221. package/dist/mcp/secrets.js +339 -0
  222. package/dist/mcp/secrets.js.map +1 -0
  223. package/dist/memory/index.d.ts +14 -0
  224. package/dist/memory/index.d.ts.map +1 -0
  225. package/dist/memory/index.js +98 -0
  226. package/dist/memory/index.js.map +1 -0
  227. package/dist/onboard/agents-md-builder.d.ts.map +1 -1
  228. package/dist/onboard/agents-md-builder.js +45 -0
  229. package/dist/onboard/agents-md-builder.js.map +1 -1
  230. package/dist/onboard/claude-inference.d.ts.map +1 -1
  231. package/dist/onboard/claude-inference.js +15 -4
  232. package/dist/onboard/claude-inference.js.map +1 -1
  233. package/dist/onboard/context7-fetcher.d.ts +1 -1
  234. package/dist/onboard/context7-fetcher.d.ts.map +1 -1
  235. package/dist/onboard/context7-fetcher.js +50 -16
  236. package/dist/onboard/context7-fetcher.js.map +1 -1
  237. package/dist/onboard/docs-builder.d.ts.map +1 -1
  238. package/dist/onboard/docs-builder.js +523 -50
  239. package/dist/onboard/docs-builder.js.map +1 -1
  240. package/dist/onboard/index.d.ts.map +1 -1
  241. package/dist/onboard/index.js +74 -25
  242. package/dist/onboard/index.js.map +1 -1
  243. package/dist/onboard/stack-detector.d.ts.map +1 -1
  244. package/dist/onboard/stack-detector.js +5 -55
  245. package/dist/onboard/stack-detector.js.map +1 -1
  246. package/dist/project/constants.d.ts +21 -0
  247. package/dist/project/constants.d.ts.map +1 -0
  248. package/dist/project/constants.js +21 -0
  249. package/dist/project/constants.js.map +1 -0
  250. package/dist/project/format.d.ts +16 -0
  251. package/dist/project/format.d.ts.map +1 -0
  252. package/dist/project/format.js +40 -0
  253. package/dist/project/format.js.map +1 -0
  254. package/dist/project/git.d.ts +28 -0
  255. package/dist/project/git.d.ts.map +1 -0
  256. package/dist/project/git.js +93 -0
  257. package/dist/project/git.js.map +1 -0
  258. package/dist/project/index.d.ts +36 -0
  259. package/dist/project/index.d.ts.map +1 -0
  260. package/dist/project/index.js +272 -0
  261. package/dist/project/index.js.map +1 -0
  262. package/dist/project/mapper.d.ts +27 -0
  263. package/dist/project/mapper.d.ts.map +1 -0
  264. package/dist/project/mapper.js +64 -0
  265. package/dist/project/mapper.js.map +1 -0
  266. package/dist/project/storage.d.ts +71 -0
  267. package/dist/project/storage.d.ts.map +1 -0
  268. package/dist/project/storage.js +274 -0
  269. package/dist/project/storage.js.map +1 -0
  270. package/dist/project/sync-bridge.d.ts +33 -0
  271. package/dist/project/sync-bridge.d.ts.map +1 -0
  272. package/dist/project/sync-bridge.js +155 -0
  273. package/dist/project/sync-bridge.js.map +1 -0
  274. package/dist/project/types.d.ts +107 -0
  275. package/dist/project/types.d.ts.map +1 -0
  276. package/dist/project/types.js +77 -0
  277. package/dist/project/types.js.map +1 -0
  278. package/dist/publish/index.d.ts +4 -0
  279. package/dist/publish/index.d.ts.map +1 -0
  280. package/dist/publish/index.js +92 -0
  281. package/dist/publish/index.js.map +1 -0
  282. package/dist/setup.d.ts.map +1 -1
  283. package/dist/setup.js +29 -10
  284. package/dist/setup.js.map +1 -1
  285. package/dist/skills/index.d.ts +51 -0
  286. package/dist/skills/index.d.ts.map +1 -0
  287. package/dist/skills/index.js +509 -0
  288. package/dist/skills/index.js.map +1 -0
  289. package/dist/stacks/check.d.ts +2 -0
  290. package/dist/stacks/check.d.ts.map +1 -0
  291. package/dist/stacks/check.js +144 -0
  292. package/dist/stacks/check.js.map +1 -0
  293. package/dist/stacks/diff.d.ts +11 -0
  294. package/dist/stacks/diff.d.ts.map +1 -0
  295. package/dist/stacks/diff.js +123 -0
  296. package/dist/stacks/diff.js.map +1 -0
  297. package/dist/stacks/index.d.ts +17 -0
  298. package/dist/stacks/index.d.ts.map +1 -0
  299. package/dist/stacks/index.js +525 -0
  300. package/dist/stacks/index.js.map +1 -0
  301. package/dist/stacks/index.refactored.d.ts.map +1 -0
  302. package/dist/stacks/index.refactored.js.map +1 -0
  303. package/dist/stacks/io.d.ts +11 -0
  304. package/dist/stacks/io.d.ts.map +1 -0
  305. package/dist/stacks/io.js +179 -0
  306. package/dist/stacks/io.js.map +1 -0
  307. package/dist/stacks/rollback.d.ts +5 -0
  308. package/dist/stacks/rollback.d.ts.map +1 -0
  309. package/dist/stacks/rollback.js +162 -0
  310. package/dist/stacks/rollback.js.map +1 -0
  311. package/dist/stacks/types.d.ts +70 -0
  312. package/dist/stacks/types.d.ts.map +1 -0
  313. package/dist/stacks/types.js +6 -0
  314. package/dist/stacks/types.js.map +1 -0
  315. package/dist/stacks/utils.d.ts +9 -0
  316. package/dist/stacks/utils.d.ts.map +1 -0
  317. package/dist/stacks/utils.js +11 -0
  318. package/dist/stacks/utils.js.map +1 -0
  319. package/dist/start/index.d.ts +23 -0
  320. package/dist/start/index.d.ts.map +1 -0
  321. package/dist/start/index.js +386 -0
  322. package/dist/start/index.js.map +1 -0
  323. package/dist/sync/index.d.ts +49 -0
  324. package/dist/sync/index.d.ts.map +1 -0
  325. package/dist/sync/index.js +207 -0
  326. package/dist/sync/index.js.map +1 -0
  327. package/dist/sync-engine/__tests__/test-helpers.d.ts +14 -0
  328. package/dist/sync-engine/__tests__/test-helpers.d.ts.map +1 -0
  329. package/dist/sync-engine/__tests__/test-helpers.js +73 -0
  330. package/dist/sync-engine/__tests__/test-helpers.js.map +1 -0
  331. package/dist/sync-engine/client.d.ts +128 -0
  332. package/dist/sync-engine/client.d.ts.map +1 -0
  333. package/dist/sync-engine/client.js +289 -0
  334. package/dist/sync-engine/client.js.map +1 -0
  335. package/dist/sync-engine/health.d.ts +38 -0
  336. package/dist/sync-engine/health.d.ts.map +1 -0
  337. package/dist/sync-engine/health.js +259 -0
  338. package/dist/sync-engine/health.js.map +1 -0
  339. package/dist/sync-engine/index.d.ts +34 -0
  340. package/dist/sync-engine/index.d.ts.map +1 -0
  341. package/dist/sync-engine/index.js +197 -0
  342. package/dist/sync-engine/index.js.map +1 -0
  343. package/dist/sync-engine/protocol.d.ts +153 -0
  344. package/dist/sync-engine/protocol.d.ts.map +1 -0
  345. package/dist/sync-engine/protocol.js +5 -0
  346. package/dist/sync-engine/protocol.js.map +1 -0
  347. package/dist/tasks/index.d.ts +14 -0
  348. package/dist/tasks/index.d.ts.map +1 -0
  349. package/dist/tasks/index.js +109 -0
  350. package/dist/tasks/index.js.map +1 -0
  351. package/dist/team/index.d.ts +12 -0
  352. package/dist/team/index.d.ts.map +1 -0
  353. package/dist/team/index.js +151 -0
  354. package/dist/team/index.js.map +1 -0
  355. package/dist/updater.d.ts +5 -5
  356. package/dist/updater.d.ts.map +1 -1
  357. package/dist/updater.js +24 -88
  358. package/dist/updater.js.map +1 -1
  359. package/dist/usage/index.d.ts +10 -0
  360. package/dist/usage/index.d.ts.map +1 -0
  361. package/dist/usage/index.js +104 -0
  362. package/dist/usage/index.js.map +1 -0
  363. package/dist/webhooks/index.d.ts +7 -0
  364. package/dist/webhooks/index.d.ts.map +1 -0
  365. package/dist/webhooks/index.js +81 -0
  366. package/dist/webhooks/index.js.map +1 -0
  367. package/package.json +26 -15
  368. package/scripts/postinstall.js +282 -0
@@ -0,0 +1,228 @@
1
+ import ora from 'ora';
2
+ import { getApiClient, ApiError } from '../lib/api.js';
3
+ import { requireAuth } from '../auth/config.js';
4
+ import { getCredential } from '../auth/keychain.js';
5
+ import { theme, formatError, formatWarning } from '../lib/theme.js';
6
+ import * as readline from 'readline';
7
+ /**
8
+ * Mask an API key for display
9
+ */
10
+ function maskKey(keyPrefix) {
11
+ return `${keyPrefix}****`;
12
+ }
13
+ /**
14
+ * Prompt for confirmation
15
+ */
16
+ async function confirm(question) {
17
+ const rl = readline.createInterface({
18
+ input: process.stdin,
19
+ output: process.stdout,
20
+ });
21
+ return new Promise((resolve) => {
22
+ rl.question(`${question} (y/N) `, (answer) => {
23
+ rl.close();
24
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
25
+ });
26
+ });
27
+ }
28
+ /**
29
+ * List all API keys
30
+ */
31
+ export async function runKeysList() {
32
+ await requireAuth();
33
+ const spinner = ora('Loading API keys...').start();
34
+ try {
35
+ const api = getApiClient();
36
+ const { data } = await api.get('/keys');
37
+ if (!data) {
38
+ spinner.fail('Failed to load API keys');
39
+ console.error(` ${formatError('No data received from server', 'ERR_NO_DATA')}`);
40
+ process.exit(1);
41
+ }
42
+ spinner.stop();
43
+ console.log();
44
+ console.log(` ${theme.bold('API Keys')}`);
45
+ const keysLimitDisplay = data.quota.limit === null ? 'unlimited' : String(data.quota.limit);
46
+ console.log(` ${theme.muted(`${data.quota.used}/${keysLimitDisplay} keys used`)}`);
47
+ console.log();
48
+ if (data.keys.length === 0) {
49
+ console.log(` ${theme.muted('No API keys created yet.')}`);
50
+ console.log();
51
+ console.log(` ${theme.muted(`Run ${theme.command('claudetools keys create <name>')} to create one.`)}`);
52
+ console.log();
53
+ return;
54
+ }
55
+ // Get current key to mark it
56
+ const currentKey = await getCredential();
57
+ const currentKeyPrefix = currentKey ? currentKey.substring(0, 8) : null;
58
+ // Display keys
59
+ data.keys.forEach((key) => {
60
+ const isCurrent = currentKeyPrefix && key.keyPrefix === currentKeyPrefix;
61
+ const indicator = isCurrent ? theme.success('*') : ' ';
62
+ const maskedKey = maskKey(key.keyPrefix);
63
+ const lastUsed = key.lastUsedAt
64
+ ? new Date(key.lastUsedAt).toLocaleDateString()
65
+ : 'Never';
66
+ console.log(` ${indicator} ${theme.bold(key.name)}`);
67
+ console.log(` ${theme.muted('Key:')} ${maskedKey}`);
68
+ console.log(` ${theme.muted('ID:')} ${key.id}`);
69
+ console.log(` ${theme.muted('Last used:')} ${lastUsed}`);
70
+ console.log(` ${theme.muted('Created:')} ${new Date(key.createdAt).toLocaleDateString()}`);
71
+ console.log();
72
+ });
73
+ if (currentKeyPrefix) {
74
+ console.log(` ${theme.muted('* = Currently active key')}`);
75
+ console.log();
76
+ }
77
+ }
78
+ catch (error) {
79
+ spinner.fail('Failed to load API keys');
80
+ if (error instanceof ApiError && error.code === 'AUTH_REQUIRED') {
81
+ console.log();
82
+ console.log(` ${formatWarning('Session expired. Please log in again.')}`);
83
+ console.log(` ${theme.muted(`Run ${theme.command('claudetools login')}`)}`);
84
+ console.log();
85
+ }
86
+ else {
87
+ console.error(` ${formatError(error instanceof Error ? error.message : 'Unknown error', 'ERR_API')}`);
88
+ }
89
+ process.exit(1);
90
+ }
91
+ }
92
+ /**
93
+ * Create a new API key
94
+ */
95
+ export async function runKeysCreate(name) {
96
+ await requireAuth();
97
+ if (!name) {
98
+ console.log();
99
+ console.log(` ${formatError('Key name is required', 'ERR_MISSING_NAME')}`);
100
+ console.log();
101
+ console.log(` ${theme.muted('Usage: claudetools keys create <name>')}`);
102
+ console.log();
103
+ process.exit(1);
104
+ }
105
+ const spinner = ora(`Creating API key "${name}"...`).start();
106
+ try {
107
+ const api = getApiClient();
108
+ const { data } = await api.post('/keys', {
109
+ name,
110
+ scopes: ['*'], // Default to all scopes
111
+ });
112
+ if (!data) {
113
+ spinner.fail('Failed to create API key');
114
+ console.error(` ${formatError('No data received from server', 'ERR_NO_DATA')}`);
115
+ process.exit(1);
116
+ }
117
+ spinner.succeed(`API key "${name}" created`);
118
+ console.log();
119
+ console.log(` ${theme.warning(theme.bold('Save this key now - it will not be shown again!'))}`);
120
+ console.log();
121
+ console.log(` ${theme.bold('Your API key:')}`);
122
+ console.log(` ${theme.success(data.key)}`);
123
+ console.log();
124
+ console.log(` ${theme.muted('Copy to clipboard:')}`);
125
+ console.log(` ${theme.muted(`echo "${data.key}" | pbcopy`)}`);
126
+ console.log();
127
+ }
128
+ catch (error) {
129
+ spinner.fail('Failed to create API key');
130
+ if (error instanceof ApiError && error.code === 'AUTH_REQUIRED') {
131
+ console.log();
132
+ console.log(` ${formatWarning('Session expired. Please log in again.')}`);
133
+ console.log(` ${theme.muted(`Run ${theme.command('claudetools login')}`)}`);
134
+ console.log();
135
+ }
136
+ else if (error instanceof ApiError && error.code === 'QUOTA_EXCEEDED') {
137
+ console.log();
138
+ console.log(` ${formatWarning('API key quota exceeded.')}`);
139
+ console.log(` ${theme.muted('Delete an existing key or upgrade your plan.')}`);
140
+ console.log();
141
+ }
142
+ else {
143
+ console.error(` ${formatError(error instanceof Error ? error.message : 'Unknown error', 'ERR_API')}`);
144
+ }
145
+ process.exit(1);
146
+ }
147
+ }
148
+ /**
149
+ * Revoke an API key
150
+ */
151
+ export async function runKeysRevoke(keyId, options = {}) {
152
+ await requireAuth();
153
+ if (!keyId) {
154
+ console.log();
155
+ console.log(` ${formatError('Key ID is required', 'ERR_MISSING_ID')}`);
156
+ console.log();
157
+ console.log(` ${theme.muted('Usage: claudetools keys revoke <id>')}`);
158
+ console.log(` ${theme.muted(`Run ${theme.command('claudetools keys list')} to see key IDs`)}`);
159
+ console.log();
160
+ process.exit(1);
161
+ }
162
+ // Check if trying to revoke current key
163
+ const currentKey = await getCredential();
164
+ if (currentKey) {
165
+ // Get the key details first to check the prefix
166
+ const spinner = ora('Checking key...').start();
167
+ try {
168
+ const api = getApiClient();
169
+ const { data } = await api.get('/keys');
170
+ spinner.stop();
171
+ if (data) {
172
+ const keyToRevoke = data.keys.find(k => k.id === keyId);
173
+ if (keyToRevoke) {
174
+ const currentKeyPrefix = currentKey.substring(0, 8);
175
+ if (keyToRevoke.keyPrefix === currentKeyPrefix) {
176
+ console.log();
177
+ console.log(` ${formatError('Cannot revoke the currently active key', 'ERR_ACTIVE_KEY')}`);
178
+ console.log(` ${theme.muted('Log in with a different key or create a new one first')}`);
179
+ console.log();
180
+ process.exit(1);
181
+ }
182
+ }
183
+ }
184
+ }
185
+ catch {
186
+ spinner.stop();
187
+ // Continue - we'll let the API handle validation
188
+ }
189
+ }
190
+ // Prompt for confirmation unless --force
191
+ if (!options.force) {
192
+ console.log();
193
+ const confirmed = await confirm(` ${theme.warning('Are you sure you want to revoke this API key?')}`);
194
+ if (!confirmed) {
195
+ console.log();
196
+ console.log(` ${theme.muted('Cancelled.')}`);
197
+ console.log();
198
+ return;
199
+ }
200
+ }
201
+ const spinner = ora('Revoking API key...').start();
202
+ try {
203
+ const api = getApiClient();
204
+ await api.delete(`/keys/${keyId}`);
205
+ spinner.succeed('API key revoked');
206
+ console.log();
207
+ }
208
+ catch (error) {
209
+ spinner.fail('Failed to revoke API key');
210
+ if (error instanceof ApiError && error.code === 'AUTH_REQUIRED') {
211
+ console.log();
212
+ console.log(` ${formatWarning('Session expired. Please log in again.')}`);
213
+ console.log(` ${theme.muted(`Run ${theme.command('claudetools login')}`)}`);
214
+ console.log();
215
+ }
216
+ else if (error instanceof ApiError && error.code === 'NOT_FOUND') {
217
+ console.log();
218
+ console.log(` ${formatWarning('Key not found.')}`);
219
+ console.log(` ${theme.muted(`Run ${theme.command('claudetools keys list')} to see available keys`)}`);
220
+ console.log();
221
+ }
222
+ else {
223
+ console.error(` ${formatError(error instanceof Error ? error.message : 'Unknown error', 'ERR_API')}`);
224
+ }
225
+ process.exit(1);
226
+ }
227
+ }
228
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api-keys/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface UserConfig {
2
+ userId?: string;
3
+ email?: string;
4
+ name?: string;
5
+ tier?: string;
6
+ activeTeam?: string;
7
+ tokenExpiresAt?: number;
8
+ }
9
+ export declare function loadConfig(): UserConfig;
10
+ export declare function saveConfig(config: UserConfig): void;
11
+ export declare function clearConfig(): void;
12
+ export declare function isLoggedIn(): Promise<boolean>;
13
+ export declare function requireAuth(): Promise<UserConfig>;
14
+ export declare function getConfigDir(): string;
15
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/auth/config.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAQD,wBAAgB,UAAU,IAAI,UAAU,CAUvC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAOnD;AAED,wBAAgB,WAAW,IAAI,IAAI,CAQlC;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAanD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,UAAU,CAAC,CASvD;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
@@ -0,0 +1,67 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
2
+ import { homedir } from 'os';
3
+ import { join } from 'path';
4
+ import { hasCredential } from './keychain.js';
5
+ const CONFIG_DIR = join(homedir(), '.claudetools');
6
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
7
+ function ensureConfigDir() {
8
+ if (!existsSync(CONFIG_DIR)) {
9
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
10
+ }
11
+ }
12
+ export function loadConfig() {
13
+ try {
14
+ if (!existsSync(CONFIG_FILE)) {
15
+ return {};
16
+ }
17
+ const content = readFileSync(CONFIG_FILE, 'utf-8');
18
+ return JSON.parse(content);
19
+ }
20
+ catch {
21
+ return {};
22
+ }
23
+ }
24
+ export function saveConfig(config) {
25
+ ensureConfigDir();
26
+ const existing = loadConfig();
27
+ const merged = { ...existing, ...config };
28
+ writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2), {
29
+ mode: 0o600,
30
+ });
31
+ }
32
+ export function clearConfig() {
33
+ try {
34
+ if (existsSync(CONFIG_FILE)) {
35
+ unlinkSync(CONFIG_FILE);
36
+ }
37
+ }
38
+ catch {
39
+ // Ignore errors
40
+ }
41
+ }
42
+ export async function isLoggedIn() {
43
+ const config = loadConfig();
44
+ if (!config.userId || !config.email) {
45
+ return false;
46
+ }
47
+ // Verify an actual credential exists (not just a crafted config)
48
+ const credentialExists = await hasCredential();
49
+ if (!credentialExists) {
50
+ return false;
51
+ }
52
+ return true;
53
+ }
54
+ export async function requireAuth() {
55
+ if (!(await isLoggedIn())) {
56
+ console.log();
57
+ console.log(' Authentication required.');
58
+ console.log(' Run: claudetools login');
59
+ console.log();
60
+ process.exit(1);
61
+ }
62
+ return loadConfig();
63
+ }
64
+ export function getConfigDir() {
65
+ return CONFIG_DIR;
66
+ }
67
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/auth/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AACnD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAWpD,SAAS,eAAe;IACtB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,eAAe,EAAE,CAAC;IAClB,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QAC1D,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,UAAU,CAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,iEAAiE;IACjE,MAAM,gBAAgB,GAAG,MAAM,aAAa,EAAE,CAAC;IAC/C,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC,CAAC,MAAM,UAAU,EAAE,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare function runLogin(options?: {
2
+ noBrowser?: boolean;
3
+ }): Promise<void>;
4
+ export declare function runLogout(): Promise<void>;
5
+ export declare function runWhoami(options?: {
6
+ json?: boolean;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAoDA,wBAAsB,QAAQ,CAAC,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFnF;AA+HD,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAmC/C;AAED,wBAAsB,SAAS,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAkE/E"}
@@ -0,0 +1,299 @@
1
+ import { createServer } from 'node:http';
2
+ import { URL } from 'node:url';
3
+ import crypto from 'node:crypto';
4
+ import ora from 'ora';
5
+ import { getApiClient, ApiError } from '../lib/api.js';
6
+ import { saveConfig, clearConfig, isLoggedIn } from './config.js';
7
+ import { storeCredential, deleteCredential } from './keychain.js';
8
+ import { theme, formatError, formatSuccess, formatWarning, formatInfo } from '../lib/theme.js';
9
+ import { openBrowser } from '../lib/browser.js';
10
+ function formatTier(tier) {
11
+ switch (tier) {
12
+ case 'free':
13
+ return theme.muted('🆓 Free');
14
+ case 'pro':
15
+ return theme.highlight('⭐ Pro');
16
+ case 'team':
17
+ return theme.brand('👥 Team');
18
+ case 'enterprise':
19
+ return theme.warning('🏢 Enterprise');
20
+ default:
21
+ return tier;
22
+ }
23
+ }
24
+ export async function runLogin(options = {}) {
25
+ // Check if already logged in
26
+ if (await isLoggedIn()) {
27
+ console.log();
28
+ console.log(` ${formatInfo('Already logged in.')}`);
29
+ console.log(` ${theme.muted(`Run ${theme.command('claudetools logout')} to sign out first.`)}`);
30
+ console.log();
31
+ return;
32
+ }
33
+ // Generate a random state for CSRF protection
34
+ const state = crypto.randomUUID();
35
+ // Start local HTTP server on a random available port
36
+ const { port, waitForCallback, close } = await startCallbackServer(state);
37
+ // Build the auth URL — derive web origin from the API base URL
38
+ const apiBase = process.env.CLAUDETOOLS_API_URL || 'https://claudetools.com/api';
39
+ const webBase = apiBase.replace(/\/api\/?$/, '');
40
+ const authUrl = `${webBase}/cli-auth?port=${port}&state=${state}`;
41
+ console.log();
42
+ console.log(` ${theme.bold('To authenticate, visit:')}`);
43
+ console.log();
44
+ console.log(` ${theme.highlight(authUrl)}`);
45
+ console.log();
46
+ // Open browser automatically unless --no-browser
47
+ if (!options.noBrowser) {
48
+ try {
49
+ await openBrowser(authUrl);
50
+ console.log(` ${theme.muted('Browser opened automatically.')}`);
51
+ }
52
+ catch {
53
+ console.log(` ${theme.muted('Could not open browser. Please visit the URL above.')}`);
54
+ }
55
+ }
56
+ console.log();
57
+ const spinner = ora('Waiting for authentication...').start();
58
+ try {
59
+ // Wait for the redirect callback (timeout after 5 minutes)
60
+ const credentials = await waitForCallback(5 * 60 * 1000);
61
+ spinner.succeed('Authenticated successfully!');
62
+ // Store credentials in keychain
63
+ const tokenExpiresAt = Date.now() + credentials.expiresIn * 1000;
64
+ await storeCredential(credentials.token);
65
+ saveConfig({
66
+ userId: credentials.userId,
67
+ email: credentials.email,
68
+ name: credentials.name || undefined,
69
+ tier: credentials.tier,
70
+ tokenExpiresAt,
71
+ });
72
+ // Push credentials to sync engine for cloud sync
73
+ try {
74
+ const { isSyncEngineRunning, getSyncEngineClient } = await import('../sync-engine/client.js');
75
+ if (await isSyncEngineRunning()) {
76
+ const syncClient = getSyncEngineClient();
77
+ await syncClient.authStore({
78
+ token: credentials.token,
79
+ userId: credentials.userId,
80
+ email: credentials.email,
81
+ tier: credentials.tier,
82
+ expiresAt: new Date(tokenExpiresAt).toISOString(),
83
+ refreshToken: undefined,
84
+ });
85
+ }
86
+ }
87
+ catch {
88
+ // Best-effort — cloud sync will work when engine starts
89
+ }
90
+ console.log();
91
+ console.log(` ${formatSuccess(`Welcome, ${theme.bold(credentials.name || credentials.email)}!`)}`);
92
+ console.log();
93
+ }
94
+ catch (authError) {
95
+ spinner.fail(authError instanceof Error ? authError.message : 'Authentication failed');
96
+ process.exit(1);
97
+ }
98
+ finally {
99
+ close();
100
+ }
101
+ }
102
+ // ── Local callback server ─────────────────────────────────────────────
103
+ async function startCallbackServer(expectedState) {
104
+ return new Promise((resolveServer, rejectServer) => {
105
+ let callbackResolve;
106
+ let timeoutId;
107
+ const server = createServer(async (req, res) => {
108
+ const requestUrl = new URL(req.url || '/', 'http://localhost');
109
+ if (requestUrl.pathname === '/callback') {
110
+ try {
111
+ let params;
112
+ if (req.method === 'POST') {
113
+ // Parse URL-encoded form body with size limit
114
+ const MAX_BODY_SIZE = 8192;
115
+ let body;
116
+ try {
117
+ body = await new Promise((resolve, reject) => {
118
+ let formData = '';
119
+ req.on('data', (chunk) => {
120
+ formData += chunk.toString();
121
+ if (formData.length > MAX_BODY_SIZE) {
122
+ req.destroy();
123
+ reject(new Error('Body too large'));
124
+ }
125
+ });
126
+ req.on('end', () => { resolve(formData); });
127
+ });
128
+ }
129
+ catch {
130
+ res.writeHead(413, { 'Content-Type': 'text/html' });
131
+ res.end('<html><body><h2>Authentication failed</h2>' +
132
+ '<p>Request body too large.</p></body></html>');
133
+ return;
134
+ }
135
+ params = new URLSearchParams(body);
136
+ }
137
+ else {
138
+ // GET fallback for backwards compatibility
139
+ params = requestUrl.searchParams;
140
+ }
141
+ const receivedState = params.get('state');
142
+ const token = params.get('token');
143
+ const userId = params.get('userId');
144
+ const email = params.get('email');
145
+ const name = params.get('name') || '';
146
+ const tier = params.get('tier') || 'free';
147
+ const expiresIn = parseInt(params.get('expiresIn') || '604800', 10);
148
+ // Validate state to prevent CSRF
149
+ if (receivedState !== expectedState) {
150
+ res.writeHead(400, { 'Content-Type': 'text/html' });
151
+ res.end('<html><body><h2>Authentication failed</h2>' +
152
+ '<p>Invalid state parameter. Please try again.</p></body></html>');
153
+ return;
154
+ }
155
+ if (!token || !userId || !email) {
156
+ res.writeHead(400, { 'Content-Type': 'text/html' });
157
+ res.end('<html><body><h2>Authentication failed</h2>' +
158
+ '<p>Missing required parameters.</p></body></html>');
159
+ return;
160
+ }
161
+ // Send success page to browser
162
+ res.writeHead(200, { 'Content-Type': 'text/html' });
163
+ res.end('<html><body style="text-align:center;padding:40px;font-family:system-ui;">' +
164
+ '<h2>Authentication successful!</h2>' +
165
+ '<p>You can close this tab and return to your terminal.</p>' +
166
+ '</body></html>');
167
+ // Resolve the callback promise
168
+ callbackResolve({ token, userId, email, name, tier, expiresIn });
169
+ clearTimeout(timeoutId);
170
+ }
171
+ catch {
172
+ res.writeHead(500, { 'Content-Type': 'text/html' });
173
+ res.end('<html><body><h2>Authentication failed</h2><p>Internal error. Please try again.</p></body></html>');
174
+ }
175
+ }
176
+ else {
177
+ res.writeHead(404);
178
+ res.end();
179
+ }
180
+ });
181
+ // Listen on random available port (0 = OS assigns)
182
+ server.listen(0, '127.0.0.1', () => {
183
+ const address = server.address();
184
+ if (!address || typeof address === 'string') {
185
+ rejectServer(new Error('Failed to start callback server'));
186
+ return;
187
+ }
188
+ resolveServer({
189
+ port: address.port,
190
+ waitForCallback: (timeoutMs) => {
191
+ return new Promise((resolve, reject) => {
192
+ callbackResolve = resolve;
193
+ timeoutId = setTimeout(() => {
194
+ reject(new Error('Authentication timed out. Please try again.'));
195
+ server.close();
196
+ }, timeoutMs);
197
+ });
198
+ },
199
+ close: () => {
200
+ clearTimeout(timeoutId);
201
+ server.close();
202
+ },
203
+ });
204
+ });
205
+ server.on('error', (serverError) => {
206
+ rejectServer(new Error(`Failed to start callback server: ${serverError.message}`));
207
+ });
208
+ });
209
+ }
210
+ export async function runLogout() {
211
+ if (!(await isLoggedIn())) {
212
+ console.log();
213
+ console.log(` ${theme.muted('Not logged in.')}`);
214
+ console.log();
215
+ return;
216
+ }
217
+ const spinner = ora('Signing out...').start();
218
+ try {
219
+ // Clear stored credentials
220
+ await deleteCredential();
221
+ clearConfig();
222
+ // Clear sync engine credentials
223
+ try {
224
+ const { isSyncEngineRunning, getSyncEngineClient } = await import('../sync-engine/client.js');
225
+ if (await isSyncEngineRunning()) {
226
+ const syncClient = getSyncEngineClient();
227
+ await syncClient.authClear();
228
+ }
229
+ }
230
+ catch {
231
+ // Best-effort — sync engine may not be running
232
+ }
233
+ spinner.succeed('Signed out successfully');
234
+ console.log();
235
+ }
236
+ catch (error) {
237
+ spinner.fail('Failed to sign out');
238
+ console.error(` ${formatError(error instanceof Error ? error.message : 'Unknown error', 'ERR_LOGOUT')}`);
239
+ process.exit(1);
240
+ }
241
+ }
242
+ export async function runWhoami(options = {}) {
243
+ if (!(await isLoggedIn())) {
244
+ console.log();
245
+ console.log(` ${formatWarning('Not logged in.')}`);
246
+ console.log(` ${theme.muted(`Run ${theme.command('claudetools login')} to authenticate.`)}`);
247
+ console.log();
248
+ return;
249
+ }
250
+ const spinner = ora('Loading user info...').start();
251
+ try {
252
+ const api = getApiClient();
253
+ const { data: user } = await api.get('/users/me');
254
+ if (!user) {
255
+ spinner.fail('Failed to load user info');
256
+ console.error(` ${formatError('No data received from server', 'ERR_NO_DATA')}`);
257
+ process.exit(1);
258
+ }
259
+ spinner.stop();
260
+ if (options.json) {
261
+ console.log(JSON.stringify(user, null, 2));
262
+ return;
263
+ }
264
+ console.log();
265
+ console.log(` ${theme.bold('Name:')} ${user.name || theme.muted('Not set')}`);
266
+ console.log(` ${theme.bold('Email:')} ${user.email}`);
267
+ console.log(` ${theme.bold('Tier:')} ${formatTier(user.tier)}`);
268
+ // Show subscription info for paid tiers
269
+ if (user.tier !== 'free' && user.subscriptionCurrentPeriodEnd) {
270
+ const renewDate = new Date(user.subscriptionCurrentPeriodEnd).toLocaleDateString();
271
+ console.log(` ${theme.bold('Renews:')} ${renewDate}`);
272
+ if (user.subscriptionStatus && user.subscriptionStatus !== 'active') {
273
+ console.log(` ${theme.bold('Status:')} ${theme.warning(user.subscriptionStatus)}`);
274
+ }
275
+ }
276
+ console.log(` ${theme.bold('ID:')} ${theme.muted(user.id)}`);
277
+ console.log();
278
+ // Show upgrade prompt for free users
279
+ if (user.tier === 'free') {
280
+ console.log(` ${theme.muted('Upgrade to Pro for cloud sync and unlimited stacks:')}`);
281
+ console.log(` ${theme.command('claudetools upgrade')}`);
282
+ console.log();
283
+ }
284
+ }
285
+ catch (error) {
286
+ spinner.fail('Failed to load user info');
287
+ if (error instanceof ApiError && error.code === 'AUTH_REQUIRED') {
288
+ console.log();
289
+ console.log(` ${formatWarning('Session expired. Please log in again.')}`);
290
+ console.log(` ${theme.muted(`Run ${theme.command('claudetools login')}`)}`);
291
+ console.log();
292
+ }
293
+ else {
294
+ console.error(` ${formatError(error instanceof Error ? error.message : 'Unknown error', 'ERR_WHOAMI')}`);
295
+ }
296
+ process.exit(1);
297
+ }
298
+ }
299
+ //# sourceMappingURL=index.js.map