@cleocode/caamp 0.2.0 → 0.4.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/README.md +19 -2
- package/dist/{chunk-RW745KDU.js → chunk-ZYINKJDE.js} +948 -122
- package/dist/chunk-ZYINKJDE.js.map +1 -0
- package/dist/cli.js +1225 -29
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1764 -80
- package/dist/index.js +39 -1
- package/package.json +14 -10
- package/dist/chunk-RW745KDU.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -2,157 +2,584 @@
|
|
|
2
2
|
* CAAMP - Central AI Agent Managed Packages
|
|
3
3
|
* Core type definitions
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Supported configuration file formats.
|
|
7
|
+
*
|
|
8
|
+
* - `"json"` - Standard JSON
|
|
9
|
+
* - `"jsonc"` - JSON with comments (comment-preserving via jsonc-parser)
|
|
10
|
+
* - `"yaml"` - YAML (via js-yaml)
|
|
11
|
+
* - `"toml"` - TOML (via @iarna/toml)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const format: ConfigFormat = "jsonc";
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
5
18
|
type ConfigFormat = "json" | "jsonc" | "yaml" | "toml";
|
|
19
|
+
/**
|
|
20
|
+
* MCP server transport protocol type.
|
|
21
|
+
*
|
|
22
|
+
* - `"stdio"` - Standard input/output (local process)
|
|
23
|
+
* - `"sse"` - Server-Sent Events (remote)
|
|
24
|
+
* - `"http"` - HTTP/Streamable HTTP (remote)
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const transport: TransportType = "stdio";
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
6
31
|
type TransportType = "stdio" | "sse" | "http";
|
|
32
|
+
/**
|
|
33
|
+
* Method used to detect whether an AI agent is installed on the system.
|
|
34
|
+
*
|
|
35
|
+
* - `"binary"` - Check if a CLI binary exists on PATH
|
|
36
|
+
* - `"directory"` - Check if known config/data directories exist
|
|
37
|
+
* - `"appBundle"` - Check for macOS .app bundle in /Applications
|
|
38
|
+
* - `"flatpak"` - Check for Flatpak installation on Linux
|
|
39
|
+
*/
|
|
7
40
|
type DetectionMethod = "binary" | "directory" | "appBundle" | "flatpak";
|
|
41
|
+
/**
|
|
42
|
+
* Configuration for detecting whether a provider is installed.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const config: DetectionConfig = {
|
|
47
|
+
* methods: ["binary", "directory"],
|
|
48
|
+
* binary: "claude",
|
|
49
|
+
* directories: ["~/.config/claude"],
|
|
50
|
+
* };
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
8
53
|
interface DetectionConfig {
|
|
54
|
+
/** Detection methods to try, in order. */
|
|
9
55
|
methods: DetectionMethod[];
|
|
56
|
+
/** Binary name to look up on PATH (for `"binary"` method). */
|
|
10
57
|
binary?: string;
|
|
58
|
+
/** Directories to check for existence (for `"directory"` method). */
|
|
11
59
|
directories?: string[];
|
|
60
|
+
/** macOS .app bundle name (for `"appBundle"` method). */
|
|
12
61
|
appBundle?: string;
|
|
62
|
+
/** Flatpak application ID (for `"flatpak"` method). */
|
|
13
63
|
flatpakId?: string;
|
|
14
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Priority tier for a provider, used for sorting and default selection.
|
|
67
|
+
*
|
|
68
|
+
* - `"high"` - Major, widely-used agents
|
|
69
|
+
* - `"medium"` - Established but less common agents
|
|
70
|
+
* - `"low"` - Niche or experimental agents
|
|
71
|
+
*/
|
|
15
72
|
type ProviderPriority = "high" | "medium" | "low";
|
|
73
|
+
/**
|
|
74
|
+
* Lifecycle status of a provider in the registry.
|
|
75
|
+
*
|
|
76
|
+
* - `"active"` - Fully supported
|
|
77
|
+
* - `"beta"` - Supported but may have rough edges
|
|
78
|
+
* - `"deprecated"` - Still present but no longer recommended
|
|
79
|
+
* - `"planned"` - Not yet implemented
|
|
80
|
+
*/
|
|
16
81
|
type ProviderStatus = "active" | "beta" | "deprecated" | "planned";
|
|
82
|
+
/**
|
|
83
|
+
* A resolved AI agent provider definition with platform-specific paths.
|
|
84
|
+
*
|
|
85
|
+
* Providers are loaded from `providers/registry.json` and resolved at runtime
|
|
86
|
+
* to expand platform-specific path variables (`$HOME`, `$CONFIG`, etc.).
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const provider = getProvider("claude-code");
|
|
91
|
+
* if (provider) {
|
|
92
|
+
* console.log(provider.configPathGlobal);
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
17
96
|
interface Provider {
|
|
97
|
+
/** Unique provider identifier (e.g. `"claude-code"`). */
|
|
18
98
|
id: string;
|
|
99
|
+
/** Human-readable tool name (e.g. `"Claude Code"`). */
|
|
19
100
|
toolName: string;
|
|
101
|
+
/** Vendor/company name (e.g. `"Anthropic"`). */
|
|
20
102
|
vendor: string;
|
|
103
|
+
/** CLI flag name for `--agent` selection. */
|
|
21
104
|
agentFlag: string;
|
|
105
|
+
/** Alternative names that resolve to this provider. */
|
|
22
106
|
aliases: string[];
|
|
107
|
+
/** Resolved global instruction file directory path. */
|
|
23
108
|
pathGlobal: string;
|
|
109
|
+
/** Project-relative instruction file directory path. */
|
|
24
110
|
pathProject: string;
|
|
111
|
+
/** Instruction file name (e.g. `"CLAUDE.md"`, `"AGENTS.md"`). */
|
|
25
112
|
instructFile: string;
|
|
113
|
+
/** Dot-notation key path for MCP server config (e.g. `"mcpServers"`). */
|
|
26
114
|
configKey: string;
|
|
115
|
+
/** Config file format used by this provider. */
|
|
27
116
|
configFormat: ConfigFormat;
|
|
117
|
+
/** Resolved global config file path. */
|
|
28
118
|
configPathGlobal: string;
|
|
119
|
+
/** Project-relative config file path, or `null` if unsupported. */
|
|
29
120
|
configPathProject: string | null;
|
|
121
|
+
/** Resolved global skills directory path. */
|
|
30
122
|
pathSkills: string;
|
|
123
|
+
/** Project-relative skills directory path. */
|
|
31
124
|
pathProjectSkills: string;
|
|
125
|
+
/** Detection configuration for auto-discovering this provider. */
|
|
32
126
|
detection: DetectionConfig;
|
|
127
|
+
/** MCP transport protocols this provider supports. */
|
|
33
128
|
supportedTransports: TransportType[];
|
|
129
|
+
/** Whether the provider supports custom HTTP headers for remote MCP servers. */
|
|
34
130
|
supportsHeaders: boolean;
|
|
131
|
+
/** Priority tier for sorting and default selection. */
|
|
35
132
|
priority: ProviderPriority;
|
|
133
|
+
/** Lifecycle status in the registry. */
|
|
36
134
|
status: ProviderStatus;
|
|
135
|
+
/** Whether the provider is compatible with the Agent Skills standard. */
|
|
37
136
|
agentSkillsCompatible: boolean;
|
|
38
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Canonical MCP server configuration.
|
|
140
|
+
*
|
|
141
|
+
* Represents either a remote server (via `url`) or a local stdio process
|
|
142
|
+
* (via `command` + `args`). This canonical format is transformed to
|
|
143
|
+
* provider-specific shapes before writing to config files.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* // Remote server
|
|
148
|
+
* const remote: McpServerConfig = {
|
|
149
|
+
* type: "http",
|
|
150
|
+
* url: "https://mcp.example.com/sse",
|
|
151
|
+
* };
|
|
152
|
+
*
|
|
153
|
+
* // Local stdio server
|
|
154
|
+
* const local: McpServerConfig = {
|
|
155
|
+
* command: "npx",
|
|
156
|
+
* args: ["-y", "@modelcontextprotocol/server-filesystem"],
|
|
157
|
+
* };
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
39
160
|
interface McpServerConfig {
|
|
161
|
+
/** Transport type (`"stdio"`, `"sse"`, or `"http"`). */
|
|
40
162
|
type?: TransportType;
|
|
163
|
+
/** URL for remote MCP servers. */
|
|
41
164
|
url?: string;
|
|
165
|
+
/** HTTP headers for remote MCP servers. */
|
|
42
166
|
headers?: Record<string, string>;
|
|
167
|
+
/** Command to run for stdio MCP servers. */
|
|
43
168
|
command?: string;
|
|
169
|
+
/** Arguments for the stdio command. */
|
|
44
170
|
args?: string[];
|
|
171
|
+
/** Environment variables for the stdio process. */
|
|
45
172
|
env?: Record<string, string>;
|
|
46
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Classified type of an MCP server or skill source.
|
|
176
|
+
*
|
|
177
|
+
* - `"remote"` - HTTP/HTTPS URL to a remote MCP server
|
|
178
|
+
* - `"package"` - npm package name
|
|
179
|
+
* - `"command"` - Shell command string
|
|
180
|
+
* - `"github"` - GitHub repository (URL or shorthand)
|
|
181
|
+
* - `"gitlab"` - GitLab repository URL
|
|
182
|
+
* - `"local"` - Local filesystem path
|
|
183
|
+
*/
|
|
47
184
|
type SourceType = "remote" | "package" | "command" | "github" | "gitlab" | "local";
|
|
185
|
+
/**
|
|
186
|
+
* Result of parsing a source string into its typed components.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* const parsed: ParsedSource = {
|
|
191
|
+
* type: "github",
|
|
192
|
+
* value: "https://github.com/owner/repo",
|
|
193
|
+
* inferredName: "repo",
|
|
194
|
+
* owner: "owner",
|
|
195
|
+
* repo: "repo",
|
|
196
|
+
* };
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
48
199
|
interface ParsedSource {
|
|
200
|
+
/** Classified source type. */
|
|
49
201
|
type: SourceType;
|
|
202
|
+
/** Original or normalized source value. */
|
|
50
203
|
value: string;
|
|
204
|
+
/** Display name inferred from the source. */
|
|
51
205
|
inferredName: string;
|
|
206
|
+
/** Repository owner (for GitHub/GitLab sources). */
|
|
52
207
|
owner?: string;
|
|
208
|
+
/** Repository name (for GitHub/GitLab sources). */
|
|
53
209
|
repo?: string;
|
|
210
|
+
/** Path within the repository (for GitHub/GitLab sources). */
|
|
54
211
|
path?: string;
|
|
212
|
+
/** Git ref / branch / tag (for GitHub/GitLab sources). */
|
|
55
213
|
ref?: string;
|
|
56
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Metadata extracted from a SKILL.md frontmatter.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* const meta: SkillMetadata = {
|
|
221
|
+
* name: "my-skill",
|
|
222
|
+
* description: "A useful skill for code generation",
|
|
223
|
+
* version: "1.0.0",
|
|
224
|
+
* };
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
57
227
|
interface SkillMetadata {
|
|
228
|
+
/** Skill name (lowercase, hyphens only). */
|
|
58
229
|
name: string;
|
|
230
|
+
/** Human-readable description. */
|
|
59
231
|
description: string;
|
|
232
|
+
/** SPDX license identifier. */
|
|
60
233
|
license?: string;
|
|
234
|
+
/** Compatibility notes (e.g. agent versions). */
|
|
61
235
|
compatibility?: string;
|
|
236
|
+
/** Arbitrary key-value metadata. */
|
|
62
237
|
metadata?: Record<string, string>;
|
|
238
|
+
/** List of tools the skill is allowed to use. */
|
|
63
239
|
allowedTools?: string[];
|
|
240
|
+
/** Semantic version string. */
|
|
64
241
|
version?: string;
|
|
65
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* A discovered skill entry with its location and metadata.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```typescript
|
|
248
|
+
* const entry: SkillEntry = {
|
|
249
|
+
* name: "my-skill",
|
|
250
|
+
* scopedName: "my-skill",
|
|
251
|
+
* path: "/home/user/.agents/skills/my-skill",
|
|
252
|
+
* metadata: { name: "my-skill", description: "A skill" },
|
|
253
|
+
* };
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
66
256
|
interface SkillEntry {
|
|
257
|
+
/** Skill name. */
|
|
67
258
|
name: string;
|
|
259
|
+
/** Scoped name (may include marketplace scope). */
|
|
68
260
|
scopedName: string;
|
|
261
|
+
/** Absolute path to the skill directory. */
|
|
69
262
|
path: string;
|
|
263
|
+
/** Parsed SKILL.md frontmatter metadata. */
|
|
70
264
|
metadata: SkillMetadata;
|
|
265
|
+
/** Original source from which the skill was installed. */
|
|
71
266
|
source?: string;
|
|
72
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* A single entry in the CAAMP lock file tracking an installed skill or MCP server.
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```typescript
|
|
273
|
+
* const entry: LockEntry = {
|
|
274
|
+
* name: "my-skill",
|
|
275
|
+
* scopedName: "my-skill",
|
|
276
|
+
* source: "https://github.com/owner/repo",
|
|
277
|
+
* sourceType: "github",
|
|
278
|
+
* installedAt: "2025-01-15T10:30:00.000Z",
|
|
279
|
+
* agents: ["claude-code", "cursor"],
|
|
280
|
+
* canonicalPath: "/home/user/.agents/skills/my-skill",
|
|
281
|
+
* isGlobal: true,
|
|
282
|
+
* };
|
|
283
|
+
* ```
|
|
284
|
+
*/
|
|
73
285
|
interface LockEntry {
|
|
286
|
+
/** Skill or server name. */
|
|
74
287
|
name: string;
|
|
288
|
+
/** Scoped name (may include marketplace scope). */
|
|
75
289
|
scopedName: string;
|
|
290
|
+
/** Original source string. */
|
|
76
291
|
source: string;
|
|
292
|
+
/** Classified source type. */
|
|
77
293
|
sourceType: SourceType;
|
|
294
|
+
/** Version string or commit SHA. */
|
|
78
295
|
version?: string;
|
|
296
|
+
/** ISO 8601 timestamp of first installation. */
|
|
79
297
|
installedAt: string;
|
|
298
|
+
/** ISO 8601 timestamp of last update. */
|
|
80
299
|
updatedAt?: string;
|
|
300
|
+
/** Provider IDs this entry is linked to. */
|
|
81
301
|
agents: string[];
|
|
302
|
+
/** Absolute path to canonical installation. */
|
|
82
303
|
canonicalPath: string;
|
|
304
|
+
/** Whether this was installed globally. */
|
|
83
305
|
isGlobal: boolean;
|
|
306
|
+
/** Project directory (for project-scoped installs). */
|
|
84
307
|
projectDir?: string;
|
|
85
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* The CAAMP lock file structure, stored at `~/.agents/.caamp-lock.json`.
|
|
311
|
+
*
|
|
312
|
+
* Tracks all installed skills and MCP servers along with their sources,
|
|
313
|
+
* versions, and linked agents.
|
|
314
|
+
*
|
|
315
|
+
* @example
|
|
316
|
+
* ```typescript
|
|
317
|
+
* const lock: CaampLockFile = {
|
|
318
|
+
* version: 1,
|
|
319
|
+
* skills: {},
|
|
320
|
+
* mcpServers: {},
|
|
321
|
+
* lastSelectedAgents: ["claude-code"],
|
|
322
|
+
* };
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
86
325
|
interface CaampLockFile {
|
|
326
|
+
/** Lock file schema version. */
|
|
87
327
|
version: 1;
|
|
328
|
+
/** Installed skills keyed by name. */
|
|
88
329
|
skills: Record<string, LockEntry>;
|
|
330
|
+
/** Installed MCP servers keyed by name. */
|
|
89
331
|
mcpServers: Record<string, LockEntry>;
|
|
332
|
+
/** Last selected agent IDs for UX persistence. */
|
|
90
333
|
lastSelectedAgents?: string[];
|
|
91
334
|
}
|
|
335
|
+
/**
|
|
336
|
+
* A skill listing from a marketplace search result.
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```typescript
|
|
340
|
+
* const skill: MarketplaceSkill = {
|
|
341
|
+
* id: "abc123",
|
|
342
|
+
* name: "my-skill",
|
|
343
|
+
* scopedName: "@author/my-skill",
|
|
344
|
+
* description: "A useful skill",
|
|
345
|
+
* author: "author",
|
|
346
|
+
* stars: 42,
|
|
347
|
+
* forks: 5,
|
|
348
|
+
* githubUrl: "https://github.com/author/my-skill",
|
|
349
|
+
* repoFullName: "author/my-skill",
|
|
350
|
+
* path: "/",
|
|
351
|
+
* hasContent: true,
|
|
352
|
+
* };
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
92
355
|
interface MarketplaceSkill {
|
|
356
|
+
/** Unique marketplace identifier. */
|
|
93
357
|
id: string;
|
|
358
|
+
/** Skill name. */
|
|
94
359
|
name: string;
|
|
360
|
+
/** Scoped name (e.g. `"@author/my-skill"`). */
|
|
95
361
|
scopedName: string;
|
|
362
|
+
/** Short description. */
|
|
96
363
|
description: string;
|
|
364
|
+
/** Author / publisher name. */
|
|
97
365
|
author: string;
|
|
366
|
+
/** GitHub star count. */
|
|
98
367
|
stars: number;
|
|
368
|
+
/** GitHub fork count. */
|
|
99
369
|
forks: number;
|
|
370
|
+
/** GitHub repository URL. */
|
|
100
371
|
githubUrl: string;
|
|
372
|
+
/** Full `owner/repo` name. */
|
|
101
373
|
repoFullName: string;
|
|
374
|
+
/** Path within the repository. */
|
|
102
375
|
path: string;
|
|
376
|
+
/** Optional category tag. */
|
|
103
377
|
category?: string;
|
|
378
|
+
/** Whether SKILL.md content was fetched. */
|
|
104
379
|
hasContent: boolean;
|
|
105
380
|
}
|
|
381
|
+
/**
|
|
382
|
+
* Paginated search results from a marketplace API.
|
|
383
|
+
*
|
|
384
|
+
* @example
|
|
385
|
+
* ```typescript
|
|
386
|
+
* const result: MarketplaceSearchResult = {
|
|
387
|
+
* skills: [],
|
|
388
|
+
* total: 0,
|
|
389
|
+
* limit: 20,
|
|
390
|
+
* offset: 0,
|
|
391
|
+
* };
|
|
392
|
+
* ```
|
|
393
|
+
*/
|
|
106
394
|
interface MarketplaceSearchResult {
|
|
395
|
+
/** Array of matching skills. */
|
|
107
396
|
skills: MarketplaceSkill[];
|
|
397
|
+
/** Total number of matching results. */
|
|
108
398
|
total: number;
|
|
399
|
+
/** Maximum results per page. */
|
|
109
400
|
limit: number;
|
|
401
|
+
/** Offset into the result set. */
|
|
110
402
|
offset: number;
|
|
111
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* Severity level for a security audit finding.
|
|
406
|
+
*
|
|
407
|
+
* Ordered from most to least severe: `"critical"` > `"high"` > `"medium"` > `"low"` > `"info"`.
|
|
408
|
+
*/
|
|
112
409
|
type AuditSeverity = "critical" | "high" | "medium" | "low" | "info";
|
|
410
|
+
/**
|
|
411
|
+
* A security audit rule definition with a regex pattern to match against skill content.
|
|
412
|
+
*
|
|
413
|
+
* @example
|
|
414
|
+
* ```typescript
|
|
415
|
+
* const rule: AuditRule = {
|
|
416
|
+
* id: "SEC001",
|
|
417
|
+
* name: "shell-injection",
|
|
418
|
+
* description: "Potential shell injection vector",
|
|
419
|
+
* severity: "critical",
|
|
420
|
+
* category: "injection",
|
|
421
|
+
* pattern: /rm\s+-rf\s+\//,
|
|
422
|
+
* };
|
|
423
|
+
* ```
|
|
424
|
+
*/
|
|
113
425
|
interface AuditRule {
|
|
426
|
+
/** Unique rule identifier (e.g. `"SEC001"`). */
|
|
114
427
|
id: string;
|
|
428
|
+
/** Rule name. */
|
|
115
429
|
name: string;
|
|
430
|
+
/** Human-readable description of what the rule detects. */
|
|
116
431
|
description: string;
|
|
432
|
+
/** Severity level of findings from this rule. */
|
|
117
433
|
severity: AuditSeverity;
|
|
434
|
+
/** Category grouping (e.g. `"injection"`, `"exfiltration"`). */
|
|
118
435
|
category: string;
|
|
436
|
+
/** Regex pattern to match against each line of content. */
|
|
119
437
|
pattern: RegExp;
|
|
120
438
|
}
|
|
439
|
+
/**
|
|
440
|
+
* A single finding from a security audit scan, with line-level location.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* ```typescript
|
|
444
|
+
* const finding: AuditFinding = {
|
|
445
|
+
* rule: myRule,
|
|
446
|
+
* line: 42,
|
|
447
|
+
* column: 10,
|
|
448
|
+
* match: "rm -rf /",
|
|
449
|
+
* context: "Execute: rm -rf / to clean up",
|
|
450
|
+
* };
|
|
451
|
+
* ```
|
|
452
|
+
*/
|
|
121
453
|
interface AuditFinding {
|
|
454
|
+
/** The rule that triggered this finding. */
|
|
122
455
|
rule: AuditRule;
|
|
456
|
+
/** Line number (1-based). */
|
|
123
457
|
line: number;
|
|
458
|
+
/** Column number (1-based). */
|
|
124
459
|
column: number;
|
|
460
|
+
/** The matched text. */
|
|
125
461
|
match: string;
|
|
462
|
+
/** The full line of text for context. */
|
|
126
463
|
context: string;
|
|
127
464
|
}
|
|
465
|
+
/**
|
|
466
|
+
* Aggregate audit result for a single file.
|
|
467
|
+
*
|
|
468
|
+
* Includes a security score (100 = clean, 0 = very dangerous) and a pass/fail
|
|
469
|
+
* status based on the presence of critical or high severity findings.
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* ```typescript
|
|
473
|
+
* const result: AuditResult = {
|
|
474
|
+
* file: "/path/to/SKILL.md",
|
|
475
|
+
* findings: [],
|
|
476
|
+
* score: 100,
|
|
477
|
+
* passed: true,
|
|
478
|
+
* };
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
128
481
|
interface AuditResult {
|
|
482
|
+
/** Path to the scanned file. */
|
|
129
483
|
file: string;
|
|
484
|
+
/** All findings for this file. */
|
|
130
485
|
findings: AuditFinding[];
|
|
486
|
+
/** Security score from 0 (dangerous) to 100 (clean). */
|
|
131
487
|
score: number;
|
|
488
|
+
/** Whether the file passed the audit (no critical/high findings). */
|
|
132
489
|
passed: boolean;
|
|
133
490
|
}
|
|
491
|
+
/**
|
|
492
|
+
* Status of a CAAMP injection block in an instruction file.
|
|
493
|
+
*
|
|
494
|
+
* - `"current"` - Injection block exists and matches expected content
|
|
495
|
+
* - `"outdated"` - Injection block exists but content differs
|
|
496
|
+
* - `"missing"` - Instruction file does not exist
|
|
497
|
+
* - `"none"` - File exists but has no CAAMP injection block
|
|
498
|
+
*/
|
|
134
499
|
type InjectionStatus = "current" | "outdated" | "missing" | "none";
|
|
500
|
+
/**
|
|
501
|
+
* Result of checking a single instruction file for CAAMP injection status.
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* ```typescript
|
|
505
|
+
* const check: InjectionCheckResult = {
|
|
506
|
+
* file: "/project/CLAUDE.md",
|
|
507
|
+
* provider: "claude-code",
|
|
508
|
+
* status: "current",
|
|
509
|
+
* fileExists: true,
|
|
510
|
+
* };
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
135
513
|
interface InjectionCheckResult {
|
|
514
|
+
/** Absolute path to the instruction file. */
|
|
136
515
|
file: string;
|
|
516
|
+
/** Provider ID that owns this instruction file. */
|
|
137
517
|
provider: string;
|
|
518
|
+
/** Current injection status. */
|
|
138
519
|
status: InjectionStatus;
|
|
520
|
+
/** Whether the instruction file exists on disk. */
|
|
139
521
|
fileExists: boolean;
|
|
140
522
|
}
|
|
523
|
+
/**
|
|
524
|
+
* An MCP server entry read from a provider's config file.
|
|
525
|
+
*
|
|
526
|
+
* Returned by {@link listMcpServers} and {@link listAllMcpServers}.
|
|
527
|
+
*
|
|
528
|
+
* @example
|
|
529
|
+
* ```typescript
|
|
530
|
+
* const entry: McpServerEntry = {
|
|
531
|
+
* name: "filesystem",
|
|
532
|
+
* providerId: "claude-code",
|
|
533
|
+
* providerName: "Claude Code",
|
|
534
|
+
* scope: "project",
|
|
535
|
+
* configPath: "/project/.claude/settings.json",
|
|
536
|
+
* config: { command: "npx", args: ["-y", "@mcp/server-filesystem"] },
|
|
537
|
+
* };
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
141
540
|
interface McpServerEntry {
|
|
541
|
+
/** Server name (the key in the config file). */
|
|
142
542
|
name: string;
|
|
543
|
+
/** Provider ID that owns this config file. */
|
|
143
544
|
providerId: string;
|
|
545
|
+
/** Human-readable provider name. */
|
|
144
546
|
providerName: string;
|
|
547
|
+
/** Whether from project or global config. */
|
|
145
548
|
scope: "project" | "global";
|
|
549
|
+
/** Absolute path to the config file. */
|
|
146
550
|
configPath: string;
|
|
551
|
+
/** Raw server configuration object. */
|
|
147
552
|
config: Record<string, unknown>;
|
|
148
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* Global CLI options shared across all CAAMP commands.
|
|
556
|
+
*
|
|
557
|
+
* @example
|
|
558
|
+
* ```typescript
|
|
559
|
+
* const opts: GlobalOptions = {
|
|
560
|
+
* agent: ["claude-code", "cursor"],
|
|
561
|
+
* global: true,
|
|
562
|
+
* json: true,
|
|
563
|
+
* };
|
|
564
|
+
* ```
|
|
565
|
+
*/
|
|
149
566
|
interface GlobalOptions {
|
|
567
|
+
/** Target agent IDs (repeatable). */
|
|
150
568
|
agent?: string[];
|
|
569
|
+
/** Operate on global config instead of project. */
|
|
151
570
|
global?: boolean;
|
|
571
|
+
/** Skip confirmation prompts. */
|
|
152
572
|
yes?: boolean;
|
|
573
|
+
/** Target all detected agents. */
|
|
153
574
|
all?: boolean;
|
|
575
|
+
/** Output as JSON. */
|
|
154
576
|
json?: boolean;
|
|
577
|
+
/** Preview changes without writing. */
|
|
155
578
|
dryRun?: boolean;
|
|
579
|
+
/** Enable debug logging. */
|
|
580
|
+
verbose?: boolean;
|
|
581
|
+
/** Suppress non-error output. */
|
|
582
|
+
quiet?: boolean;
|
|
156
583
|
}
|
|
157
584
|
|
|
158
585
|
/**
|
|
@@ -162,19 +589,95 @@ interface GlobalOptions {
|
|
|
162
589
|
* by checking binaries, directories, app bundles, and flatpak.
|
|
163
590
|
*/
|
|
164
591
|
|
|
592
|
+
/**
|
|
593
|
+
* Result of detecting whether a provider is installed on the system.
|
|
594
|
+
*
|
|
595
|
+
* @example
|
|
596
|
+
* ```typescript
|
|
597
|
+
* const result = detectProvider(provider);
|
|
598
|
+
* if (result.installed) {
|
|
599
|
+
* console.log(`Found via: ${result.methods.join(", ")}`);
|
|
600
|
+
* }
|
|
601
|
+
* ```
|
|
602
|
+
*/
|
|
165
603
|
interface DetectionResult {
|
|
604
|
+
/** The provider that was checked. */
|
|
166
605
|
provider: Provider;
|
|
606
|
+
/** Whether the provider was detected as installed. */
|
|
167
607
|
installed: boolean;
|
|
608
|
+
/** Detection methods that matched (e.g. `["binary", "directory"]`). */
|
|
168
609
|
methods: string[];
|
|
610
|
+
/** Whether the provider has project-level config in the current directory. */
|
|
169
611
|
projectDetected: boolean;
|
|
170
612
|
}
|
|
171
|
-
/**
|
|
613
|
+
/**
|
|
614
|
+
* Detect if a single provider is installed on the system.
|
|
615
|
+
*
|
|
616
|
+
* Checks each detection method configured for the provider (binary, directory,
|
|
617
|
+
* appBundle, flatpak) and returns which methods matched.
|
|
618
|
+
*
|
|
619
|
+
* @param provider - The provider to detect
|
|
620
|
+
* @returns Detection result with installation status and matched methods
|
|
621
|
+
*
|
|
622
|
+
* @example
|
|
623
|
+
* ```typescript
|
|
624
|
+
* const provider = getProvider("claude-code")!;
|
|
625
|
+
* const result = detectProvider(provider);
|
|
626
|
+
* if (result.installed) {
|
|
627
|
+
* console.log(`Claude Code found via: ${result.methods.join(", ")}`);
|
|
628
|
+
* }
|
|
629
|
+
* ```
|
|
630
|
+
*/
|
|
172
631
|
declare function detectProvider(provider: Provider): DetectionResult;
|
|
173
|
-
/**
|
|
632
|
+
/**
|
|
633
|
+
* Detect all registered providers and return their installation status.
|
|
634
|
+
*
|
|
635
|
+
* Runs detection for every provider in the registry.
|
|
636
|
+
*
|
|
637
|
+
* @returns Array of detection results for all providers
|
|
638
|
+
*
|
|
639
|
+
* @example
|
|
640
|
+
* ```typescript
|
|
641
|
+
* const results = detectAllProviders();
|
|
642
|
+
* const installed = results.filter(r => r.installed);
|
|
643
|
+
* console.log(`${installed.length} agents detected`);
|
|
644
|
+
* ```
|
|
645
|
+
*/
|
|
174
646
|
declare function detectAllProviders(): DetectionResult[];
|
|
175
|
-
/**
|
|
647
|
+
/**
|
|
648
|
+
* Get only providers that are currently installed on the system.
|
|
649
|
+
*
|
|
650
|
+
* Convenience wrapper that filters {@link detectAllProviders} results to only
|
|
651
|
+
* those with `installed === true`.
|
|
652
|
+
*
|
|
653
|
+
* @returns Array of installed provider definitions
|
|
654
|
+
*
|
|
655
|
+
* @example
|
|
656
|
+
* ```typescript
|
|
657
|
+
* const installed = getInstalledProviders();
|
|
658
|
+
* console.log(installed.map(p => p.toolName).join(", "));
|
|
659
|
+
* ```
|
|
660
|
+
*/
|
|
176
661
|
declare function getInstalledProviders(): Provider[];
|
|
177
|
-
/**
|
|
662
|
+
/**
|
|
663
|
+
* Detect all providers and enrich results with project-level presence.
|
|
664
|
+
*
|
|
665
|
+
* Extends {@link detectAllProviders} by also checking whether each provider
|
|
666
|
+
* has a project-level config file in the given directory.
|
|
667
|
+
*
|
|
668
|
+
* @param projectDir - Absolute path to the project directory to check
|
|
669
|
+
* @returns Array of detection results with `projectDetected` populated
|
|
670
|
+
*
|
|
671
|
+
* @example
|
|
672
|
+
* ```typescript
|
|
673
|
+
* const results = detectProjectProviders("/home/user/my-project");
|
|
674
|
+
* for (const r of results) {
|
|
675
|
+
* if (r.projectDetected) {
|
|
676
|
+
* console.log(`${r.provider.toolName} has project config`);
|
|
677
|
+
* }
|
|
678
|
+
* }
|
|
679
|
+
* ```
|
|
680
|
+
*/
|
|
178
681
|
declare function detectProjectProviders(projectDir: string): DetectionResult[];
|
|
179
682
|
|
|
180
683
|
/**
|
|
@@ -184,18 +687,94 @@ declare function detectProjectProviders(projectDir: string): DetectionResult[];
|
|
|
184
687
|
* handling per-agent formats, keys, and transformations.
|
|
185
688
|
*/
|
|
186
689
|
|
|
690
|
+
/**
|
|
691
|
+
* Result of installing an MCP server configuration to a single provider.
|
|
692
|
+
*
|
|
693
|
+
* @example
|
|
694
|
+
* ```typescript
|
|
695
|
+
* const result = await installMcpServer(provider, "my-server", config);
|
|
696
|
+
* if (result.success) {
|
|
697
|
+
* console.log(`Written to ${result.configPath}`);
|
|
698
|
+
* }
|
|
699
|
+
* ```
|
|
700
|
+
*/
|
|
187
701
|
interface InstallResult {
|
|
702
|
+
/** The provider the config was written to. */
|
|
188
703
|
provider: Provider;
|
|
704
|
+
/** Whether project or global scope was used. */
|
|
189
705
|
scope: "project" | "global";
|
|
706
|
+
/** Absolute path to the config file that was written. */
|
|
190
707
|
configPath: string;
|
|
708
|
+
/** Whether the write succeeded. */
|
|
191
709
|
success: boolean;
|
|
710
|
+
/** Error message if the write failed. */
|
|
192
711
|
error?: string;
|
|
193
712
|
}
|
|
194
|
-
/**
|
|
713
|
+
/**
|
|
714
|
+
* Install an MCP server configuration for a single provider.
|
|
715
|
+
*
|
|
716
|
+
* Applies provider-specific transforms (e.g. Goose, Zed, Codex) and writes
|
|
717
|
+
* the config to the provider's config file in the specified scope.
|
|
718
|
+
*
|
|
719
|
+
* @param provider - Target provider to write config for
|
|
720
|
+
* @param serverName - Name/key for the MCP server entry
|
|
721
|
+
* @param config - Canonical MCP server configuration
|
|
722
|
+
* @param scope - Whether to write to project or global config (default: `"project"`)
|
|
723
|
+
* @param projectDir - Project directory path (defaults to `process.cwd()`)
|
|
724
|
+
* @returns Install result with success status and config path
|
|
725
|
+
*
|
|
726
|
+
* @example
|
|
727
|
+
* ```typescript
|
|
728
|
+
* const provider = getProvider("claude-code")!;
|
|
729
|
+
* const result = await installMcpServer(provider, "filesystem", {
|
|
730
|
+
* command: "npx",
|
|
731
|
+
* args: ["-y", "@modelcontextprotocol/server-filesystem"],
|
|
732
|
+
* });
|
|
733
|
+
* ```
|
|
734
|
+
*/
|
|
195
735
|
declare function installMcpServer(provider: Provider, serverName: string, config: McpServerConfig, scope?: "project" | "global", projectDir?: string): Promise<InstallResult>;
|
|
196
|
-
/**
|
|
736
|
+
/**
|
|
737
|
+
* Install an MCP server configuration to multiple providers.
|
|
738
|
+
*
|
|
739
|
+
* Calls {@link installMcpServer} for each provider sequentially and collects results.
|
|
740
|
+
*
|
|
741
|
+
* @param providers - Array of target providers
|
|
742
|
+
* @param serverName - Name/key for the MCP server entry
|
|
743
|
+
* @param config - Canonical MCP server configuration
|
|
744
|
+
* @param scope - Whether to write to project or global config (default: `"project"`)
|
|
745
|
+
* @param projectDir - Project directory path (defaults to `process.cwd()`)
|
|
746
|
+
* @returns Array of install results, one per provider
|
|
747
|
+
*
|
|
748
|
+
* @example
|
|
749
|
+
* ```typescript
|
|
750
|
+
* const providers = getInstalledProviders();
|
|
751
|
+
* const results = await installMcpServerToAll(providers, "my-server", config);
|
|
752
|
+
* const successes = results.filter(r => r.success);
|
|
753
|
+
* ```
|
|
754
|
+
*/
|
|
197
755
|
declare function installMcpServerToAll(providers: Provider[], serverName: string, config: McpServerConfig, scope?: "project" | "global", projectDir?: string): Promise<InstallResult[]>;
|
|
198
|
-
/**
|
|
756
|
+
/**
|
|
757
|
+
* Build a canonical {@link McpServerConfig} from a parsed source.
|
|
758
|
+
*
|
|
759
|
+
* Maps source types to appropriate transport configurations:
|
|
760
|
+
* - `"remote"` sources become HTTP/SSE configs with a `url`
|
|
761
|
+
* - `"package"` sources become `npx -y <package>` stdio configs
|
|
762
|
+
* - All others are treated as shell commands split into `command` + `args`
|
|
763
|
+
*
|
|
764
|
+
* @param source - Parsed source with `type` and `value`
|
|
765
|
+
* @param transport - Override transport type for remote sources (default: `"http"`)
|
|
766
|
+
* @param headers - Optional HTTP headers for remote servers
|
|
767
|
+
* @returns Canonical MCP server configuration
|
|
768
|
+
*
|
|
769
|
+
* @example
|
|
770
|
+
* ```typescript
|
|
771
|
+
* buildServerConfig({ type: "package", value: "@mcp/server-fs" });
|
|
772
|
+
* // { command: "npx", args: ["-y", "@mcp/server-fs"] }
|
|
773
|
+
*
|
|
774
|
+
* buildServerConfig({ type: "remote", value: "https://mcp.example.com" });
|
|
775
|
+
* // { type: "http", url: "https://mcp.example.com" }
|
|
776
|
+
* ```
|
|
777
|
+
*/
|
|
199
778
|
declare function buildServerConfig(source: {
|
|
200
779
|
type: string;
|
|
201
780
|
value: string;
|
|
@@ -208,21 +787,83 @@ declare function buildServerConfig(source: {
|
|
|
208
787
|
* and symlinked to each target agent's skills directory.
|
|
209
788
|
*/
|
|
210
789
|
|
|
790
|
+
/**
|
|
791
|
+
* Result of installing a skill to the canonical location and linking to agents.
|
|
792
|
+
*
|
|
793
|
+
* @example
|
|
794
|
+
* ```typescript
|
|
795
|
+
* const result = await installSkill(sourcePath, "my-skill", providers, true);
|
|
796
|
+
* if (result.success) {
|
|
797
|
+
* console.log(`Installed to ${result.canonicalPath}`);
|
|
798
|
+
* console.log(`Linked to: ${result.linkedAgents.join(", ")}`);
|
|
799
|
+
* }
|
|
800
|
+
* ```
|
|
801
|
+
*/
|
|
211
802
|
interface SkillInstallResult {
|
|
803
|
+
/** Skill name. */
|
|
212
804
|
name: string;
|
|
805
|
+
/** Absolute path to the canonical installation directory. */
|
|
213
806
|
canonicalPath: string;
|
|
807
|
+
/** Provider IDs that were successfully linked. */
|
|
214
808
|
linkedAgents: string[];
|
|
809
|
+
/** Error messages from failed link operations. */
|
|
215
810
|
errors: string[];
|
|
811
|
+
/** Whether at least one agent was successfully linked. */
|
|
216
812
|
success: boolean;
|
|
217
813
|
}
|
|
218
|
-
/**
|
|
814
|
+
/**
|
|
815
|
+
* Install a skill from a local path to the canonical location and link to agents.
|
|
816
|
+
*
|
|
817
|
+
* Copies the skill directory to `~/.agents/skills/<name>/` and creates symlinks
|
|
818
|
+
* (or copies on Windows) from each provider's skills directory to the canonical path.
|
|
819
|
+
*
|
|
820
|
+
* @param sourcePath - Local path to the skill directory to install
|
|
821
|
+
* @param skillName - Name for the installed skill
|
|
822
|
+
* @param providers - Target providers to link the skill to
|
|
823
|
+
* @param isGlobal - Whether to link to global or project skill directories
|
|
824
|
+
* @param projectDir - Project directory (defaults to `process.cwd()`)
|
|
825
|
+
* @returns Install result with linked agents and any errors
|
|
826
|
+
*
|
|
827
|
+
* @example
|
|
828
|
+
* ```typescript
|
|
829
|
+
* const result = await installSkill("/tmp/my-skill", "my-skill", providers, true);
|
|
830
|
+
* ```
|
|
831
|
+
*/
|
|
219
832
|
declare function installSkill(sourcePath: string, skillName: string, providers: Provider[], isGlobal: boolean, projectDir?: string): Promise<SkillInstallResult>;
|
|
220
|
-
/**
|
|
833
|
+
/**
|
|
834
|
+
* Remove a skill from the canonical location and all agent symlinks.
|
|
835
|
+
*
|
|
836
|
+
* Removes symlinks from each provider's skills directory and then removes the
|
|
837
|
+
* canonical copy from `~/.agents/skills/<name>/`.
|
|
838
|
+
*
|
|
839
|
+
* @param skillName - Name of the skill to remove
|
|
840
|
+
* @param providers - Providers to unlink the skill from
|
|
841
|
+
* @param isGlobal - Whether to target global or project skill directories
|
|
842
|
+
* @param projectDir - Project directory (defaults to `process.cwd()`)
|
|
843
|
+
* @returns Object with arrays of successfully removed provider IDs and error messages
|
|
844
|
+
*
|
|
845
|
+
* @example
|
|
846
|
+
* ```typescript
|
|
847
|
+
* const { removed, errors } = await removeSkill("my-skill", providers, true);
|
|
848
|
+
* ```
|
|
849
|
+
*/
|
|
221
850
|
declare function removeSkill(skillName: string, providers: Provider[], isGlobal: boolean, projectDir?: string): Promise<{
|
|
222
851
|
removed: string[];
|
|
223
852
|
errors: string[];
|
|
224
853
|
}>;
|
|
225
|
-
/**
|
|
854
|
+
/**
|
|
855
|
+
* List all skills installed in the canonical directory (`~/.agents/skills/`).
|
|
856
|
+
*
|
|
857
|
+
* Returns the directory names of all skills, which correspond to skill names.
|
|
858
|
+
*
|
|
859
|
+
* @returns Array of skill names
|
|
860
|
+
*
|
|
861
|
+
* @example
|
|
862
|
+
* ```typescript
|
|
863
|
+
* const skills = await listCanonicalSkills();
|
|
864
|
+
* // ["my-skill", "another-skill"]
|
|
865
|
+
* ```
|
|
866
|
+
*/
|
|
226
867
|
declare function listCanonicalSkills(): Promise<string[]>;
|
|
227
868
|
|
|
228
869
|
/**
|
|
@@ -230,19 +871,326 @@ declare function listCanonicalSkills(): Promise<string[]>;
|
|
|
230
871
|
*
|
|
231
872
|
* Validates skill files against the Agent Skills standard.
|
|
232
873
|
*/
|
|
874
|
+
/**
|
|
875
|
+
* A single validation issue found during SKILL.md validation.
|
|
876
|
+
*
|
|
877
|
+
* @example
|
|
878
|
+
* ```typescript
|
|
879
|
+
* const issue: ValidationIssue = {
|
|
880
|
+
* level: "error",
|
|
881
|
+
* field: "name",
|
|
882
|
+
* message: "Missing required field: name",
|
|
883
|
+
* };
|
|
884
|
+
* ```
|
|
885
|
+
*/
|
|
233
886
|
interface ValidationIssue {
|
|
887
|
+
/** Severity: `"error"` causes validation failure, `"warning"` does not. */
|
|
234
888
|
level: "error" | "warning";
|
|
889
|
+
/** The field or section that triggered the issue. */
|
|
235
890
|
field: string;
|
|
891
|
+
/** Human-readable description of the issue. */
|
|
236
892
|
message: string;
|
|
237
893
|
}
|
|
894
|
+
/**
|
|
895
|
+
* Result of validating a SKILL.md file against the Agent Skills standard.
|
|
896
|
+
*
|
|
897
|
+
* @example
|
|
898
|
+
* ```typescript
|
|
899
|
+
* const result = await validateSkill("/path/to/SKILL.md");
|
|
900
|
+
* if (!result.valid) {
|
|
901
|
+
* for (const issue of result.issues) {
|
|
902
|
+
* console.log(`[${issue.level}] ${issue.field}: ${issue.message}`);
|
|
903
|
+
* }
|
|
904
|
+
* }
|
|
905
|
+
* ```
|
|
906
|
+
*/
|
|
238
907
|
interface ValidationResult {
|
|
908
|
+
/** Whether the skill passed validation (no error-level issues). */
|
|
239
909
|
valid: boolean;
|
|
910
|
+
/** All issues found during validation. */
|
|
240
911
|
issues: ValidationIssue[];
|
|
912
|
+
/** Parsed frontmatter metadata, or `null` if parsing failed. */
|
|
241
913
|
metadata: Record<string, unknown> | null;
|
|
242
914
|
}
|
|
243
|
-
/**
|
|
915
|
+
/**
|
|
916
|
+
* Validate a SKILL.md file against the Agent Skills standard.
|
|
917
|
+
*
|
|
918
|
+
* Checks for required frontmatter fields (`name`, `description`), validates
|
|
919
|
+
* naming conventions, enforces length limits, checks for reserved names,
|
|
920
|
+
* and warns about long skill bodies.
|
|
921
|
+
*
|
|
922
|
+
* @param filePath - Absolute path to the SKILL.md file to validate
|
|
923
|
+
* @returns Validation result with issues and parsed metadata
|
|
924
|
+
*
|
|
925
|
+
* @example
|
|
926
|
+
* ```typescript
|
|
927
|
+
* const result = await validateSkill("/path/to/SKILL.md");
|
|
928
|
+
* console.log(result.valid ? "Valid" : `${result.issues.length} issues found`);
|
|
929
|
+
* ```
|
|
930
|
+
*/
|
|
244
931
|
declare function validateSkill(filePath: string): Promise<ValidationResult>;
|
|
245
932
|
|
|
933
|
+
/**
|
|
934
|
+
* Marketplace types shared between adapters
|
|
935
|
+
*/
|
|
936
|
+
interface MarketplaceAdapter {
|
|
937
|
+
name: string;
|
|
938
|
+
search(query: string, limit?: number): Promise<MarketplaceResult[]>;
|
|
939
|
+
getSkill(scopedName: string): Promise<MarketplaceResult | null>;
|
|
940
|
+
}
|
|
941
|
+
interface MarketplaceResult {
|
|
942
|
+
name: string;
|
|
943
|
+
scopedName: string;
|
|
944
|
+
description: string;
|
|
945
|
+
author: string;
|
|
946
|
+
stars: number;
|
|
947
|
+
githubUrl: string;
|
|
948
|
+
repoFullName: string;
|
|
949
|
+
path: string;
|
|
950
|
+
source: string;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
declare const RECOMMENDATION_ERROR_CODES: {
|
|
954
|
+
readonly QUERY_INVALID: "E_SKILLS_QUERY_INVALID";
|
|
955
|
+
readonly NO_MATCHES: "E_SKILLS_NO_MATCHES";
|
|
956
|
+
readonly SOURCE_UNAVAILABLE: "E_SKILLS_SOURCE_UNAVAILABLE";
|
|
957
|
+
readonly CRITERIA_CONFLICT: "E_SKILLS_CRITERIA_CONFLICT";
|
|
958
|
+
};
|
|
959
|
+
type RecommendationErrorCode = (typeof RECOMMENDATION_ERROR_CODES)[keyof typeof RECOMMENDATION_ERROR_CODES];
|
|
960
|
+
interface RecommendationValidationIssue {
|
|
961
|
+
code: RecommendationErrorCode;
|
|
962
|
+
field: "query" | "mustHave" | "prefer" | "exclude";
|
|
963
|
+
message: string;
|
|
964
|
+
}
|
|
965
|
+
interface RecommendationValidationResult {
|
|
966
|
+
valid: boolean;
|
|
967
|
+
issues: RecommendationValidationIssue[];
|
|
968
|
+
}
|
|
969
|
+
interface RecommendationCriteriaInput {
|
|
970
|
+
query?: string;
|
|
971
|
+
mustHave?: string | string[];
|
|
972
|
+
prefer?: string | string[];
|
|
973
|
+
exclude?: string | string[];
|
|
974
|
+
}
|
|
975
|
+
interface NormalizedRecommendationCriteria {
|
|
976
|
+
query: string;
|
|
977
|
+
queryTokens: string[];
|
|
978
|
+
mustHave: string[];
|
|
979
|
+
prefer: string[];
|
|
980
|
+
exclude: string[];
|
|
981
|
+
}
|
|
982
|
+
type RecommendationReasonCode = "MATCH_TOPIC_GITBOOK" | "HAS_GIT_SYNC" | "HAS_API_WORKFLOW" | "PENALTY_LEGACY_CLI" | "MUST_HAVE_MATCH" | "MISSING_MUST_HAVE" | "PREFER_MATCH" | "QUERY_MATCH" | "STAR_SIGNAL" | "METADATA_SIGNAL" | "MODERN_MARKER" | "LEGACY_MARKER" | "EXCLUDE_MATCH";
|
|
983
|
+
interface RecommendationReason {
|
|
984
|
+
code: RecommendationReasonCode;
|
|
985
|
+
detail?: string;
|
|
986
|
+
}
|
|
987
|
+
interface RecommendationScoreBreakdown {
|
|
988
|
+
mustHave: number;
|
|
989
|
+
prefer: number;
|
|
990
|
+
query: number;
|
|
991
|
+
stars: number;
|
|
992
|
+
metadata: number;
|
|
993
|
+
modernity: number;
|
|
994
|
+
exclusionPenalty: number;
|
|
995
|
+
total: number;
|
|
996
|
+
}
|
|
997
|
+
interface RankedSkillRecommendation {
|
|
998
|
+
skill: MarketplaceResult;
|
|
999
|
+
score: number;
|
|
1000
|
+
reasons: RecommendationReason[];
|
|
1001
|
+
tradeoffs: string[];
|
|
1002
|
+
excluded: boolean;
|
|
1003
|
+
breakdown?: RecommendationScoreBreakdown;
|
|
1004
|
+
}
|
|
1005
|
+
interface RecommendationOptions {
|
|
1006
|
+
top?: number;
|
|
1007
|
+
includeDetails?: boolean;
|
|
1008
|
+
weights?: Partial<RecommendationWeights>;
|
|
1009
|
+
modernMarkers?: string[];
|
|
1010
|
+
legacyMarkers?: string[];
|
|
1011
|
+
}
|
|
1012
|
+
interface RecommendationWeights {
|
|
1013
|
+
mustHaveMatch: number;
|
|
1014
|
+
preferMatch: number;
|
|
1015
|
+
queryTokenMatch: number;
|
|
1016
|
+
starsFactor: number;
|
|
1017
|
+
metadataBoost: number;
|
|
1018
|
+
modernMarkerBoost: number;
|
|
1019
|
+
legacyMarkerPenalty: number;
|
|
1020
|
+
excludePenalty: number;
|
|
1021
|
+
missingMustHavePenalty: number;
|
|
1022
|
+
}
|
|
1023
|
+
interface RecommendSkillsResult {
|
|
1024
|
+
criteria: NormalizedRecommendationCriteria;
|
|
1025
|
+
ranking: RankedSkillRecommendation[];
|
|
1026
|
+
}
|
|
1027
|
+
declare function tokenizeCriteriaValue(value: string): string[];
|
|
1028
|
+
declare function validateRecommendationCriteria(input: RecommendationCriteriaInput): RecommendationValidationResult;
|
|
1029
|
+
declare function normalizeRecommendationCriteria(input: RecommendationCriteriaInput): NormalizedRecommendationCriteria;
|
|
1030
|
+
declare function scoreSkillRecommendation(skill: MarketplaceResult, criteria: NormalizedRecommendationCriteria, options?: RecommendationOptions): RankedSkillRecommendation;
|
|
1031
|
+
declare function recommendSkills$1(skills: MarketplaceResult[], criteriaInput: RecommendationCriteriaInput, options?: RecommendationOptions): RecommendSkillsResult;
|
|
1032
|
+
declare const rankSkills: typeof recommendSkills$1;
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* Advanced orchestration helpers for multi-provider operations.
|
|
1036
|
+
*
|
|
1037
|
+
* These helpers compose CAAMP's lower-level APIs into production patterns:
|
|
1038
|
+
* tier-based targeting, conflict-aware installs, and rollback-capable batches.
|
|
1039
|
+
*/
|
|
1040
|
+
|
|
1041
|
+
type Scope = "project" | "global";
|
|
1042
|
+
/**
|
|
1043
|
+
* Filter providers by minimum priority and return them in deterministic tier order.
|
|
1044
|
+
*
|
|
1045
|
+
* `minimumPriority = "medium"` returns `high` + `medium`.
|
|
1046
|
+
*/
|
|
1047
|
+
declare function selectProvidersByMinimumPriority(providers: Provider[], minimumPriority?: ProviderPriority): Provider[];
|
|
1048
|
+
/**
|
|
1049
|
+
* Single MCP operation entry used by batch orchestration.
|
|
1050
|
+
*/
|
|
1051
|
+
interface McpBatchOperation {
|
|
1052
|
+
serverName: string;
|
|
1053
|
+
config: McpServerConfig;
|
|
1054
|
+
scope?: Scope;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Single skill operation entry used by batch orchestration.
|
|
1058
|
+
*/
|
|
1059
|
+
interface SkillBatchOperation {
|
|
1060
|
+
sourcePath: string;
|
|
1061
|
+
skillName: string;
|
|
1062
|
+
isGlobal?: boolean;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Options for rollback-capable batch installation.
|
|
1066
|
+
*/
|
|
1067
|
+
interface BatchInstallOptions {
|
|
1068
|
+
providers?: Provider[];
|
|
1069
|
+
minimumPriority?: ProviderPriority;
|
|
1070
|
+
mcp?: McpBatchOperation[];
|
|
1071
|
+
skills?: SkillBatchOperation[];
|
|
1072
|
+
projectDir?: string;
|
|
1073
|
+
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Result of rollback-capable batch installation.
|
|
1076
|
+
*/
|
|
1077
|
+
interface BatchInstallResult {
|
|
1078
|
+
success: boolean;
|
|
1079
|
+
providerIds: string[];
|
|
1080
|
+
mcpApplied: number;
|
|
1081
|
+
skillsApplied: number;
|
|
1082
|
+
rollbackPerformed: boolean;
|
|
1083
|
+
rollbackErrors: string[];
|
|
1084
|
+
error?: string;
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Install multiple MCP servers and skills across filtered providers with rollback.
|
|
1088
|
+
*
|
|
1089
|
+
* Rollback behavior:
|
|
1090
|
+
* - MCP config files are restored exactly from snapshots.
|
|
1091
|
+
* - Skill state is restored for canonical skill dirs and targeted provider link paths.
|
|
1092
|
+
*/
|
|
1093
|
+
declare function installBatchWithRollback(options: BatchInstallOptions): Promise<BatchInstallResult>;
|
|
1094
|
+
/**
|
|
1095
|
+
* Conflict policy when applying MCP install plans.
|
|
1096
|
+
*/
|
|
1097
|
+
type ConflictPolicy = "fail" | "skip" | "overwrite";
|
|
1098
|
+
/**
|
|
1099
|
+
* MCP conflict code.
|
|
1100
|
+
*/
|
|
1101
|
+
type McpConflictCode = "unsupported-transport" | "unsupported-headers" | "existing-mismatch";
|
|
1102
|
+
/**
|
|
1103
|
+
* Conflict detected during preflight.
|
|
1104
|
+
*/
|
|
1105
|
+
interface McpConflict {
|
|
1106
|
+
providerId: string;
|
|
1107
|
+
serverName: string;
|
|
1108
|
+
scope: Scope;
|
|
1109
|
+
code: McpConflictCode;
|
|
1110
|
+
message: string;
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Result from applying install plan with conflict policy.
|
|
1114
|
+
*/
|
|
1115
|
+
interface McpPlanApplyResult {
|
|
1116
|
+
conflicts: McpConflict[];
|
|
1117
|
+
applied: InstallResult[];
|
|
1118
|
+
skipped: Array<{
|
|
1119
|
+
providerId: string;
|
|
1120
|
+
serverName: string;
|
|
1121
|
+
scope: Scope;
|
|
1122
|
+
reason: McpConflictCode;
|
|
1123
|
+
}>;
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Preflight conflict detection for MCP install plans across providers.
|
|
1127
|
+
*/
|
|
1128
|
+
declare function detectMcpConfigConflicts(providers: Provider[], operations: McpBatchOperation[], projectDir?: string): Promise<McpConflict[]>;
|
|
1129
|
+
/**
|
|
1130
|
+
* Apply MCP install plan with a conflict policy.
|
|
1131
|
+
*/
|
|
1132
|
+
declare function applyMcpInstallWithPolicy(providers: Provider[], operations: McpBatchOperation[], policy?: ConflictPolicy, projectDir?: string): Promise<McpPlanApplyResult>;
|
|
1133
|
+
/**
|
|
1134
|
+
* Result of a single-operation instruction update across providers.
|
|
1135
|
+
*/
|
|
1136
|
+
interface InstructionUpdateSummary {
|
|
1137
|
+
scope: Scope;
|
|
1138
|
+
updatedFiles: number;
|
|
1139
|
+
actions: Array<{
|
|
1140
|
+
file: string;
|
|
1141
|
+
action: "created" | "added" | "updated";
|
|
1142
|
+
providers: string[];
|
|
1143
|
+
configFormats: ConfigFormat[];
|
|
1144
|
+
}>;
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Update instruction files across providers as a single operation.
|
|
1148
|
+
*
|
|
1149
|
+
* Works the same regardless of provider config format (JSON/YAML/TOML/JSONC)
|
|
1150
|
+
* because instruction files are handled through CAAMP markers.
|
|
1151
|
+
*/
|
|
1152
|
+
declare function updateInstructionsSingleOperation(providers: Provider[], content: string, scope?: Scope, projectDir?: string): Promise<InstructionUpdateSummary>;
|
|
1153
|
+
/**
|
|
1154
|
+
* Request payload for dual-scope provider configuration.
|
|
1155
|
+
*/
|
|
1156
|
+
interface DualScopeConfigureOptions {
|
|
1157
|
+
globalMcp?: Array<{
|
|
1158
|
+
serverName: string;
|
|
1159
|
+
config: McpServerConfig;
|
|
1160
|
+
}>;
|
|
1161
|
+
projectMcp?: Array<{
|
|
1162
|
+
serverName: string;
|
|
1163
|
+
config: McpServerConfig;
|
|
1164
|
+
}>;
|
|
1165
|
+
instructionContent?: string | {
|
|
1166
|
+
global?: string;
|
|
1167
|
+
project?: string;
|
|
1168
|
+
};
|
|
1169
|
+
projectDir?: string;
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Result of dual-scope provider configuration.
|
|
1173
|
+
*/
|
|
1174
|
+
interface DualScopeConfigureResult {
|
|
1175
|
+
providerId: string;
|
|
1176
|
+
configPaths: {
|
|
1177
|
+
global: string | null;
|
|
1178
|
+
project: string | null;
|
|
1179
|
+
};
|
|
1180
|
+
mcp: {
|
|
1181
|
+
global: InstallResult[];
|
|
1182
|
+
project: InstallResult[];
|
|
1183
|
+
};
|
|
1184
|
+
instructions: {
|
|
1185
|
+
global?: Map<string, "created" | "added" | "updated">;
|
|
1186
|
+
project?: Map<string, "created" | "added" | "updated">;
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Configure both global and project-level settings for one provider in one call.
|
|
1191
|
+
*/
|
|
1192
|
+
declare function configureProviderGlobalAndProject(provider: Provider, options: DualScopeConfigureOptions): Promise<DualScopeConfigureResult>;
|
|
1193
|
+
|
|
246
1194
|
/**
|
|
247
1195
|
* Provider registry loader
|
|
248
1196
|
*
|
|
@@ -250,23 +1198,121 @@ declare function validateSkill(filePath: string): Promise<ValidationResult>;
|
|
|
250
1198
|
* platform-specific paths at runtime.
|
|
251
1199
|
*/
|
|
252
1200
|
|
|
253
|
-
/**
|
|
1201
|
+
/**
|
|
1202
|
+
* Retrieve all registered providers with resolved platform paths.
|
|
1203
|
+
*
|
|
1204
|
+
* Providers are lazily loaded from `providers/registry.json` on first call
|
|
1205
|
+
* and cached for subsequent calls.
|
|
1206
|
+
*
|
|
1207
|
+
* @returns Array of all provider definitions
|
|
1208
|
+
*
|
|
1209
|
+
* @example
|
|
1210
|
+
* ```typescript
|
|
1211
|
+
* const providers = getAllProviders();
|
|
1212
|
+
* console.log(`${providers.length} providers registered`);
|
|
1213
|
+
* ```
|
|
1214
|
+
*/
|
|
254
1215
|
declare function getAllProviders(): Provider[];
|
|
255
|
-
/**
|
|
1216
|
+
/**
|
|
1217
|
+
* Look up a provider by its ID or any of its aliases.
|
|
1218
|
+
*
|
|
1219
|
+
* @param idOrAlias - Provider ID (e.g. `"claude-code"`) or alias (e.g. `"claude"`)
|
|
1220
|
+
* @returns The matching provider, or `undefined` if not found
|
|
1221
|
+
*
|
|
1222
|
+
* @example
|
|
1223
|
+
* ```typescript
|
|
1224
|
+
* const provider = getProvider("claude");
|
|
1225
|
+
* // Returns the claude-code provider via alias resolution
|
|
1226
|
+
* ```
|
|
1227
|
+
*/
|
|
256
1228
|
declare function getProvider(idOrAlias: string): Provider | undefined;
|
|
257
|
-
/**
|
|
1229
|
+
/**
|
|
1230
|
+
* Resolve an alias to its canonical provider ID.
|
|
1231
|
+
*
|
|
1232
|
+
* If the input is already a canonical ID (or unrecognized), it is returned as-is.
|
|
1233
|
+
*
|
|
1234
|
+
* @param idOrAlias - Provider ID or alias to resolve
|
|
1235
|
+
* @returns The canonical provider ID
|
|
1236
|
+
*
|
|
1237
|
+
* @example
|
|
1238
|
+
* ```typescript
|
|
1239
|
+
* resolveAlias("claude"); // "claude-code"
|
|
1240
|
+
* resolveAlias("claude-code"); // "claude-code"
|
|
1241
|
+
* resolveAlias("unknown"); // "unknown"
|
|
1242
|
+
* ```
|
|
1243
|
+
*/
|
|
258
1244
|
declare function resolveAlias(idOrAlias: string): string;
|
|
259
|
-
/**
|
|
1245
|
+
/**
|
|
1246
|
+
* Filter providers by their priority tier.
|
|
1247
|
+
*
|
|
1248
|
+
* @param priority - Priority level to filter by (`"high"`, `"medium"`, or `"low"`)
|
|
1249
|
+
* @returns Array of providers matching the given priority
|
|
1250
|
+
*
|
|
1251
|
+
* @example
|
|
1252
|
+
* ```typescript
|
|
1253
|
+
* const highPriority = getProvidersByPriority("high");
|
|
1254
|
+
* ```
|
|
1255
|
+
*/
|
|
260
1256
|
declare function getProvidersByPriority(priority: ProviderPriority): Provider[];
|
|
261
|
-
/**
|
|
1257
|
+
/**
|
|
1258
|
+
* Filter providers by their lifecycle status.
|
|
1259
|
+
*
|
|
1260
|
+
* @param status - Status to filter by (`"active"`, `"beta"`, `"deprecated"`, or `"planned"`)
|
|
1261
|
+
* @returns Array of providers matching the given status
|
|
1262
|
+
*
|
|
1263
|
+
* @example
|
|
1264
|
+
* ```typescript
|
|
1265
|
+
* const active = getProvidersByStatus("active");
|
|
1266
|
+
* ```
|
|
1267
|
+
*/
|
|
262
1268
|
declare function getProvidersByStatus(status: ProviderStatus): Provider[];
|
|
263
|
-
/**
|
|
1269
|
+
/**
|
|
1270
|
+
* Filter providers that use a specific instruction file.
|
|
1271
|
+
*
|
|
1272
|
+
* Multiple providers often share the same instruction file (e.g. many use `"AGENTS.md"`).
|
|
1273
|
+
*
|
|
1274
|
+
* @param file - Instruction file name (e.g. `"CLAUDE.md"`, `"AGENTS.md"`)
|
|
1275
|
+
* @returns Array of providers that use the given instruction file
|
|
1276
|
+
*
|
|
1277
|
+
* @example
|
|
1278
|
+
* ```typescript
|
|
1279
|
+
* const claudeProviders = getProvidersByInstructFile("CLAUDE.md");
|
|
1280
|
+
* ```
|
|
1281
|
+
*/
|
|
264
1282
|
declare function getProvidersByInstructFile(file: string): Provider[];
|
|
265
|
-
/**
|
|
1283
|
+
/**
|
|
1284
|
+
* Get the set of all unique instruction file names across all providers.
|
|
1285
|
+
*
|
|
1286
|
+
* @returns Array of unique instruction file names (e.g. `["CLAUDE.md", "AGENTS.md", "GEMINI.md"]`)
|
|
1287
|
+
*
|
|
1288
|
+
* @example
|
|
1289
|
+
* ```typescript
|
|
1290
|
+
* const files = getInstructionFiles();
|
|
1291
|
+
* // ["CLAUDE.md", "AGENTS.md", "GEMINI.md"]
|
|
1292
|
+
* ```
|
|
1293
|
+
*/
|
|
266
1294
|
declare function getInstructionFiles(): string[];
|
|
267
|
-
/**
|
|
1295
|
+
/**
|
|
1296
|
+
* Get the total number of registered providers.
|
|
1297
|
+
*
|
|
1298
|
+
* @returns Count of providers in the registry
|
|
1299
|
+
*
|
|
1300
|
+
* @example
|
|
1301
|
+
* ```typescript
|
|
1302
|
+
* console.log(`Registry has ${getProviderCount()} providers`);
|
|
1303
|
+
* ```
|
|
1304
|
+
*/
|
|
268
1305
|
declare function getProviderCount(): number;
|
|
269
|
-
/**
|
|
1306
|
+
/**
|
|
1307
|
+
* Get the semantic version string of the provider registry.
|
|
1308
|
+
*
|
|
1309
|
+
* @returns Version string from `providers/registry.json` (e.g. `"1.0.0"`)
|
|
1310
|
+
*
|
|
1311
|
+
* @example
|
|
1312
|
+
* ```typescript
|
|
1313
|
+
* console.log(`Registry version: ${getRegistryVersion()}`);
|
|
1314
|
+
* ```
|
|
1315
|
+
*/
|
|
270
1316
|
declare function getRegistryVersion(): string;
|
|
271
1317
|
|
|
272
1318
|
/**
|
|
@@ -276,9 +1322,42 @@ declare function getRegistryVersion(): string;
|
|
|
276
1322
|
* GitLab URLs, local paths, or shell commands.
|
|
277
1323
|
*/
|
|
278
1324
|
|
|
279
|
-
/**
|
|
1325
|
+
/**
|
|
1326
|
+
* Parse and classify a source string into a typed {@link ParsedSource}.
|
|
1327
|
+
*
|
|
1328
|
+
* Supports GitHub URLs, GitLab URLs, GitHub shorthand (`owner/repo`),
|
|
1329
|
+
* HTTP URLs (remote MCP servers), npm package names, local paths, and
|
|
1330
|
+
* shell commands as a fallback.
|
|
1331
|
+
*
|
|
1332
|
+
* @param input - Raw source string to classify
|
|
1333
|
+
* @returns Parsed source with type, value, and inferred name
|
|
1334
|
+
*
|
|
1335
|
+
* @example
|
|
1336
|
+
* ```typescript
|
|
1337
|
+
* parseSource("owner/repo");
|
|
1338
|
+
* // { type: "github", value: "https://github.com/owner/repo", inferredName: "repo", ... }
|
|
1339
|
+
*
|
|
1340
|
+
* parseSource("https://mcp.example.com/sse");
|
|
1341
|
+
* // { type: "remote", value: "https://mcp.example.com/sse", inferredName: "example" }
|
|
1342
|
+
*
|
|
1343
|
+
* parseSource("@modelcontextprotocol/server-filesystem");
|
|
1344
|
+
* // { type: "package", value: "@modelcontextprotocol/server-filesystem", inferredName: "filesystem" }
|
|
1345
|
+
* ```
|
|
1346
|
+
*/
|
|
280
1347
|
declare function parseSource(input: string): ParsedSource;
|
|
281
|
-
/**
|
|
1348
|
+
/**
|
|
1349
|
+
* Check if a source string looks like a marketplace scoped name (`@author/name`).
|
|
1350
|
+
*
|
|
1351
|
+
* @param input - Source string to check
|
|
1352
|
+
* @returns `true` if the input matches the `@scope/name` pattern
|
|
1353
|
+
*
|
|
1354
|
+
* @example
|
|
1355
|
+
* ```typescript
|
|
1356
|
+
* isMarketplaceScoped("@anthropic/my-skill"); // true
|
|
1357
|
+
* isMarketplaceScoped("my-skill"); // false
|
|
1358
|
+
* isMarketplaceScoped("owner/repo"); // false
|
|
1359
|
+
* ```
|
|
1360
|
+
*/
|
|
282
1361
|
declare function isMarketplaceScoped(input: string): boolean;
|
|
283
1362
|
|
|
284
1363
|
/**
|
|
@@ -287,13 +1366,72 @@ declare function isMarketplaceScoped(input: string): boolean;
|
|
|
287
1366
|
* Scans directories for SKILL.md files and parses their frontmatter.
|
|
288
1367
|
*/
|
|
289
1368
|
|
|
290
|
-
/**
|
|
1369
|
+
/**
|
|
1370
|
+
* Parse a SKILL.md file and extract its frontmatter metadata.
|
|
1371
|
+
*
|
|
1372
|
+
* Reads the file, parses YAML frontmatter via `gray-matter`, and maps the
|
|
1373
|
+
* fields to a {@link SkillMetadata} object. Returns `null` if the file cannot
|
|
1374
|
+
* be read or lacks required `name` and `description` fields.
|
|
1375
|
+
*
|
|
1376
|
+
* @param filePath - Absolute path to the SKILL.md file
|
|
1377
|
+
* @returns Parsed metadata, or `null` if invalid
|
|
1378
|
+
*
|
|
1379
|
+
* @example
|
|
1380
|
+
* ```typescript
|
|
1381
|
+
* const meta = await parseSkillFile("/path/to/SKILL.md");
|
|
1382
|
+
* if (meta) {
|
|
1383
|
+
* console.log(`${meta.name}: ${meta.description}`);
|
|
1384
|
+
* }
|
|
1385
|
+
* ```
|
|
1386
|
+
*/
|
|
291
1387
|
declare function parseSkillFile(filePath: string): Promise<SkillMetadata | null>;
|
|
292
|
-
/**
|
|
1388
|
+
/**
|
|
1389
|
+
* Discover a single skill at a given directory path.
|
|
1390
|
+
*
|
|
1391
|
+
* Checks for a `SKILL.md` file in the directory and parses its metadata.
|
|
1392
|
+
*
|
|
1393
|
+
* @param skillDir - Absolute path to a skill directory (containing SKILL.md)
|
|
1394
|
+
* @returns Skill entry with metadata, or `null` if no valid SKILL.md exists
|
|
1395
|
+
*
|
|
1396
|
+
* @example
|
|
1397
|
+
* ```typescript
|
|
1398
|
+
* const skill = await discoverSkill("/home/user/.agents/skills/my-skill");
|
|
1399
|
+
* if (skill) {
|
|
1400
|
+
* console.log(`Found: ${skill.name}`);
|
|
1401
|
+
* }
|
|
1402
|
+
* ```
|
|
1403
|
+
*/
|
|
293
1404
|
declare function discoverSkill(skillDir: string): Promise<SkillEntry | null>;
|
|
294
|
-
/**
|
|
1405
|
+
/**
|
|
1406
|
+
* Scan a directory for skill subdirectories, each containing a SKILL.md file.
|
|
1407
|
+
*
|
|
1408
|
+
* Iterates over directories and symlinks in `rootDir` and calls
|
|
1409
|
+
* {@link discoverSkill} on each.
|
|
1410
|
+
*
|
|
1411
|
+
* @param rootDir - Absolute path to a skills root directory to scan
|
|
1412
|
+
* @returns Array of discovered skill entries
|
|
1413
|
+
*
|
|
1414
|
+
* @example
|
|
1415
|
+
* ```typescript
|
|
1416
|
+
* const skills = await discoverSkills("/home/user/.agents/skills");
|
|
1417
|
+
* console.log(`Found ${skills.length} skills`);
|
|
1418
|
+
* ```
|
|
1419
|
+
*/
|
|
295
1420
|
declare function discoverSkills(rootDir: string): Promise<SkillEntry[]>;
|
|
296
1421
|
|
|
1422
|
+
interface SearchSkillsOptions {
|
|
1423
|
+
limit?: number;
|
|
1424
|
+
}
|
|
1425
|
+
interface RecommendSkillsQueryOptions extends RecommendationOptions {
|
|
1426
|
+
limit?: number;
|
|
1427
|
+
}
|
|
1428
|
+
declare function formatSkillRecommendations(result: RecommendSkillsResult, opts: {
|
|
1429
|
+
mode: "human" | "json";
|
|
1430
|
+
details?: boolean;
|
|
1431
|
+
}): string | Record<string, unknown>;
|
|
1432
|
+
declare function searchSkills(query: string, options?: SearchSkillsOptions): Promise<MarketplaceResult[]>;
|
|
1433
|
+
declare function recommendSkills(query: string, criteria: Omit<RecommendationCriteriaInput, "query">, options?: RecommendSkillsQueryOptions): Promise<RecommendSkillsResult>;
|
|
1434
|
+
|
|
297
1435
|
/**
|
|
298
1436
|
* Security scanning engine for SKILL.md files
|
|
299
1437
|
*
|
|
@@ -301,11 +1439,55 @@ declare function discoverSkills(rootDir: string): Promise<SkillEntry[]>;
|
|
|
301
1439
|
* and produces findings with line-level precision.
|
|
302
1440
|
*/
|
|
303
1441
|
|
|
304
|
-
/**
|
|
1442
|
+
/**
|
|
1443
|
+
* Scan a single file against security audit rules.
|
|
1444
|
+
*
|
|
1445
|
+
* Checks each line of the file against all active rules and produces findings
|
|
1446
|
+
* with line-level precision. Calculates a security score (100 = clean, 0 = dangerous)
|
|
1447
|
+
* based on severity-weighted penalties.
|
|
1448
|
+
*
|
|
1449
|
+
* @param filePath - Absolute path to the file to scan
|
|
1450
|
+
* @param rules - Custom rules to scan against (defaults to the built-in 46+ rules)
|
|
1451
|
+
* @returns Audit result with findings, score, and pass/fail status
|
|
1452
|
+
*
|
|
1453
|
+
* @example
|
|
1454
|
+
* ```typescript
|
|
1455
|
+
* const result = await scanFile("/path/to/SKILL.md");
|
|
1456
|
+
* console.log(`Score: ${result.score}/100, Passed: ${result.passed}`);
|
|
1457
|
+
* ```
|
|
1458
|
+
*/
|
|
305
1459
|
declare function scanFile(filePath: string, rules?: AuditRule[]): Promise<AuditResult>;
|
|
306
|
-
/**
|
|
1460
|
+
/**
|
|
1461
|
+
* Scan a directory of skills for security issues.
|
|
1462
|
+
*
|
|
1463
|
+
* Iterates over skill subdirectories and scans each `SKILL.md` file found.
|
|
1464
|
+
*
|
|
1465
|
+
* @param dirPath - Absolute path to the skills directory to scan
|
|
1466
|
+
* @returns Array of audit results, one per scanned SKILL.md
|
|
1467
|
+
*
|
|
1468
|
+
* @example
|
|
1469
|
+
* ```typescript
|
|
1470
|
+
* const results = await scanDirectory("/home/user/.agents/skills");
|
|
1471
|
+
* const failing = results.filter(r => !r.passed);
|
|
1472
|
+
* ```
|
|
1473
|
+
*/
|
|
307
1474
|
declare function scanDirectory(dirPath: string): Promise<AuditResult[]>;
|
|
308
|
-
/**
|
|
1475
|
+
/**
|
|
1476
|
+
* Convert audit results to SARIF 2.1.0 format (Static Analysis Results Interchange Format).
|
|
1477
|
+
*
|
|
1478
|
+
* Produces a standards-compliant SARIF document suitable for CI/CD integration
|
|
1479
|
+
* and code scanning tools (e.g. GitHub Code Scanning).
|
|
1480
|
+
*
|
|
1481
|
+
* @param results - Array of audit results to convert
|
|
1482
|
+
* @returns SARIF 2.1.0 JSON object
|
|
1483
|
+
*
|
|
1484
|
+
* @example
|
|
1485
|
+
* ```typescript
|
|
1486
|
+
* const results = await scanDirectory("/path/to/skills");
|
|
1487
|
+
* const sarif = toSarif(results);
|
|
1488
|
+
* writeFileSync("audit.sarif", JSON.stringify(sarif, null, 2));
|
|
1489
|
+
* ```
|
|
1490
|
+
*/
|
|
309
1491
|
declare function toSarif(results: AuditResult[]): object;
|
|
310
1492
|
|
|
311
1493
|
/**
|
|
@@ -315,7 +1497,24 @@ declare function toSarif(results: AuditResult[]): object;
|
|
|
315
1497
|
* These transforms handle agents with non-standard schemas.
|
|
316
1498
|
*/
|
|
317
1499
|
|
|
318
|
-
/**
|
|
1500
|
+
/**
|
|
1501
|
+
* Get the config transform function for a provider, or `undefined` for passthrough.
|
|
1502
|
+
*
|
|
1503
|
+
* Providers with non-standard MCP config schemas (Goose, Zed, OpenCode, Codex, Cursor)
|
|
1504
|
+
* require transforms to convert the canonical {@link McpServerConfig} into their
|
|
1505
|
+
* provider-specific format.
|
|
1506
|
+
*
|
|
1507
|
+
* @param providerId - Provider ID to look up (e.g. `"goose"`, `"zed"`)
|
|
1508
|
+
* @returns Transform function, or `undefined` if the provider uses the canonical format
|
|
1509
|
+
*
|
|
1510
|
+
* @example
|
|
1511
|
+
* ```typescript
|
|
1512
|
+
* const transform = getTransform("goose");
|
|
1513
|
+
* if (transform) {
|
|
1514
|
+
* const gooseConfig = transform("my-server", canonicalConfig);
|
|
1515
|
+
* }
|
|
1516
|
+
* ```
|
|
1517
|
+
*/
|
|
319
1518
|
declare function getTransform(providerId: string): ((name: string, config: McpServerConfig) => unknown) | undefined;
|
|
320
1519
|
|
|
321
1520
|
/**
|
|
@@ -325,15 +1524,87 @@ declare function getTransform(providerId: string): ((name: string, config: McpSe
|
|
|
325
1524
|
* Provides the programmatic API that CLI commands delegate to.
|
|
326
1525
|
*/
|
|
327
1526
|
|
|
328
|
-
/**
|
|
1527
|
+
/**
|
|
1528
|
+
* Resolve the absolute config file path for a provider and scope.
|
|
1529
|
+
*
|
|
1530
|
+
* For project scope, joins the project directory with the provider's relative
|
|
1531
|
+
* config path. For global scope, returns the provider's global config path.
|
|
1532
|
+
*
|
|
1533
|
+
* @param provider - Provider to resolve config path for
|
|
1534
|
+
* @param scope - Whether to resolve project or global config path
|
|
1535
|
+
* @param projectDir - Project directory (defaults to `process.cwd()`)
|
|
1536
|
+
* @returns Absolute config file path, or `null` if the provider does not support the given scope
|
|
1537
|
+
*
|
|
1538
|
+
* @example
|
|
1539
|
+
* ```typescript
|
|
1540
|
+
* const path = resolveConfigPath(provider, "project", "/home/user/my-project");
|
|
1541
|
+
* // "/home/user/my-project/.claude/settings.json"
|
|
1542
|
+
* ```
|
|
1543
|
+
*/
|
|
329
1544
|
declare function resolveConfigPath(provider: Provider, scope: "project" | "global", projectDir?: string): string | null;
|
|
330
|
-
/**
|
|
1545
|
+
/**
|
|
1546
|
+
* List MCP servers configured for a single provider.
|
|
1547
|
+
*
|
|
1548
|
+
* Reads the provider's config file, extracts the MCP servers section using the
|
|
1549
|
+
* provider's `configKey`, and returns each server entry with metadata.
|
|
1550
|
+
*
|
|
1551
|
+
* @param provider - Provider whose config file to read
|
|
1552
|
+
* @param scope - Whether to read project or global config
|
|
1553
|
+
* @param projectDir - Project directory (defaults to `process.cwd()`)
|
|
1554
|
+
* @returns Array of MCP server entries found in the config file
|
|
1555
|
+
*
|
|
1556
|
+
* @example
|
|
1557
|
+
* ```typescript
|
|
1558
|
+
* const servers = await listMcpServers(provider, "project");
|
|
1559
|
+
* for (const s of servers) {
|
|
1560
|
+
* console.log(`${s.name} (${s.scope})`);
|
|
1561
|
+
* }
|
|
1562
|
+
* ```
|
|
1563
|
+
*/
|
|
331
1564
|
declare function listMcpServers(provider: Provider, scope: "project" | "global", projectDir?: string): Promise<McpServerEntry[]>;
|
|
332
|
-
/**
|
|
1565
|
+
/**
|
|
1566
|
+
* List MCP servers across all given providers, deduplicating by config path.
|
|
1567
|
+
*
|
|
1568
|
+
* Multiple providers may share the same config file. This function ensures each
|
|
1569
|
+
* config file is read only once to avoid duplicate entries.
|
|
1570
|
+
*
|
|
1571
|
+
* @param providers - Array of providers to query
|
|
1572
|
+
* @param scope - Whether to read project or global config
|
|
1573
|
+
* @param projectDir - Project directory (defaults to `process.cwd()`)
|
|
1574
|
+
* @returns Combined array of MCP server entries from all providers
|
|
1575
|
+
*
|
|
1576
|
+
* @example
|
|
1577
|
+
* ```typescript
|
|
1578
|
+
* const allServers = await listAllMcpServers(getInstalledProviders(), "global");
|
|
1579
|
+
* ```
|
|
1580
|
+
*/
|
|
333
1581
|
declare function listAllMcpServers(providers: Provider[], scope: "project" | "global", projectDir?: string): Promise<McpServerEntry[]>;
|
|
334
|
-
/**
|
|
1582
|
+
/**
|
|
1583
|
+
* Remove an MCP server entry from a provider's config file.
|
|
1584
|
+
*
|
|
1585
|
+
* @param provider - Provider whose config file to modify
|
|
1586
|
+
* @param serverName - Name/key of the MCP server to remove
|
|
1587
|
+
* @param scope - Whether to modify project or global config
|
|
1588
|
+
* @param projectDir - Project directory (defaults to `process.cwd()`)
|
|
1589
|
+
* @returns `true` if the entry was removed, `false` if no config path exists
|
|
1590
|
+
*
|
|
1591
|
+
* @example
|
|
1592
|
+
* ```typescript
|
|
1593
|
+
* const removed = await removeMcpServer(provider, "my-server", "project");
|
|
1594
|
+
* ```
|
|
1595
|
+
*/
|
|
335
1596
|
declare function removeMcpServer(provider: Provider, serverName: string, scope: "project" | "global", projectDir?: string): Promise<boolean>;
|
|
336
1597
|
|
|
1598
|
+
/**
|
|
1599
|
+
* Shared lock file utilities
|
|
1600
|
+
*
|
|
1601
|
+
* Single source of truth for reading/writing ~/.agents/.caamp-lock.json.
|
|
1602
|
+
* Both MCP and skills lock modules import from here.
|
|
1603
|
+
*/
|
|
1604
|
+
|
|
1605
|
+
/** Read the lock file */
|
|
1606
|
+
declare function readLockFile(): Promise<CaampLockFile>;
|
|
1607
|
+
|
|
337
1608
|
/**
|
|
338
1609
|
* MCP lock file management
|
|
339
1610
|
*
|
|
@@ -341,17 +1612,74 @@ declare function removeMcpServer(provider: Provider, serverName: string, scope:
|
|
|
341
1612
|
* Stored at ~/.agents/.caamp-lock.json (shared with skills lock).
|
|
342
1613
|
*/
|
|
343
1614
|
|
|
344
|
-
/**
|
|
345
|
-
|
|
346
|
-
|
|
1615
|
+
/**
|
|
1616
|
+
* Record an MCP server installation in the lock file.
|
|
1617
|
+
*
|
|
1618
|
+
* Creates or updates an entry in `lock.mcpServers`. If the server already exists,
|
|
1619
|
+
* the agent list is merged and `updatedAt` is refreshed while `installedAt` is preserved.
|
|
1620
|
+
*
|
|
1621
|
+
* @param serverName - Name/key of the MCP server
|
|
1622
|
+
* @param source - Original source string
|
|
1623
|
+
* @param sourceType - Classified source type
|
|
1624
|
+
* @param agents - Provider IDs the server was installed to
|
|
1625
|
+
* @param isGlobal - Whether this is a global installation
|
|
1626
|
+
*
|
|
1627
|
+
* @example
|
|
1628
|
+
* ```typescript
|
|
1629
|
+
* await recordMcpInstall("filesystem", "@mcp/server-fs", "package", ["claude-code"], true);
|
|
1630
|
+
* ```
|
|
1631
|
+
*/
|
|
347
1632
|
declare function recordMcpInstall(serverName: string, source: string, sourceType: SourceType, agents: string[], isGlobal: boolean): Promise<void>;
|
|
348
|
-
/**
|
|
1633
|
+
/**
|
|
1634
|
+
* Remove an MCP server entry from the lock file.
|
|
1635
|
+
*
|
|
1636
|
+
* @param serverName - Name/key of the MCP server to remove
|
|
1637
|
+
* @returns `true` if the entry was found and removed, `false` if not found
|
|
1638
|
+
*
|
|
1639
|
+
* @example
|
|
1640
|
+
* ```typescript
|
|
1641
|
+
* const removed = await removeMcpFromLock("filesystem");
|
|
1642
|
+
* ```
|
|
1643
|
+
*/
|
|
349
1644
|
declare function removeMcpFromLock(serverName: string): Promise<boolean>;
|
|
350
|
-
/**
|
|
1645
|
+
/**
|
|
1646
|
+
* Get all MCP servers tracked in the lock file.
|
|
1647
|
+
*
|
|
1648
|
+
* @returns Record of server name to lock entry
|
|
1649
|
+
*
|
|
1650
|
+
* @example
|
|
1651
|
+
* ```typescript
|
|
1652
|
+
* const servers = await getTrackedMcpServers();
|
|
1653
|
+
* for (const [name, entry] of Object.entries(servers)) {
|
|
1654
|
+
* console.log(`${name}: installed ${entry.installedAt}`);
|
|
1655
|
+
* }
|
|
1656
|
+
* ```
|
|
1657
|
+
*/
|
|
351
1658
|
declare function getTrackedMcpServers(): Promise<Record<string, LockEntry>>;
|
|
352
|
-
/**
|
|
1659
|
+
/**
|
|
1660
|
+
* Save the last selected agent IDs to the lock file for UX persistence.
|
|
1661
|
+
*
|
|
1662
|
+
* Used to remember the user's agent selection between CLI invocations.
|
|
1663
|
+
*
|
|
1664
|
+
* @param agents - Array of provider IDs to remember
|
|
1665
|
+
*
|
|
1666
|
+
* @example
|
|
1667
|
+
* ```typescript
|
|
1668
|
+
* await saveLastSelectedAgents(["claude-code", "cursor"]);
|
|
1669
|
+
* ```
|
|
1670
|
+
*/
|
|
353
1671
|
declare function saveLastSelectedAgents(agents: string[]): Promise<void>;
|
|
354
|
-
/**
|
|
1672
|
+
/**
|
|
1673
|
+
* Retrieve the last selected agent IDs from the lock file.
|
|
1674
|
+
*
|
|
1675
|
+
* @returns Array of provider IDs, or `undefined` if none were saved
|
|
1676
|
+
*
|
|
1677
|
+
* @example
|
|
1678
|
+
* ```typescript
|
|
1679
|
+
* const agents = await getLastSelectedAgents();
|
|
1680
|
+
* // ["claude-code", "cursor"] or undefined
|
|
1681
|
+
* ```
|
|
1682
|
+
*/
|
|
355
1683
|
declare function getLastSelectedAgents(): Promise<string[] | undefined>;
|
|
356
1684
|
|
|
357
1685
|
/**
|
|
@@ -360,13 +1688,75 @@ declare function getLastSelectedAgents(): Promise<string[] | undefined>;
|
|
|
360
1688
|
* Shares the same lock file as MCP (~/.agents/.caamp-lock.json).
|
|
361
1689
|
*/
|
|
362
1690
|
|
|
363
|
-
/**
|
|
1691
|
+
/**
|
|
1692
|
+
* Record a skill installation in the lock file.
|
|
1693
|
+
*
|
|
1694
|
+
* Creates or updates an entry in `lock.skills`. If the skill already exists,
|
|
1695
|
+
* the agent list is merged and `updatedAt` is refreshed while `installedAt` is preserved.
|
|
1696
|
+
*
|
|
1697
|
+
* @param skillName - Skill name
|
|
1698
|
+
* @param scopedName - Scoped name (may include marketplace scope)
|
|
1699
|
+
* @param source - Original source string
|
|
1700
|
+
* @param sourceType - Classified source type
|
|
1701
|
+
* @param agents - Provider IDs the skill was linked to
|
|
1702
|
+
* @param canonicalPath - Absolute path to the canonical installation
|
|
1703
|
+
* @param isGlobal - Whether this is a global installation
|
|
1704
|
+
* @param projectDir - Project directory (for project-scoped installs)
|
|
1705
|
+
* @param version - Version string or commit SHA
|
|
1706
|
+
*
|
|
1707
|
+
* @example
|
|
1708
|
+
* ```typescript
|
|
1709
|
+
* await recordSkillInstall(
|
|
1710
|
+
* "my-skill", "my-skill", "owner/repo", "github",
|
|
1711
|
+
* ["claude-code"], "/home/user/.agents/skills/my-skill", true,
|
|
1712
|
+
* );
|
|
1713
|
+
* ```
|
|
1714
|
+
*/
|
|
364
1715
|
declare function recordSkillInstall(skillName: string, scopedName: string, source: string, sourceType: SourceType, agents: string[], canonicalPath: string, isGlobal: boolean, projectDir?: string, version?: string): Promise<void>;
|
|
365
|
-
/**
|
|
1716
|
+
/**
|
|
1717
|
+
* Remove a skill entry from the lock file.
|
|
1718
|
+
*
|
|
1719
|
+
* @param skillName - Name of the skill to remove
|
|
1720
|
+
* @returns `true` if the entry was found and removed, `false` if not found
|
|
1721
|
+
*
|
|
1722
|
+
* @example
|
|
1723
|
+
* ```typescript
|
|
1724
|
+
* const removed = await removeSkillFromLock("my-skill");
|
|
1725
|
+
* ```
|
|
1726
|
+
*/
|
|
366
1727
|
declare function removeSkillFromLock(skillName: string): Promise<boolean>;
|
|
367
|
-
/**
|
|
1728
|
+
/**
|
|
1729
|
+
* Get all skills tracked in the lock file.
|
|
1730
|
+
*
|
|
1731
|
+
* @returns Record of skill name to lock entry
|
|
1732
|
+
*
|
|
1733
|
+
* @example
|
|
1734
|
+
* ```typescript
|
|
1735
|
+
* const skills = await getTrackedSkills();
|
|
1736
|
+
* for (const [name, entry] of Object.entries(skills)) {
|
|
1737
|
+
* console.log(`${name}: ${entry.source}`);
|
|
1738
|
+
* }
|
|
1739
|
+
* ```
|
|
1740
|
+
*/
|
|
368
1741
|
declare function getTrackedSkills(): Promise<Record<string, LockEntry>>;
|
|
369
|
-
/**
|
|
1742
|
+
/**
|
|
1743
|
+
* Check if a skill has updates available by comparing the installed version
|
|
1744
|
+
* against the latest remote commit SHA.
|
|
1745
|
+
*
|
|
1746
|
+
* Only supports GitHub and GitLab sources. Returns `"unknown"` for local,
|
|
1747
|
+
* package, or other source types.
|
|
1748
|
+
*
|
|
1749
|
+
* @param skillName - Name of the installed skill to check
|
|
1750
|
+
* @returns Object with update status, current version, and latest version
|
|
1751
|
+
*
|
|
1752
|
+
* @example
|
|
1753
|
+
* ```typescript
|
|
1754
|
+
* const update = await checkSkillUpdate("my-skill");
|
|
1755
|
+
* if (update.hasUpdate) {
|
|
1756
|
+
* console.log(`Update available: ${update.currentVersion} -> ${update.latestVersion}`);
|
|
1757
|
+
* }
|
|
1758
|
+
* ```
|
|
1759
|
+
*/
|
|
370
1760
|
declare function checkSkillUpdate(skillName: string): Promise<{
|
|
371
1761
|
hasUpdate: boolean;
|
|
372
1762
|
currentVersion?: string;
|
|
@@ -374,26 +1764,6 @@ declare function checkSkillUpdate(skillName: string): Promise<{
|
|
|
374
1764
|
status: "up-to-date" | "update-available" | "unknown";
|
|
375
1765
|
}>;
|
|
376
1766
|
|
|
377
|
-
/**
|
|
378
|
-
* Marketplace types shared between adapters
|
|
379
|
-
*/
|
|
380
|
-
interface MarketplaceAdapter {
|
|
381
|
-
name: string;
|
|
382
|
-
search(query: string, limit?: number): Promise<MarketplaceResult[]>;
|
|
383
|
-
getSkill(scopedName: string): Promise<MarketplaceResult | null>;
|
|
384
|
-
}
|
|
385
|
-
interface MarketplaceResult {
|
|
386
|
-
name: string;
|
|
387
|
-
scopedName: string;
|
|
388
|
-
description: string;
|
|
389
|
-
author: string;
|
|
390
|
-
stars: number;
|
|
391
|
-
githubUrl: string;
|
|
392
|
-
repoFullName: string;
|
|
393
|
-
path: string;
|
|
394
|
-
source: string;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
1767
|
/**
|
|
398
1768
|
* Unified marketplace client
|
|
399
1769
|
*
|
|
@@ -401,12 +1771,68 @@ interface MarketplaceResult {
|
|
|
401
1771
|
* deduplicates, and sorts by relevance.
|
|
402
1772
|
*/
|
|
403
1773
|
|
|
1774
|
+
/**
|
|
1775
|
+
* Unified marketplace client that aggregates results from multiple marketplace adapters.
|
|
1776
|
+
*
|
|
1777
|
+
* Queries all configured marketplaces in parallel, deduplicates results by scoped name,
|
|
1778
|
+
* and sorts by star count.
|
|
1779
|
+
*
|
|
1780
|
+
* @example
|
|
1781
|
+
* ```typescript
|
|
1782
|
+
* const client = new MarketplaceClient();
|
|
1783
|
+
* const results = await client.search("filesystem");
|
|
1784
|
+
* for (const r of results) {
|
|
1785
|
+
* console.log(`${r.scopedName} (${r.stars} stars)`);
|
|
1786
|
+
* }
|
|
1787
|
+
* ```
|
|
1788
|
+
*/
|
|
404
1789
|
declare class MarketplaceClient {
|
|
405
1790
|
private adapters;
|
|
1791
|
+
/**
|
|
1792
|
+
* Create a new marketplace client.
|
|
1793
|
+
*
|
|
1794
|
+
* @param adapters - Custom marketplace adapters (defaults to agentskills.in and skills.sh)
|
|
1795
|
+
*
|
|
1796
|
+
* @example
|
|
1797
|
+
* ```typescript
|
|
1798
|
+
* // Use default adapters
|
|
1799
|
+
* const client = new MarketplaceClient();
|
|
1800
|
+
*
|
|
1801
|
+
* // Use custom adapters
|
|
1802
|
+
* const client = new MarketplaceClient([myAdapter]);
|
|
1803
|
+
* ```
|
|
1804
|
+
*/
|
|
406
1805
|
constructor(adapters?: MarketplaceAdapter[]);
|
|
407
|
-
/**
|
|
1806
|
+
/**
|
|
1807
|
+
* Search all marketplaces and return deduplicated, sorted results.
|
|
1808
|
+
*
|
|
1809
|
+
* Queries all adapters in parallel and deduplicates by `scopedName`,
|
|
1810
|
+
* keeping the entry with the highest star count. Results are sorted by
|
|
1811
|
+
* stars descending.
|
|
1812
|
+
*
|
|
1813
|
+
* @param query - Search query string
|
|
1814
|
+
* @param limit - Maximum number of results to return (default: 20)
|
|
1815
|
+
* @returns Deduplicated and sorted marketplace results
|
|
1816
|
+
*
|
|
1817
|
+
* @example
|
|
1818
|
+
* ```typescript
|
|
1819
|
+
* const results = await client.search("code review", 10);
|
|
1820
|
+
* ```
|
|
1821
|
+
*/
|
|
408
1822
|
search(query: string, limit?: number): Promise<MarketplaceResult[]>;
|
|
409
|
-
/**
|
|
1823
|
+
/**
|
|
1824
|
+
* Get a specific skill by its scoped name from any marketplace.
|
|
1825
|
+
*
|
|
1826
|
+
* Tries each adapter in order and returns the first match.
|
|
1827
|
+
*
|
|
1828
|
+
* @param scopedName - Scoped skill name (e.g. `"@author/my-skill"`)
|
|
1829
|
+
* @returns The marketplace result, or `null` if not found in any marketplace
|
|
1830
|
+
*
|
|
1831
|
+
* @example
|
|
1832
|
+
* ```typescript
|
|
1833
|
+
* const skill = await client.getSkill("@anthropic/memory");
|
|
1834
|
+
* ```
|
|
1835
|
+
*/
|
|
410
1836
|
getSkill(scopedName: string): Promise<MarketplaceResult | null>;
|
|
411
1837
|
}
|
|
412
1838
|
|
|
@@ -417,15 +1843,99 @@ declare class MarketplaceClient {
|
|
|
417
1843
|
* (CLAUDE.md, AGENTS.md, GEMINI.md).
|
|
418
1844
|
*/
|
|
419
1845
|
|
|
420
|
-
/**
|
|
1846
|
+
/**
|
|
1847
|
+
* Check the status of a CAAMP injection block in an instruction file.
|
|
1848
|
+
*
|
|
1849
|
+
* Returns the injection status:
|
|
1850
|
+
* - `"missing"` - File does not exist
|
|
1851
|
+
* - `"none"` - File exists but has no CAAMP markers
|
|
1852
|
+
* - `"current"` - CAAMP block exists and matches expected content (or no expected content given)
|
|
1853
|
+
* - `"outdated"` - CAAMP block exists but differs from expected content
|
|
1854
|
+
*
|
|
1855
|
+
* @param filePath - Absolute path to the instruction file
|
|
1856
|
+
* @param expectedContent - Optional expected content to compare against
|
|
1857
|
+
* @returns The injection status
|
|
1858
|
+
*
|
|
1859
|
+
* @example
|
|
1860
|
+
* ```typescript
|
|
1861
|
+
* const status = await checkInjection("/project/CLAUDE.md", expectedContent);
|
|
1862
|
+
* if (status === "outdated") {
|
|
1863
|
+
* console.log("CAAMP injection needs updating");
|
|
1864
|
+
* }
|
|
1865
|
+
* ```
|
|
1866
|
+
*/
|
|
421
1867
|
declare function checkInjection(filePath: string, expectedContent?: string): Promise<InjectionStatus>;
|
|
422
|
-
/**
|
|
1868
|
+
/**
|
|
1869
|
+
* Inject content into an instruction file between CAAMP markers.
|
|
1870
|
+
*
|
|
1871
|
+
* Behavior depends on the file state:
|
|
1872
|
+
* - File does not exist: creates the file with the injection block
|
|
1873
|
+
* - File exists without markers: prepends the injection block
|
|
1874
|
+
* - File exists with markers: replaces the existing injection block
|
|
1875
|
+
*
|
|
1876
|
+
* @param filePath - Absolute path to the instruction file
|
|
1877
|
+
* @param content - Content to inject between CAAMP markers
|
|
1878
|
+
* @returns Action taken: `"created"`, `"added"`, or `"updated"`
|
|
1879
|
+
*
|
|
1880
|
+
* @example
|
|
1881
|
+
* ```typescript
|
|
1882
|
+
* const action = await inject("/project/CLAUDE.md", "## My Config\nSome content");
|
|
1883
|
+
* console.log(`File ${action}`);
|
|
1884
|
+
* ```
|
|
1885
|
+
*/
|
|
423
1886
|
declare function inject(filePath: string, content: string): Promise<"created" | "added" | "updated">;
|
|
424
|
-
/**
|
|
1887
|
+
/**
|
|
1888
|
+
* Remove the CAAMP injection block from an instruction file.
|
|
1889
|
+
*
|
|
1890
|
+
* If removing the block would leave the file empty, the file is deleted entirely.
|
|
1891
|
+
*
|
|
1892
|
+
* @param filePath - Absolute path to the instruction file
|
|
1893
|
+
* @returns `true` if a CAAMP block was found and removed, `false` otherwise
|
|
1894
|
+
*
|
|
1895
|
+
* @example
|
|
1896
|
+
* ```typescript
|
|
1897
|
+
* const removed = await removeInjection("/project/CLAUDE.md");
|
|
1898
|
+
* ```
|
|
1899
|
+
*/
|
|
425
1900
|
declare function removeInjection(filePath: string): Promise<boolean>;
|
|
426
|
-
/**
|
|
1901
|
+
/**
|
|
1902
|
+
* Check injection status across all providers' instruction files.
|
|
1903
|
+
*
|
|
1904
|
+
* Deduplicates by file path since multiple providers may share the same
|
|
1905
|
+
* instruction file (e.g. many providers use `AGENTS.md`).
|
|
1906
|
+
*
|
|
1907
|
+
* @param providers - Array of providers to check
|
|
1908
|
+
* @param projectDir - Absolute path to the project directory
|
|
1909
|
+
* @param scope - Whether to check project or global instruction files
|
|
1910
|
+
* @param expectedContent - Optional expected content to compare against
|
|
1911
|
+
* @returns Array of injection check results, one per unique instruction file
|
|
1912
|
+
*
|
|
1913
|
+
* @example
|
|
1914
|
+
* ```typescript
|
|
1915
|
+
* const results = await checkAllInjections(providers, "/project", "project");
|
|
1916
|
+
* const outdated = results.filter(r => r.status === "outdated");
|
|
1917
|
+
* ```
|
|
1918
|
+
*/
|
|
427
1919
|
declare function checkAllInjections(providers: Provider[], projectDir: string, scope: "project" | "global", expectedContent?: string): Promise<InjectionCheckResult[]>;
|
|
428
|
-
/**
|
|
1920
|
+
/**
|
|
1921
|
+
* Inject content into all providers' instruction files.
|
|
1922
|
+
*
|
|
1923
|
+
* Deduplicates by file path to avoid injecting the same file multiple times.
|
|
1924
|
+
*
|
|
1925
|
+
* @param providers - Array of providers to inject into
|
|
1926
|
+
* @param projectDir - Absolute path to the project directory
|
|
1927
|
+
* @param scope - Whether to target project or global instruction files
|
|
1928
|
+
* @param content - Content to inject between CAAMP markers
|
|
1929
|
+
* @returns Map of file path to action taken (`"created"`, `"added"`, or `"updated"`)
|
|
1930
|
+
*
|
|
1931
|
+
* @example
|
|
1932
|
+
* ```typescript
|
|
1933
|
+
* const results = await injectAll(providers, "/project", "project", content);
|
|
1934
|
+
* for (const [file, action] of results) {
|
|
1935
|
+
* console.log(`${file}: ${action}`);
|
|
1936
|
+
* }
|
|
1937
|
+
* ```
|
|
1938
|
+
*/
|
|
429
1939
|
declare function injectAll(providers: Provider[], projectDir: string, scope: "project" | "global", content: string): Promise<Map<string, "created" | "added" | "updated">>;
|
|
430
1940
|
|
|
431
1941
|
/**
|
|
@@ -434,33 +1944,207 @@ declare function injectAll(providers: Provider[], projectDir: string, scope: "pr
|
|
|
434
1944
|
* Generates injection content based on provider capabilities.
|
|
435
1945
|
*/
|
|
436
1946
|
|
|
437
|
-
/**
|
|
1947
|
+
/**
|
|
1948
|
+
* Generate a standard CAAMP injection block for instruction files.
|
|
1949
|
+
*
|
|
1950
|
+
* Produces markdown content suitable for injection between CAAMP markers.
|
|
1951
|
+
* Optionally includes MCP server and custom content sections.
|
|
1952
|
+
*
|
|
1953
|
+
* @param options - Optional configuration for the generated content
|
|
1954
|
+
* @param options.mcpServerName - MCP server name to include a server section
|
|
1955
|
+
* @param options.customContent - Additional custom markdown content to append
|
|
1956
|
+
* @returns Generated markdown string
|
|
1957
|
+
*
|
|
1958
|
+
* @example
|
|
1959
|
+
* ```typescript
|
|
1960
|
+
* const content = generateInjectionContent({ mcpServerName: "filesystem" });
|
|
1961
|
+
* ```
|
|
1962
|
+
*/
|
|
438
1963
|
declare function generateInjectionContent(options?: {
|
|
439
1964
|
mcpServerName?: string;
|
|
440
1965
|
customContent?: string;
|
|
441
1966
|
}): string;
|
|
442
|
-
/**
|
|
1967
|
+
/**
|
|
1968
|
+
* Group providers by their instruction file name.
|
|
1969
|
+
*
|
|
1970
|
+
* Useful for determining which providers share the same instruction file
|
|
1971
|
+
* (e.g. multiple providers using `AGENTS.md`).
|
|
1972
|
+
*
|
|
1973
|
+
* @param providers - Array of providers to group
|
|
1974
|
+
* @returns Map from instruction file name to array of providers using that file
|
|
1975
|
+
*
|
|
1976
|
+
* @example
|
|
1977
|
+
* ```typescript
|
|
1978
|
+
* const groups = groupByInstructFile(getAllProviders());
|
|
1979
|
+
* for (const [file, providers] of groups) {
|
|
1980
|
+
* console.log(`${file}: ${providers.map(p => p.id).join(", ")}`);
|
|
1981
|
+
* }
|
|
1982
|
+
* ```
|
|
1983
|
+
*/
|
|
443
1984
|
declare function groupByInstructFile(providers: Provider[]): Map<string, Provider[]>;
|
|
444
1985
|
|
|
445
1986
|
/**
|
|
446
1987
|
* Format utility functions
|
|
447
1988
|
*/
|
|
448
|
-
/**
|
|
1989
|
+
/**
|
|
1990
|
+
* Deep merge two objects, with `source` values winning on conflict.
|
|
1991
|
+
*
|
|
1992
|
+
* Recursively merges nested plain objects. Arrays and non-object values from
|
|
1993
|
+
* `source` overwrite `target` values.
|
|
1994
|
+
*
|
|
1995
|
+
* @param target - Base object to merge into
|
|
1996
|
+
* @param source - Object with values that take precedence
|
|
1997
|
+
* @returns A new merged object (does not mutate inputs)
|
|
1998
|
+
*
|
|
1999
|
+
* @example
|
|
2000
|
+
* ```typescript
|
|
2001
|
+
* deepMerge({ a: 1, b: { c: 2 } }, { b: { d: 3 } });
|
|
2002
|
+
* // { a: 1, b: { c: 2, d: 3 } }
|
|
2003
|
+
* ```
|
|
2004
|
+
*/
|
|
449
2005
|
declare function deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): Record<string, unknown>;
|
|
450
|
-
/**
|
|
2006
|
+
/**
|
|
2007
|
+
* Get a nested value from an object using a dot-notation key path.
|
|
2008
|
+
*
|
|
2009
|
+
* @param obj - Object to traverse
|
|
2010
|
+
* @param keyPath - Dot-separated key path (e.g. `"mcpServers"` or `"a.b.c"`)
|
|
2011
|
+
* @returns The value at the key path, or `undefined` if not found
|
|
2012
|
+
*
|
|
2013
|
+
* @example
|
|
2014
|
+
* ```typescript
|
|
2015
|
+
* getNestedValue({ a: { b: { c: 42 } } }, "a.b.c"); // 42
|
|
2016
|
+
* getNestedValue({ a: 1 }, "a.b"); // undefined
|
|
2017
|
+
* ```
|
|
2018
|
+
*/
|
|
451
2019
|
declare function getNestedValue(obj: Record<string, unknown>, keyPath: string): unknown;
|
|
452
|
-
/**
|
|
2020
|
+
/**
|
|
2021
|
+
* Ensure that the parent directories of a file path exist.
|
|
2022
|
+
*
|
|
2023
|
+
* Creates directories recursively if they do not exist.
|
|
2024
|
+
*
|
|
2025
|
+
* @param filePath - Absolute path to a file (parent directories will be created)
|
|
2026
|
+
*
|
|
2027
|
+
* @example
|
|
2028
|
+
* ```typescript
|
|
2029
|
+
* await ensureDir("/path/to/new/dir/file.json");
|
|
2030
|
+
* // /path/to/new/dir/ now exists
|
|
2031
|
+
* ```
|
|
2032
|
+
*/
|
|
453
2033
|
declare function ensureDir(filePath: string): Promise<void>;
|
|
454
2034
|
|
|
455
2035
|
/**
|
|
456
2036
|
* Format router - dispatches config reads/writes to format-specific handlers
|
|
457
2037
|
*/
|
|
458
2038
|
|
|
459
|
-
/**
|
|
2039
|
+
/**
|
|
2040
|
+
* Read and parse a config file in the specified format.
|
|
2041
|
+
*
|
|
2042
|
+
* Dispatches to the appropriate format handler (JSON/JSONC, YAML, or TOML).
|
|
2043
|
+
*
|
|
2044
|
+
* @param filePath - Absolute path to the config file
|
|
2045
|
+
* @param format - Config file format
|
|
2046
|
+
* @returns Parsed config object
|
|
2047
|
+
* @throws If the file cannot be read or the format is unsupported
|
|
2048
|
+
*
|
|
2049
|
+
* @example
|
|
2050
|
+
* ```typescript
|
|
2051
|
+
* const config = await readConfig("/path/to/config.json", "jsonc");
|
|
2052
|
+
* ```
|
|
2053
|
+
*/
|
|
460
2054
|
declare function readConfig(filePath: string, format: ConfigFormat): Promise<Record<string, unknown>>;
|
|
461
|
-
/**
|
|
2055
|
+
/**
|
|
2056
|
+
* Write a server entry to a config file, preserving existing content.
|
|
2057
|
+
*
|
|
2058
|
+
* Dispatches to the appropriate format handler. For JSONC files, comments are
|
|
2059
|
+
* preserved using `jsonc-parser`.
|
|
2060
|
+
*
|
|
2061
|
+
* @param filePath - Absolute path to the config file
|
|
2062
|
+
* @param format - Config file format
|
|
2063
|
+
* @param key - Dot-notation key path to the servers section (e.g. `"mcpServers"`)
|
|
2064
|
+
* @param serverName - Name/key for the server entry
|
|
2065
|
+
* @param serverConfig - Server configuration object to write
|
|
2066
|
+
* @throws If the format is unsupported
|
|
2067
|
+
*
|
|
2068
|
+
* @example
|
|
2069
|
+
* ```typescript
|
|
2070
|
+
* await writeConfig("/path/to/config.json", "jsonc", "mcpServers", "my-server", config);
|
|
2071
|
+
* ```
|
|
2072
|
+
*/
|
|
462
2073
|
declare function writeConfig(filePath: string, format: ConfigFormat, key: string, serverName: string, serverConfig: unknown): Promise<void>;
|
|
463
|
-
/**
|
|
2074
|
+
/**
|
|
2075
|
+
* Remove a server entry from a config file in the specified format.
|
|
2076
|
+
*
|
|
2077
|
+
* @param filePath - Absolute path to the config file
|
|
2078
|
+
* @param format - Config file format
|
|
2079
|
+
* @param key - Dot-notation key path to the servers section
|
|
2080
|
+
* @param serverName - Name/key of the server entry to remove
|
|
2081
|
+
* @returns `true` if the entry was removed, `false` otherwise
|
|
2082
|
+
* @throws If the format is unsupported
|
|
2083
|
+
*
|
|
2084
|
+
* @example
|
|
2085
|
+
* ```typescript
|
|
2086
|
+
* const removed = await removeConfig("/path/to/config.json", "jsonc", "mcpServers", "my-server");
|
|
2087
|
+
* ```
|
|
2088
|
+
*/
|
|
464
2089
|
declare function removeConfig(filePath: string, format: ConfigFormat, key: string, serverName: string): Promise<boolean>;
|
|
465
2090
|
|
|
466
|
-
|
|
2091
|
+
/**
|
|
2092
|
+
* Simple logger with verbose/quiet mode support.
|
|
2093
|
+
*
|
|
2094
|
+
* - verbose: enables debug output to stderr
|
|
2095
|
+
* - quiet: suppresses info and warn output (errors always shown)
|
|
2096
|
+
*/
|
|
2097
|
+
/**
|
|
2098
|
+
* Enable or disable verbose (debug) logging mode.
|
|
2099
|
+
*
|
|
2100
|
+
* When enabled, debug messages are written to stderr.
|
|
2101
|
+
*
|
|
2102
|
+
* @param v - `true` to enable verbose mode, `false` to disable
|
|
2103
|
+
*
|
|
2104
|
+
* @example
|
|
2105
|
+
* ```typescript
|
|
2106
|
+
* setVerbose(true);
|
|
2107
|
+
* ```
|
|
2108
|
+
*/
|
|
2109
|
+
declare function setVerbose(v: boolean): void;
|
|
2110
|
+
/**
|
|
2111
|
+
* Enable or disable quiet mode.
|
|
2112
|
+
*
|
|
2113
|
+
* When enabled, info and warning messages are suppressed. Errors are always shown.
|
|
2114
|
+
*
|
|
2115
|
+
* @param q - `true` to enable quiet mode, `false` to disable
|
|
2116
|
+
*
|
|
2117
|
+
* @example
|
|
2118
|
+
* ```typescript
|
|
2119
|
+
* setQuiet(true);
|
|
2120
|
+
* ```
|
|
2121
|
+
*/
|
|
2122
|
+
declare function setQuiet(q: boolean): void;
|
|
2123
|
+
/**
|
|
2124
|
+
* Check if verbose (debug) logging is currently enabled.
|
|
2125
|
+
*
|
|
2126
|
+
* @returns `true` if verbose mode is active
|
|
2127
|
+
*
|
|
2128
|
+
* @example
|
|
2129
|
+
* ```typescript
|
|
2130
|
+
* if (isVerbose()) {
|
|
2131
|
+
* console.error("Extra debug info");
|
|
2132
|
+
* }
|
|
2133
|
+
* ```
|
|
2134
|
+
*/
|
|
2135
|
+
declare function isVerbose(): boolean;
|
|
2136
|
+
/**
|
|
2137
|
+
* Check if quiet mode is currently enabled.
|
|
2138
|
+
*
|
|
2139
|
+
* @returns `true` if quiet mode is active
|
|
2140
|
+
*
|
|
2141
|
+
* @example
|
|
2142
|
+
* ```typescript
|
|
2143
|
+
* if (!isQuiet()) {
|
|
2144
|
+
* console.log("Status message");
|
|
2145
|
+
* }
|
|
2146
|
+
* ```
|
|
2147
|
+
*/
|
|
2148
|
+
declare function isQuiet(): boolean;
|
|
2149
|
+
|
|
2150
|
+
export { type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type BatchInstallOptions, type BatchInstallResult, type CaampLockFile, type ConfigFormat, type ConflictPolicy, type DetectionResult, type DualScopeConfigureOptions, type DualScopeConfigureResult, type GlobalOptions, type InjectionCheckResult, type InjectionStatus, type InstallResult, type InstructionUpdateSummary, type LockEntry, MarketplaceClient, type MarketplaceResult, type MarketplaceSearchResult, type MarketplaceSkill, type McpBatchOperation, type McpConflict, type McpConflictCode, type McpPlanApplyResult, type McpServerConfig, type McpServerEntry, type NormalizedRecommendationCriteria, type ParsedSource, type Provider, type ProviderPriority, type ProviderStatus, RECOMMENDATION_ERROR_CODES, type RankedSkillRecommendation, type RecommendSkillsResult, type RecommendationCriteriaInput, type RecommendationErrorCode, type RecommendationOptions, type RecommendationReason, type RecommendationReasonCode, type RecommendationScoreBreakdown, type RecommendationValidationIssue, type RecommendationValidationResult, type RecommendationWeights, type SkillBatchOperation, type SkillEntry, type SkillInstallResult, type SkillMetadata, type SourceType, type TransportType, type ValidationIssue, type ValidationResult, applyMcpInstallWithPolicy, buildServerConfig, checkAllInjections, checkInjection, checkSkillUpdate, configureProviderGlobalAndProject, deepMerge, detectAllProviders, detectMcpConfigConflicts, detectProjectProviders, detectProvider, discoverSkill, discoverSkills, ensureDir, formatSkillRecommendations, generateInjectionContent, getAllProviders, getInstalledProviders, getInstructionFiles, getLastSelectedAgents, getNestedValue, getProvider, getProviderCount, getProvidersByInstructFile, getProvidersByPriority, getProvidersByStatus, getRegistryVersion, getTrackedMcpServers, getTrackedSkills, getTransform, groupByInstructFile, inject, injectAll, installBatchWithRollback, installMcpServer, installMcpServerToAll, installSkill, isMarketplaceScoped, isQuiet, isVerbose, listAllMcpServers, listCanonicalSkills, listMcpServers, normalizeRecommendationCriteria, parseSkillFile, parseSource, rankSkills, readConfig, readLockFile, recommendSkills, recordMcpInstall, recordSkillInstall, removeConfig, removeInjection, removeMcpFromLock, removeMcpServer, removeSkill, removeSkillFromLock, resolveAlias, resolveConfigPath, saveLastSelectedAgents, scanDirectory, scanFile, scoreSkillRecommendation, searchSkills, selectProvidersByMinimumPriority, setQuiet, setVerbose, toSarif, tokenizeCriteriaValue, updateInstructionsSingleOperation, validateRecommendationCriteria, validateSkill, writeConfig };
|