# 第五阶段 · 模块五 · 第二节:插件注册与配置
插件配置存储在哪里?enabledPlugins 的数据结构是什么?插件的作用域如何决定?
Claude Code 全局架构
┌─────────────────────────────────────────────────────────────────────┐
│ 插件系统 │
│ │
│ 插件配置 ──> settings.json ──> 本节 │
│ 插件注册 ──> enabledPlugins ──> 本节 │
└─────────────────────────────────────────────────────────────────────┘
源码位置:`src/utils/settings/settings.ts` 第 309 行
export function getSettingsForSource(
source: SettingSource,
): SettingsJson | null {
// 设置缓存
const cached = getCachedSettingsForSource(source);
if (cached !== undefined) return cached;
const result = getSettingsForSourceUncached(source);
setCachedSettingsForSource(source, result);
return result;
}
type SettingSource =
| 'userSettings' // ~/.claude/settings.json
| 'projectSettings' // .claude/settings.json
| 'policySettings' // 企业策略
| 'flagSettings'; // 命令行标志
// 文件路径
~/.claude/settings.json // 用户级别
<project>/.claude/settings.json // 项目级别
问 1:为什么要区分 user 和 project 设置?
// userSettings:用户个人的配置
// 影响该用户所有项目
// projectSettings:项目级别的配置
// 只影响当前项目,团队共享
// 示例:用户想要所有项目启用某个插件
// → userSettings.enabledPlugins['my-plugin'] = true
// 示例:项目要求所有成员使用某个插件
// → projectSettings.enabledPlugins['my-plugin'] = true
问 2:配置优先级?
// 优先级(高 → 低)
policySettings > projectSettings > userSettings > flagSettings
// 企业管理员可以强制要求某些插件
// 项目可以覆盖用户设置
// 用户可以覆盖默认设置
源码位置:`src/services/plugins/pluginOperations.ts` 第 189 行
// settings.json 中的 enabledPlugins 结构
interface EnabledPlugins {
[pluginId: string]:
| boolean // 简单启用/禁用
| string[]; // 启用特定命令
}
// 示例
{
"enabledPlugins": {
"user/format-tool": true, // 全部启用
"project/lint-plugin": ["lint", "fix"], // 只启用特定命令
"marketplace/quick-actions": false // 禁用
}
}
function getEnabledPlugins(source: SettingSource): Record<string, boolean | string[]> {
const settings = getSettingsForSource(source);
return settings?.enabledPlugins ?? {};
}
// 合并所有来源的插件
function getAllEnabledPlugins(): Record<string, boolean | string[]> {
const user = getEnabledPlugins('userSettings');
const project = getEnabledPlugins('projectSettings');
return { ...user, ...project }; // project 覆盖 user
}
问 1:boolean 和 string[] 有什么区别?
// true:启用插件的所有功能
// string[]:只启用指定的命令
{
"my-plugin": true, // 所有命令可用
"my-plugin": ["cmd1", "cmd2"] // 只有这两个命令可用
}
问 2:false 和 undefined 的区别?
// false:明确禁用
"my-plugin": false
// undefined:未配置,使用默认或继承
// 如果 userSettings 设为 false,但 projectSettings 未配置
// projectSettings 会继承 userSettings 的设置
// 建议:明确设置,不要依赖隐式行为
type PluginScope = 'user' | 'project' | 'marketplace';
// user:用户级别插件
// ~/.claude/plugins/my-plugin
// project:项目级别插件
// <project>/.claude/plugins/my-plugin
// marketplace:市场安装的插件
// 跨项目共享
源码位置:`src/services/plugins/pluginOperations.ts` 第 130 行
function isPluginEnabledForScope(
pluginId: string,
scope: PluginScope,
): boolean {
const settings = getSettingsForSource(
scope === 'project' ? 'projectSettings' : 'userSettings'
);
return settings?.enabledPlugins?.[pluginId] === true;
}
问 1:用户插件可以被项目覆盖吗?
// 可以,但只能禁用,不能启用
// 如果用户在 userSettings 中启用了某个插件
// 项目可以在 projectSettings 中禁用它
// 反过来不行:用户在 userSettings 中禁用
// 项目不能在 projectSettings 中启用
问 2:marketplace 插件的作用域?
// marketplace 插件默认安装为 user 级别
// 可以指定安装为 project 级别
claude plugin install my-plugin --scope project
async function enablePlugin(
pluginId: string,
scope: PluginScope = 'user',
): Promise<void> {
// 1. 获取配置源
const settingsSource = scope === 'project'
? 'projectSettings'
: 'userSettings';
// 2. 读取现有配置
const settings = getSettingsForSource(settingsSource);
// 3. 更新 enabledPlugins
settings.enabledPlugins = {
...settings.enabledPlugins,
[pluginId]: true,
};
// 4. 保存
await saveSettings(settingsSource, settings);
}
// 启用多个插件
async function enablePlugins(
pluginIds: string[],
scope: PluginScope,
): Promise<void> {
const settings = getSettingsForSource(
scope === 'project' ? 'projectSettings' : 'userSettings'
);
for (const pluginId of pluginIds) {
settings.enabledPlugins[pluginId] = true;
}
await saveSettings(scope, settings);
}
问 1:安装时自动启用吗?
// 默认自动启用
// 用户可以手动选择不启用
claude plugin install my-plugin --no-enable
// 这样只会安装,不会加入 enabledPlugins
问 2:如何查看所有启用的插件?
function listEnabledPlugins(): Array<{
pluginId: string;
scope: PluginScope;
commands?: string[];
}> {
const result = [];
// 检查 userSettings
const userPlugins = getEnabledPlugins('userSettings');
for (const [id, value] of Object.entries(userPlugins)) {
result.push({ pluginId: id, scope: 'user', commands: value });
}
// 检查 projectSettings
const projectPlugins = getEnabledPlugins('projectSettings');
for (const [id, value] of Object.entries(projectPlugins)) {
result.push({ pluginId: id, scope: 'project', commands: value });
}
return result;
}
答案:
// 方法 1:清空 enabledPlugins
async function disableAllPlugins(): Promise<void> {
const settings = getSettingsForSource('userSettings');
settings.enabledPlugins = {};
await saveSettings('userSettings', settings);
}
// 方法 2:使用 CLI
claude plugin disable --all
答案:
// 如果 settings.json 损坏
// 1. 自动备份
// ~/.claude/settings.json.backup
// 2. 恢复备份
cp ~/.claude/settings.json.backup ~/.claude/settings.json
// 3. 如果备份也损坏,重置为默认
// Claude Code 会创建新的空配置
答案:
// 导出
const settings = getSettingsForSource('userSettings');
console.log(JSON.stringify(settings.enabledPlugins, null, 2));
// 导入
async function importPlugins(plugins: Record<string, boolean | string[]>) {
const settings = getSettingsForSource('userSettings');
settings.enabledPlugins = { ...settings.enabledPlugins, ...plugins };
await saveSettings('userSettings', settings);
}
| 文件 | 核心内容 |
| `src/utils/settings/settings.ts` | 配置管理 |
| `src/services/plugins/pluginOperations.ts` | 插件操作 |
| `src/types/plugin.ts` | 插件类型定义 |
下一节我们将深入 插件生命周期:
- 插件的加载时机
- 插件的初始化
- 插件的卸载
*- 第一轮:□ 事实准确性*
*- 第二轮:□ 深度与洞见*
*- 第三轮:□ 可读性与价值*