1
>
/*---------------------------------------------------------------------------------------------
claudeNativePluginScan.ts
2
>
* Copyright (c) Microsoft Corporation. All rights reserved.
3
>
* Licensed under the MIT License. See License.txt in the project root for license information.
4
>
*--------------------------------------------------------------------------------------------*/
5
>
6
>
import { URI } from '../../../../../../base/common/uri.js';
7
>
import { ResourceSet } from '../../../../../../base/common/map.js';
8
>
import { IFileService } from '../../../../../files/common/files.js';
9
>
import { ILogService } from '../../../../../log/common/log.js';
10
>
import { detectPluginFormat, parsePlugin, readJsonFile, type IParsedPlugin } from '../../../../../agentPlugins/common/pluginParsers.js';
11
>
12
>
/**
13
>
* A Claude-native plugin enabled via `enabledPlugins` and resolved to its
14
>
* real on-disk root, paired with its parsed components.
15
>
*/
16
>
export interface IResolvedNativePlugin {
17
>
/** The `enabledPlugins` id, e.g. `telegram@claude-plugins-official`. */
18
>
readonly id: string;
19
>
/** The resolved plugin root directory (a real, openable `file:` URI). */
20
>
readonly root: URI;
21
>
/** The plugin's parsed components (skills / agents / hooks / MCP / rules). */
22
>
readonly parsed: IParsedPlugin;
23
>
}
24
>
25
>
/**
26
>
* The marketplace id used by Claude for in-place `@skills-dir` plugins,
27
>
* which live under `<scope>/.claude/skills/<name>/` rather than the
28
>
* marketplace cache.
29
>
*/
30
>
const SKILLS_DIR_MARKETPLACE = 'skills-dir';
31
>
32
>
/**
33
>
* The settings files a Claude session reads `enabledPlugins` from, in
34
>
* **ascending precedence** (`user < project < local`, per the SDK: a
35
>
* `false` in `.claude/settings.local.json` disables a plugin that project
36
>
* or user settings enabled). Iterating in this order and letting later
37
>
* scopes overwrite earlier ones yields the effective enabled set. The
38
>
* `managed` scope is intentionally excluded.
39
>
*/
40
function claudeSettingsFilesByPrecedence(workingDirectory: URI | undefined, userHome: URI): URI[] {
41
const files: URI[] = [URI.joinPath(userHome, '.claude', 'settings.json')];