@cleocode/caamp 0.1.0 → 0.3.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/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
- /** Detect if a single provider is installed */
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
- /** Detect all installed providers */
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
- /** Get only installed providers */
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
- /** Detect providers with project-level presence */
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
- /** Install an MCP server config for a single provider */
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
- /** Install an MCP server config for multiple providers */
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
- /** Build a canonical MCP server config from parsed source */
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
- /** Install a skill from a local path to canonical + link to agents */
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
- /** Remove a skill from canonical location and all agent symlinks */
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
- /** List all canonically installed skills */
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,17 +871,63 @@ 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
- /** Validate a SKILL.md file */
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
 
246
933
  /**
@@ -250,23 +937,121 @@ declare function validateSkill(filePath: string): Promise<ValidationResult>;
250
937
  * platform-specific paths at runtime.
251
938
  */
252
939
 
253
- /** Get all providers */
940
+ /**
941
+ * Retrieve all registered providers with resolved platform paths.
942
+ *
943
+ * Providers are lazily loaded from `providers/registry.json` on first call
944
+ * and cached for subsequent calls.
945
+ *
946
+ * @returns Array of all provider definitions
947
+ *
948
+ * @example
949
+ * ```typescript
950
+ * const providers = getAllProviders();
951
+ * console.log(`${providers.length} providers registered`);
952
+ * ```
953
+ */
254
954
  declare function getAllProviders(): Provider[];
255
- /** Get a provider by ID or alias */
955
+ /**
956
+ * Look up a provider by its ID or any of its aliases.
957
+ *
958
+ * @param idOrAlias - Provider ID (e.g. `"claude-code"`) or alias (e.g. `"claude"`)
959
+ * @returns The matching provider, or `undefined` if not found
960
+ *
961
+ * @example
962
+ * ```typescript
963
+ * const provider = getProvider("claude");
964
+ * // Returns the claude-code provider via alias resolution
965
+ * ```
966
+ */
256
967
  declare function getProvider(idOrAlias: string): Provider | undefined;
257
- /** Resolve an alias to provider ID */
968
+ /**
969
+ * Resolve an alias to its canonical provider ID.
970
+ *
971
+ * If the input is already a canonical ID (or unrecognized), it is returned as-is.
972
+ *
973
+ * @param idOrAlias - Provider ID or alias to resolve
974
+ * @returns The canonical provider ID
975
+ *
976
+ * @example
977
+ * ```typescript
978
+ * resolveAlias("claude"); // "claude-code"
979
+ * resolveAlias("claude-code"); // "claude-code"
980
+ * resolveAlias("unknown"); // "unknown"
981
+ * ```
982
+ */
258
983
  declare function resolveAlias(idOrAlias: string): string;
259
- /** Get providers by priority tier */
984
+ /**
985
+ * Filter providers by their priority tier.
986
+ *
987
+ * @param priority - Priority level to filter by (`"high"`, `"medium"`, or `"low"`)
988
+ * @returns Array of providers matching the given priority
989
+ *
990
+ * @example
991
+ * ```typescript
992
+ * const highPriority = getProvidersByPriority("high");
993
+ * ```
994
+ */
260
995
  declare function getProvidersByPriority(priority: ProviderPriority): Provider[];
261
- /** Get providers by status */
996
+ /**
997
+ * Filter providers by their lifecycle status.
998
+ *
999
+ * @param status - Status to filter by (`"active"`, `"beta"`, `"deprecated"`, or `"planned"`)
1000
+ * @returns Array of providers matching the given status
1001
+ *
1002
+ * @example
1003
+ * ```typescript
1004
+ * const active = getProvidersByStatus("active");
1005
+ * ```
1006
+ */
262
1007
  declare function getProvidersByStatus(status: ProviderStatus): Provider[];
263
- /** Get providers that use a specific instruction file */
1008
+ /**
1009
+ * Filter providers that use a specific instruction file.
1010
+ *
1011
+ * Multiple providers often share the same instruction file (e.g. many use `"AGENTS.md"`).
1012
+ *
1013
+ * @param file - Instruction file name (e.g. `"CLAUDE.md"`, `"AGENTS.md"`)
1014
+ * @returns Array of providers that use the given instruction file
1015
+ *
1016
+ * @example
1017
+ * ```typescript
1018
+ * const claudeProviders = getProvidersByInstructFile("CLAUDE.md");
1019
+ * ```
1020
+ */
264
1021
  declare function getProvidersByInstructFile(file: string): Provider[];
265
- /** Get all unique instruction files */
1022
+ /**
1023
+ * Get the set of all unique instruction file names across all providers.
1024
+ *
1025
+ * @returns Array of unique instruction file names (e.g. `["CLAUDE.md", "AGENTS.md", "GEMINI.md"]`)
1026
+ *
1027
+ * @example
1028
+ * ```typescript
1029
+ * const files = getInstructionFiles();
1030
+ * // ["CLAUDE.md", "AGENTS.md", "GEMINI.md"]
1031
+ * ```
1032
+ */
266
1033
  declare function getInstructionFiles(): string[];
267
- /** Get provider count */
1034
+ /**
1035
+ * Get the total number of registered providers.
1036
+ *
1037
+ * @returns Count of providers in the registry
1038
+ *
1039
+ * @example
1040
+ * ```typescript
1041
+ * console.log(`Registry has ${getProviderCount()} providers`);
1042
+ * ```
1043
+ */
268
1044
  declare function getProviderCount(): number;
269
- /** Get registry version */
1045
+ /**
1046
+ * Get the semantic version string of the provider registry.
1047
+ *
1048
+ * @returns Version string from `providers/registry.json` (e.g. `"1.0.0"`)
1049
+ *
1050
+ * @example
1051
+ * ```typescript
1052
+ * console.log(`Registry version: ${getRegistryVersion()}`);
1053
+ * ```
1054
+ */
270
1055
  declare function getRegistryVersion(): string;
271
1056
 
272
1057
  /**
@@ -276,9 +1061,42 @@ declare function getRegistryVersion(): string;
276
1061
  * GitLab URLs, local paths, or shell commands.
277
1062
  */
278
1063
 
279
- /** Parse a source string into a typed ParsedSource */
1064
+ /**
1065
+ * Parse and classify a source string into a typed {@link ParsedSource}.
1066
+ *
1067
+ * Supports GitHub URLs, GitLab URLs, GitHub shorthand (`owner/repo`),
1068
+ * HTTP URLs (remote MCP servers), npm package names, local paths, and
1069
+ * shell commands as a fallback.
1070
+ *
1071
+ * @param input - Raw source string to classify
1072
+ * @returns Parsed source with type, value, and inferred name
1073
+ *
1074
+ * @example
1075
+ * ```typescript
1076
+ * parseSource("owner/repo");
1077
+ * // { type: "github", value: "https://github.com/owner/repo", inferredName: "repo", ... }
1078
+ *
1079
+ * parseSource("https://mcp.example.com/sse");
1080
+ * // { type: "remote", value: "https://mcp.example.com/sse", inferredName: "example" }
1081
+ *
1082
+ * parseSource("@modelcontextprotocol/server-filesystem");
1083
+ * // { type: "package", value: "@modelcontextprotocol/server-filesystem", inferredName: "filesystem" }
1084
+ * ```
1085
+ */
280
1086
  declare function parseSource(input: string): ParsedSource;
281
- /** Check if source looks like an MCP marketplace scoped name (@author/name) */
1087
+ /**
1088
+ * Check if a source string looks like a marketplace scoped name (`@author/name`).
1089
+ *
1090
+ * @param input - Source string to check
1091
+ * @returns `true` if the input matches the `@scope/name` pattern
1092
+ *
1093
+ * @example
1094
+ * ```typescript
1095
+ * isMarketplaceScoped("@anthropic/my-skill"); // true
1096
+ * isMarketplaceScoped("my-skill"); // false
1097
+ * isMarketplaceScoped("owner/repo"); // false
1098
+ * ```
1099
+ */
282
1100
  declare function isMarketplaceScoped(input: string): boolean;
283
1101
 
284
1102
  /**
@@ -287,11 +1105,57 @@ declare function isMarketplaceScoped(input: string): boolean;
287
1105
  * Scans directories for SKILL.md files and parses their frontmatter.
288
1106
  */
289
1107
 
290
- /** Parse a SKILL.md file and extract metadata */
1108
+ /**
1109
+ * Parse a SKILL.md file and extract its frontmatter metadata.
1110
+ *
1111
+ * Reads the file, parses YAML frontmatter via `gray-matter`, and maps the
1112
+ * fields to a {@link SkillMetadata} object. Returns `null` if the file cannot
1113
+ * be read or lacks required `name` and `description` fields.
1114
+ *
1115
+ * @param filePath - Absolute path to the SKILL.md file
1116
+ * @returns Parsed metadata, or `null` if invalid
1117
+ *
1118
+ * @example
1119
+ * ```typescript
1120
+ * const meta = await parseSkillFile("/path/to/SKILL.md");
1121
+ * if (meta) {
1122
+ * console.log(`${meta.name}: ${meta.description}`);
1123
+ * }
1124
+ * ```
1125
+ */
291
1126
  declare function parseSkillFile(filePath: string): Promise<SkillMetadata | null>;
292
- /** Discover a skill at a given path (directory containing SKILL.md) */
1127
+ /**
1128
+ * Discover a single skill at a given directory path.
1129
+ *
1130
+ * Checks for a `SKILL.md` file in the directory and parses its metadata.
1131
+ *
1132
+ * @param skillDir - Absolute path to a skill directory (containing SKILL.md)
1133
+ * @returns Skill entry with metadata, or `null` if no valid SKILL.md exists
1134
+ *
1135
+ * @example
1136
+ * ```typescript
1137
+ * const skill = await discoverSkill("/home/user/.agents/skills/my-skill");
1138
+ * if (skill) {
1139
+ * console.log(`Found: ${skill.name}`);
1140
+ * }
1141
+ * ```
1142
+ */
293
1143
  declare function discoverSkill(skillDir: string): Promise<SkillEntry | null>;
294
- /** Scan a directory for skill directories (each containing SKILL.md) */
1144
+ /**
1145
+ * Scan a directory for skill subdirectories, each containing a SKILL.md file.
1146
+ *
1147
+ * Iterates over directories and symlinks in `rootDir` and calls
1148
+ * {@link discoverSkill} on each.
1149
+ *
1150
+ * @param rootDir - Absolute path to a skills root directory to scan
1151
+ * @returns Array of discovered skill entries
1152
+ *
1153
+ * @example
1154
+ * ```typescript
1155
+ * const skills = await discoverSkills("/home/user/.agents/skills");
1156
+ * console.log(`Found ${skills.length} skills`);
1157
+ * ```
1158
+ */
295
1159
  declare function discoverSkills(rootDir: string): Promise<SkillEntry[]>;
296
1160
 
297
1161
  /**
@@ -301,11 +1165,55 @@ declare function discoverSkills(rootDir: string): Promise<SkillEntry[]>;
301
1165
  * and produces findings with line-level precision.
302
1166
  */
303
1167
 
304
- /** Scan a single file against all rules */
1168
+ /**
1169
+ * Scan a single file against security audit rules.
1170
+ *
1171
+ * Checks each line of the file against all active rules and produces findings
1172
+ * with line-level precision. Calculates a security score (100 = clean, 0 = dangerous)
1173
+ * based on severity-weighted penalties.
1174
+ *
1175
+ * @param filePath - Absolute path to the file to scan
1176
+ * @param rules - Custom rules to scan against (defaults to the built-in 46+ rules)
1177
+ * @returns Audit result with findings, score, and pass/fail status
1178
+ *
1179
+ * @example
1180
+ * ```typescript
1181
+ * const result = await scanFile("/path/to/SKILL.md");
1182
+ * console.log(`Score: ${result.score}/100, Passed: ${result.passed}`);
1183
+ * ```
1184
+ */
305
1185
  declare function scanFile(filePath: string, rules?: AuditRule[]): Promise<AuditResult>;
306
- /** Scan a directory of skills */
1186
+ /**
1187
+ * Scan a directory of skills for security issues.
1188
+ *
1189
+ * Iterates over skill subdirectories and scans each `SKILL.md` file found.
1190
+ *
1191
+ * @param dirPath - Absolute path to the skills directory to scan
1192
+ * @returns Array of audit results, one per scanned SKILL.md
1193
+ *
1194
+ * @example
1195
+ * ```typescript
1196
+ * const results = await scanDirectory("/home/user/.agents/skills");
1197
+ * const failing = results.filter(r => !r.passed);
1198
+ * ```
1199
+ */
307
1200
  declare function scanDirectory(dirPath: string): Promise<AuditResult[]>;
308
- /** Format findings as SARIF (Static Analysis Results Interchange Format) */
1201
+ /**
1202
+ * Convert audit results to SARIF 2.1.0 format (Static Analysis Results Interchange Format).
1203
+ *
1204
+ * Produces a standards-compliant SARIF document suitable for CI/CD integration
1205
+ * and code scanning tools (e.g. GitHub Code Scanning).
1206
+ *
1207
+ * @param results - Array of audit results to convert
1208
+ * @returns SARIF 2.1.0 JSON object
1209
+ *
1210
+ * @example
1211
+ * ```typescript
1212
+ * const results = await scanDirectory("/path/to/skills");
1213
+ * const sarif = toSarif(results);
1214
+ * writeFileSync("audit.sarif", JSON.stringify(sarif, null, 2));
1215
+ * ```
1216
+ */
309
1217
  declare function toSarif(results: AuditResult[]): object;
310
1218
 
311
1219
  /**
@@ -315,7 +1223,24 @@ declare function toSarif(results: AuditResult[]): object;
315
1223
  * These transforms handle agents with non-standard schemas.
316
1224
  */
317
1225
 
318
- /** Get the transform function for a provider, or undefined for passthrough */
1226
+ /**
1227
+ * Get the config transform function for a provider, or `undefined` for passthrough.
1228
+ *
1229
+ * Providers with non-standard MCP config schemas (Goose, Zed, OpenCode, Codex, Cursor)
1230
+ * require transforms to convert the canonical {@link McpServerConfig} into their
1231
+ * provider-specific format.
1232
+ *
1233
+ * @param providerId - Provider ID to look up (e.g. `"goose"`, `"zed"`)
1234
+ * @returns Transform function, or `undefined` if the provider uses the canonical format
1235
+ *
1236
+ * @example
1237
+ * ```typescript
1238
+ * const transform = getTransform("goose");
1239
+ * if (transform) {
1240
+ * const gooseConfig = transform("my-server", canonicalConfig);
1241
+ * }
1242
+ * ```
1243
+ */
319
1244
  declare function getTransform(providerId: string): ((name: string, config: McpServerConfig) => unknown) | undefined;
320
1245
 
321
1246
  /**
@@ -325,15 +1250,87 @@ declare function getTransform(providerId: string): ((name: string, config: McpSe
325
1250
  * Provides the programmatic API that CLI commands delegate to.
326
1251
  */
327
1252
 
328
- /** Resolve the config file path for a provider and scope */
1253
+ /**
1254
+ * Resolve the absolute config file path for a provider and scope.
1255
+ *
1256
+ * For project scope, joins the project directory with the provider's relative
1257
+ * config path. For global scope, returns the provider's global config path.
1258
+ *
1259
+ * @param provider - Provider to resolve config path for
1260
+ * @param scope - Whether to resolve project or global config path
1261
+ * @param projectDir - Project directory (defaults to `process.cwd()`)
1262
+ * @returns Absolute config file path, or `null` if the provider does not support the given scope
1263
+ *
1264
+ * @example
1265
+ * ```typescript
1266
+ * const path = resolveConfigPath(provider, "project", "/home/user/my-project");
1267
+ * // "/home/user/my-project/.claude/settings.json"
1268
+ * ```
1269
+ */
329
1270
  declare function resolveConfigPath(provider: Provider, scope: "project" | "global", projectDir?: string): string | null;
330
- /** List MCP servers configured for a single provider */
1271
+ /**
1272
+ * List MCP servers configured for a single provider.
1273
+ *
1274
+ * Reads the provider's config file, extracts the MCP servers section using the
1275
+ * provider's `configKey`, and returns each server entry with metadata.
1276
+ *
1277
+ * @param provider - Provider whose config file to read
1278
+ * @param scope - Whether to read project or global config
1279
+ * @param projectDir - Project directory (defaults to `process.cwd()`)
1280
+ * @returns Array of MCP server entries found in the config file
1281
+ *
1282
+ * @example
1283
+ * ```typescript
1284
+ * const servers = await listMcpServers(provider, "project");
1285
+ * for (const s of servers) {
1286
+ * console.log(`${s.name} (${s.scope})`);
1287
+ * }
1288
+ * ```
1289
+ */
331
1290
  declare function listMcpServers(provider: Provider, scope: "project" | "global", projectDir?: string): Promise<McpServerEntry[]>;
332
- /** List MCP servers across all given providers, deduplicating by config path */
1291
+ /**
1292
+ * List MCP servers across all given providers, deduplicating by config path.
1293
+ *
1294
+ * Multiple providers may share the same config file. This function ensures each
1295
+ * config file is read only once to avoid duplicate entries.
1296
+ *
1297
+ * @param providers - Array of providers to query
1298
+ * @param scope - Whether to read project or global config
1299
+ * @param projectDir - Project directory (defaults to `process.cwd()`)
1300
+ * @returns Combined array of MCP server entries from all providers
1301
+ *
1302
+ * @example
1303
+ * ```typescript
1304
+ * const allServers = await listAllMcpServers(getInstalledProviders(), "global");
1305
+ * ```
1306
+ */
333
1307
  declare function listAllMcpServers(providers: Provider[], scope: "project" | "global", projectDir?: string): Promise<McpServerEntry[]>;
334
- /** Remove an MCP server entry from a provider's config file */
1308
+ /**
1309
+ * Remove an MCP server entry from a provider's config file.
1310
+ *
1311
+ * @param provider - Provider whose config file to modify
1312
+ * @param serverName - Name/key of the MCP server to remove
1313
+ * @param scope - Whether to modify project or global config
1314
+ * @param projectDir - Project directory (defaults to `process.cwd()`)
1315
+ * @returns `true` if the entry was removed, `false` if no config path exists
1316
+ *
1317
+ * @example
1318
+ * ```typescript
1319
+ * const removed = await removeMcpServer(provider, "my-server", "project");
1320
+ * ```
1321
+ */
335
1322
  declare function removeMcpServer(provider: Provider, serverName: string, scope: "project" | "global", projectDir?: string): Promise<boolean>;
336
1323
 
1324
+ /**
1325
+ * Shared lock file utilities
1326
+ *
1327
+ * Single source of truth for reading/writing ~/.agents/.caamp-lock.json.
1328
+ * Both MCP and skills lock modules import from here.
1329
+ */
1330
+
1331
+ /** Read the lock file */
1332
+ declare function readLockFile(): Promise<CaampLockFile>;
1333
+
337
1334
  /**
338
1335
  * MCP lock file management
339
1336
  *
@@ -341,17 +1338,74 @@ declare function removeMcpServer(provider: Provider, serverName: string, scope:
341
1338
  * Stored at ~/.agents/.caamp-lock.json (shared with skills lock).
342
1339
  */
343
1340
 
344
- /** Read the lock file */
345
- declare function readLockFile(): Promise<CaampLockFile>;
346
- /** Record an MCP server installation */
1341
+ /**
1342
+ * Record an MCP server installation in the lock file.
1343
+ *
1344
+ * Creates or updates an entry in `lock.mcpServers`. If the server already exists,
1345
+ * the agent list is merged and `updatedAt` is refreshed while `installedAt` is preserved.
1346
+ *
1347
+ * @param serverName - Name/key of the MCP server
1348
+ * @param source - Original source string
1349
+ * @param sourceType - Classified source type
1350
+ * @param agents - Provider IDs the server was installed to
1351
+ * @param isGlobal - Whether this is a global installation
1352
+ *
1353
+ * @example
1354
+ * ```typescript
1355
+ * await recordMcpInstall("filesystem", "@mcp/server-fs", "package", ["claude-code"], true);
1356
+ * ```
1357
+ */
347
1358
  declare function recordMcpInstall(serverName: string, source: string, sourceType: SourceType, agents: string[], isGlobal: boolean): Promise<void>;
348
- /** Remove an MCP server from the lock file */
1359
+ /**
1360
+ * Remove an MCP server entry from the lock file.
1361
+ *
1362
+ * @param serverName - Name/key of the MCP server to remove
1363
+ * @returns `true` if the entry was found and removed, `false` if not found
1364
+ *
1365
+ * @example
1366
+ * ```typescript
1367
+ * const removed = await removeMcpFromLock("filesystem");
1368
+ * ```
1369
+ */
349
1370
  declare function removeMcpFromLock(serverName: string): Promise<boolean>;
350
- /** Get all tracked MCP servers */
1371
+ /**
1372
+ * Get all MCP servers tracked in the lock file.
1373
+ *
1374
+ * @returns Record of server name to lock entry
1375
+ *
1376
+ * @example
1377
+ * ```typescript
1378
+ * const servers = await getTrackedMcpServers();
1379
+ * for (const [name, entry] of Object.entries(servers)) {
1380
+ * console.log(`${name}: installed ${entry.installedAt}`);
1381
+ * }
1382
+ * ```
1383
+ */
351
1384
  declare function getTrackedMcpServers(): Promise<Record<string, LockEntry>>;
352
- /** Save last selected agents for UX */
1385
+ /**
1386
+ * Save the last selected agent IDs to the lock file for UX persistence.
1387
+ *
1388
+ * Used to remember the user's agent selection between CLI invocations.
1389
+ *
1390
+ * @param agents - Array of provider IDs to remember
1391
+ *
1392
+ * @example
1393
+ * ```typescript
1394
+ * await saveLastSelectedAgents(["claude-code", "cursor"]);
1395
+ * ```
1396
+ */
353
1397
  declare function saveLastSelectedAgents(agents: string[]): Promise<void>;
354
- /** Get last selected agents */
1398
+ /**
1399
+ * Retrieve the last selected agent IDs from the lock file.
1400
+ *
1401
+ * @returns Array of provider IDs, or `undefined` if none were saved
1402
+ *
1403
+ * @example
1404
+ * ```typescript
1405
+ * const agents = await getLastSelectedAgents();
1406
+ * // ["claude-code", "cursor"] or undefined
1407
+ * ```
1408
+ */
355
1409
  declare function getLastSelectedAgents(): Promise<string[] | undefined>;
356
1410
 
357
1411
  /**
@@ -360,17 +1414,80 @@ declare function getLastSelectedAgents(): Promise<string[] | undefined>;
360
1414
  * Shares the same lock file as MCP (~/.agents/.caamp-lock.json).
361
1415
  */
362
1416
 
363
- /** Record a skill installation */
1417
+ /**
1418
+ * Record a skill installation in the lock file.
1419
+ *
1420
+ * Creates or updates an entry in `lock.skills`. If the skill already exists,
1421
+ * the agent list is merged and `updatedAt` is refreshed while `installedAt` is preserved.
1422
+ *
1423
+ * @param skillName - Skill name
1424
+ * @param scopedName - Scoped name (may include marketplace scope)
1425
+ * @param source - Original source string
1426
+ * @param sourceType - Classified source type
1427
+ * @param agents - Provider IDs the skill was linked to
1428
+ * @param canonicalPath - Absolute path to the canonical installation
1429
+ * @param isGlobal - Whether this is a global installation
1430
+ * @param projectDir - Project directory (for project-scoped installs)
1431
+ * @param version - Version string or commit SHA
1432
+ *
1433
+ * @example
1434
+ * ```typescript
1435
+ * await recordSkillInstall(
1436
+ * "my-skill", "my-skill", "owner/repo", "github",
1437
+ * ["claude-code"], "/home/user/.agents/skills/my-skill", true,
1438
+ * );
1439
+ * ```
1440
+ */
364
1441
  declare function recordSkillInstall(skillName: string, scopedName: string, source: string, sourceType: SourceType, agents: string[], canonicalPath: string, isGlobal: boolean, projectDir?: string, version?: string): Promise<void>;
365
- /** Remove a skill from the lock file */
1442
+ /**
1443
+ * Remove a skill entry from the lock file.
1444
+ *
1445
+ * @param skillName - Name of the skill to remove
1446
+ * @returns `true` if the entry was found and removed, `false` if not found
1447
+ *
1448
+ * @example
1449
+ * ```typescript
1450
+ * const removed = await removeSkillFromLock("my-skill");
1451
+ * ```
1452
+ */
366
1453
  declare function removeSkillFromLock(skillName: string): Promise<boolean>;
367
- /** Get all tracked skills */
1454
+ /**
1455
+ * Get all skills tracked in the lock file.
1456
+ *
1457
+ * @returns Record of skill name to lock entry
1458
+ *
1459
+ * @example
1460
+ * ```typescript
1461
+ * const skills = await getTrackedSkills();
1462
+ * for (const [name, entry] of Object.entries(skills)) {
1463
+ * console.log(`${name}: ${entry.source}`);
1464
+ * }
1465
+ * ```
1466
+ */
368
1467
  declare function getTrackedSkills(): Promise<Record<string, LockEntry>>;
369
- /** Check if a skill has updates available (comparing version/hash) */
1468
+ /**
1469
+ * Check if a skill has updates available by comparing the installed version
1470
+ * against the latest remote commit SHA.
1471
+ *
1472
+ * Only supports GitHub and GitLab sources. Returns `"unknown"` for local,
1473
+ * package, or other source types.
1474
+ *
1475
+ * @param skillName - Name of the installed skill to check
1476
+ * @returns Object with update status, current version, and latest version
1477
+ *
1478
+ * @example
1479
+ * ```typescript
1480
+ * const update = await checkSkillUpdate("my-skill");
1481
+ * if (update.hasUpdate) {
1482
+ * console.log(`Update available: ${update.currentVersion} -> ${update.latestVersion}`);
1483
+ * }
1484
+ * ```
1485
+ */
370
1486
  declare function checkSkillUpdate(skillName: string): Promise<{
371
1487
  hasUpdate: boolean;
372
1488
  currentVersion?: string;
373
1489
  latestVersion?: string;
1490
+ status: "up-to-date" | "update-available" | "unknown";
374
1491
  }>;
375
1492
 
376
1493
  /**
@@ -400,12 +1517,68 @@ interface MarketplaceResult {
400
1517
  * deduplicates, and sorts by relevance.
401
1518
  */
402
1519
 
1520
+ /**
1521
+ * Unified marketplace client that aggregates results from multiple marketplace adapters.
1522
+ *
1523
+ * Queries all configured marketplaces in parallel, deduplicates results by scoped name,
1524
+ * and sorts by star count.
1525
+ *
1526
+ * @example
1527
+ * ```typescript
1528
+ * const client = new MarketplaceClient();
1529
+ * const results = await client.search("filesystem");
1530
+ * for (const r of results) {
1531
+ * console.log(`${r.scopedName} (${r.stars} stars)`);
1532
+ * }
1533
+ * ```
1534
+ */
403
1535
  declare class MarketplaceClient {
404
1536
  private adapters;
1537
+ /**
1538
+ * Create a new marketplace client.
1539
+ *
1540
+ * @param adapters - Custom marketplace adapters (defaults to agentskills.in and skills.sh)
1541
+ *
1542
+ * @example
1543
+ * ```typescript
1544
+ * // Use default adapters
1545
+ * const client = new MarketplaceClient();
1546
+ *
1547
+ * // Use custom adapters
1548
+ * const client = new MarketplaceClient([myAdapter]);
1549
+ * ```
1550
+ */
405
1551
  constructor(adapters?: MarketplaceAdapter[]);
406
- /** Search all marketplaces and deduplicate results */
1552
+ /**
1553
+ * Search all marketplaces and return deduplicated, sorted results.
1554
+ *
1555
+ * Queries all adapters in parallel and deduplicates by `scopedName`,
1556
+ * keeping the entry with the highest star count. Results are sorted by
1557
+ * stars descending.
1558
+ *
1559
+ * @param query - Search query string
1560
+ * @param limit - Maximum number of results to return (default: 20)
1561
+ * @returns Deduplicated and sorted marketplace results
1562
+ *
1563
+ * @example
1564
+ * ```typescript
1565
+ * const results = await client.search("code review", 10);
1566
+ * ```
1567
+ */
407
1568
  search(query: string, limit?: number): Promise<MarketplaceResult[]>;
408
- /** Get a specific skill by scoped name */
1569
+ /**
1570
+ * Get a specific skill by its scoped name from any marketplace.
1571
+ *
1572
+ * Tries each adapter in order and returns the first match.
1573
+ *
1574
+ * @param scopedName - Scoped skill name (e.g. `"@author/my-skill"`)
1575
+ * @returns The marketplace result, or `null` if not found in any marketplace
1576
+ *
1577
+ * @example
1578
+ * ```typescript
1579
+ * const skill = await client.getSkill("@anthropic/memory");
1580
+ * ```
1581
+ */
409
1582
  getSkill(scopedName: string): Promise<MarketplaceResult | null>;
410
1583
  }
411
1584
 
@@ -416,15 +1589,99 @@ declare class MarketplaceClient {
416
1589
  * (CLAUDE.md, AGENTS.md, GEMINI.md).
417
1590
  */
418
1591
 
419
- /** Check if a file has a CAAMP injection block */
1592
+ /**
1593
+ * Check the status of a CAAMP injection block in an instruction file.
1594
+ *
1595
+ * Returns the injection status:
1596
+ * - `"missing"` - File does not exist
1597
+ * - `"none"` - File exists but has no CAAMP markers
1598
+ * - `"current"` - CAAMP block exists and matches expected content (or no expected content given)
1599
+ * - `"outdated"` - CAAMP block exists but differs from expected content
1600
+ *
1601
+ * @param filePath - Absolute path to the instruction file
1602
+ * @param expectedContent - Optional expected content to compare against
1603
+ * @returns The injection status
1604
+ *
1605
+ * @example
1606
+ * ```typescript
1607
+ * const status = await checkInjection("/project/CLAUDE.md", expectedContent);
1608
+ * if (status === "outdated") {
1609
+ * console.log("CAAMP injection needs updating");
1610
+ * }
1611
+ * ```
1612
+ */
420
1613
  declare function checkInjection(filePath: string, expectedContent?: string): Promise<InjectionStatus>;
421
- /** Inject content into a file */
1614
+ /**
1615
+ * Inject content into an instruction file between CAAMP markers.
1616
+ *
1617
+ * Behavior depends on the file state:
1618
+ * - File does not exist: creates the file with the injection block
1619
+ * - File exists without markers: prepends the injection block
1620
+ * - File exists with markers: replaces the existing injection block
1621
+ *
1622
+ * @param filePath - Absolute path to the instruction file
1623
+ * @param content - Content to inject between CAAMP markers
1624
+ * @returns Action taken: `"created"`, `"added"`, or `"updated"`
1625
+ *
1626
+ * @example
1627
+ * ```typescript
1628
+ * const action = await inject("/project/CLAUDE.md", "## My Config\nSome content");
1629
+ * console.log(`File ${action}`);
1630
+ * ```
1631
+ */
422
1632
  declare function inject(filePath: string, content: string): Promise<"created" | "added" | "updated">;
423
- /** Remove the CAAMP injection block from a file */
1633
+ /**
1634
+ * Remove the CAAMP injection block from an instruction file.
1635
+ *
1636
+ * If removing the block would leave the file empty, the file is deleted entirely.
1637
+ *
1638
+ * @param filePath - Absolute path to the instruction file
1639
+ * @returns `true` if a CAAMP block was found and removed, `false` otherwise
1640
+ *
1641
+ * @example
1642
+ * ```typescript
1643
+ * const removed = await removeInjection("/project/CLAUDE.md");
1644
+ * ```
1645
+ */
424
1646
  declare function removeInjection(filePath: string): Promise<boolean>;
425
- /** Check injection status across all providers' instruction files */
1647
+ /**
1648
+ * Check injection status across all providers' instruction files.
1649
+ *
1650
+ * Deduplicates by file path since multiple providers may share the same
1651
+ * instruction file (e.g. many providers use `AGENTS.md`).
1652
+ *
1653
+ * @param providers - Array of providers to check
1654
+ * @param projectDir - Absolute path to the project directory
1655
+ * @param scope - Whether to check project or global instruction files
1656
+ * @param expectedContent - Optional expected content to compare against
1657
+ * @returns Array of injection check results, one per unique instruction file
1658
+ *
1659
+ * @example
1660
+ * ```typescript
1661
+ * const results = await checkAllInjections(providers, "/project", "project");
1662
+ * const outdated = results.filter(r => r.status === "outdated");
1663
+ * ```
1664
+ */
426
1665
  declare function checkAllInjections(providers: Provider[], projectDir: string, scope: "project" | "global", expectedContent?: string): Promise<InjectionCheckResult[]>;
427
- /** Inject content into all providers' instruction files */
1666
+ /**
1667
+ * Inject content into all providers' instruction files.
1668
+ *
1669
+ * Deduplicates by file path to avoid injecting the same file multiple times.
1670
+ *
1671
+ * @param providers - Array of providers to inject into
1672
+ * @param projectDir - Absolute path to the project directory
1673
+ * @param scope - Whether to target project or global instruction files
1674
+ * @param content - Content to inject between CAAMP markers
1675
+ * @returns Map of file path to action taken (`"created"`, `"added"`, or `"updated"`)
1676
+ *
1677
+ * @example
1678
+ * ```typescript
1679
+ * const results = await injectAll(providers, "/project", "project", content);
1680
+ * for (const [file, action] of results) {
1681
+ * console.log(`${file}: ${action}`);
1682
+ * }
1683
+ * ```
1684
+ */
428
1685
  declare function injectAll(providers: Provider[], projectDir: string, scope: "project" | "global", content: string): Promise<Map<string, "created" | "added" | "updated">>;
429
1686
 
430
1687
  /**
@@ -433,33 +1690,207 @@ declare function injectAll(providers: Provider[], projectDir: string, scope: "pr
433
1690
  * Generates injection content based on provider capabilities.
434
1691
  */
435
1692
 
436
- /** Generate a standard CAAMP injection block */
1693
+ /**
1694
+ * Generate a standard CAAMP injection block for instruction files.
1695
+ *
1696
+ * Produces markdown content suitable for injection between CAAMP markers.
1697
+ * Optionally includes MCP server and custom content sections.
1698
+ *
1699
+ * @param options - Optional configuration for the generated content
1700
+ * @param options.mcpServerName - MCP server name to include a server section
1701
+ * @param options.customContent - Additional custom markdown content to append
1702
+ * @returns Generated markdown string
1703
+ *
1704
+ * @example
1705
+ * ```typescript
1706
+ * const content = generateInjectionContent({ mcpServerName: "filesystem" });
1707
+ * ```
1708
+ */
437
1709
  declare function generateInjectionContent(options?: {
438
1710
  mcpServerName?: string;
439
1711
  customContent?: string;
440
1712
  }): string;
441
- /** Group providers by instruction file */
1713
+ /**
1714
+ * Group providers by their instruction file name.
1715
+ *
1716
+ * Useful for determining which providers share the same instruction file
1717
+ * (e.g. multiple providers using `AGENTS.md`).
1718
+ *
1719
+ * @param providers - Array of providers to group
1720
+ * @returns Map from instruction file name to array of providers using that file
1721
+ *
1722
+ * @example
1723
+ * ```typescript
1724
+ * const groups = groupByInstructFile(getAllProviders());
1725
+ * for (const [file, providers] of groups) {
1726
+ * console.log(`${file}: ${providers.map(p => p.id).join(", ")}`);
1727
+ * }
1728
+ * ```
1729
+ */
442
1730
  declare function groupByInstructFile(providers: Provider[]): Map<string, Provider[]>;
443
1731
 
444
1732
  /**
445
1733
  * Format utility functions
446
1734
  */
447
- /** Deep merge two objects, source wins on conflict */
1735
+ /**
1736
+ * Deep merge two objects, with `source` values winning on conflict.
1737
+ *
1738
+ * Recursively merges nested plain objects. Arrays and non-object values from
1739
+ * `source` overwrite `target` values.
1740
+ *
1741
+ * @param target - Base object to merge into
1742
+ * @param source - Object with values that take precedence
1743
+ * @returns A new merged object (does not mutate inputs)
1744
+ *
1745
+ * @example
1746
+ * ```typescript
1747
+ * deepMerge({ a: 1, b: { c: 2 } }, { b: { d: 3 } });
1748
+ * // { a: 1, b: { c: 2, d: 3 } }
1749
+ * ```
1750
+ */
448
1751
  declare function deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): Record<string, unknown>;
449
- /** Get a nested value using dot-notation key path */
1752
+ /**
1753
+ * Get a nested value from an object using a dot-notation key path.
1754
+ *
1755
+ * @param obj - Object to traverse
1756
+ * @param keyPath - Dot-separated key path (e.g. `"mcpServers"` or `"a.b.c"`)
1757
+ * @returns The value at the key path, or `undefined` if not found
1758
+ *
1759
+ * @example
1760
+ * ```typescript
1761
+ * getNestedValue({ a: { b: { c: 42 } } }, "a.b.c"); // 42
1762
+ * getNestedValue({ a: 1 }, "a.b"); // undefined
1763
+ * ```
1764
+ */
450
1765
  declare function getNestedValue(obj: Record<string, unknown>, keyPath: string): unknown;
451
- /** Ensure parent directories exist */
1766
+ /**
1767
+ * Ensure that the parent directories of a file path exist.
1768
+ *
1769
+ * Creates directories recursively if they do not exist.
1770
+ *
1771
+ * @param filePath - Absolute path to a file (parent directories will be created)
1772
+ *
1773
+ * @example
1774
+ * ```typescript
1775
+ * await ensureDir("/path/to/new/dir/file.json");
1776
+ * // /path/to/new/dir/ now exists
1777
+ * ```
1778
+ */
452
1779
  declare function ensureDir(filePath: string): Promise<void>;
453
1780
 
454
1781
  /**
455
1782
  * Format router - dispatches config reads/writes to format-specific handlers
456
1783
  */
457
1784
 
458
- /** Read a config file in the specified format */
1785
+ /**
1786
+ * Read and parse a config file in the specified format.
1787
+ *
1788
+ * Dispatches to the appropriate format handler (JSON/JSONC, YAML, or TOML).
1789
+ *
1790
+ * @param filePath - Absolute path to the config file
1791
+ * @param format - Config file format
1792
+ * @returns Parsed config object
1793
+ * @throws If the file cannot be read or the format is unsupported
1794
+ *
1795
+ * @example
1796
+ * ```typescript
1797
+ * const config = await readConfig("/path/to/config.json", "jsonc");
1798
+ * ```
1799
+ */
459
1800
  declare function readConfig(filePath: string, format: ConfigFormat): Promise<Record<string, unknown>>;
460
- /** Write a config file in the specified format, preserving existing content */
1801
+ /**
1802
+ * Write a server entry to a config file, preserving existing content.
1803
+ *
1804
+ * Dispatches to the appropriate format handler. For JSONC files, comments are
1805
+ * preserved using `jsonc-parser`.
1806
+ *
1807
+ * @param filePath - Absolute path to the config file
1808
+ * @param format - Config file format
1809
+ * @param key - Dot-notation key path to the servers section (e.g. `"mcpServers"`)
1810
+ * @param serverName - Name/key for the server entry
1811
+ * @param serverConfig - Server configuration object to write
1812
+ * @throws If the format is unsupported
1813
+ *
1814
+ * @example
1815
+ * ```typescript
1816
+ * await writeConfig("/path/to/config.json", "jsonc", "mcpServers", "my-server", config);
1817
+ * ```
1818
+ */
461
1819
  declare function writeConfig(filePath: string, format: ConfigFormat, key: string, serverName: string, serverConfig: unknown): Promise<void>;
462
- /** Remove a server entry from a config file in the specified format */
1820
+ /**
1821
+ * Remove a server entry from a config file in the specified format.
1822
+ *
1823
+ * @param filePath - Absolute path to the config file
1824
+ * @param format - Config file format
1825
+ * @param key - Dot-notation key path to the servers section
1826
+ * @param serverName - Name/key of the server entry to remove
1827
+ * @returns `true` if the entry was removed, `false` otherwise
1828
+ * @throws If the format is unsupported
1829
+ *
1830
+ * @example
1831
+ * ```typescript
1832
+ * const removed = await removeConfig("/path/to/config.json", "jsonc", "mcpServers", "my-server");
1833
+ * ```
1834
+ */
463
1835
  declare function removeConfig(filePath: string, format: ConfigFormat, key: string, serverName: string): Promise<boolean>;
464
1836
 
465
- export { type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type CaampLockFile, type ConfigFormat, type DetectionResult, type GlobalOptions, type InjectionCheckResult, type InjectionStatus, type InstallResult, type LockEntry, MarketplaceClient, type MarketplaceSearchResult, type MarketplaceSkill, type McpServerConfig, type McpServerEntry, type ParsedSource, type Provider, type SkillEntry, type SkillInstallResult, type SkillMetadata, type SourceType, type TransportType, type ValidationIssue, type ValidationResult, buildServerConfig, checkAllInjections, checkInjection, checkSkillUpdate, deepMerge, detectAllProviders, detectProjectProviders, detectProvider, discoverSkill, discoverSkills, ensureDir, generateInjectionContent, getAllProviders, getInstalledProviders, getInstructionFiles, getLastSelectedAgents, getNestedValue, getProvider, getProviderCount, getProvidersByInstructFile, getProvidersByPriority, getProvidersByStatus, getRegistryVersion, getTrackedMcpServers, getTrackedSkills, getTransform, groupByInstructFile, inject, injectAll, installMcpServer, installMcpServerToAll, installSkill, isMarketplaceScoped, listAllMcpServers, listCanonicalSkills, listMcpServers, parseSkillFile, parseSource, readConfig, readLockFile, recordMcpInstall, recordSkillInstall, removeConfig, removeInjection, removeMcpFromLock, removeMcpServer, removeSkill, removeSkillFromLock, resolveAlias, resolveConfigPath, saveLastSelectedAgents, scanDirectory, scanFile, toSarif, validateSkill, writeConfig };
1837
+ /**
1838
+ * Simple logger with verbose/quiet mode support.
1839
+ *
1840
+ * - verbose: enables debug output to stderr
1841
+ * - quiet: suppresses info and warn output (errors always shown)
1842
+ */
1843
+ /**
1844
+ * Enable or disable verbose (debug) logging mode.
1845
+ *
1846
+ * When enabled, debug messages are written to stderr.
1847
+ *
1848
+ * @param v - `true` to enable verbose mode, `false` to disable
1849
+ *
1850
+ * @example
1851
+ * ```typescript
1852
+ * setVerbose(true);
1853
+ * ```
1854
+ */
1855
+ declare function setVerbose(v: boolean): void;
1856
+ /**
1857
+ * Enable or disable quiet mode.
1858
+ *
1859
+ * When enabled, info and warning messages are suppressed. Errors are always shown.
1860
+ *
1861
+ * @param q - `true` to enable quiet mode, `false` to disable
1862
+ *
1863
+ * @example
1864
+ * ```typescript
1865
+ * setQuiet(true);
1866
+ * ```
1867
+ */
1868
+ declare function setQuiet(q: boolean): void;
1869
+ /**
1870
+ * Check if verbose (debug) logging is currently enabled.
1871
+ *
1872
+ * @returns `true` if verbose mode is active
1873
+ *
1874
+ * @example
1875
+ * ```typescript
1876
+ * if (isVerbose()) {
1877
+ * console.error("Extra debug info");
1878
+ * }
1879
+ * ```
1880
+ */
1881
+ declare function isVerbose(): boolean;
1882
+ /**
1883
+ * Check if quiet mode is currently enabled.
1884
+ *
1885
+ * @returns `true` if quiet mode is active
1886
+ *
1887
+ * @example
1888
+ * ```typescript
1889
+ * if (!isQuiet()) {
1890
+ * console.log("Status message");
1891
+ * }
1892
+ * ```
1893
+ */
1894
+ declare function isQuiet(): boolean;
1895
+
1896
+ export { type AuditFinding, type AuditResult, type AuditRule, type AuditSeverity, type CaampLockFile, type ConfigFormat, type DetectionResult, type GlobalOptions, type InjectionCheckResult, type InjectionStatus, type InstallResult, type LockEntry, MarketplaceClient, type MarketplaceResult, type MarketplaceSearchResult, type MarketplaceSkill, type McpServerConfig, type McpServerEntry, type ParsedSource, type Provider, type ProviderPriority, type ProviderStatus, type SkillEntry, type SkillInstallResult, type SkillMetadata, type SourceType, type TransportType, type ValidationIssue, type ValidationResult, buildServerConfig, checkAllInjections, checkInjection, checkSkillUpdate, deepMerge, detectAllProviders, detectProjectProviders, detectProvider, discoverSkill, discoverSkills, ensureDir, generateInjectionContent, getAllProviders, getInstalledProviders, getInstructionFiles, getLastSelectedAgents, getNestedValue, getProvider, getProviderCount, getProvidersByInstructFile, getProvidersByPriority, getProvidersByStatus, getRegistryVersion, getTrackedMcpServers, getTrackedSkills, getTransform, groupByInstructFile, inject, injectAll, installMcpServer, installMcpServerToAll, installSkill, isMarketplaceScoped, isQuiet, isVerbose, listAllMcpServers, listCanonicalSkills, listMcpServers, parseSkillFile, parseSource, readConfig, readLockFile, recordMcpInstall, recordSkillInstall, removeConfig, removeInjection, removeMcpFromLock, removeMcpServer, removeSkill, removeSkillFromLock, resolveAlias, resolveConfigPath, saveLastSelectedAgents, scanDirectory, scanFile, setQuiet, setVerbose, toSarif, validateSkill, writeConfig };