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.
- package/LICENSE +21 -0
- package/README.md +369 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +192 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/access.d.ts +6 -0
- package/dist/commands/access.js +12 -0
- package/dist/commands/access.js.map +1 -0
- package/dist/commands/caps.d.ts +6 -0
- package/dist/commands/caps.js +12 -0
- package/dist/commands/caps.js.map +1 -0
- package/dist/commands/discover.d.ts +10 -0
- package/dist/commands/discover.js +120 -0
- package/dist/commands/discover.js.map +1 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.js +12 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/launch-tui.d.ts +15 -0
- package/dist/commands/launch-tui.js +53 -0
- package/dist/commands/launch-tui.js.map +1 -0
- package/dist/commands/list.d.ts +11 -0
- package/dist/commands/list.js +51 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/mcp.d.ts +6 -0
- package/dist/commands/mcp.js +12 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/scan-all.d.ts +15 -0
- package/dist/commands/scan-all.js +32 -0
- package/dist/commands/scan-all.js.map +1 -0
- package/dist/commands/show.d.ts +7 -0
- package/dist/commands/show.js +12 -0
- package/dist/commands/show.js.map +1 -0
- package/dist/commands/watch.d.ts +32 -0
- package/dist/commands/watch.js +205 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config/ankui-config.d.ts +13 -0
- package/dist/config/ankui-config.js +123 -0
- package/dist/config/ankui-config.js.map +1 -0
- package/dist/scanner/access-review.d.ts +2 -0
- package/dist/scanner/access-review.js +183 -0
- package/dist/scanner/access-review.js.map +1 -0
- package/dist/scanner/adapters/claude.d.ts +2 -0
- package/dist/scanner/adapters/claude.js +298 -0
- package/dist/scanner/adapters/claude.js.map +1 -0
- package/dist/scanner/adapters/codex.d.ts +2 -0
- package/dist/scanner/adapters/codex.js +152 -0
- package/dist/scanner/adapters/codex.js.map +1 -0
- package/dist/scanner/adapters/cursor.d.ts +2 -0
- package/dist/scanner/adapters/cursor.js +114 -0
- package/dist/scanner/adapters/cursor.js.map +1 -0
- package/dist/scanner/adapters/gemini.d.ts +2 -0
- package/dist/scanner/adapters/gemini.js +191 -0
- package/dist/scanner/adapters/gemini.js.map +1 -0
- package/dist/scanner/adapters/index.d.ts +35 -0
- package/dist/scanner/adapters/index.js +85 -0
- package/dist/scanner/adapters/index.js.map +1 -0
- package/dist/scanner/adapters/opencode.d.ts +2 -0
- package/dist/scanner/adapters/opencode.js +231 -0
- package/dist/scanner/adapters/opencode.js.map +1 -0
- package/dist/scanner/adapters/shared.d.ts +57 -0
- package/dist/scanner/adapters/shared.js +239 -0
- package/dist/scanner/adapters/shared.js.map +1 -0
- package/dist/scanner/adapters/skills-sh.d.ts +2 -0
- package/dist/scanner/adapters/skills-sh.js +71 -0
- package/dist/scanner/adapters/skills-sh.js.map +1 -0
- package/dist/scanner/capability-map.d.ts +8 -0
- package/dist/scanner/capability-map.js +57 -0
- package/dist/scanner/capability-map.js.map +1 -0
- package/dist/scanner/discovery.d.ts +31 -0
- package/dist/scanner/discovery.js +320 -0
- package/dist/scanner/discovery.js.map +1 -0
- package/dist/scanner/filesystem-crawler.d.ts +32 -0
- package/dist/scanner/filesystem-crawler.js +210 -0
- package/dist/scanner/filesystem-crawler.js.map +1 -0
- package/dist/scanner/index.d.ts +8 -0
- package/dist/scanner/index.js +120 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/multi-project.d.ts +31 -0
- package/dist/scanner/multi-project.js +227 -0
- package/dist/scanner/multi-project.js.map +1 -0
- package/dist/scanner/parallel.d.ts +4 -0
- package/dist/scanner/parallel.js +41 -0
- package/dist/scanner/parallel.js.map +1 -0
- package/dist/scanner/parsing.d.ts +9 -0
- package/dist/scanner/parsing.js +135 -0
- package/dist/scanner/parsing.js.map +1 -0
- package/dist/scanner/paths.d.ts +8 -0
- package/dist/scanner/paths.js +39 -0
- package/dist/scanner/paths.js.map +1 -0
- package/dist/scanner/preview.d.ts +12 -0
- package/dist/scanner/preview.js +29 -0
- package/dist/scanner/preview.js.map +1 -0
- package/dist/scanner/project-discovery.d.ts +11 -0
- package/dist/scanner/project-discovery.js +35 -0
- package/dist/scanner/project-discovery.js.map +1 -0
- package/dist/scanner/ripgrep.d.ts +11 -0
- package/dist/scanner/ripgrep.js +61 -0
- package/dist/scanner/ripgrep.js.map +1 -0
- package/dist/scanner/safety.d.ts +37 -0
- package/dist/scanner/safety.js +330 -0
- package/dist/scanner/safety.js.map +1 -0
- package/dist/scanner/skill-naming.d.ts +5 -0
- package/dist/scanner/skill-naming.js +53 -0
- package/dist/scanner/skill-naming.js.map +1 -0
- package/dist/scanner/watcher.d.ts +15 -0
- package/dist/scanner/watcher.js +71 -0
- package/dist/scanner/watcher.js.map +1 -0
- package/dist/tui/App.d.ts +33 -0
- package/dist/tui/App.js +201 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/components/Breadcrumb.d.ts +10 -0
- package/dist/tui/components/Breadcrumb.js +11 -0
- package/dist/tui/components/Breadcrumb.js.map +1 -0
- package/dist/tui/components/DisclosureRow.d.ts +17 -0
- package/dist/tui/components/DisclosureRow.js +13 -0
- package/dist/tui/components/DisclosureRow.js.map +1 -0
- package/dist/tui/components/DotLeaderRow.d.ts +17 -0
- package/dist/tui/components/DotLeaderRow.js +34 -0
- package/dist/tui/components/DotLeaderRow.js.map +1 -0
- package/dist/tui/components/EmptyStateWhisper.d.ts +5 -0
- package/dist/tui/components/EmptyStateWhisper.js +6 -0
- package/dist/tui/components/EmptyStateWhisper.js.map +1 -0
- package/dist/tui/components/Frame.d.ts +15 -0
- package/dist/tui/components/Frame.js +21 -0
- package/dist/tui/components/Frame.js.map +1 -0
- package/dist/tui/components/IdleWhisper.d.ts +11 -0
- package/dist/tui/components/IdleWhisper.js +12 -0
- package/dist/tui/components/IdleWhisper.js.map +1 -0
- package/dist/tui/components/KeyHint.d.ts +13 -0
- package/dist/tui/components/KeyHint.js +12 -0
- package/dist/tui/components/KeyHint.js.map +1 -0
- package/dist/tui/components/LoadingSplash.d.ts +12 -0
- package/dist/tui/components/LoadingSplash.js +55 -0
- package/dist/tui/components/LoadingSplash.js.map +1 -0
- package/dist/tui/components/ProgressBar.d.ts +16 -0
- package/dist/tui/components/ProgressBar.js +24 -0
- package/dist/tui/components/ProgressBar.js.map +1 -0
- package/dist/tui/components/SearchBox.d.ts +5 -0
- package/dist/tui/components/SearchBox.js +6 -0
- package/dist/tui/components/SearchBox.js.map +1 -0
- package/dist/tui/components/SectionHeader.d.ts +12 -0
- package/dist/tui/components/SectionHeader.js +14 -0
- package/dist/tui/components/SectionHeader.js.map +1 -0
- package/dist/tui/components/SkillViewport.d.ts +8 -0
- package/dist/tui/components/SkillViewport.js +42 -0
- package/dist/tui/components/SkillViewport.js.map +1 -0
- package/dist/tui/components/Spinner.d.ts +11 -0
- package/dist/tui/components/Spinner.js +13 -0
- package/dist/tui/components/Spinner.js.map +1 -0
- package/dist/tui/components/StatusPill.d.ts +13 -0
- package/dist/tui/components/StatusPill.js +15 -0
- package/dist/tui/components/StatusPill.js.map +1 -0
- package/dist/tui/components/TabBar.d.ts +20 -0
- package/dist/tui/components/TabBar.js +26 -0
- package/dist/tui/components/TabBar.js.map +1 -0
- package/dist/tui/components/TextInput.d.ts +13 -0
- package/dist/tui/components/TextInput.js +34 -0
- package/dist/tui/components/TextInput.js.map +1 -0
- package/dist/tui/hooks/use-idle-whisper.d.ts +17 -0
- package/dist/tui/hooks/use-idle-whisper.js +66 -0
- package/dist/tui/hooks/use-idle-whisper.js.map +1 -0
- package/dist/tui/hooks/use-rotating-message.d.ts +20 -0
- package/dist/tui/hooks/use-rotating-message.js +34 -0
- package/dist/tui/hooks/use-rotating-message.js.map +1 -0
- package/dist/tui/input/use-keys.d.ts +16 -0
- package/dist/tui/input/use-keys.js +32 -0
- package/dist/tui/input/use-keys.js.map +1 -0
- package/dist/tui/messages.d.ts +18 -0
- package/dist/tui/messages.js +59 -0
- package/dist/tui/messages.js.map +1 -0
- package/dist/tui/render.d.ts +12 -0
- package/dist/tui/render.js +112 -0
- package/dist/tui/render.js.map +1 -0
- package/dist/tui/screens/AccessTab.d.ts +6 -0
- package/dist/tui/screens/AccessTab.js +26 -0
- package/dist/tui/screens/AccessTab.js.map +1 -0
- package/dist/tui/screens/DoctorTab.d.ts +6 -0
- package/dist/tui/screens/DoctorTab.js +24 -0
- package/dist/tui/screens/DoctorTab.js.map +1 -0
- package/dist/tui/screens/FirstRunScan.d.ts +11 -0
- package/dist/tui/screens/FirstRunScan.js +128 -0
- package/dist/tui/screens/FirstRunScan.js.map +1 -0
- package/dist/tui/screens/McpsTab.d.ts +6 -0
- package/dist/tui/screens/McpsTab.js +30 -0
- package/dist/tui/screens/McpsTab.js.map +1 -0
- package/dist/tui/screens/Overview.d.ts +6 -0
- package/dist/tui/screens/Overview.js +75 -0
- package/dist/tui/screens/Overview.js.map +1 -0
- package/dist/tui/screens/ProjectDrillIn.d.ts +10 -0
- package/dist/tui/screens/ProjectDrillIn.js +16 -0
- package/dist/tui/screens/ProjectDrillIn.js.map +1 -0
- package/dist/tui/screens/Settings.d.ts +8 -0
- package/dist/tui/screens/Settings.js +71 -0
- package/dist/tui/screens/Settings.js.map +1 -0
- package/dist/tui/screens/ToolTab.d.ts +9 -0
- package/dist/tui/screens/ToolTab.js +38 -0
- package/dist/tui/screens/ToolTab.js.map +1 -0
- package/dist/tui/screens/UserScopeDrillIn.d.ts +13 -0
- package/dist/tui/screens/UserScopeDrillIn.js +15 -0
- package/dist/tui/screens/UserScopeDrillIn.js.map +1 -0
- package/dist/tui/state/navigation.d.ts +1 -0
- package/dist/tui/state/navigation.js +11 -0
- package/dist/tui/state/navigation.js.map +1 -0
- package/dist/tui/state/settings-state.d.ts +22 -0
- package/dist/tui/state/settings-state.js +30 -0
- package/dist/tui/state/settings-state.js.map +1 -0
- package/dist/tui/state/tui-state.d.ts +57 -0
- package/dist/tui/state/tui-state.js +86 -0
- package/dist/tui/state/tui-state.js.map +1 -0
- package/dist/tui/theme/borders.d.ts +20 -0
- package/dist/tui/theme/borders.js +25 -0
- package/dist/tui/theme/borders.js.map +1 -0
- package/dist/tui/theme/colors.d.ts +14 -0
- package/dist/tui/theme/colors.js +18 -0
- package/dist/tui/theme/colors.js.map +1 -0
- package/dist/tui/theme/icons.d.ts +30 -0
- package/dist/tui/theme/icons.js +51 -0
- package/dist/tui/theme/icons.js.map +1 -0
- package/dist/tui/util/doctor-grouping.d.ts +27 -0
- package/dist/tui/util/doctor-grouping.js +67 -0
- package/dist/tui/util/doctor-grouping.js.map +1 -0
- package/dist/tui/util/finding-grouping.d.ts +24 -0
- package/dist/tui/util/finding-grouping.js +43 -0
- package/dist/tui/util/finding-grouping.js.map +1 -0
- package/dist/tui/util/mcp-grouping.d.ts +27 -0
- package/dist/tui/util/mcp-grouping.js +96 -0
- package/dist/tui/util/mcp-grouping.js.map +1 -0
- package/dist/tui/util/scan-history.d.ts +15 -0
- package/dist/tui/util/scan-history.js +43 -0
- package/dist/tui/util/scan-history.js.map +1 -0
- package/dist/tui/util/skill-filter.d.ts +2 -0
- package/dist/tui/util/skill-filter.js +7 -0
- package/dist/tui/util/skill-filter.js.map +1 -0
- package/dist/tui/util/skill-grouping.d.ts +3 -0
- package/dist/tui/util/skill-grouping.js +31 -0
- package/dist/tui/util/skill-grouping.js.map +1 -0
- package/dist/types.d.ts +151 -0
- package/dist/types.js +143 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/errors.d.ts +1 -0
- package/dist/utils/errors.js +7 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/format-access.d.ts +3 -0
- package/dist/utils/format-access.js +94 -0
- package/dist/utils/format-access.js.map +1 -0
- package/dist/utils/format-caps.d.ts +3 -0
- package/dist/utils/format-caps.js +139 -0
- package/dist/utils/format-caps.js.map +1 -0
- package/dist/utils/format-doctor.d.ts +3 -0
- package/dist/utils/format-doctor.js +105 -0
- package/dist/utils/format-doctor.js.map +1 -0
- package/dist/utils/format-list.d.ts +7 -0
- package/dist/utils/format-list.js +112 -0
- package/dist/utils/format-list.js.map +1 -0
- package/dist/utils/format-mcp.d.ts +3 -0
- package/dist/utils/format-mcp.js +130 -0
- package/dist/utils/format-mcp.js.map +1 -0
- package/dist/utils/format-multi-project.d.ts +3 -0
- package/dist/utils/format-multi-project.js +100 -0
- package/dist/utils/format-multi-project.js.map +1 -0
- package/dist/utils/format-show.d.ts +6 -0
- package/dist/utils/format-show.js +143 -0
- package/dist/utils/format-show.js.map +1 -0
- package/dist/utils/format.d.ts +3 -0
- package/dist/utils/format.js +53 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/paths.d.ts +1 -0
- package/dist/utils/paths.js +10 -0
- package/dist/utils/paths.js.map +1 -0
- 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
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
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -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,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 };
|