ankui 0.1.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 (270) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +369 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +192 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/access.d.ts +6 -0
  7. package/dist/commands/access.js +12 -0
  8. package/dist/commands/access.js.map +1 -0
  9. package/dist/commands/caps.d.ts +6 -0
  10. package/dist/commands/caps.js +12 -0
  11. package/dist/commands/caps.js.map +1 -0
  12. package/dist/commands/discover.d.ts +10 -0
  13. package/dist/commands/discover.js +120 -0
  14. package/dist/commands/discover.js.map +1 -0
  15. package/dist/commands/doctor.d.ts +6 -0
  16. package/dist/commands/doctor.js +12 -0
  17. package/dist/commands/doctor.js.map +1 -0
  18. package/dist/commands/launch-tui.d.ts +15 -0
  19. package/dist/commands/launch-tui.js +53 -0
  20. package/dist/commands/launch-tui.js.map +1 -0
  21. package/dist/commands/list.d.ts +11 -0
  22. package/dist/commands/list.js +51 -0
  23. package/dist/commands/list.js.map +1 -0
  24. package/dist/commands/mcp.d.ts +6 -0
  25. package/dist/commands/mcp.js +12 -0
  26. package/dist/commands/mcp.js.map +1 -0
  27. package/dist/commands/scan-all.d.ts +15 -0
  28. package/dist/commands/scan-all.js +32 -0
  29. package/dist/commands/scan-all.js.map +1 -0
  30. package/dist/commands/show.d.ts +7 -0
  31. package/dist/commands/show.js +12 -0
  32. package/dist/commands/show.js.map +1 -0
  33. package/dist/commands/watch.d.ts +32 -0
  34. package/dist/commands/watch.js +205 -0
  35. package/dist/commands/watch.js.map +1 -0
  36. package/dist/config/ankui-config.d.ts +13 -0
  37. package/dist/config/ankui-config.js +123 -0
  38. package/dist/config/ankui-config.js.map +1 -0
  39. package/dist/scanner/access-review.d.ts +2 -0
  40. package/dist/scanner/access-review.js +183 -0
  41. package/dist/scanner/access-review.js.map +1 -0
  42. package/dist/scanner/adapters/claude.d.ts +2 -0
  43. package/dist/scanner/adapters/claude.js +298 -0
  44. package/dist/scanner/adapters/claude.js.map +1 -0
  45. package/dist/scanner/adapters/codex.d.ts +2 -0
  46. package/dist/scanner/adapters/codex.js +152 -0
  47. package/dist/scanner/adapters/codex.js.map +1 -0
  48. package/dist/scanner/adapters/cursor.d.ts +2 -0
  49. package/dist/scanner/adapters/cursor.js +114 -0
  50. package/dist/scanner/adapters/cursor.js.map +1 -0
  51. package/dist/scanner/adapters/gemini.d.ts +2 -0
  52. package/dist/scanner/adapters/gemini.js +191 -0
  53. package/dist/scanner/adapters/gemini.js.map +1 -0
  54. package/dist/scanner/adapters/index.d.ts +35 -0
  55. package/dist/scanner/adapters/index.js +85 -0
  56. package/dist/scanner/adapters/index.js.map +1 -0
  57. package/dist/scanner/adapters/opencode.d.ts +2 -0
  58. package/dist/scanner/adapters/opencode.js +231 -0
  59. package/dist/scanner/adapters/opencode.js.map +1 -0
  60. package/dist/scanner/adapters/shared.d.ts +57 -0
  61. package/dist/scanner/adapters/shared.js +239 -0
  62. package/dist/scanner/adapters/shared.js.map +1 -0
  63. package/dist/scanner/adapters/skills-sh.d.ts +2 -0
  64. package/dist/scanner/adapters/skills-sh.js +71 -0
  65. package/dist/scanner/adapters/skills-sh.js.map +1 -0
  66. package/dist/scanner/capability-map.d.ts +8 -0
  67. package/dist/scanner/capability-map.js +57 -0
  68. package/dist/scanner/capability-map.js.map +1 -0
  69. package/dist/scanner/discovery.d.ts +31 -0
  70. package/dist/scanner/discovery.js +320 -0
  71. package/dist/scanner/discovery.js.map +1 -0
  72. package/dist/scanner/filesystem-crawler.d.ts +32 -0
  73. package/dist/scanner/filesystem-crawler.js +210 -0
  74. package/dist/scanner/filesystem-crawler.js.map +1 -0
  75. package/dist/scanner/index.d.ts +8 -0
  76. package/dist/scanner/index.js +120 -0
  77. package/dist/scanner/index.js.map +1 -0
  78. package/dist/scanner/multi-project.d.ts +31 -0
  79. package/dist/scanner/multi-project.js +227 -0
  80. package/dist/scanner/multi-project.js.map +1 -0
  81. package/dist/scanner/parallel.d.ts +4 -0
  82. package/dist/scanner/parallel.js +41 -0
  83. package/dist/scanner/parallel.js.map +1 -0
  84. package/dist/scanner/parsing.d.ts +9 -0
  85. package/dist/scanner/parsing.js +135 -0
  86. package/dist/scanner/parsing.js.map +1 -0
  87. package/dist/scanner/paths.d.ts +8 -0
  88. package/dist/scanner/paths.js +39 -0
  89. package/dist/scanner/paths.js.map +1 -0
  90. package/dist/scanner/preview.d.ts +12 -0
  91. package/dist/scanner/preview.js +29 -0
  92. package/dist/scanner/preview.js.map +1 -0
  93. package/dist/scanner/project-discovery.d.ts +11 -0
  94. package/dist/scanner/project-discovery.js +35 -0
  95. package/dist/scanner/project-discovery.js.map +1 -0
  96. package/dist/scanner/ripgrep.d.ts +11 -0
  97. package/dist/scanner/ripgrep.js +61 -0
  98. package/dist/scanner/ripgrep.js.map +1 -0
  99. package/dist/scanner/safety.d.ts +37 -0
  100. package/dist/scanner/safety.js +330 -0
  101. package/dist/scanner/safety.js.map +1 -0
  102. package/dist/scanner/skill-naming.d.ts +5 -0
  103. package/dist/scanner/skill-naming.js +53 -0
  104. package/dist/scanner/skill-naming.js.map +1 -0
  105. package/dist/scanner/watcher.d.ts +15 -0
  106. package/dist/scanner/watcher.js +71 -0
  107. package/dist/scanner/watcher.js.map +1 -0
  108. package/dist/tui/App.d.ts +33 -0
  109. package/dist/tui/App.js +201 -0
  110. package/dist/tui/App.js.map +1 -0
  111. package/dist/tui/components/Breadcrumb.d.ts +10 -0
  112. package/dist/tui/components/Breadcrumb.js +11 -0
  113. package/dist/tui/components/Breadcrumb.js.map +1 -0
  114. package/dist/tui/components/DisclosureRow.d.ts +17 -0
  115. package/dist/tui/components/DisclosureRow.js +13 -0
  116. package/dist/tui/components/DisclosureRow.js.map +1 -0
  117. package/dist/tui/components/DotLeaderRow.d.ts +17 -0
  118. package/dist/tui/components/DotLeaderRow.js +34 -0
  119. package/dist/tui/components/DotLeaderRow.js.map +1 -0
  120. package/dist/tui/components/EmptyStateWhisper.d.ts +5 -0
  121. package/dist/tui/components/EmptyStateWhisper.js +6 -0
  122. package/dist/tui/components/EmptyStateWhisper.js.map +1 -0
  123. package/dist/tui/components/Frame.d.ts +15 -0
  124. package/dist/tui/components/Frame.js +21 -0
  125. package/dist/tui/components/Frame.js.map +1 -0
  126. package/dist/tui/components/IdleWhisper.d.ts +11 -0
  127. package/dist/tui/components/IdleWhisper.js +12 -0
  128. package/dist/tui/components/IdleWhisper.js.map +1 -0
  129. package/dist/tui/components/KeyHint.d.ts +13 -0
  130. package/dist/tui/components/KeyHint.js +12 -0
  131. package/dist/tui/components/KeyHint.js.map +1 -0
  132. package/dist/tui/components/LoadingSplash.d.ts +12 -0
  133. package/dist/tui/components/LoadingSplash.js +55 -0
  134. package/dist/tui/components/LoadingSplash.js.map +1 -0
  135. package/dist/tui/components/ProgressBar.d.ts +16 -0
  136. package/dist/tui/components/ProgressBar.js +24 -0
  137. package/dist/tui/components/ProgressBar.js.map +1 -0
  138. package/dist/tui/components/SearchBox.d.ts +5 -0
  139. package/dist/tui/components/SearchBox.js +6 -0
  140. package/dist/tui/components/SearchBox.js.map +1 -0
  141. package/dist/tui/components/SectionHeader.d.ts +12 -0
  142. package/dist/tui/components/SectionHeader.js +14 -0
  143. package/dist/tui/components/SectionHeader.js.map +1 -0
  144. package/dist/tui/components/SkillViewport.d.ts +8 -0
  145. package/dist/tui/components/SkillViewport.js +42 -0
  146. package/dist/tui/components/SkillViewport.js.map +1 -0
  147. package/dist/tui/components/Spinner.d.ts +11 -0
  148. package/dist/tui/components/Spinner.js +13 -0
  149. package/dist/tui/components/Spinner.js.map +1 -0
  150. package/dist/tui/components/StatusPill.d.ts +13 -0
  151. package/dist/tui/components/StatusPill.js +15 -0
  152. package/dist/tui/components/StatusPill.js.map +1 -0
  153. package/dist/tui/components/TabBar.d.ts +20 -0
  154. package/dist/tui/components/TabBar.js +26 -0
  155. package/dist/tui/components/TabBar.js.map +1 -0
  156. package/dist/tui/components/TextInput.d.ts +13 -0
  157. package/dist/tui/components/TextInput.js +34 -0
  158. package/dist/tui/components/TextInput.js.map +1 -0
  159. package/dist/tui/hooks/use-idle-whisper.d.ts +17 -0
  160. package/dist/tui/hooks/use-idle-whisper.js +66 -0
  161. package/dist/tui/hooks/use-idle-whisper.js.map +1 -0
  162. package/dist/tui/hooks/use-rotating-message.d.ts +20 -0
  163. package/dist/tui/hooks/use-rotating-message.js +34 -0
  164. package/dist/tui/hooks/use-rotating-message.js.map +1 -0
  165. package/dist/tui/input/use-keys.d.ts +16 -0
  166. package/dist/tui/input/use-keys.js +32 -0
  167. package/dist/tui/input/use-keys.js.map +1 -0
  168. package/dist/tui/messages.d.ts +18 -0
  169. package/dist/tui/messages.js +59 -0
  170. package/dist/tui/messages.js.map +1 -0
  171. package/dist/tui/render.d.ts +12 -0
  172. package/dist/tui/render.js +112 -0
  173. package/dist/tui/render.js.map +1 -0
  174. package/dist/tui/screens/AccessTab.d.ts +6 -0
  175. package/dist/tui/screens/AccessTab.js +26 -0
  176. package/dist/tui/screens/AccessTab.js.map +1 -0
  177. package/dist/tui/screens/DoctorTab.d.ts +6 -0
  178. package/dist/tui/screens/DoctorTab.js +24 -0
  179. package/dist/tui/screens/DoctorTab.js.map +1 -0
  180. package/dist/tui/screens/FirstRunScan.d.ts +11 -0
  181. package/dist/tui/screens/FirstRunScan.js +128 -0
  182. package/dist/tui/screens/FirstRunScan.js.map +1 -0
  183. package/dist/tui/screens/McpsTab.d.ts +6 -0
  184. package/dist/tui/screens/McpsTab.js +30 -0
  185. package/dist/tui/screens/McpsTab.js.map +1 -0
  186. package/dist/tui/screens/Overview.d.ts +6 -0
  187. package/dist/tui/screens/Overview.js +75 -0
  188. package/dist/tui/screens/Overview.js.map +1 -0
  189. package/dist/tui/screens/ProjectDrillIn.d.ts +10 -0
  190. package/dist/tui/screens/ProjectDrillIn.js +16 -0
  191. package/dist/tui/screens/ProjectDrillIn.js.map +1 -0
  192. package/dist/tui/screens/Settings.d.ts +8 -0
  193. package/dist/tui/screens/Settings.js +71 -0
  194. package/dist/tui/screens/Settings.js.map +1 -0
  195. package/dist/tui/screens/ToolTab.d.ts +9 -0
  196. package/dist/tui/screens/ToolTab.js +38 -0
  197. package/dist/tui/screens/ToolTab.js.map +1 -0
  198. package/dist/tui/screens/UserScopeDrillIn.d.ts +13 -0
  199. package/dist/tui/screens/UserScopeDrillIn.js +15 -0
  200. package/dist/tui/screens/UserScopeDrillIn.js.map +1 -0
  201. package/dist/tui/state/navigation.d.ts +1 -0
  202. package/dist/tui/state/navigation.js +11 -0
  203. package/dist/tui/state/navigation.js.map +1 -0
  204. package/dist/tui/state/settings-state.d.ts +22 -0
  205. package/dist/tui/state/settings-state.js +30 -0
  206. package/dist/tui/state/settings-state.js.map +1 -0
  207. package/dist/tui/state/tui-state.d.ts +57 -0
  208. package/dist/tui/state/tui-state.js +86 -0
  209. package/dist/tui/state/tui-state.js.map +1 -0
  210. package/dist/tui/theme/borders.d.ts +20 -0
  211. package/dist/tui/theme/borders.js +25 -0
  212. package/dist/tui/theme/borders.js.map +1 -0
  213. package/dist/tui/theme/colors.d.ts +14 -0
  214. package/dist/tui/theme/colors.js +18 -0
  215. package/dist/tui/theme/colors.js.map +1 -0
  216. package/dist/tui/theme/icons.d.ts +30 -0
  217. package/dist/tui/theme/icons.js +51 -0
  218. package/dist/tui/theme/icons.js.map +1 -0
  219. package/dist/tui/util/doctor-grouping.d.ts +27 -0
  220. package/dist/tui/util/doctor-grouping.js +67 -0
  221. package/dist/tui/util/doctor-grouping.js.map +1 -0
  222. package/dist/tui/util/finding-grouping.d.ts +24 -0
  223. package/dist/tui/util/finding-grouping.js +43 -0
  224. package/dist/tui/util/finding-grouping.js.map +1 -0
  225. package/dist/tui/util/mcp-grouping.d.ts +27 -0
  226. package/dist/tui/util/mcp-grouping.js +96 -0
  227. package/dist/tui/util/mcp-grouping.js.map +1 -0
  228. package/dist/tui/util/scan-history.d.ts +15 -0
  229. package/dist/tui/util/scan-history.js +43 -0
  230. package/dist/tui/util/scan-history.js.map +1 -0
  231. package/dist/tui/util/skill-filter.d.ts +2 -0
  232. package/dist/tui/util/skill-filter.js +7 -0
  233. package/dist/tui/util/skill-filter.js.map +1 -0
  234. package/dist/tui/util/skill-grouping.d.ts +3 -0
  235. package/dist/tui/util/skill-grouping.js +31 -0
  236. package/dist/tui/util/skill-grouping.js.map +1 -0
  237. package/dist/types.d.ts +151 -0
  238. package/dist/types.js +143 -0
  239. package/dist/types.js.map +1 -0
  240. package/dist/utils/errors.d.ts +1 -0
  241. package/dist/utils/errors.js +7 -0
  242. package/dist/utils/errors.js.map +1 -0
  243. package/dist/utils/format-access.d.ts +3 -0
  244. package/dist/utils/format-access.js +94 -0
  245. package/dist/utils/format-access.js.map +1 -0
  246. package/dist/utils/format-caps.d.ts +3 -0
  247. package/dist/utils/format-caps.js +139 -0
  248. package/dist/utils/format-caps.js.map +1 -0
  249. package/dist/utils/format-doctor.d.ts +3 -0
  250. package/dist/utils/format-doctor.js +105 -0
  251. package/dist/utils/format-doctor.js.map +1 -0
  252. package/dist/utils/format-list.d.ts +7 -0
  253. package/dist/utils/format-list.js +112 -0
  254. package/dist/utils/format-list.js.map +1 -0
  255. package/dist/utils/format-mcp.d.ts +3 -0
  256. package/dist/utils/format-mcp.js +130 -0
  257. package/dist/utils/format-mcp.js.map +1 -0
  258. package/dist/utils/format-multi-project.d.ts +3 -0
  259. package/dist/utils/format-multi-project.js +100 -0
  260. package/dist/utils/format-multi-project.js.map +1 -0
  261. package/dist/utils/format-show.d.ts +6 -0
  262. package/dist/utils/format-show.js +143 -0
  263. package/dist/utils/format-show.js.map +1 -0
  264. package/dist/utils/format.d.ts +3 -0
  265. package/dist/utils/format.js +53 -0
  266. package/dist/utils/format.js.map +1 -0
  267. package/dist/utils/paths.d.ts +1 -0
  268. package/dist/utils/paths.js +10 -0
  269. package/dist/utils/paths.js.map +1 -0
  270. package/package.json +61 -0
@@ -0,0 +1,120 @@
1
+ import os from "node:os";
2
+ import { getAnkuiConfigPath, mergeDevRoots, readAnkuiConfig, writeAnkuiConfig } from "../config/ankui-config.js";
3
+ import { crawlForProjects } from "../scanner/filesystem-crawler.js";
4
+ import { groupProjectsByParent, selectDefaultOnRoots } from "../scanner/project-discovery.js";
5
+ import { relativizeHome } from "../utils/paths.js";
6
+ export async function runDiscoverCommand(options) {
7
+ const homeDir = options.homeDir ?? os.homedir();
8
+ const now = options.now ?? (() => new Date());
9
+ const scannedAt = now().toISOString();
10
+ const configPath = getAnkuiConfigPath(homeDir);
11
+ const crawl = await crawlForProjects({ rootDir: homeDir });
12
+ const candidates = groupProjectsByParent(crawl.projects);
13
+ let applied = false;
14
+ let previousDevRoots = [];
15
+ let nextDevRoots = [];
16
+ let writeOutcome = "skipped";
17
+ if (options.apply) {
18
+ const existing = await readAnkuiConfig(homeDir);
19
+ previousDevRoots = existing.config.devRoots;
20
+ const merged = mergeDevRoots(previousDevRoots, selectDefaultOnRoots(candidates));
21
+ const unchanged = merged.length === previousDevRoots.length &&
22
+ merged.every((entry, idx) => entry === previousDevRoots[idx]);
23
+ if (unchanged) {
24
+ writeOutcome = "no-op";
25
+ nextDevRoots = previousDevRoots;
26
+ }
27
+ else {
28
+ await writeAnkuiConfig({ version: 1, devRoots: merged }, homeDir);
29
+ writeOutcome = "wrote";
30
+ nextDevRoots = merged;
31
+ }
32
+ applied = true;
33
+ }
34
+ if (options.json) {
35
+ options.write(`${JSON.stringify({
36
+ scannedAt,
37
+ homeDir,
38
+ configPath,
39
+ stats: {
40
+ pathsVisited: crawl.stats.pathsVisited,
41
+ durationMs: crawl.stats.durationMs,
42
+ projectsFound: crawl.projects.length
43
+ },
44
+ candidates: candidates.map((c) => ({
45
+ parentPath: c.parentPath,
46
+ displayPath: relativizeHome(c.parentPath, homeDir),
47
+ projectCount: c.projectCount,
48
+ projectPaths: c.projectPaths,
49
+ defaultOn: c.defaultOn
50
+ })),
51
+ warnings: crawl.warnings,
52
+ applied,
53
+ previousDevRoots: applied ? previousDevRoots : [],
54
+ nextDevRoots: applied ? nextDevRoots : []
55
+ }, null, 2)}\n`);
56
+ return;
57
+ }
58
+ options.write(`${formatDiscoverHuman({
59
+ crawlStats: crawl.stats,
60
+ crawlProjects: crawl.projects,
61
+ candidates,
62
+ homeDir,
63
+ apply: options.apply,
64
+ writeOutcome,
65
+ previousDevRoots,
66
+ nextDevRoots,
67
+ configPath
68
+ })}\n`);
69
+ }
70
+ function formatDiscoverHuman(args) {
71
+ const seconds = (args.crawlStats.durationMs / 1000).toFixed(2);
72
+ const pathsVisited = args.crawlStats.pathsVisited.toLocaleString("en-US");
73
+ const header = `Ankui discover — crawl of ~ in ${seconds}s, ${pathsVisited} paths visited, ${args.crawlProjects.length} projects found`;
74
+ if (args.candidates.length === 0) {
75
+ return `${header}\n\nNo projects found. Either no AI tools are configured, or the crawl was constrained by the skip list. Try running scan in a specific project directory.`;
76
+ }
77
+ const defaultOn = args.candidates.filter((c) => c.defaultOn);
78
+ const suggested = args.candidates.filter((c) => !c.defaultOn);
79
+ const sections = [];
80
+ if (defaultOn.length === 0) {
81
+ sections.push("No dev roots found with 3+ projects.");
82
+ }
83
+ else {
84
+ sections.push([
85
+ `Default-ON dev roots (${defaultOn.length})`,
86
+ "────────────────────────",
87
+ ...defaultOn.map((c) => formatCandidateRow(c, args.homeDir, "●"))
88
+ ].join("\n"));
89
+ }
90
+ if (suggested.length > 0) {
91
+ sections.push([
92
+ `Suggested (1-2 projects, off by default)`,
93
+ "────────────────────────────────────────",
94
+ ...suggested.map((c) => formatCandidateRow(c, args.homeDir, "○"))
95
+ ].join("\n"));
96
+ }
97
+ let footer;
98
+ if (!args.apply) {
99
+ const displayConfig = relativizeHome(args.configPath, args.homeDir);
100
+ footer = `No changes applied. Re-run with --apply to register the default-ON roots in ${displayConfig}.`;
101
+ }
102
+ else if (args.writeOutcome === "no-op") {
103
+ footer = `Config already up to date — no changes written.`;
104
+ }
105
+ else {
106
+ const added = args.nextDevRoots.length - args.previousDevRoots.length;
107
+ const kept = args.previousDevRoots.length;
108
+ const displayConfig = relativizeHome(args.configPath, args.homeDir);
109
+ footer = `Wrote ${args.nextDevRoots.length} dev root(s) to ${displayConfig} (added ${added}, kept ${kept}).`;
110
+ }
111
+ return [header, "", sections.join("\n\n"), "", footer].join("\n");
112
+ }
113
+ function formatCandidateRow(candidate, homeDir, icon) {
114
+ const display = relativizeHome(candidate.parentPath, homeDir).padEnd(38);
115
+ return `${icon} ${display} ${plural(candidate.projectCount, "project")}`;
116
+ }
117
+ function plural(n, noun) {
118
+ return `${n} ${noun}${n === 1 ? "" : "s"}`;
119
+ }
120
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/commands/discover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type ScanOptions } from "../scanner/index.js";
2
+ export interface DoctorCommandOptions extends ScanOptions {
3
+ json: boolean;
4
+ write: (chunk: string) => void;
5
+ }
6
+ export declare function runDoctorCommand(options: DoctorCommandOptions): Promise<void>;
@@ -0,0 +1,12 @@
1
+ import { scan } from "../scanner/index.js";
2
+ import { formatDoctor, formatDoctorJson } from "../utils/format-doctor.js";
3
+ export async function runDoctorCommand(options) {
4
+ const { json, write, ...scanOptions } = options;
5
+ const result = await scan(scanOptions);
6
+ if (json) {
7
+ write(formatDoctorJson(result));
8
+ return;
9
+ }
10
+ write(`${formatDoctor(result)}\n`);
11
+ }
12
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAoB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAO3E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAA6B;IAClE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAChD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC;IAEvC,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IAED,KAAK,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { MultiProjectScanResult } from "../types.js";
2
+ export interface BuildLaunchTuiResultOptions {
3
+ homeDir: string;
4
+ env: Record<string, string | undefined>;
5
+ now?: Date;
6
+ }
7
+ /**
8
+ * Builds the `MultiProjectScanResult` that `launchTui` passes to `renderTui`.
9
+ *
10
+ * When `~/.config/ankui/config.json` has no `devRoots` registered yet, we skip
11
+ * the expensive user-scope scan (which is the bulk of first-run wall time) and
12
+ * return an empty result. The TUI's first-run screen handles this state without
13
+ * needing populated scan data; the discovery splash is the right next step.
14
+ */
15
+ export declare function buildLaunchTuiResult(options: BuildLaunchTuiResultOptions): Promise<MultiProjectScanResult>;
@@ -0,0 +1,53 @@
1
+ import { loadAllScans, readDevRootsConfig } from "../scanner/multi-project.js";
2
+ /**
3
+ * Builds the `MultiProjectScanResult` that `launchTui` passes to `renderTui`.
4
+ *
5
+ * When `~/.config/ankui/config.json` has no `devRoots` registered yet, we skip
6
+ * the expensive user-scope scan (which is the bulk of first-run wall time) and
7
+ * return an empty result. The TUI's first-run screen handles this state without
8
+ * needing populated scan data; the discovery splash is the right next step.
9
+ */
10
+ export async function buildLaunchTuiResult(options) {
11
+ const now = options.now ?? new Date();
12
+ const config = await readDevRootsConfig(options.homeDir);
13
+ if (config.devRoots.length === 0) {
14
+ return {
15
+ scannedAt: now.toISOString(),
16
+ cwd: options.homeDir,
17
+ homeDir: options.homeDir,
18
+ devRoots: [],
19
+ userScope: {
20
+ scannedAt: now.toISOString(),
21
+ cwd: options.homeDir,
22
+ homeDir: options.homeDir,
23
+ tools: [],
24
+ findings: [],
25
+ warnings: [],
26
+ summary: {
27
+ detectedTools: 0,
28
+ totalSkills: 0,
29
+ totalMcpServers: 0,
30
+ uniqueMcpServers: 0,
31
+ customCommands: 0,
32
+ customTools: 0,
33
+ plugins: 0,
34
+ memoryFiles: 0,
35
+ agentSkills: 0,
36
+ skillsShSkills: 0,
37
+ totalFindings: 0,
38
+ broadAccessFindings: 0
39
+ }
40
+ },
41
+ projects: [],
42
+ warnings: config.warnings,
43
+ totals: { projectCount: 0, skillsAcrossProjects: 0, userScopeSkills: 0 }
44
+ };
45
+ }
46
+ return loadAllScans({
47
+ devRoots: config.devRoots,
48
+ homeDir: options.homeDir,
49
+ env: options.env,
50
+ now
51
+ });
52
+ }
53
+ //# sourceMappingURL=launch-tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch-tui.js","sourceRoot":"","sources":["../../src/commands/launch-tui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAS/E;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAoC;IAEpC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO;YACL,SAAS,EAAE,GAAG,CAAC,WAAW,EAAE;YAC5B,GAAG,EAAE,OAAO,CAAC,OAAO;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE;gBACT,SAAS,EAAE,GAAG,CAAC,WAAW,EAAE;gBAC5B,GAAG,EAAE,OAAO,CAAC,OAAO;gBACpB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,KAAK,EAAE,EAAE;gBACT,QAAQ,EAAE,EAAE;gBACZ,QAAQ,EAAE,EAAE;gBACZ,OAAO,EAAE;oBACP,aAAa,EAAE,CAAC;oBAChB,WAAW,EAAE,CAAC;oBACd,eAAe,EAAE,CAAC;oBAClB,gBAAgB,EAAE,CAAC;oBACnB,cAAc,EAAE,CAAC;oBACjB,WAAW,EAAE,CAAC;oBACd,OAAO,EAAE,CAAC;oBACV,WAAW,EAAE,CAAC;oBACd,WAAW,EAAE,CAAC;oBACd,cAAc,EAAE,CAAC;oBACjB,aAAa,EAAE,CAAC;oBAChB,mBAAmB,EAAE,CAAC;iBACvB;aACF;YACD,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE;SACzE,CAAC;IACJ,CAAC;IAED,OAAO,YAAY,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG;KACJ,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type ScanOptions } from "../scanner/index.js";
2
+ export interface ListCommandOptions extends ScanOptions {
3
+ json: boolean;
4
+ kind?: string;
5
+ tool?: string;
6
+ write: (chunk: string) => void;
7
+ }
8
+ export declare class InvalidFilterError extends Error {
9
+ constructor(message: string);
10
+ }
11
+ export declare function runListCommand(options: ListCommandOptions): Promise<void>;
@@ -0,0 +1,51 @@
1
+ import { scan } from "../scanner/index.js";
2
+ import { formatList, formatListJson } from "../utils/format-list.js";
3
+ import { TOOL_DEFINITIONS } from "../types.js";
4
+ export class InvalidFilterError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "InvalidFilterError";
8
+ }
9
+ }
10
+ const VALID_KINDS = [
11
+ "mcp_server",
12
+ "custom_commands",
13
+ "custom_agents",
14
+ "custom_prompts",
15
+ "custom_tools",
16
+ "plugins",
17
+ "rules",
18
+ "memory_file",
19
+ "agent_skill",
20
+ "skills_sh_skill"
21
+ ];
22
+ const VALID_TOOL_IDS = TOOL_DEFINITIONS.map((t) => t.id);
23
+ export async function runListCommand(options) {
24
+ const filters = validateFilters({ kind: options.kind, tool: options.tool });
25
+ const { json, write, kind: _k, tool: _t, ...scanOptions } = options;
26
+ void _k;
27
+ void _t;
28
+ const result = await scan(scanOptions);
29
+ if (json) {
30
+ write(formatListJson(result, filters));
31
+ return;
32
+ }
33
+ write(`${formatList(result, filters)}\n`);
34
+ }
35
+ function validateFilters(input) {
36
+ const filters = {};
37
+ if (input.kind !== undefined) {
38
+ if (!VALID_KINDS.includes(input.kind)) {
39
+ throw new InvalidFilterError(`Unknown --kind value: ${input.kind}. Valid kinds: ${VALID_KINDS.join(", ")}.`);
40
+ }
41
+ filters.kind = input.kind;
42
+ }
43
+ if (input.tool !== undefined) {
44
+ if (!VALID_TOOL_IDS.includes(input.tool)) {
45
+ throw new InvalidFilterError(`Unknown --tool value: ${input.tool}. Valid tools: ${VALID_TOOL_IDS.join(", ")}.`);
46
+ }
47
+ filters.tool = input.tool;
48
+ }
49
+ return filters;
50
+ }
51
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAoB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAoB,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAA+B,MAAM,aAAa,CAAC;AAS5E,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,WAAW,GAA6B;IAC5C,YAAY;IACZ,iBAAiB;IACjB,eAAe;IACf,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,OAAO;IACP,aAAa;IACb,aAAa;IACb,iBAAiB;CAClB,CAAC;AAEF,MAAM,cAAc,GAA0B,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAEhF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAA2B;IAC9D,MAAM,OAAO,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5E,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IACpE,KAAK,EAAE,CAAC;IAAC,KAAK,EAAE,CAAC;IACjB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC;IAEvC,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IACD,KAAK,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,eAAe,CAAC,KAAuC;IAC9D,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAiB,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,kBAAkB,CAC1B,yBAAyB,KAAK,CAAC,IAAI,kBAAkB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC/E,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,IAAiB,CAAC;IACzC,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAc,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,kBAAkB,CAC1B,yBAAyB,KAAK,CAAC,IAAI,kBAAkB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAClF,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,IAAc,CAAC;IACtC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { type ScanOptions } from "../scanner/index.js";
2
+ export interface McpCommandOptions extends ScanOptions {
3
+ json: boolean;
4
+ write: (chunk: string) => void;
5
+ }
6
+ export declare function runMcpCommand(options: McpCommandOptions): Promise<void>;
@@ -0,0 +1,12 @@
1
+ import { scan } from "../scanner/index.js";
2
+ import { formatMcpOverview, formatMcpOverviewJson } from "../utils/format-mcp.js";
3
+ export async function runMcpCommand(options) {
4
+ const { json, write, ...scanOptions } = options;
5
+ const result = await scan(scanOptions);
6
+ if (json) {
7
+ write(formatMcpOverviewJson(result));
8
+ return;
9
+ }
10
+ write(`${formatMcpOverview(result)}\n`);
11
+ }
12
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAoB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAOlF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA0B;IAC5D,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAChD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC;IAEvC,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,KAAK,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ScanOptions } from "../scanner/index.js";
2
+ import type { ScanResult } from "../types.js";
3
+ export interface ScanAllCommandOptions {
4
+ json: boolean;
5
+ write: (chunk: string) => void;
6
+ homeDir?: string;
7
+ env?: Record<string, string | undefined>;
8
+ /** Override the dev roots read from ~/.config/ankui/config.json. */
9
+ devRoots?: readonly string[];
10
+ /** Fixed clock for deterministic tests. */
11
+ now?: Date;
12
+ /** Test hook — forwarded to loadAllScans. Not for production. */
13
+ __scanForTesting?: (options: ScanOptions) => Promise<ScanResult>;
14
+ }
15
+ export declare function runScanAllCommand(options: ScanAllCommandOptions): Promise<void>;
@@ -0,0 +1,32 @@
1
+ import os from "node:os";
2
+ import { loadAllScans, readDevRootsConfig } from "../scanner/multi-project.js";
3
+ import { formatMultiProjectJson, formatMultiProjectSummary } from "../utils/format-multi-project.js";
4
+ export async function runScanAllCommand(options) {
5
+ const homeDir = options.homeDir ?? os.homedir();
6
+ const env = options.env ?? process.env;
7
+ let devRoots;
8
+ let configWarnings = [];
9
+ if (options.devRoots !== undefined) {
10
+ devRoots = options.devRoots;
11
+ }
12
+ else {
13
+ const config = await readDevRootsConfig(homeDir);
14
+ devRoots = config.devRoots;
15
+ configWarnings = config.warnings;
16
+ }
17
+ const result = await loadAllScans({
18
+ devRoots,
19
+ homeDir,
20
+ env,
21
+ now: options.now,
22
+ __scanForTesting: options.__scanForTesting
23
+ });
24
+ // Merge config-read warnings into the aggregate result so they surface in output.
25
+ result.warnings = [...configWarnings, ...result.warnings];
26
+ if (options.json) {
27
+ options.write(formatMultiProjectJson(result));
28
+ return;
29
+ }
30
+ options.write(`${formatMultiProjectSummary(result)}\n`);
31
+ }
32
+ //# sourceMappingURL=scan-all.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-all.js","sourceRoot":"","sources":["../../src/commands/scan-all.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAG/E,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,kCAAkC,CAAC;AAe1C,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAA8B;IACpE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;IAChD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAEvC,IAAI,QAA2B,CAAC;IAChC,IAAI,cAAc,GAA+D,EAAE,CAAC;IAEpF,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACjD,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC3B,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC;IACnC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;QAChC,QAAQ;QACR,OAAO;QACP,GAAG;QACH,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;KAC3C,CAAC,CAAC;IAEH,kFAAkF;IAClF,MAAM,CAAC,QAAQ,GAAG,CAAC,GAAG,cAAc,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE1D,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,GAAG,yBAAyB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type ScanOptions } from "../scanner/index.js";
2
+ export interface ShowCommandOptions extends ScanOptions {
3
+ toolId: string;
4
+ json: boolean;
5
+ write: (chunk: string) => void;
6
+ }
7
+ export declare function runShowCommand(options: ShowCommandOptions): Promise<void>;
@@ -0,0 +1,12 @@
1
+ import { scan } from "../scanner/index.js";
2
+ import { formatShow, formatShowJson } from "../utils/format-show.js";
3
+ export async function runShowCommand(options) {
4
+ const { toolId, json, write, ...scanOptions } = options;
5
+ const result = await scan(scanOptions);
6
+ if (json) {
7
+ write(formatShowJson(result, toolId));
8
+ return;
9
+ }
10
+ write(`${formatShow(result, toolId)}\n`);
11
+ }
12
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAoB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAQrE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAA2B;IAC9D,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IACxD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC;IAEvC,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACtC,OAAO;IACT,CAAC;IACD,KAAK,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { MultiProjectScanResult } from "../types.js";
2
+ import { type LoadAllScansOptions } from "../scanner/multi-project.js";
3
+ import type { DataSource } from "../tui/App.js";
4
+ export interface CollectWatchPathsOptions {
5
+ homeDir: string;
6
+ devRoots: readonly string[];
7
+ }
8
+ export declare function collectWatchPaths(options: CollectWatchPathsOptions): Promise<string[]>;
9
+ export interface RunWatchCommandOptions {
10
+ /** Defaults to os.homedir(). */
11
+ homeDir?: string;
12
+ /** Defaults to process.env. */
13
+ env?: Record<string, string | undefined>;
14
+ /** Override registered dev roots — used by tests. Otherwise read from ~/.config/ankui/config.json. */
15
+ devRoots?: readonly string[];
16
+ /** Watcher debounce in ms. Default 300. */
17
+ debounceMs?: number;
18
+ /** Test hook — replaces `loadAllScans`. */
19
+ __loadAllScansForTesting?: (options: LoadAllScansOptions) => Promise<MultiProjectScanResult>;
20
+ /** Test hook — replaces the Ink render call. */
21
+ __mountTui?: (dataSource: DataSource) => Promise<{
22
+ waitUntilExit: () => Promise<void>;
23
+ unsubscribe: () => void;
24
+ }>;
25
+ }
26
+ export interface RunWatchCommandHandle {
27
+ /** Resolves when the TUI mounts and the user quits, or the test driver finishes. */
28
+ exitPromise: Promise<void>;
29
+ /** Explicit cleanup — stops the watcher even if the TUI did not call exit. */
30
+ shutdown(): Promise<void>;
31
+ }
32
+ export declare function runWatchCommand(options?: RunWatchCommandOptions): Promise<RunWatchCommandHandle>;
@@ -0,0 +1,205 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { loadAllScans as defaultLoadAllScans, readDevRootsConfig, PROJECT_MARKER_DIRS, PROJECT_MARKER_FILES } from "../scanner/multi-project.js";
5
+ import { isSensitivePath } from "../scanner/safety.js";
6
+ import { createWatcher } from "../scanner/watcher.js";
7
+ import { renderTui as defaultRenderTui } from "../tui/render.js";
8
+ const USER_SCOPE_RELATIVE_PATHS = [
9
+ ".claude",
10
+ ".claude.json",
11
+ ".codex",
12
+ ".cursor",
13
+ ".gemini",
14
+ ".config/opencode",
15
+ ".skills",
16
+ ".config/skills"
17
+ ];
18
+ export async function collectWatchPaths(options) {
19
+ const collected = new Set();
20
+ // User-scope: known tool config dirs/files under homeDir, only if they exist
21
+ // and are not sensitive.
22
+ for (const rel of USER_SCOPE_RELATIVE_PATHS) {
23
+ const candidate = path.join(options.homeDir, rel);
24
+ if (isSensitivePath(candidate))
25
+ continue;
26
+ if (await pathExists(candidate)) {
27
+ collected.add(candidate);
28
+ }
29
+ }
30
+ // Project-scope: every immediate child of each dev root that has an AI marker.
31
+ for (const devRoot of options.devRoots) {
32
+ let entries;
33
+ try {
34
+ entries = await fs.readdir(devRoot, { withFileTypes: true });
35
+ }
36
+ catch {
37
+ continue;
38
+ }
39
+ for (const entry of entries) {
40
+ if (!entry.isDirectory() && !entry.isSymbolicLink())
41
+ continue;
42
+ if (entry.name.startsWith("."))
43
+ continue;
44
+ const projectPath = path.join(devRoot, entry.name);
45
+ if (isSensitivePath(projectPath))
46
+ continue;
47
+ if (await hasProjectMarker(projectPath)) {
48
+ collected.add(projectPath);
49
+ }
50
+ }
51
+ }
52
+ return [...collected].sort();
53
+ }
54
+ async function pathExists(p) {
55
+ try {
56
+ await fs.stat(p);
57
+ return true;
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ async function hasProjectMarker(projectPath) {
64
+ for (const dirName of PROJECT_MARKER_DIRS) {
65
+ try {
66
+ const stat = await fs.stat(path.join(projectPath, dirName));
67
+ if (stat.isDirectory())
68
+ return true;
69
+ }
70
+ catch {
71
+ // not present
72
+ }
73
+ }
74
+ for (const fileName of PROJECT_MARKER_FILES) {
75
+ try {
76
+ const stat = await fs.stat(path.join(projectPath, fileName));
77
+ if (stat.isFile())
78
+ return true;
79
+ }
80
+ catch {
81
+ // not present
82
+ }
83
+ }
84
+ return false;
85
+ }
86
+ export async function runWatchCommand(options = {}) {
87
+ const homeDir = options.homeDir ?? os.homedir();
88
+ const env = options.env ?? process.env;
89
+ const loadAllScansImpl = options.__loadAllScansForTesting ?? defaultLoadAllScans;
90
+ const mountTui = options.__mountTui ?? defaultMountTui;
91
+ const debounceMs = options.debounceMs ?? 300;
92
+ const devRoots = options.devRoots ?? (await readDevRootsConfig(homeDir)).devRoots;
93
+ const watchPaths = await collectWatchPaths({ homeDir, devRoots });
94
+ // Initial scan, awaited before mounting the TUI so the user sees real data
95
+ // immediately (not a frame of empty state).
96
+ const initial = await loadAllScansImpl({
97
+ devRoots,
98
+ homeDir,
99
+ env
100
+ });
101
+ const listeners = new Set();
102
+ const subscribe = (cb) => {
103
+ listeners.add(cb);
104
+ return () => {
105
+ listeners.delete(cb);
106
+ };
107
+ };
108
+ // Rescan coordinator: serialize scans, collapse overlapping triggers.
109
+ let scanInFlight = false;
110
+ let rescanQueued = false;
111
+ let stopped = false;
112
+ const triggerRescan = async () => {
113
+ if (stopped)
114
+ return;
115
+ if (scanInFlight) {
116
+ rescanQueued = true;
117
+ return;
118
+ }
119
+ scanInFlight = true;
120
+ try {
121
+ const next = await loadAllScansImpl({ devRoots, homeDir, env });
122
+ if (stopped)
123
+ return;
124
+ for (const listener of listeners) {
125
+ try {
126
+ listener(next);
127
+ }
128
+ catch {
129
+ // a listener throwing must never crash the watch loop
130
+ }
131
+ }
132
+ }
133
+ catch (error) {
134
+ // Per spec: scan failures become warnings on stderr, never crash.
135
+ process.stderr.write(`ankui watch: rescan failed: ${error instanceof Error ? error.message : String(error)}\n`);
136
+ }
137
+ finally {
138
+ scanInFlight = false;
139
+ if (rescanQueued && !stopped) {
140
+ rescanQueued = false;
141
+ // Schedule on the macrotask queue so the current event loop tick clears.
142
+ setImmediate(() => {
143
+ void triggerRescan();
144
+ });
145
+ }
146
+ }
147
+ };
148
+ const watcher = createWatcher({
149
+ paths: watchPaths,
150
+ onChange: () => {
151
+ void triggerRescan();
152
+ },
153
+ isIgnored: (eventPath) => isSensitivePath(eventPath),
154
+ debounceMs
155
+ });
156
+ await watcher.start();
157
+ // Mount the TUI with a live data source.
158
+ const tui = await mountTui({
159
+ initial,
160
+ subscribe
161
+ });
162
+ // SIGINT handler — clean shutdown.
163
+ const onSigint = () => {
164
+ void shutdown();
165
+ };
166
+ process.once("SIGINT", onSigint);
167
+ const shutdown = async () => {
168
+ if (stopped)
169
+ return;
170
+ stopped = true;
171
+ process.off("SIGINT", onSigint);
172
+ await watcher.stop();
173
+ tui.unsubscribe();
174
+ };
175
+ const exitPromise = (async () => {
176
+ try {
177
+ await tui.waitUntilExit();
178
+ }
179
+ finally {
180
+ await shutdown();
181
+ }
182
+ })();
183
+ return { exitPromise, shutdown };
184
+ }
185
+ async function defaultMountTui(dataSource) {
186
+ // Track the App-side unsubscribe through the subscribe closure: we wrap the
187
+ // caller's subscribe to capture and return its cleanup function.
188
+ let appUnsubscribe;
189
+ const wrapped = {
190
+ initial: dataSource.initial,
191
+ subscribe: (cb) => {
192
+ const off = dataSource.subscribe(cb);
193
+ appUnsubscribe = off;
194
+ return off;
195
+ }
196
+ };
197
+ const waitUntilExit = defaultRenderTui(wrapped);
198
+ return {
199
+ waitUntilExit: () => waitUntilExit,
200
+ unsubscribe: () => {
201
+ appUnsubscribe?.();
202
+ }
203
+ };
204
+ }
205
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"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"}