@lnar/cli 0.0.1-dev.1da013d

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 (104) hide show
  1. package/README.md +96 -0
  2. package/dist/api-client.d.ts +17 -0
  3. package/dist/api-client.js +35 -0
  4. package/dist/api-client.js.map +1 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +91 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/daemon.d.ts +5 -0
  9. package/dist/commands/daemon.js +158 -0
  10. package/dist/commands/daemon.js.map +1 -0
  11. package/dist/commands/down.d.ts +1 -0
  12. package/dist/commands/down.js +12 -0
  13. package/dist/commands/down.js.map +1 -0
  14. package/dist/commands/login.d.ts +6 -0
  15. package/dist/commands/login.js +86 -0
  16. package/dist/commands/login.js.map +1 -0
  17. package/dist/commands/scan.d.ts +4 -0
  18. package/dist/commands/scan.js +36 -0
  19. package/dist/commands/scan.js.map +1 -0
  20. package/dist/commands/status.d.ts +1 -0
  21. package/dist/commands/status.js +32 -0
  22. package/dist/commands/status.js.map +1 -0
  23. package/dist/commands/sync.d.ts +4 -0
  24. package/dist/commands/sync.js +96 -0
  25. package/dist/commands/sync.js.map +1 -0
  26. package/dist/commands/up.d.ts +3 -0
  27. package/dist/commands/up.js +27 -0
  28. package/dist/commands/up.js.map +1 -0
  29. package/dist/config.d.ts +25 -0
  30. package/dist/config.js +82 -0
  31. package/dist/config.js.map +1 -0
  32. package/dist/hash.d.ts +7 -0
  33. package/dist/hash.js +12 -0
  34. package/dist/hash.js.map +1 -0
  35. package/dist/oauth-client.d.ts +32 -0
  36. package/dist/oauth-client.js +62 -0
  37. package/dist/oauth-client.js.map +1 -0
  38. package/dist/pending-client.d.ts +40 -0
  39. package/dist/pending-client.js +48 -0
  40. package/dist/pending-client.js.map +1 -0
  41. package/dist/scanners/_normalize.d.ts +13 -0
  42. package/dist/scanners/_normalize.js +76 -0
  43. package/dist/scanners/_normalize.js.map +1 -0
  44. package/dist/scanners/chatgpt.d.ts +20 -0
  45. package/dist/scanners/chatgpt.js +49 -0
  46. package/dist/scanners/chatgpt.js.map +1 -0
  47. package/dist/scanners/claude-code-plugins.d.ts +2 -0
  48. package/dist/scanners/claude-code-plugins.js +104 -0
  49. package/dist/scanners/claude-code-plugins.js.map +1 -0
  50. package/dist/scanners/claude-code.d.ts +13 -0
  51. package/dist/scanners/claude-code.js +221 -0
  52. package/dist/scanners/claude-code.js.map +1 -0
  53. package/dist/scanners/claude-desktop.d.ts +1 -0
  54. package/dist/scanners/claude-desktop.js +2 -0
  55. package/dist/scanners/claude-desktop.js.map +1 -0
  56. package/dist/scanners/codex.d.ts +5 -0
  57. package/dist/scanners/codex.js +69 -0
  58. package/dist/scanners/codex.js.map +1 -0
  59. package/dist/scanners/cursor.d.ts +9 -0
  60. package/dist/scanners/cursor.js +25 -0
  61. package/dist/scanners/cursor.js.map +1 -0
  62. package/dist/scanners/gemini-cli.d.ts +21 -0
  63. package/dist/scanners/gemini-cli.js +37 -0
  64. package/dist/scanners/gemini-cli.js.map +1 -0
  65. package/dist/scanners/index.d.ts +6 -0
  66. package/dist/scanners/index.js +16 -0
  67. package/dist/scanners/index.js.map +1 -0
  68. package/dist/service/files.d.ts +26 -0
  69. package/dist/service/files.js +119 -0
  70. package/dist/service/files.js.map +1 -0
  71. package/dist/service/install.d.ts +14 -0
  72. package/dist/service/install.js +231 -0
  73. package/dist/service/install.js.map +1 -0
  74. package/dist/types.d.ts +161 -0
  75. package/dist/types.js +53 -0
  76. package/dist/types.js.map +1 -0
  77. package/dist/writers/_fs.d.ts +22 -0
  78. package/dist/writers/_fs.js +55 -0
  79. package/dist/writers/_fs.js.map +1 -0
  80. package/dist/writers/chatgpt.d.ts +8 -0
  81. package/dist/writers/chatgpt.js +12 -0
  82. package/dist/writers/chatgpt.js.map +1 -0
  83. package/dist/writers/claude-code-plugins.d.ts +3 -0
  84. package/dist/writers/claude-code-plugins.js +74 -0
  85. package/dist/writers/claude-code-plugins.js.map +1 -0
  86. package/dist/writers/claude-code.d.ts +4 -0
  87. package/dist/writers/claude-code.js +128 -0
  88. package/dist/writers/claude-code.js.map +1 -0
  89. package/dist/writers/codex.d.ts +4 -0
  90. package/dist/writers/codex.js +88 -0
  91. package/dist/writers/codex.js.map +1 -0
  92. package/dist/writers/cursor.d.ts +4 -0
  93. package/dist/writers/cursor.js +74 -0
  94. package/dist/writers/cursor.js.map +1 -0
  95. package/dist/writers/gemini-cli.d.ts +4 -0
  96. package/dist/writers/gemini-cli.js +87 -0
  97. package/dist/writers/gemini-cli.js.map +1 -0
  98. package/dist/writers/index.d.ts +18 -0
  99. package/dist/writers/index.js +11 -0
  100. package/dist/writers/index.js.map +1 -0
  101. package/dist/writers/registry.d.ts +7 -0
  102. package/dist/writers/registry.js +31 -0
  103. package/dist/writers/registry.js.map +1 -0
  104. package/package.json +38 -0
@@ -0,0 +1,49 @@
1
+ import { stat } from 'node:fs/promises';
2
+ import { homedir, platform } from 'node:os';
3
+ import { join } from 'node:path';
4
+ /**
5
+ * ChatGPT Desktop / ChatGPT connectors のスキャナー (placeholder)。
6
+ *
7
+ * 現状の制限:
8
+ * ChatGPT Desktop (macOS) の connector 一覧は
9
+ * `~/Library/Application Support/com.openai.chat/connector-apps-<uuid>/apps.data` に
10
+ * **暗号化されたバイナリ** で保存されており、平文の MCP 設定として読めない。
11
+ * 暗号鍵は OS Keychain (`com.openai.chat`) に格納されている可能性が高く、
12
+ * ユーザー同意なくアクセスするのは不適切。
13
+ *
14
+ * したがって本スキャナーは「ChatGPT Desktop が **インストールされている**」ことだけを
15
+ * 検出し、agent_kind='chatgpt' の空 snapshot を返す。MCP リストの取得は将来 OpenAI 側で
16
+ * 公開 API が用意されるか、ユーザー操作で明示的に export してもらう必要がある。
17
+ */
18
+ export const chatgptDataDir = (home = homedir(), os = platform()) => {
19
+ if (os === 'darwin') {
20
+ return join(home, 'Library', 'Application Support', 'com.openai.chat');
21
+ }
22
+ if (os === 'win32') {
23
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
24
+ return join(appdata, 'OpenAI', 'ChatGPT');
25
+ }
26
+ // Linux 用クライアントは未公式
27
+ return null;
28
+ };
29
+ const exists = async (path) => {
30
+ if (path == null)
31
+ return false;
32
+ try {
33
+ const s = await stat(path);
34
+ return s.isDirectory();
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ };
40
+ export const scanChatgpt = async (options = {}) => {
41
+ const dir = chatgptDataDir(options.home, options.platform);
42
+ if (!(await exists(dir))) {
43
+ return null;
44
+ }
45
+ // インストール検出済み。設定の読み出しは未対応 — 空 snapshot を返して
46
+ // 「ユーザーが ChatGPT を使っている」事実だけ伝える。
47
+ return { agentKind: 'chatgpt', servers: [] };
48
+ };
49
+ //# sourceMappingURL=chatgpt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatgpt.js","sourceRoot":"","sources":["../../src/scanners/chatgpt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;;;;;;;;;;;GAaG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,OAAe,OAAO,EAAE,EACxB,KAAsB,QAAQ,EAAE,EACjB,EAAE;IACjB,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC;IACD,oBAAoB;IACpB,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,KAAK,EAAE,IAAmB,EAAoB,EAAE;IAC7D,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,UAAyD,EAAE,EAC5B,EAAE;IACjC,MAAM,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3D,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,2CAA2C;IAC3C,iCAAiC;IACjC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAC/C,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { PluginEntry } from '../types.js';
2
+ export declare const scanClaudeCodePlugins: (home?: string) => Promise<PluginEntry[]>;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Claude Code の plugin インストール状態をスキャンする。
3
+ *
4
+ * 読み取り対象:
5
+ * - `~/.claude/plugins/installed_plugins.json`
6
+ * インストール済み plugin の中央レジストリ。`plugins: { <name@marketplace>: [
7
+ * { scope, projectPath, version, installPath, ... } ] }` の形。
8
+ * 1 plugin が user / local / project に複数登録されることがあるので配列。
9
+ * - `~/.claude/settings.json` の `enabledPlugins`
10
+ * user scope での有効/無効フラグ。`{ "<name>@<marketplace>": true }` の dict。
11
+ * - `~/.claude.json` の `projects[<path>].enabledPlugins`
12
+ * local scope での有効/無効フラグ。
13
+ *
14
+ * 注意:
15
+ * - 値ではなく状態 (どれが入っているか) だけを送る
16
+ * - plugin の中に MCP サーバーが入っているケースは別 scanner (claude-code) が
17
+ * `plugin:<name>:<mcp>` として既に拾っているので、ここでは plugin 自体の
18
+ * メタデータだけを扱う
19
+ */
20
+ import { readFile } from 'node:fs/promises';
21
+ import { homedir } from 'node:os';
22
+ import { join } from 'node:path';
23
+ const readJsonOrNull = async (path) => {
24
+ try {
25
+ const text = await readFile(path, 'utf-8');
26
+ return JSON.parse(text);
27
+ }
28
+ catch (err) {
29
+ if (err.code === 'ENOENT')
30
+ return null;
31
+ throw err;
32
+ }
33
+ };
34
+ const VALID_SCOPES = new Set(['user', 'local', 'project']);
35
+ const coerceScope = (raw) => {
36
+ // installed_plugins.json は scope: "project" / "local" / "user" を返す。
37
+ // 想定外の値が来たら drop して呼び出し側で無視する。
38
+ return VALID_SCOPES.has(raw) ? raw : null;
39
+ };
40
+ /**
41
+ * 個別 plugin record を CLI snapshot 用の PluginEntry に正規化する。
42
+ * enabled の判定: scope に応じて user / project のいずれかの enabledPlugins を引く。
43
+ */
44
+ const buildEntry = (name, record, userEnabled, localEnabledByProject) => {
45
+ const scope = coerceScope(record.scope);
46
+ if (scope == null)
47
+ return null;
48
+ let enabled = false;
49
+ if (scope === 'user') {
50
+ enabled = Boolean(userEnabled[name]);
51
+ }
52
+ else if (scope === 'local' && record.projectPath) {
53
+ const projectMap = localEnabledByProject[record.projectPath] ?? {};
54
+ enabled = Boolean(projectMap[name]);
55
+ }
56
+ else if (scope === 'project' && record.projectPath) {
57
+ // project scope は .claude/settings.json (commit される) を読むのが本来だが、
58
+ // 現状は CLI 実行ユーザーから直接見えるとは限らない (別 host のチェックアウト
59
+ // にも入っている可能性があるため)。判定不能なら false にしておく。
60
+ enabled = false;
61
+ }
62
+ return {
63
+ name,
64
+ version: record.version ?? 'unknown',
65
+ scope,
66
+ projectPath: record.projectPath ?? null,
67
+ installPath: record.installPath ?? null,
68
+ enabled,
69
+ installedAt: record.installedAt ?? null,
70
+ lastUpdatedAt: record.lastUpdated ?? null,
71
+ gitCommitSha: record.gitCommitSha ?? null,
72
+ };
73
+ };
74
+ export const scanClaudeCodePlugins = async (home = homedir()) => {
75
+ const installedPath = join(home, '.claude', 'plugins', 'installed_plugins.json');
76
+ const settingsPath = join(home, '.claude', 'settings.json');
77
+ const claudeJsonPath = join(home, '.claude.json');
78
+ const [installed, settings, claudeJson] = await Promise.all([
79
+ readJsonOrNull(installedPath),
80
+ readJsonOrNull(settingsPath),
81
+ readJsonOrNull(claudeJsonPath),
82
+ ]);
83
+ if (installed?.plugins == null)
84
+ return [];
85
+ const userEnabled = settings?.enabledPlugins ?? {};
86
+ const localEnabledByProject = {};
87
+ for (const [projectPath, projectConfig] of Object.entries(claudeJson?.projects ?? {})) {
88
+ if (projectConfig.enabledPlugins) {
89
+ localEnabledByProject[projectPath] = projectConfig.enabledPlugins;
90
+ }
91
+ }
92
+ const entries = [];
93
+ for (const [name, records] of Object.entries(installed.plugins)) {
94
+ if (!Array.isArray(records))
95
+ continue;
96
+ for (const record of records) {
97
+ const entry = buildEntry(name, record, userEnabled, localEnabledByProject);
98
+ if (entry != null)
99
+ entries.push(entry);
100
+ }
101
+ }
102
+ return entries;
103
+ };
104
+ //# sourceMappingURL=claude-code-plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-plugins.js","sourceRoot":"","sources":["../../src/scanners/claude-code-plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AA0BhC,MAAM,cAAc,GAAG,KAAK,EAAK,IAAY,EAAqB,EAAE;IAClE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAA;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QACjE,MAAM,GAAG,CAAA;IACX,CAAC;AACH,CAAC,CAAA;AAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAc,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAA;AAEvE,MAAM,WAAW,GAAG,CAAC,GAAW,EAAsB,EAAE;IACtD,oEAAoE;IACpE,+BAA+B;IAC/B,OAAO,YAAY,CAAC,GAAG,CAAC,GAAkB,CAAC,CAAC,CAAC,CAAE,GAAmB,CAAC,CAAC,CAAC,IAAI,CAAA;AAC3E,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,GAAG,CACjB,IAAY,EACZ,MAA6B,EAC7B,WAAoC,EACpC,qBAA8D,EAC1C,EAAE;IACtB,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACvC,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAA;IAE9B,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;IACtC,CAAC;SAAM,IAAI,KAAK,KAAK,OAAO,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACnD,MAAM,UAAU,GAAG,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAA;QAClE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAA;IACrC,CAAC;SAAM,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACrD,gEAAgE;QAChE,+CAA+C;QAC/C,uCAAuC;QACvC,OAAO,GAAG,KAAK,CAAA;IACjB,CAAC;IAED,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,SAAS;QACpC,KAAK;QACL,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;QACvC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;QACvC,OAAO;QACP,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;QACvC,aAAa,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;QACzC,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI;KAC1C,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,OAAe,OAAO,EAAE,EACA,EAAE;IAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,wBAAwB,CAAC,CAAA;IAChF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,CAAA;IAC3D,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;IAEjD,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1D,cAAc,CAAuB,aAAa,CAAC;QACnD,cAAc,CAAiB,YAAY,CAAC;QAC5C,cAAc,CAAuB,cAAc,CAAC;KACrD,CAAC,CAAA;IAEF,IAAI,SAAS,EAAE,OAAO,IAAI,IAAI;QAAE,OAAO,EAAE,CAAA;IAEzC,MAAM,WAAW,GAAG,QAAQ,EAAE,cAAc,IAAI,EAAE,CAAA;IAClD,MAAM,qBAAqB,GAA4C,EAAE,CAAA;IACzE,KAAK,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,IAAI,MAAM,CAAC,OAAO,CACvD,UAAU,EAAE,QAAQ,IAAI,EAAE,CAC3B,EAAE,CAAC;QACF,IAAI,aAAa,CAAC,cAAc,EAAE,CAAC;YACjC,qBAAqB,CAAC,WAAW,CAAC,GAAG,aAAa,CAAC,cAAc,CAAA;QACnE,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAkB,EAAE,CAAA;IACjC,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;QAChE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,SAAQ;QACrC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,qBAAqB,CAAC,CAAA;YAC1E,IAAI,KAAK,IAAI,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
@@ -0,0 +1,13 @@
1
+ import type { AgentSnapshot, McpServerEntry } from '../types.js';
2
+ export declare const claudeCodePaths: (home?: string, cwd?: string) => {
3
+ global: string;
4
+ project: string;
5
+ pluginsManifest: string;
6
+ };
7
+ export declare const parseClaudeMcpListForRemote: (output: string) => McpServerEntry[];
8
+ export type ScanClaudeCodeOptions = {
9
+ home?: string;
10
+ cwd?: string;
11
+ includeRemote?: boolean;
12
+ };
13
+ export declare const scanClaudeCode: (options?: ScanClaudeCodeOptions) => Promise<AgentSnapshot | null>;
@@ -0,0 +1,221 @@
1
+ import { exec } from 'node:child_process';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { promisify } from 'node:util';
5
+ import { hashConfig } from '../hash.js';
6
+ import { extractFromMcpServersField, readJsonIfExists } from './_normalize.js';
7
+ import { scanClaudeCodePlugins } from './claude-code-plugins.js';
8
+ const execAsync = promisify(exec);
9
+ export const claudeCodePaths = (home = homedir(), cwd = process.cwd()) => ({
10
+ global: join(home, '.claude.json'),
11
+ project: join(cwd, '.mcp.json'),
12
+ pluginsManifest: join(home, '.claude', 'plugins', 'installed_plugins.json'),
13
+ });
14
+ // ---------------------------------------------------------------------------
15
+ // A: project shared (`<project>/.mcp.json`) — チームで共有される
16
+ //
17
+ // 単一の cwd ではなく、`~/.claude.json#projects` に登録された全 project ディレクトリと
18
+ // 現在の cwd を巡回する。Claude Code は過去にユーザーが開いた project を全て projects[]
19
+ // に記録しているため、これでマシン上の "実利用されている" .mcp.json を網羅できる。
20
+ // 全く未使用な project の .mcp.json (Claude Code でまだ開いたことがない) は対象外で問題ない。
21
+ // ---------------------------------------------------------------------------
22
+ const readProjectShared = async (path) => {
23
+ const data = await readJsonIfExists(path);
24
+ if (data == null)
25
+ return [];
26
+ return extractFromMcpServersField(data, 'mcpServers', 'project', path);
27
+ };
28
+ const readAllProjectShared = async (globalPath, cwd) => {
29
+ // 巡回対象の project ディレクトリ一覧を作る。重複は Set で除去。
30
+ const root = await readJsonIfExists(globalPath);
31
+ const projectDirs = new Set();
32
+ projectDirs.add(cwd);
33
+ if (root && typeof root === 'object' && !Array.isArray(root)) {
34
+ const projects = root.projects;
35
+ if (projects && typeof projects === 'object' && !Array.isArray(projects)) {
36
+ for (const dir of Object.keys(projects)) {
37
+ projectDirs.add(dir);
38
+ }
39
+ }
40
+ }
41
+ const results = await Promise.all(Array.from(projectDirs).map((dir) => readProjectShared(join(dir, '.mcp.json'))));
42
+ return results.flat();
43
+ };
44
+ // ---------------------------------------------------------------------------
45
+ // 全体: `~/.claude.json`
46
+ // top-level `mcpServers` → global scope
47
+ // `projects[<absolute path>].mcpServers` → local scope (per-project, per-user)
48
+ // ---------------------------------------------------------------------------
49
+ const readGlobalClaudeJson = async (path) => {
50
+ const data = await readJsonIfExists(path);
51
+ if (data == null || typeof data !== 'object') {
52
+ return { global: [], local: [] };
53
+ }
54
+ const root = data;
55
+ const globalServers = extractFromMcpServersField(root, 'mcpServers', 'global', path);
56
+ const localServers = [];
57
+ const projects = root.projects;
58
+ if (projects && typeof projects === 'object' && !Array.isArray(projects)) {
59
+ for (const [projectPath, projectEntry] of Object.entries(projects)) {
60
+ if (!projectEntry || typeof projectEntry !== 'object')
61
+ continue;
62
+ const servers = extractFromMcpServersField(projectEntry, 'mcpServers', 'local', `${path}#projects[${projectPath}]`);
63
+ localServers.push(...servers);
64
+ }
65
+ }
66
+ return { global: globalServers, local: localServers };
67
+ };
68
+ const baseName = (pluginId) => {
69
+ // 例: "context7@claude-plugins-official" → "context7"
70
+ const at = pluginId.indexOf('@');
71
+ return at === -1 ? pluginId : pluginId.slice(0, at);
72
+ };
73
+ const readPluginMcpFile = async (installPath) => {
74
+ // プラグインの .mcp.json は 2 つの形式が混在する:
75
+ // (a) flat: { "<server>": { command, args, ... } } (context7, playwright)
76
+ // (b) wrapped: { "mcpServers": { "<server>": {...} } } (subframe, vercel)
77
+ // wrapped を優先し、無ければ flat を採用する。
78
+ const path = join(installPath, '.mcp.json');
79
+ const data = await readJsonIfExists(path);
80
+ if (data == null || typeof data !== 'object' || Array.isArray(data))
81
+ return null;
82
+ const root = data;
83
+ const wrapped = root.mcpServers;
84
+ if (wrapped && typeof wrapped === 'object' && !Array.isArray(wrapped)) {
85
+ return wrapped;
86
+ }
87
+ return root;
88
+ };
89
+ const readPluginServers = async (manifestPath) => {
90
+ const data = await readJsonIfExists(manifestPath);
91
+ if (data == null || typeof data !== 'object')
92
+ return [];
93
+ const plugins = data.plugins;
94
+ if (!plugins || typeof plugins !== 'object' || Array.isArray(plugins))
95
+ return [];
96
+ const seen = new Set();
97
+ const results = [];
98
+ for (const [pluginId, records] of Object.entries(plugins)) {
99
+ if (!Array.isArray(records) || records.length === 0)
100
+ continue;
101
+ const base = baseName(pluginId);
102
+ if (seen.has(base))
103
+ continue;
104
+ seen.add(base);
105
+ for (const record of records) {
106
+ const installPath = typeof record.installPath === 'string' ? record.installPath : null;
107
+ if (installPath == null)
108
+ continue;
109
+ const mcpMap = await readPluginMcpFile(installPath);
110
+ if (mcpMap == null)
111
+ break;
112
+ for (const [serverName, raw] of Object.entries(mcpMap)) {
113
+ if (!raw || typeof raw !== 'object')
114
+ continue;
115
+ // plugin の .mcp.json は { server: { command, args, ... } } のフラット構造なので
116
+ // 共通 normalize を使うために { mcpServers: { ... } } 形にラップする
117
+ const wrapped = { mcpServers: { [serverName]: raw } };
118
+ const entries = extractFromMcpServersField(wrapped, 'mcpServers', 'global', join(installPath, '.mcp.json'));
119
+ for (const entry of entries) {
120
+ // claude mcp list と同じ命名: plugin:<base>:<server>
121
+ results.push({ ...entry, name: `plugin:${base}:${serverName}` });
122
+ }
123
+ }
124
+ break; // 同じ plugin の 2 個目以降の install record はスキップ
125
+ }
126
+ }
127
+ return results;
128
+ };
129
+ // ---------------------------------------------------------------------------
130
+ // D: claude.ai 経由のリモート MCP
131
+ // ローカル設定ファイルには出てこない。`claude mcp list` の出力をパースする
132
+ // subprocess フォールバック。`claude` CLI が無ければ静かに空配列を返す。
133
+ // ---------------------------------------------------------------------------
134
+ const CLAUDE_AI_PREFIX = 'claude.ai ';
135
+ export const parseClaudeMcpListForRemote = (output) => {
136
+ const results = [];
137
+ for (const rawLine of output.split('\n')) {
138
+ const line = rawLine.trim();
139
+ if (!line.startsWith(CLAUDE_AI_PREFIX))
140
+ continue;
141
+ // 行は `claude.ai <name>: <target> [(HTTP)] - <status>` の形
142
+ const colonIdx = line.indexOf(': ');
143
+ if (colonIdx < 0)
144
+ continue;
145
+ const name = line.slice(0, colonIdx);
146
+ const afterColon = line.slice(colonIdx + 2);
147
+ const dashIdx = afterColon.lastIndexOf(' - ');
148
+ const targetPart = (dashIdx >= 0 ? afterColon.slice(0, dashIdx) : afterColon)
149
+ .replace(/\s+\(HTTP\)\s*$/i, '')
150
+ .trim();
151
+ let transport = 'http';
152
+ let url;
153
+ let command;
154
+ let args;
155
+ if (/^https?:\/\//.test(targetPart)) {
156
+ url = targetPart;
157
+ }
158
+ else {
159
+ transport = 'stdio';
160
+ const tokens = targetPart.split(/\s+/);
161
+ command = tokens[0];
162
+ args = tokens.slice(1);
163
+ }
164
+ results.push({
165
+ name,
166
+ transport,
167
+ command,
168
+ args,
169
+ url,
170
+ configHash: hashConfig({ transport, command, args, url }),
171
+ sourceScope: 'remote',
172
+ sourcePath: '<claude mcp list>',
173
+ });
174
+ }
175
+ return results;
176
+ };
177
+ const scanClaudeAiRemote = async () => {
178
+ try {
179
+ // `claude mcp list` は内部で全 MCP の health check を実行するため、サーバー数が多いと
180
+ // 30 秒以上かかる場合がある。Monitoring としては結果が取れれば良いので余裕を持たせる。
181
+ const { stdout } = await execAsync('claude mcp list', {
182
+ timeout: 60_000,
183
+ maxBuffer: 4 * 1024 * 1024,
184
+ });
185
+ return parseClaudeMcpListForRemote(stdout);
186
+ }
187
+ catch {
188
+ // claude CLI が無い / 認証エラー / timeout 等は無視
189
+ return [];
190
+ }
191
+ };
192
+ export const scanClaudeCode = async (options = {}) => {
193
+ const home = options.home ?? homedir();
194
+ const cwd = options.cwd ?? process.cwd();
195
+ const includeRemote = options.includeRemote ?? true;
196
+ const paths = claudeCodePaths(home, cwd);
197
+ const [projectShared, globalAndLocal, plugins, remote, installedPlugins] = await Promise.all([
198
+ readAllProjectShared(paths.global, cwd),
199
+ readGlobalClaudeJson(paths.global),
200
+ readPluginServers(paths.pluginsManifest),
201
+ includeRemote ? scanClaudeAiRemote() : Promise.resolve([]),
202
+ scanClaudeCodePlugins(home),
203
+ ]);
204
+ const all = [
205
+ ...projectShared,
206
+ ...globalAndLocal.global,
207
+ ...globalAndLocal.local,
208
+ ...plugins,
209
+ ...remote,
210
+ ];
211
+ if (all.length === 0 && installedPlugins.length === 0) {
212
+ // 検出ゼロでもファイルが一つでも存在すれば「Claude Code を使っているマシン」と
213
+ // みなして空 snapshot を返す。すべて読めなかった場合のみ null。
214
+ const anyConfigSeen = (await readJsonIfExists(paths.global)) !== null ||
215
+ (await readJsonIfExists(paths.project)) !== null;
216
+ if (!anyConfigSeen)
217
+ return null;
218
+ }
219
+ return { agentKind: 'claude_code', servers: all, plugins: installedPlugins };
220
+ };
221
+ //# sourceMappingURL=claude-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/scanners/claude-code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=claude-desktop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-desktop.js","sourceRoot":"","sources":["../../src/scanners/claude-desktop.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ import type { AgentSnapshot } from '../types.js';
2
+ export declare const codexConfigPath: (home?: string) => string;
3
+ export declare const scanCodex: (options?: {
4
+ home?: string;
5
+ }) => Promise<AgentSnapshot | null>;
@@ -0,0 +1,69 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { parse as parseToml } from 'smol-toml';
4
+ import { hashConfig } from '../hash.js';
5
+ import { readTextIfExists } from './_normalize.js';
6
+ const isStringArray = (v) => Array.isArray(v) && v.every((x) => typeof x === 'string');
7
+ const envKeysOf = (env) => {
8
+ if (env && typeof env === 'object' && !Array.isArray(env)) {
9
+ return Object.keys(env).sort();
10
+ }
11
+ return undefined;
12
+ };
13
+ const inferTransport = (raw) => {
14
+ const t = typeof raw.transport === 'string' ? raw.transport.toLowerCase() : undefined;
15
+ if (t === 'sse')
16
+ return 'sse';
17
+ if (t === 'http' || t === 'streamable-http' || t === 'streamable_http')
18
+ return 'http';
19
+ if (t === 'stdio')
20
+ return 'stdio';
21
+ if (typeof raw.url === 'string')
22
+ return 'http';
23
+ return 'stdio';
24
+ };
25
+ export const codexConfigPath = (home = homedir()) => join(home, '.codex', 'config.toml');
26
+ export const scanCodex = async (options = {}) => {
27
+ const path = codexConfigPath(options.home);
28
+ const text = await readTextIfExists(path);
29
+ if (text == null)
30
+ return null;
31
+ let parsed;
32
+ try {
33
+ parsed = parseToml(text);
34
+ }
35
+ catch {
36
+ return { agentKind: 'codex', servers: [] };
37
+ }
38
+ if (!parsed || typeof parsed !== 'object') {
39
+ return { agentKind: 'codex', servers: [] };
40
+ }
41
+ const section = parsed.mcp_servers;
42
+ if (!section || typeof section !== 'object' || Array.isArray(section)) {
43
+ return { agentKind: 'codex', servers: [] };
44
+ }
45
+ const servers = [];
46
+ for (const [name, raw] of Object.entries(section)) {
47
+ if (!raw || typeof raw !== 'object')
48
+ continue;
49
+ const entry = raw;
50
+ const transport = inferTransport(entry);
51
+ const command = typeof entry.command === 'string' ? entry.command : undefined;
52
+ const args = isStringArray(entry.args) ? entry.args : undefined;
53
+ const url = typeof entry.url === 'string' ? entry.url : undefined;
54
+ const envKeys = envKeysOf(entry.env);
55
+ servers.push({
56
+ name,
57
+ transport,
58
+ command,
59
+ args,
60
+ url,
61
+ envKeys,
62
+ configHash: hashConfig({ transport, command, args, url, envKeys }),
63
+ sourceScope: 'global',
64
+ sourcePath: path,
65
+ });
66
+ }
67
+ return { agentKind: 'codex', servers };
68
+ };
69
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/scanners/codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { AgentSnapshot } from '../types.js';
2
+ export declare const cursorPaths: (home?: string, cwd?: string) => {
3
+ global: string;
4
+ project: string;
5
+ };
6
+ export declare const scanCursor: (options?: {
7
+ home?: string;
8
+ cwd?: string;
9
+ }) => Promise<AgentSnapshot | null>;
@@ -0,0 +1,25 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { extractFromMcpServersField, readJsonIfExists } from './_normalize.js';
4
+ export const cursorPaths = (home = homedir(), cwd = process.cwd()) => ({
5
+ global: join(home, '.cursor', 'mcp.json'),
6
+ project: join(cwd, '.cursor', 'mcp.json'),
7
+ });
8
+ export const scanCursor = async (options = {}) => {
9
+ const paths = cursorPaths(options.home, options.cwd);
10
+ const [globalData, projectData] = await Promise.all([
11
+ readJsonIfExists(paths.global),
12
+ readJsonIfExists(paths.project),
13
+ ]);
14
+ if (globalData == null && projectData == null)
15
+ return null;
16
+ const servers = [];
17
+ if (globalData != null) {
18
+ servers.push(...extractFromMcpServersField(globalData, 'mcpServers', 'global', paths.global));
19
+ }
20
+ if (projectData != null) {
21
+ servers.push(...extractFromMcpServersField(projectData, 'mcpServers', 'project', paths.project));
22
+ }
23
+ return { agentKind: 'cursor', servers };
24
+ };
25
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/scanners/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE/E,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAe,OAAO,EAAE,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACrF,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC;IACzC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC;CAC1C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAC7B,UAA2C,EAAE,EACd,EAAE;IACjC,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACrD,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAClD,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9B,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC;KAChC,CAAC,CAAC;IACH,IAAI,UAAU,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAE3D,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,GAAG,0BAA0B,CAAC,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CACV,GAAG,0BAA0B,CAAC,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CACnF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC1C,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { AgentSnapshot } from '../types.js';
2
+ /**
3
+ * Google Gemini CLI scanner.
4
+ *
5
+ * 設定パス:
6
+ * - global : ~/.gemini/settings.json (mcpServers キー)
7
+ * - project : <cwd>/.gemini/settings.json (mcpServers キー、存在すれば)
8
+ *
9
+ * いずれも JSON で形式は Claude Code と互換:
10
+ * { "mcpServers": { "<name>": { command, args, url, env, type, ... } } }
11
+ *
12
+ * 参考: https://github.com/google-gemini/gemini-cli (settings.json schema)
13
+ */
14
+ export declare const geminiCliPaths: (home?: string, cwd?: string) => {
15
+ global: string;
16
+ project: string;
17
+ };
18
+ export declare const scanGeminiCli: (options?: {
19
+ home?: string;
20
+ cwd?: string;
21
+ }) => Promise<AgentSnapshot | null>;
@@ -0,0 +1,37 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { extractFromMcpServersField, readJsonIfExists } from './_normalize.js';
4
+ /**
5
+ * Google Gemini CLI scanner.
6
+ *
7
+ * 設定パス:
8
+ * - global : ~/.gemini/settings.json (mcpServers キー)
9
+ * - project : <cwd>/.gemini/settings.json (mcpServers キー、存在すれば)
10
+ *
11
+ * いずれも JSON で形式は Claude Code と互換:
12
+ * { "mcpServers": { "<name>": { command, args, url, env, type, ... } } }
13
+ *
14
+ * 参考: https://github.com/google-gemini/gemini-cli (settings.json schema)
15
+ */
16
+ export const geminiCliPaths = (home = homedir(), cwd = process.cwd()) => ({
17
+ global: join(home, '.gemini', 'settings.json'),
18
+ project: join(cwd, '.gemini', 'settings.json'),
19
+ });
20
+ export const scanGeminiCli = async (options = {}) => {
21
+ const paths = geminiCliPaths(options.home, options.cwd);
22
+ const [globalData, projectData] = await Promise.all([
23
+ readJsonIfExists(paths.global),
24
+ readJsonIfExists(paths.project),
25
+ ]);
26
+ if (globalData == null && projectData == null)
27
+ return null;
28
+ const servers = [];
29
+ if (globalData != null) {
30
+ servers.push(...extractFromMcpServersField(globalData, 'mcpServers', 'global', paths.global));
31
+ }
32
+ if (projectData != null) {
33
+ servers.push(...extractFromMcpServersField(projectData, 'mcpServers', 'project', paths.project));
34
+ }
35
+ return { agentKind: 'gemini_cli', servers };
36
+ };
37
+ //# sourceMappingURL=gemini-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-cli.js","sourceRoot":"","sources":["../../src/scanners/gemini-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE/E;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,OAAe,OAAO,EAAE,EACxB,MAAc,OAAO,CAAC,GAAG,EAAE,EAC3B,EAAE,CAAC,CAAC;IACJ,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC;IAC9C,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,eAAe,CAAC;CAC/C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,UAA2C,EAAE,EACd,EAAE;IACjC,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACxD,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAClD,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9B,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC;KAChC,CAAC,CAAC;IACH,IAAI,UAAU,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAE3D,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CACV,GAAG,0BAA0B,CAAC,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAChF,CAAC;IACJ,CAAC;IACD,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CACV,GAAG,0BAA0B,CAC3B,WAAW,EACX,YAAY,EACZ,SAAS,EACT,KAAK,CAAC,OAAO,CACd,CACF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AAC9C,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { AgentSnapshot } from '../types.js';
2
+ export type ScannerOptions = {
3
+ home?: string;
4
+ cwd?: string;
5
+ };
6
+ export declare const runAllScanners: (options?: ScannerOptions) => Promise<AgentSnapshot[]>;