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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mert Cetin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,369 @@
1
+ # Ankui
2
+
3
+ > Local-only inventory of what your AI coding tools can access.
4
+
5
+ ## What Ankui is
6
+
7
+ AI coding tools accumulate configuration, skills, rules, and MCP servers across your filesystem, and it is easy to lose track of what each one can access. Ankui is a read-only local scanner and terminal UI that inventories those resources and surfaces access findings — it never executes user code, follows remote URLs, or sends data anywhere. Supported tools: Claude, Codex, Cursor, Gemini, OpenCode, and skills.sh.
8
+
9
+ ## Try it
10
+
11
+ ```bash
12
+ npx -y ankui@latest
13
+ ```
14
+
15
+ For a persistent install:
16
+
17
+ ```bash
18
+ npm install -g ankui
19
+ ankui
20
+ ```
21
+
22
+ Requires Node >= 20.
23
+
24
+ ## Quick start
25
+
26
+ Running `ankui` with no arguments opens the interactive terminal UI. Running `ankui scan` prints a summary to stdout:
27
+
28
+ ```
29
+ Ankui scan complete
30
+
31
+ Detected tools: 5
32
+ MCP servers: 6 configured, 4 unique
33
+ Agent skills: 154
34
+ Commands/prompts/agents/rules/tools: 12
35
+ Memory files: 0
36
+ Access findings: 12
37
+ Warnings: 0
38
+
39
+ Tools:
40
+ ✓ Claude 1 MCP · 49 agent skills · 1 rules · 6 plugins · 3 findings
41
+ ✓ Codex 3 MCP · 58 agent skills · 1 rules · 5 findings
42
+ ✓ Cursor 1 MCP · 1 findings
43
+ ✓ Gemini 1 MCP · 47 agent skills · 4 plugins · 3 findings
44
+ ✓ OpenCode detected
45
+ - skills.sh not detected
46
+ ```
47
+
48
+ Add `--json` to get the full sanitized scan result as JSON:
49
+
50
+ ```bash
51
+ ankui --json | jq '[.tools[] | select(.id == "claude") | .skills[]] | length'
52
+ ```
53
+
54
+ `.tools` is an array of `{ id, skills, findings, ... }` objects, not an object keyed by tool id.
55
+
56
+ ## Privacy and safety
57
+
58
+ Ankui sends no data anywhere and calls no external APIs.
59
+
60
+ **Sensitive files skipped.** Any file matching these patterns is skipped with a `sensitive_file_skipped` warning rather than read:
61
+
62
+ - `.env` and any file starting with `.env`
63
+ - Files containing `token`, `secret`, or `credential` in the name
64
+ - Files starting with `auth`, `cookies`, or `session`
65
+ - Files ending with `.pem` or `.key`
66
+ - Files containing `apikey` or `api_key`
67
+ - Files starting with `private_key`
68
+
69
+ **Sensitive directories skipped.** Any path containing these directory segments is never entered:
70
+
71
+ - Common across all tools: `sessions`, `session`, `history`, `histories`, `conversation`, `conversations`
72
+ - Additional for OpenCode paths: `auth`, `log`, `logs`, `share`, `cache`, `database`, `databases`, `db`, `runtime`
73
+
74
+ **File size cap.** Files larger than 1 MB (`MAX_SAFE_FILE_BYTES = 1024 * 1024`) are skipped with a `file_too_large` warning.
75
+
76
+ **Symlinks.** Symlinks whose resolved targets fall inside `$HOME` or `$CWD` are followed and reported with `details.linked: true` and `details.linkTarget`. Symlinks pointing outside those roots, or whose resolved target hits a sensitive path segment, produce a `symlink_skipped` warning and are not read.
77
+
78
+ **Secret masking.** MCP server env blocks have all values replaced with `......`. Any value under a key matching `auth`, `authorization`, `token`, `secret`, `credential`, `password`, `passwd`, `apikey`, `private_key`, `access_token`, `refresh_token`, `auth_token`, or `client_secret` is masked before the result is returned. Credential URLs (Basic auth username/password) are masked in MCP command args.
79
+
80
+ **Session, history, auth, log, and database files are never read.** The directory exclusions above cover OpenCode's runtime database, session store, share store, auth store, and log directories. No conversation data or model response history is ever accessed.
81
+
82
+ ## Supported tools
83
+
84
+ | Tool | User-scope paths | Project-scope paths |
85
+ |------|-----------------|---------------------|
86
+ | **Claude** | `~/.claude/` (settings, skills, commands, agents), `~/.claude.json` | `.claude/` (settings, skills, commands, agents), `CLAUDE.md`, `CLAUDE.local.md`, `.mcp.json` |
87
+ | **Codex** | `~/.codex/config.toml` (MCP servers), `~/.codex/prompts/` (custom prompts), `~/.codex/skills/` (agent skills), `~/.codex/rules/` (permission rules) | `.codex/config.toml`, `.codex/prompts/`, `.codex/skills/`, `AGENTS.md` |
88
+ | **Cursor** | `~/.cursor/mcp.json` (MCP servers), `~/.cursor/rules/` (`.mdc` rules files) | `.cursor/mcp.json`, `.cursor/rules/`, `.mcp.json`, `.cursorrules` |
89
+ | **Gemini** | `~/.gemini/settings.json` (MCP servers), `~/.gemini/commands/` (custom commands), `~/.gemini/skills/` (agent skills), `~/.gemini/extensions/` (extensions) | `.gemini/commands/`, `.gemini/skills/`, `GEMINI.md` |
90
+ | **OpenCode** | `~/.config/opencode/` (agents, commands, tools, skills) | `opencode.json`, `opencode.jsonc` (MCP servers, plugins, tool permissions), `.opencode/` (agents, commands, tools, skills), `AGENTS.md` |
91
+ | **skills.sh** | `~/.skills/`, `~/.config/skills/` | `.skills/` |
92
+
93
+ Each tool adapter reads only from the paths listed above. All access goes through the safety layer described in the previous section.
94
+
95
+ ## CLI commands
96
+
97
+ Global flags that apply to all commands:
98
+
99
+ - `--json` — print the full sanitized result as JSON instead of human-readable output.
100
+ - `--no-color` — disable ANSI colour codes (useful in CI or when piping output).
101
+
102
+ ---
103
+
104
+ ### `ankui scan`
105
+
106
+ Run a local scan and print a summary.
107
+
108
+ ```
109
+ Usage: ankui scan [options]
110
+
111
+ Run a local scan and print a summary.
112
+ ```
113
+
114
+ No tool-specific flags. The command reads user-scope and project-scope paths for all six tools and prints the counts shown in the Quick start section above.
115
+
116
+ ---
117
+
118
+ ### `ankui tui`
119
+
120
+ Open the interactive terminal UI.
121
+
122
+ ```
123
+ Usage: ankui tui [options]
124
+
125
+ Open the interactive terminal UI.
126
+ ```
127
+
128
+ `ankui` with no arguments is equivalent to `ankui tui`. On first launch (before `~/.config/ankui/config.json` exists), the first-run wizard runs to let you pick dev roots. After that, the full multi-project TUI opens. See the TUI keybindings section below.
129
+
130
+ ---
131
+
132
+ ### `ankui watch`
133
+
134
+ Open the TUI and live-rescan when config files change.
135
+
136
+ ```
137
+ Usage: ankui watch [options]
138
+
139
+ Open the TUI and live-rescan when config files change.
140
+ ```
141
+
142
+ Uses chokidar to watch known tool directories and AI-project files under registered dev roots. File changes are debounced (300 ms stabilisation threshold). Sensitive directories are excluded from the watch list. Press `q` or `Ctrl-C` to quit.
143
+
144
+ ---
145
+
146
+ ### `ankui access`
147
+
148
+ Print findings and review recommendations from the scan.
149
+
150
+ ```
151
+ Usage: ankui access [options]
152
+
153
+ Print findings and review recommendations from the scan.
154
+ ```
155
+
156
+ Findings are grouped by category in priority order: `duplicate_mcp` (the same MCP server configured across multiple tools), `secret_reference` (MCP servers with secret-bearing env keys), `dangerous_pattern` (skills containing `curl | sh`, `rm -rf`, or similar patterns), `unknown_capability` (MCP servers not in the built-in catalog).
157
+
158
+ Example output structure:
159
+
160
+ ```
161
+ Ankui access review — 10 findings (6 dangerous_pattern · 2 duplicate_mcp · 1 secret_reference · 1 unknown_capability)
162
+
163
+ Duplicate MCP servers (2)
164
+ ─────────────────────────
165
+ • Reddit MCP is configured in 2 tools
166
+ Scope: cross_tool · Tools: codex, gemini
167
+ ...
168
+ ```
169
+
170
+ ---
171
+
172
+ ### `ankui mcp`
173
+
174
+ Print a cross-tool MCP server overview.
175
+
176
+ ```
177
+ Usage: ankui mcp [options]
178
+
179
+ Print a cross-tool MCP server overview.
180
+ ```
181
+
182
+ Groups all configured MCP servers by canonical name. Shows capability category, access level, which tools have the server configured, and whether any configuration carries secret-bearing env keys. Cross-tool duplicates are flagged with a warning line.
183
+
184
+ ---
185
+
186
+ ### `ankui caps`
187
+
188
+ Print MCP capability categories overview.
189
+
190
+ ```
191
+ Usage: ankui caps [options]
192
+
193
+ Print MCP capability categories overview.
194
+ ```
195
+
196
+ Lists classified MCP servers grouped by capability category (`network`, `communication`, `filesystem`, etc.) in descending order of count, then prints a footer with the count of markdown-backed skills that are not categorised in this view. Unknown MCP servers (not in the built-in catalog) are not included in the category groups.
197
+
198
+ ---
199
+
200
+ ### `ankui doctor`
201
+
202
+ Print detection status and scanner warnings.
203
+
204
+ ```
205
+ Usage: ankui doctor [options]
206
+
207
+ Print detection status and scanner warnings.
208
+ ```
209
+
210
+ Shows which tools were detected and which paths each tool found at user scope and project scope. After the tool list, warnings are grouped by reason (`sensitive_file_skipped`, `symlink_skipped`, `file_too_large`, `permission_denied`, `parse_error`, `timeout`). A clean machine ends with `No warnings.`
211
+
212
+ ---
213
+
214
+ ### `ankui scan-all`
215
+
216
+ Run scans across every project in every registered dev root.
217
+
218
+ ```
219
+ Usage: ankui scan-all [options]
220
+
221
+ Run scans across every project in every registered dev root.
222
+ ```
223
+
224
+ Reads dev roots from `~/.config/ankui/config.json` (written by `ankui discover --apply` or the first-run TUI wizard). Scans up to 10 projects in parallel with a 5-second per-project timeout. Output shows user-scope skill counts followed by a per-project table.
225
+
226
+ Example:
227
+
228
+ ```
229
+ Ankui multi-project scan — 16 projects across 3 dev roots, 178 user-scope skills
230
+
231
+ User scope
232
+ ──────────
233
+ ✓ Claude 63 skills
234
+ ✓ Codex 62 skills
235
+ ...
236
+
237
+ Projects (16)
238
+ ─────────────
239
+ ~/Developer/Ceto's Projects/ankui 1 skills · 0 findings
240
+ ...
241
+ ```
242
+
243
+ ---
244
+
245
+ ### `ankui list`
246
+
247
+ List skills, optionally filtered by `--kind` and `--tool`.
248
+
249
+ ```
250
+ Usage: ankui list [options]
251
+
252
+ List skills, optionally filtered by --kind and --tool.
253
+
254
+ Options:
255
+ --kind <kind> filter by skill kind (e.g., mcp_server, agent_skill)
256
+ --tool <tool> filter by tool id (e.g., claude, codex)
257
+ ```
258
+
259
+ Valid skill kinds include `mcp_server`, `agent_skill`, `custom_agents`, `custom_commands`, `custom_prompts`, `custom_tools`, `memory_file`, `rules`, `plugins`, `skills_sh_skill`. Valid tool ids are `claude`, `codex`, `cursor`, `gemini`, `opencode`, `skills-sh`. An invalid filter value exits with code 1 and a usage message.
260
+
261
+ ---
262
+
263
+ ### `ankui show <tool>`
264
+
265
+ Print one tool's detected paths and skills.
266
+
267
+ ```
268
+ Usage: ankui show [options] <tool>
269
+
270
+ Print one tool's detected paths and skills.
271
+ ```
272
+
273
+ Prints detected paths grouped by scope (user vs project), then all skills grouped by kind in canonical order. An unknown tool id exits with code 1 and lists the valid ids.
274
+
275
+ Example:
276
+
277
+ ```
278
+ Ankui — claude
279
+
280
+ Detected at:
281
+ user:
282
+ ~/.claude
283
+ ~/.claude.json
284
+ project:
285
+ ./.claude
286
+ ./.claude/settings.local.json
287
+
288
+ mcp_server (1)
289
+ ──────────────
290
+ expo-mcp ~/.claude.json
291
+
292
+ agent_skill (49)
293
+ ────────────────
294
+ autoplan ~/.claude/skills/autoplan/SKILL.md
295
+ ...
296
+ ```
297
+
298
+ ---
299
+
300
+ ### `ankui discover`
301
+
302
+ Crawl `~` for AI projects and propose dev roots for `~/.config/ankui/config.json`.
303
+
304
+ ```
305
+ Usage: ankui discover [options]
306
+
307
+ Crawl ~ for AI projects and propose dev roots for ~/.config/ankui/config.json.
308
+
309
+ Options:
310
+ --apply write the default-ON dev roots into the config file (default: false)
311
+ ```
312
+
313
+ Crawls your home directory (max depth 6, concurrency 16) for directories that contain AI-tool marker files or directories. Groups found projects by parent directory into dev-root candidates. Parents with 3 or more AI projects are marked default-ON. Prints a dry-run summary by default; pass `--apply` to merge the selected roots into `~/.config/ankui/config.json`. A second `--apply` with the same roots is a no-op.
314
+
315
+ ---
316
+
317
+ ## TUI keybindings
318
+
319
+ | Key | Action |
320
+ |-----|--------|
321
+ | `←` / `→` | Cycle between tabs |
322
+ | `↑` / `↓` | Scroll the skill list in a drill-in screen |
323
+ | `Enter` | Drill into the selected item |
324
+ | `Esc` / `Backspace` | Drill out (return to the previous screen) |
325
+ | `/` | Open incremental search (drill-in screens only) |
326
+ | `r` | Rescan (refresh data from disk) |
327
+ | `q` | Quit |
328
+
329
+ Note: `Tab` is reserved for future focus navigation and does not cycle tabs in this version.
330
+
331
+ ## Local development
332
+
333
+ ```bash
334
+ npm install
335
+ npm run typecheck # TypeScript strict-mode check (no emit)
336
+ npm test # runs 407 tests via node:test + tsx
337
+ npm run build # emits to dist/
338
+ node dist/cli.js scan # smoke test against your real local config
339
+ ```
340
+
341
+ Tests use the built-in `node:test` runner via `tsx`. Do not add Jest or Vitest unless explicitly required.
342
+
343
+ After a build, use `node dist/cli.js <command>` for local testing. All commands support `--json` for machine-readable output.
344
+
345
+ ## Contributing an adapter
346
+
347
+ Adapters live in `src/scanner/adapters/`. Each adapter exports a `ScannerAdapter` object with a `toolId` and an async `scan(context)` method.
348
+
349
+ Invariants for any new adapter:
350
+
351
+ - Use `safeReadOptions(filePath, context)` from `shared.ts` for every file read. This enforces the symlink allowlist and file size cap consistently across all adapters.
352
+ - Never throw. Wrap all I/O in try/catch or rely on the safe helpers; produce `Warning` objects for every failure and attach them to the adapter result. The adapter runner isolates each adapter with a 1-second timeout, but adapters should still handle their own errors gracefully.
353
+ - Respect the 1 MB file size cap (`MAX_SAFE_FILE_BYTES` from `safety.ts`) and the 1-second per-adapter time budget.
354
+ - For markdown-backed skill paths (skills with `SKILL.md` or similar), call `await buildLinkDetails(filePath, context)` from `shared.ts` and spread the result into the `details` object. This ensures symlink metadata (`linked`, `linkTarget`) is recorded on every markdown skill.
355
+ - Add the adapter to `src/scanner/adapters/index.ts` so the scanner runner picks it up.
356
+
357
+ The scanner invariant is: every file or directory access goes through `src/scanner/safety.ts`. No adapter should call `fs.readFile` or `fs.readdir` directly.
358
+
359
+ ## v1.1 roadmap
360
+
361
+ These items are deferred from the v1 MVP and are not scheduled:
362
+
363
+ **Similar-skill search.** Fuzzy match and token-overlap grouping across skill names, summaries, categories, and source paths. Would surface cases where the same conceptual skill (e.g. a GitHub MCP server, or a "careful" rule) is configured under multiple tools with slightly different names. No network calls; local only using the `fuse.js` dependency already present.
364
+
365
+ **Manual custom tools storage.** An Ankui-managed store (`~/.ankui/manual-tools.json`) for tracking tools that are not disk-detected. OpenCode custom tools are already in v1 because they come from real files; this deferred phase covers Ankui-managed entries only. Manual tools would be clearly marked as custom and kept separate from adapter-detected results.
366
+
367
+ ---
368
+
369
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { runAccessCommand } from "./commands/access.js";
4
+ import { runCapsCommand } from "./commands/caps.js";
5
+ import { runDiscoverCommand } from "./commands/discover.js";
6
+ import { runDoctorCommand } from "./commands/doctor.js";
7
+ import { runListCommand } from "./commands/list.js";
8
+ import { runMcpCommand } from "./commands/mcp.js";
9
+ import { runScanAllCommand } from "./commands/scan-all.js";
10
+ import { runShowCommand } from "./commands/show.js";
11
+ import { runWatchCommand } from "./commands/watch.js";
12
+ import { buildLaunchTuiResult } from "./commands/launch-tui.js";
13
+ import { getAnkuiConfigPath, mergeDevRoots, writeAnkuiConfig } from "./config/ankui-config.js";
14
+ import { scan } from "./scanner/index.js";
15
+ import { renderTui } from "./tui/render.js";
16
+ import { formatError } from "./utils/errors.js";
17
+ import { formatJson, formatScanSummary } from "./utils/format.js";
18
+ import fs from "node:fs/promises";
19
+ import os from "node:os";
20
+ const program = new Command();
21
+ program
22
+ .name("ankui")
23
+ .description("Remember what your AI agents can access.")
24
+ .option("--json", "print the full sanitized scan result as JSON")
25
+ .option("--no-color", "disable ANSI colors")
26
+ .action(async () => {
27
+ const globalOptions = program.opts();
28
+ if (globalOptions.json) {
29
+ await runScanCommand();
30
+ return;
31
+ }
32
+ await launchTui();
33
+ });
34
+ program
35
+ .command("scan")
36
+ .description("Run a local scan and print a summary.")
37
+ .action(async () => {
38
+ await runScanCommand();
39
+ });
40
+ program
41
+ .command("tui")
42
+ .description("Open the interactive terminal UI.")
43
+ .action(async () => {
44
+ await launchTui();
45
+ });
46
+ program
47
+ .command("watch")
48
+ .description("Open the TUI and live-rescan when config files change.")
49
+ .action(async () => {
50
+ const handle = await runWatchCommand();
51
+ await handle.exitPromise;
52
+ });
53
+ program
54
+ .command("access")
55
+ .description("Print findings and review recommendations from the scan.")
56
+ .action(async () => {
57
+ const globalOptions = program.opts();
58
+ await runAccessCommand({
59
+ json: Boolean(globalOptions.json),
60
+ write: (chunk) => process.stdout.write(chunk)
61
+ });
62
+ });
63
+ program
64
+ .command("mcp")
65
+ .description("Print a cross-tool MCP server overview.")
66
+ .action(async () => {
67
+ const globalOptions = program.opts();
68
+ await runMcpCommand({
69
+ json: Boolean(globalOptions.json),
70
+ write: (chunk) => process.stdout.write(chunk)
71
+ });
72
+ });
73
+ program
74
+ .command("doctor")
75
+ .description("Print detection status and scanner warnings.")
76
+ .action(async () => {
77
+ const globalOptions = program.opts();
78
+ await runDoctorCommand({
79
+ json: Boolean(globalOptions.json),
80
+ write: (chunk) => process.stdout.write(chunk)
81
+ });
82
+ });
83
+ program
84
+ .command("scan-all")
85
+ .description("Run scans across every project in every registered dev root.")
86
+ .action(async () => {
87
+ const globalOptions = program.opts();
88
+ await runScanAllCommand({
89
+ json: Boolean(globalOptions.json),
90
+ write: (chunk) => process.stdout.write(chunk)
91
+ });
92
+ });
93
+ program
94
+ .command("caps")
95
+ .description("Print MCP capability categories overview.")
96
+ .action(async () => {
97
+ const globalOptions = program.opts();
98
+ await runCapsCommand({
99
+ json: Boolean(globalOptions.json),
100
+ write: (chunk) => process.stdout.write(chunk)
101
+ });
102
+ });
103
+ program
104
+ .command("list")
105
+ .description("List skills, optionally filtered by --kind and --tool.")
106
+ .option("--kind <kind>", "filter by skill kind (e.g., mcp_server, agent_skill)")
107
+ .option("--tool <tool>", "filter by tool id (e.g., claude, codex)")
108
+ .action(async (cmdOpts) => {
109
+ const globalOptions = program.opts();
110
+ await runListCommand({
111
+ json: Boolean(globalOptions.json),
112
+ kind: cmdOpts.kind,
113
+ tool: cmdOpts.tool,
114
+ write: (chunk) => process.stdout.write(chunk)
115
+ });
116
+ });
117
+ program
118
+ .command("show <tool>")
119
+ .description("Print one tool's detected paths and skills.")
120
+ .action(async (toolId) => {
121
+ const globalOptions = program.opts();
122
+ await runShowCommand({
123
+ toolId,
124
+ json: Boolean(globalOptions.json),
125
+ write: (chunk) => process.stdout.write(chunk)
126
+ });
127
+ });
128
+ program
129
+ .command("discover")
130
+ .description("Crawl ~ for AI projects and propose dev roots for ~/.config/ankui/config.json.")
131
+ .option("--apply", "write the default-ON dev roots into the config file", false)
132
+ .action(async (cmdOpts) => {
133
+ const globalOptions = program.opts();
134
+ await runDiscoverCommand({
135
+ apply: Boolean(cmdOpts.apply),
136
+ json: Boolean(globalOptions.json),
137
+ write: (chunk) => process.stdout.write(chunk)
138
+ });
139
+ });
140
+ async function runScanCommand(options = {}) {
141
+ const result = await scan();
142
+ const globalOptions = program.opts();
143
+ if (globalOptions.json) {
144
+ process.stdout.write(formatJson(result));
145
+ return;
146
+ }
147
+ if (options.showTuiPlaceholder) {
148
+ process.stdout.write("Ankui TUI is not implemented yet. Showing scan summary instead.\n\n");
149
+ }
150
+ process.stdout.write(`${formatScanSummary(result)}\n`);
151
+ }
152
+ async function launchTui() {
153
+ const homeDir = os.homedir();
154
+ const configPath = getAnkuiConfigPath(homeDir);
155
+ if (!(await fileExists(configPath))) {
156
+ // First-run mode: render the FirstRunScan wizard. The user picks dev roots;
157
+ // onConfigChange writes the config file, then App exits Ink so the next
158
+ // `ankui` invocation launches against a freshly populated config.
159
+ await renderTui({
160
+ mode: "firstRun",
161
+ homeDir,
162
+ onConfigChange: async (devRoots) => {
163
+ const merged = mergeDevRoots([], devRoots);
164
+ await writeAnkuiConfig({ version: 1, devRoots: merged }, homeDir);
165
+ }
166
+ });
167
+ return;
168
+ }
169
+ await renderTui({
170
+ loadScan: () => buildLaunchTuiResult({
171
+ homeDir,
172
+ env: process.env
173
+ })
174
+ });
175
+ }
176
+ async function fileExists(filePath) {
177
+ try {
178
+ await fs.access(filePath);
179
+ return true;
180
+ }
181
+ catch {
182
+ return false;
183
+ }
184
+ }
185
+ try {
186
+ await program.parseAsync(process.argv);
187
+ }
188
+ catch (error) {
189
+ process.stderr.write(`ankui: ${formatError(error)}\n`);
190
+ process.exitCode = 1;
191
+ }
192
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type ScanOptions } from "../scanner/index.js";
2
+ export interface AccessCommandOptions extends ScanOptions {
3
+ json: boolean;
4
+ write: (chunk: string) => void;
5
+ }
6
+ export declare function runAccessCommand(options: AccessCommandOptions): Promise<void>;
@@ -0,0 +1,12 @@
1
+ import { scan } from "../scanner/index.js";
2
+ import { formatAccessReview, formatAccessReviewJson } from "../utils/format-access.js";
3
+ export async function runAccessCommand(options) {
4
+ const { json, write, ...scanOptions } = options;
5
+ const result = await scan(scanOptions);
6
+ if (json) {
7
+ write(formatAccessReviewJson(result));
8
+ return;
9
+ }
10
+ write(`${formatAccessReview(result)}\n`);
11
+ }
12
+ //# sourceMappingURL=access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../../src/commands/access.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAoB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAOvF,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,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;QACtC,OAAO;IACT,CAAC;IAED,KAAK,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { type ScanOptions } from "../scanner/index.js";
2
+ export interface CapsCommandOptions extends ScanOptions {
3
+ json: boolean;
4
+ write: (chunk: string) => void;
5
+ }
6
+ export declare function runCapsCommand(options: CapsCommandOptions): Promise<void>;
@@ -0,0 +1,12 @@
1
+ import { scan } from "../scanner/index.js";
2
+ import { formatCapabilities, formatCapabilitiesJson } from "../utils/format-caps.js";
3
+ export async function runCapsCommand(options) {
4
+ const { json, write, ...scanOptions } = options;
5
+ const result = await scan(scanOptions);
6
+ if (json) {
7
+ write(formatCapabilitiesJson(result));
8
+ return;
9
+ }
10
+ write(`${formatCapabilities(result)}\n`);
11
+ }
12
+ //# sourceMappingURL=caps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caps.js","sourceRoot":"","sources":["../../src/commands/caps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAoB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAOrF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAA2B;IAC9D,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,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;QACtC,OAAO;IACT,CAAC;IAED,KAAK,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Warning } from "../types.js";
2
+ export interface DiscoverCommandOptions {
3
+ apply: boolean;
4
+ json: boolean;
5
+ write: (chunk: string) => void;
6
+ homeDir?: string;
7
+ now?: () => Date;
8
+ }
9
+ export declare function runDiscoverCommand(options: DiscoverCommandOptions): Promise<void>;
10
+ export type { Warning };