@cleocode/caamp 2026.4.9 → 2026.4.11

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
@@ -2807,6 +2807,14 @@ declare function setExclusivityMode(mode: ExclusivityMode): void;
2807
2807
  * environment variable (and falls back to the default when the env var is
2808
2808
  * unset or invalid). Idempotent — safe to call when no override is active.
2809
2809
  *
2810
+ * @example
2811
+ * ```typescript
2812
+ * setExclusivityMode("force-pi");
2813
+ * // ...run test...
2814
+ * resetExclusivityModeOverride();
2815
+ * // getExclusivityMode() now reads CAAMP_EXCLUSIVITY_MODE again
2816
+ * ```
2817
+ *
2810
2818
  * @public
2811
2819
  */
2812
2820
  declare function resetExclusivityModeOverride(): void;
@@ -3122,15 +3130,27 @@ declare class PiHarness implements Harness {
3122
3130
  * auto-discovering `AGENTS.md` from the working directory upwards.
3123
3131
  */
3124
3132
  private agentsMdPath;
3125
- /** {@inheritDoc Harness.installSkill} */
3133
+ /**
3134
+ * Install a skill directory into the resolved Pi skills location.
3135
+ */
3126
3136
  installSkill(sourcePath: string, skillName: string, scope: HarnessScope): Promise<void>;
3127
- /** {@inheritDoc Harness.removeSkill} */
3137
+ /**
3138
+ * Remove a skill directory from the resolved Pi skills location.
3139
+ */
3128
3140
  removeSkill(skillName: string, scope: HarnessScope): Promise<void>;
3129
- /** {@inheritDoc Harness.listSkills} */
3141
+ /**
3142
+ * List the installed skill directories at the given scope.
3143
+ */
3130
3144
  listSkills(scope: HarnessScope): Promise<string[]>;
3131
- /** {@inheritDoc Harness.injectInstructions} */
3145
+ /**
3146
+ * Inject or replace a CAAMP-managed instruction block inside the Pi
3147
+ * `AGENTS.md` file for the resolved scope.
3148
+ */
3132
3149
  injectInstructions(content: string, scope: HarnessScope): Promise<void>;
3133
- /** {@inheritDoc Harness.removeInstructions} */
3150
+ /**
3151
+ * Remove the CAAMP-managed instruction block from the Pi `AGENTS.md`
3152
+ * file at the resolved scope.
3153
+ */
3134
3154
  removeInstructions(scope: HarnessScope): Promise<void>;
3135
3155
  /**
3136
3156
  * Spawn a subagent through Pi's configured `spawnCommand` and return a
@@ -3245,11 +3265,19 @@ declare class PiHarness implements Harness {
3245
3265
  * length entry that has no semantic meaning).
3246
3266
  */
3247
3267
  private handleStdoutLine;
3248
- /** {@inheritDoc Harness.readSettings} */
3268
+ /**
3269
+ * Read the Pi `settings.json` file for the resolved scope.
3270
+ */
3249
3271
  readSettings(scope: HarnessScope): Promise<unknown>;
3250
- /** {@inheritDoc Harness.writeSettings} */
3272
+ /**
3273
+ * Merge a partial patch into the Pi `settings.json` file for the
3274
+ * resolved scope using an atomic write.
3275
+ */
3251
3276
  writeSettings(patch: Record<string, unknown>, scope: HarnessScope): Promise<void>;
3252
- /** {@inheritDoc Harness.configureModels} */
3277
+ /**
3278
+ * Persist the supplied model-name patterns into `settings.enabledModels`
3279
+ * at the resolved scope.
3280
+ */
3253
3281
  configureModels(modelPatterns: string[], scope: HarnessScope): Promise<void>;
3254
3282
  /**
3255
3283
  * Resolve the `models.json` path for a given legacy two-tier scope.
@@ -3266,67 +3294,109 @@ declare class PiHarness implements Harness {
3266
3294
  * the single authoritative location per ADR-035 §D2.
3267
3295
  */
3268
3296
  private sessionsDir;
3269
- /** {@inheritDoc Harness.installExtension} */
3297
+ /**
3298
+ * Install a Pi extension `.ts` source file into the resolved tier's
3299
+ * extensions directory, validating that it has a default export.
3300
+ */
3270
3301
  installExtension(sourcePath: string, name: string, tier: HarnessTier, projectDir?: string, opts?: HarnessInstallOptions): Promise<{
3271
3302
  targetPath: string;
3272
3303
  tier: HarnessTier;
3273
3304
  }>;
3274
- /** {@inheritDoc Harness.removeExtension} */
3305
+ /**
3306
+ * Remove a Pi extension `.ts` source file from the resolved tier.
3307
+ */
3275
3308
  removeExtension(name: string, tier: HarnessTier, projectDir?: string): Promise<boolean>;
3276
- /** {@inheritDoc Harness.listExtensions} */
3309
+ /**
3310
+ * List Pi extension files across every tier in precedence order,
3311
+ * flagging shadowed entries from lower tiers.
3312
+ */
3277
3313
  listExtensions(projectDir?: string): Promise<ExtensionEntry[]>;
3278
- /** {@inheritDoc Harness.listSessions} */
3314
+ /**
3315
+ * List Pi session JSONL files (including subagent children when
3316
+ * requested), summarising only the header line per file.
3317
+ */
3279
3318
  listSessions(opts?: {
3280
3319
  includeSubagents?: boolean;
3281
3320
  }): Promise<SessionSummary[]>;
3282
- /** {@inheritDoc Harness.showSession} */
3321
+ /**
3322
+ * Show the full entries of a single Pi session by id.
3323
+ */
3283
3324
  showSession(id: string): Promise<SessionDocument>;
3284
- /** {@inheritDoc Harness.readModelsConfig} */
3325
+ /**
3326
+ * Read the Pi `models.json` file for the resolved scope, tolerating
3327
+ * missing or malformed files by returning an empty provider map.
3328
+ */
3285
3329
  readModelsConfig(scope: HarnessScope): Promise<PiModelsConfig>;
3286
- /** {@inheritDoc Harness.writeModelsConfig} */
3330
+ /**
3331
+ * Write the Pi `models.json` file for the resolved scope via an atomic
3332
+ * tmp-then-rename sequence.
3333
+ */
3287
3334
  writeModelsConfig(config: PiModelsConfig, scope: HarnessScope): Promise<void>;
3288
- /** {@inheritDoc Harness.listModels} */
3335
+ /**
3336
+ * Compose a flat `ModelListEntry` list from `models.json` plus the
3337
+ * `enabledModels` and default-model hints in `settings.json`.
3338
+ */
3289
3339
  listModels(scope: HarnessScope): Promise<ModelListEntry[]>;
3290
- /** {@inheritDoc Harness.installPrompt} */
3340
+ /**
3341
+ * Install a Pi prompt directory (containing `prompt.md`) into the
3342
+ * resolved tier's prompts directory.
3343
+ */
3291
3344
  installPrompt(sourceDir: string, name: string, tier: HarnessTier, projectDir?: string, opts?: HarnessInstallOptions): Promise<{
3292
3345
  targetPath: string;
3293
3346
  tier: HarnessTier;
3294
3347
  }>;
3295
- /** {@inheritDoc Harness.listPrompts} */
3348
+ /**
3349
+ * List Pi prompt directories across every tier in precedence order,
3350
+ * flagging shadowed entries from lower tiers.
3351
+ */
3296
3352
  listPrompts(projectDir?: string): Promise<PromptEntry[]>;
3297
- /** {@inheritDoc Harness.removePrompt} */
3353
+ /**
3354
+ * Remove a Pi prompt directory from the resolved tier.
3355
+ */
3298
3356
  removePrompt(name: string, tier: HarnessTier, projectDir?: string): Promise<boolean>;
3299
- /** {@inheritDoc Harness.installTheme} */
3357
+ /**
3358
+ * Install a Pi theme file (`.ts`/`.tsx`/`.mts`/`.json`) into the
3359
+ * resolved tier's themes directory, blocking same-stem conflicts
3360
+ * unless `--force` is supplied.
3361
+ */
3300
3362
  installTheme(sourceFile: string, name: string, tier: HarnessTier, projectDir?: string, opts?: HarnessInstallOptions): Promise<{
3301
3363
  targetPath: string;
3302
3364
  tier: HarnessTier;
3303
3365
  }>;
3304
- /** {@inheritDoc Harness.listThemes} */
3366
+ /**
3367
+ * List Pi theme files across every tier in precedence order, flagging
3368
+ * shadowed entries from lower tiers.
3369
+ */
3305
3370
  listThemes(projectDir?: string): Promise<ThemeEntry[]>;
3306
- /** {@inheritDoc Harness.removeTheme} */
3371
+ /**
3372
+ * Remove a Pi theme from the resolved tier, matching any of the
3373
+ * supported theme extensions for the given name stem.
3374
+ */
3307
3375
  removeTheme(name: string, tier: HarnessTier, projectDir?: string): Promise<boolean>;
3308
3376
  /**
3309
- * {@inheritDoc Harness.installCantProfile}
3377
+ * Install a `.cant` profile into the resolved tier after passing it
3378
+ * through the cant-core validator.
3310
3379
  *
3311
- * @remarks
3312
- * Validates the source via {@link validateCantProfile} before copying so
3313
- * we never persist a `.cant` file the runtime bridge cannot load. The
3314
- * target layout is `<tier-root>/cant/<name>.cant`, resolved through
3315
- * {@link resolveTierDir} so the project/user/global hierarchy stays
3316
- * consistent with the other Wave-1 verbs.
3380
+ * Validates the source via {@link PiHarness.validateCantProfile}
3381
+ * before copying so we never persist a `.cant` file the runtime bridge
3382
+ * cannot load. The target layout is `<tier-root>/cant/<name>.cant`,
3383
+ * resolved through `resolveTierDir` so the project/user/global
3384
+ * hierarchy stays consistent with the other Wave-1 verbs.
3317
3385
  */
3318
3386
  installCantProfile(sourcePath: string, name: string, tier: HarnessTier, projectDir?: string, opts?: HarnessInstallOptions): Promise<{
3319
3387
  targetPath: string;
3320
3388
  tier: HarnessTier;
3321
3389
  counts: CantProfileCounts;
3322
3390
  }>;
3323
- /** {@inheritDoc Harness.removeCantProfile} */
3391
+ /**
3392
+ * Remove a `.cant` profile from the resolved tier.
3393
+ */
3324
3394
  removeCantProfile(name: string, tier: HarnessTier, projectDir?: string): Promise<boolean>;
3325
3395
  /**
3326
- * {@inheritDoc Harness.listCantProfiles}
3396
+ * List installed `.cant` profiles across every tier in precedence
3397
+ * order, parsing each file to extract section counts.
3327
3398
  *
3328
- * @remarks
3329
- * Walks every tier in {@link TIER_PRECEDENCE} order, parsing each
3399
+ * Walks every tier in `TIER_PRECEDENCE` order, parsing each
3330
3400
  * discovered `.cant` file via cant-core to extract a
3331
3401
  * {@link CantProfileCounts} bag. Higher-precedence tiers shadow
3332
3402
  * lower-precedence entries with the same name; shadowed entries
@@ -3336,9 +3406,9 @@ declare class PiHarness implements Harness {
3336
3406
  */
3337
3407
  listCantProfiles(projectDir?: string): Promise<CantProfileEntry[]>;
3338
3408
  /**
3339
- * {@inheritDoc Harness.validateCantProfile}
3409
+ * Validate a `.cant` source file against cant-core's parser and
3410
+ * 42-rule linter, returning section counts and per-diagnostic detail.
3340
3411
  *
3341
- * @remarks
3342
3412
  * Pure validator. Reads the file, runs `parseDocument` to derive
3343
3413
  * counts (when parsing succeeds) and `validateDocument` to collect
3344
3414
  * the 42-rule diagnostic feed. The two calls are kept independent so
@@ -3422,6 +3492,13 @@ declare function getPrimaryHarness(): Harness | null;
3422
3492
  * @returns Array of harness instances, one per provider that implements
3423
3493
  * the {@link Harness} contract.
3424
3494
  *
3495
+ * @example
3496
+ * ```typescript
3497
+ * for (const harness of getAllHarnesses()) {
3498
+ * console.log(harness.provider.id); // "pi", ...
3499
+ * }
3500
+ * ```
3501
+ *
3425
3502
  * @public
3426
3503
  */
3427
3504
  declare function getAllHarnesses(): Harness[];
@@ -3444,8 +3521,9 @@ declare function getAllHarnesses(): Harness[];
3444
3521
  * dispatchers ({@link dispatchInstallSkillAcrossProviders},
3445
3522
  * {@link dispatchRemoveSkillAcrossProviders}) intentionally do not call
3446
3523
  * this function — they target every requested provider directly so that
3447
- * users in `force-pi` mode can still `caamp skills install foo --agent
3448
- * claude-code` while Pi is being installed.
3524
+ * users in `force-pi` mode can still run
3525
+ * `caamp skills install foo --agent claude-code` while Pi is being
3526
+ * installed.
3449
3527
  *
3450
3528
  * The helper is intentionally defensive: registry/detection exceptions
3451
3529
  * are caught and treated as "Pi unknown" so stubbed test environments
@@ -4865,6 +4943,13 @@ interface McpDetectionEntry {
4865
4943
  * @param projectDir - Project directory used for the `project` scope.
4866
4944
  * @returns The absolute config file path, or `null` when unavailable.
4867
4945
  *
4946
+ * @example
4947
+ * ```typescript
4948
+ * const claudeCode = getProvider("claude-code")!;
4949
+ * const path = resolveMcpConfigPath(claudeCode, "project", "/tmp/app");
4950
+ * // e.g. "/tmp/app/.mcp.json"
4951
+ * ```
4952
+ *
4868
4953
  * @public
4869
4954
  */
4870
4955
  declare function resolveMcpConfigPath(provider: Provider, scope: McpScope, projectDir?: string): string | null;
@@ -4896,6 +4981,15 @@ declare function resolveMcpConfigPath(provider: Provider, scope: McpScope, proje
4896
4981
  * (defaults to `process.cwd()`).
4897
4982
  * @returns Array of MCP server entries, or `[]` when nothing was found.
4898
4983
  *
4984
+ * @example
4985
+ * ```typescript
4986
+ * const provider = getProvider("claude-code")!;
4987
+ * const entries = await listMcpServers(provider, "project");
4988
+ * for (const entry of entries) {
4989
+ * console.log(entry.name, entry.configPath);
4990
+ * }
4991
+ * ```
4992
+ *
4899
4993
  * @public
4900
4994
  */
4901
4995
  declare function listMcpServers(provider: Provider, scope: McpScope, projectDir?: string): Promise<McpServerEntry[]>;
@@ -4930,6 +5024,14 @@ type McpServerEntriesByProvider = Map<string, McpServerEntry[]>;
4930
5024
  * @param projectDir - Project directory used for the `project` scope.
4931
5025
  * @returns Map of provider id → server entries.
4932
5026
  *
5027
+ * @example
5028
+ * ```typescript
5029
+ * const byProvider = await listAllMcpServers("global");
5030
+ * for (const [providerId, entries] of byProvider) {
5031
+ * console.log(`${providerId}: ${entries.length} server(s)`);
5032
+ * }
5033
+ * ```
5034
+ *
4933
5035
  * @public
4934
5036
  */
4935
5037
  declare function listAllMcpServers(scope: McpScope, projectDir?: string): Promise<McpServerEntriesByProvider>;
@@ -4948,6 +5050,13 @@ declare function listAllMcpServers(scope: McpScope, projectDir?: string): Promis
4948
5050
  * @param projectDir - Project directory used for the `project` scope.
4949
5051
  * @returns Array of detection entries, one per MCP-capable provider.
4950
5052
  *
5053
+ * @example
5054
+ * ```typescript
5055
+ * const hits = await detectMcpInstallations("project");
5056
+ * const installed = hits.filter((h) => h.exists);
5057
+ * console.log(`MCP found on ${installed.length} providers`);
5058
+ * ```
5059
+ *
4951
5060
  * @public
4952
5061
  */
4953
5062
  declare function detectMcpInstallations(scope: McpScope, projectDir?: string): Promise<McpDetectionEntry[]>;
@@ -5038,6 +5147,18 @@ interface InstallMcpServerResult {
5038
5147
  * @throws `Error` when the provider has no MCP capability or no
5039
5148
  * project-scoped config path is available.
5040
5149
  *
5150
+ * @example
5151
+ * ```typescript
5152
+ * const provider = getProvider("claude-code")!;
5153
+ * const result = await installMcpServer(
5154
+ * provider,
5155
+ * "github",
5156
+ * { command: "npx", args: ["-y", "@modelcontextprotocol/server-github"] },
5157
+ * { scope: "project", force: false },
5158
+ * );
5159
+ * console.log(result.installed, result.conflicted);
5160
+ * ```
5161
+ *
5041
5162
  * @public
5042
5163
  */
5043
5164
  declare function installMcpServer(provider: Provider, serverName: string, config: McpServerConfig, opts: InstallMcpServerOptions): Promise<InstallMcpServerResult>;
@@ -5116,6 +5237,13 @@ interface RemoveMcpServerResult {
5116
5237
  * @param opts - Removal options.
5117
5238
  * @returns Structured result describing whether the entry was removed.
5118
5239
  *
5240
+ * @example
5241
+ * ```typescript
5242
+ * const provider = getProvider("claude-code")!;
5243
+ * const result = await removeMcpServer(provider, "my-server", { scope: "project" });
5244
+ * console.log(result.removed); // true | false
5245
+ * ```
5246
+ *
5119
5247
  * @public
5120
5248
  */
5121
5249
  declare function removeMcpServer(provider: Provider, serverName: string, opts: RemoveMcpServerOptions): Promise<RemoveMcpServerResult>;
@@ -5135,6 +5263,13 @@ declare function removeMcpServer(provider: Provider, serverName: string, opts: R
5135
5263
  * @param opts - Removal options applied uniformly to every provider.
5136
5264
  * @returns Array of per-provider removal results.
5137
5265
  *
5266
+ * @example
5267
+ * ```typescript
5268
+ * const results = await removeMcpServerFromAll("my-server", { scope: "global" });
5269
+ * const removed = results.filter((r) => r.removed);
5270
+ * console.log(`Removed from ${removed.length} providers`);
5271
+ * ```
5272
+ *
5138
5273
  * @public
5139
5274
  */
5140
5275
  declare function removeMcpServerFromAll(serverName: string, opts: RemoveMcpServerOptions): Promise<RemoveMcpServerResult[]>;
package/dist/index.js CHANGED
@@ -70,7 +70,7 @@ import {
70
70
  validateRecommendationCriteria,
71
71
  validateSkill,
72
72
  writeConfig
73
- } from "./chunk-JC77OAHA.js";
73
+ } from "./chunk-XVZT7K6F.js";
74
74
  import {
75
75
  buildInjectionContent,
76
76
  buildSkillsMap,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/caamp",
3
- "version": "2026.4.9",
3
+ "version": "2026.4.11",
4
4
  "description": "Central AI Agent Managed Packages - unified provider registry and package manager for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -51,11 +51,12 @@
51
51
  "jsonc-parser": "^3.3.1",
52
52
  "picocolors": "^1.1.1",
53
53
  "simple-git": "3.33.0",
54
- "@cleocode/cant": "2026.4.9",
55
- "@cleocode/lafs": "2026.4.9"
54
+ "@cleocode/cant": "2026.4.11",
55
+ "@cleocode/lafs": "2026.4.11"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@biomejs/biome": "2.4.8",
59
+ "@forge-ts/cli": "0.23.0",
59
60
  "@types/js-yaml": "^4.0.9",
60
61
  "@types/node": "25.5.0",
61
62
  "@vitest/coverage-v8": "^4.1.0",
@@ -83,6 +84,8 @@
83
84
  "typecheck": "tsc --noEmit",
84
85
  "lint": "biome lint src tests",
85
86
  "lint:fix": "biome lint --write src tests",
87
+ "docs": "forge-ts check && forge-ts build --skip-api",
88
+ "docs:check": "forge-ts check",
86
89
  "docs:api": "typedoc",
87
90
  "docs:api:check": "typedoc --emit none",
88
91
  "research": "tsx scripts/provider-research.ts"