agentinit 1.22.0 → 1.23.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/CHANGELOG.md +26 -1
- package/README.md +41 -0
- package/dist/agents/Agent.d.ts +4 -0
- package/dist/agents/Agent.d.ts.map +1 -1
- package/dist/agents/Agent.js +9 -1
- package/dist/agents/Agent.js.map +1 -1
- package/dist/agents/HermesAgent.d.ts.map +1 -1
- package/dist/agents/HermesAgent.js +1 -0
- package/dist/agents/HermesAgent.js.map +1 -1
- package/dist/cli.js +938 -5
- package/dist/cli.js.map +1 -1
- package/dist/commands/agent.d.ts +3 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +303 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +55 -1
- package/dist/commands/config.js.map +1 -1
- package/dist/core/agentSettings/adapters/claude.d.ts +3 -0
- package/dist/core/agentSettings/adapters/claude.d.ts.map +1 -0
- package/dist/core/agentSettings/adapters/claude.js +147 -0
- package/dist/core/agentSettings/adapters/claude.js.map +1 -0
- package/dist/core/agentSettings/registry.d.ts +6 -0
- package/dist/core/agentSettings/registry.d.ts.map +1 -0
- package/dist/core/agentSettings/registry.js +20 -0
- package/dist/core/agentSettings/registry.js.map +1 -0
- package/dist/core/agentSettings/settingsManager.d.ts +12 -0
- package/dist/core/agentSettings/settingsManager.d.ts.map +1 -0
- package/dist/core/agentSettings/settingsManager.js +399 -0
- package/dist/core/agentSettings/settingsManager.js.map +1 -0
- package/dist/core/agentSettings/types.d.ts +93 -0
- package/dist/core/agentSettings/types.d.ts.map +1 -0
- package/dist/core/agentSettings/types.js +2 -0
- package/dist/core/agentSettings/types.js.map +1 -0
- package/dist/core/agentSettings/valueParser.d.ts +3 -0
- package/dist/core/agentSettings/valueParser.d.ts.map +1 -0
- package/dist/core/agentSettings/valueParser.js +60 -0
- package/dist/core/agentSettings/valueParser.js.map +1 -0
- package/dist/core/skillsManager.d.ts.map +1 -1
- package/dist/core/skillsManager.js +6 -3
- package/dist/core/skillsManager.js.map +1 -1
- package/dist/core/userConfig.d.ts +5 -0
- package/dist/core/userConfig.d.ts.map +1 -1
- package/dist/core/userConfig.js +33 -0
- package/dist/core/userConfig.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -12636,11 +12636,14 @@ class Agent {
|
|
|
12636
12636
|
getSkillsDir(projectPath, global3) {
|
|
12637
12637
|
if (!this.definition.skillPaths)
|
|
12638
12638
|
return null;
|
|
12639
|
-
if (global3) {
|
|
12639
|
+
if (this.getSkillsScope(global3) === "global") {
|
|
12640
12640
|
return this.definition.skillPaths.global.replace("~", homedir2());
|
|
12641
12641
|
}
|
|
12642
12642
|
return resolve6(projectPath, this.definition.skillPaths.project);
|
|
12643
12643
|
}
|
|
12644
|
+
getSkillsScope(global3) {
|
|
12645
|
+
return global3 || this.definition.skillsConfigScope === "global-only" ? "global" : "project";
|
|
12646
|
+
}
|
|
12644
12647
|
getProjectRulesStandard() {
|
|
12645
12648
|
return this.definition.projectStandards?.rules || null;
|
|
12646
12649
|
}
|
|
@@ -16148,6 +16151,7 @@ class HermesAgent extends Agent {
|
|
|
16148
16151
|
project: ".agents/skills/",
|
|
16149
16152
|
global: "~/.hermes/skills/"
|
|
16150
16153
|
},
|
|
16154
|
+
skillsConfigScope: "global-only",
|
|
16151
16155
|
projectStandards: {
|
|
16152
16156
|
skills: "agents"
|
|
16153
16157
|
}
|
|
@@ -16884,6 +16888,13 @@ function createDefaultUserConfig() {
|
|
|
16884
16888
|
verifiedGithubRepos: []
|
|
16885
16889
|
};
|
|
16886
16890
|
}
|
|
16891
|
+
function normalizeAgentSettingsDefaultScope(scope) {
|
|
16892
|
+
const normalized = scope.trim().toLowerCase();
|
|
16893
|
+
if (!AGENT_SETTINGS_SCOPES.has(normalized)) {
|
|
16894
|
+
throw new Error("Invalid agent settings default scope. Use global, project, or local.");
|
|
16895
|
+
}
|
|
16896
|
+
return normalized;
|
|
16897
|
+
}
|
|
16887
16898
|
function normalizeMarketplaceIdentifier(identifier) {
|
|
16888
16899
|
const normalized = identifier.trim().toLowerCase();
|
|
16889
16900
|
if (!MARKETPLACE_IDENTIFIER_PATTERN.test(normalized)) {
|
|
@@ -16955,8 +16966,17 @@ function sanitizeUserConfig(raw) {
|
|
|
16955
16966
|
defaultMarketplace = undefined;
|
|
16956
16967
|
}
|
|
16957
16968
|
}
|
|
16969
|
+
let defaultAgentSettingsScope;
|
|
16970
|
+
if (typeof parsed.defaultAgentSettingsScope === "string") {
|
|
16971
|
+
try {
|
|
16972
|
+
defaultAgentSettingsScope = normalizeAgentSettingsDefaultScope(parsed.defaultAgentSettingsScope);
|
|
16973
|
+
} catch {
|
|
16974
|
+
defaultAgentSettingsScope = undefined;
|
|
16975
|
+
}
|
|
16976
|
+
}
|
|
16958
16977
|
return {
|
|
16959
16978
|
...defaultMarketplace ? { defaultMarketplace } : {},
|
|
16979
|
+
...defaultAgentSettingsScope ? { defaultAgentSettingsScope } : {},
|
|
16960
16980
|
customMarketplaces,
|
|
16961
16981
|
verifiedGithubRepos
|
|
16962
16982
|
};
|
|
@@ -16989,6 +17009,19 @@ async function writeUserConfig(config) {
|
|
|
16989
17009
|
function getBuiltInVerifiedGithubRepos() {
|
|
16990
17010
|
return [...BUILTIN_VERIFIED_GITHUB_REPOS];
|
|
16991
17011
|
}
|
|
17012
|
+
function getConfiguredAgentSettingsDefaultScopeSync() {
|
|
17013
|
+
return readUserConfigSync().defaultAgentSettingsScope;
|
|
17014
|
+
}
|
|
17015
|
+
function getEffectiveAgentSettingsDefaultScopeSync() {
|
|
17016
|
+
const envScope = process.env.AGENTINIT_AGENT_DEFAULT_SCOPE;
|
|
17017
|
+
if (typeof envScope === "string") {
|
|
17018
|
+
try {
|
|
17019
|
+
return normalizeAgentSettingsDefaultScope(envScope);
|
|
17020
|
+
} catch {
|
|
17021
|
+
}
|
|
17022
|
+
}
|
|
17023
|
+
return getConfiguredAgentSettingsDefaultScopeSync() ?? "global";
|
|
17024
|
+
}
|
|
16992
17025
|
function getEffectiveVerifiedGithubReposSync() {
|
|
16993
17026
|
const repos = new Set(BUILTIN_VERIFIED_GITHUB_REPOS);
|
|
16994
17027
|
for (const repo of readUserConfigSync().verifiedGithubRepos) {
|
|
@@ -17000,7 +17033,7 @@ function isVerifiedGitHubRepoSync(owner, repo) {
|
|
|
17000
17033
|
const normalized = normalizeGitHubRepoRef(`${owner}/${repo}`);
|
|
17001
17034
|
return getEffectiveVerifiedGithubReposSync().includes(normalized);
|
|
17002
17035
|
}
|
|
17003
|
-
var sanitizeCustomMarketplaceConfig, MARKETPLACE_IDENTIFIER_PATTERN, GITHUB_REPO_PATTERN, GIT_REPO_URL_PATTERN, BUILTIN_VERIFIED_GITHUB_REPOS;
|
|
17036
|
+
var sanitizeCustomMarketplaceConfig, MARKETPLACE_IDENTIFIER_PATTERN, GITHUB_REPO_PATTERN, GIT_REPO_URL_PATTERN, BUILTIN_VERIFIED_GITHUB_REPOS, AGENT_SETTINGS_SCOPES;
|
|
17004
17037
|
var init_userConfig = __esm(() => {
|
|
17005
17038
|
init_fs();
|
|
17006
17039
|
sanitizeCustomMarketplaceConfig = function(entry) {
|
|
@@ -17023,6 +17056,7 @@ var init_userConfig = __esm(() => {
|
|
|
17023
17056
|
GITHUB_REPO_PATTERN = /^([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+)$/;
|
|
17024
17057
|
GIT_REPO_URL_PATTERN = /^(https?:\/\/|ssh:\/\/|git@).+/;
|
|
17025
17058
|
BUILTIN_VERIFIED_GITHUB_REPOS = ["openai/codex-plugin-cc"];
|
|
17059
|
+
AGENT_SETTINGS_SCOPES = new Set(["global", "project", "local"]);
|
|
17026
17060
|
});
|
|
17027
17061
|
|
|
17028
17062
|
// dist/core/marketplaceRegistry.js
|
|
@@ -19745,7 +19779,7 @@ class SkillsManager {
|
|
|
19745
19779
|
mode: "copy"
|
|
19746
19780
|
};
|
|
19747
19781
|
}
|
|
19748
|
-
const canonicalPath = this.resolveInstallPath(this.getCanonicalSkillsDir(projectPath, options2.global
|
|
19782
|
+
const canonicalPath = this.resolveInstallPath(this.getCanonicalSkillsDir(projectPath, agent.getSkillsScope(options2.global) === "global"), normalizedSkillName);
|
|
19749
19783
|
if (agentPath === canonicalPath) {
|
|
19750
19784
|
return {
|
|
19751
19785
|
path: canonicalPath,
|
|
@@ -20200,12 +20234,14 @@ class SkillsManager {
|
|
|
20200
20234
|
for (const entry of entries) {
|
|
20201
20235
|
const hashPath = entry.canonicalPath || entry.path;
|
|
20202
20236
|
const contentHash = await hashDirectory(hashPath);
|
|
20237
|
+
const agent = this.agentManager.getAgentById(entry.agent);
|
|
20238
|
+
const scope = agent?.getSkillsScope(options2.global) ?? (options2.global ? "global" : "project");
|
|
20203
20239
|
await lock.recordSkill({
|
|
20204
20240
|
action,
|
|
20205
20241
|
name: entry.skill.name,
|
|
20206
20242
|
projectPath: resolve9(projectPath),
|
|
20207
20243
|
agents: [entry.agent],
|
|
20208
|
-
scope
|
|
20244
|
+
scope,
|
|
20209
20245
|
source: lockSource,
|
|
20210
20246
|
installPath: entry.path,
|
|
20211
20247
|
mode: entry.mode,
|
|
@@ -20235,7 +20271,7 @@ class SkillsManager {
|
|
|
20235
20271
|
if (!agent.supportsSkills())
|
|
20236
20272
|
continue;
|
|
20237
20273
|
const scopes = [];
|
|
20238
|
-
if (!options2.global) {
|
|
20274
|
+
if (!options2.global && agent.getSkillsScope(false) === "project") {
|
|
20239
20275
|
scopes.push({ scope: "project", dir: agent.getSkillsDir(projectPath, false) });
|
|
20240
20276
|
}
|
|
20241
20277
|
scopes.push({ scope: "global", dir: agent.getSkillsDir(projectPath, true) });
|
|
@@ -42088,6 +42124,49 @@ function registerConfigCommand(program2) {
|
|
|
42088
42124
|
await writeUserConfig(sortConfig(configState));
|
|
42089
42125
|
logger.success("Cleared the configured default marketplace.");
|
|
42090
42126
|
});
|
|
42127
|
+
const agentSettings = config.command("agent-settings").description("Manage AgentInit defaults for agent settings commands");
|
|
42128
|
+
agentSettings.command("scope [scope]").description("Get or set the default scope used by `agentinit agent` when no scope flag is provided").action(async (scopeArg) => {
|
|
42129
|
+
logger.titleBox("AgentInit Configuration");
|
|
42130
|
+
try {
|
|
42131
|
+
if (!scopeArg) {
|
|
42132
|
+
const configState2 = await readUserConfig();
|
|
42133
|
+
const configuredScope = configState2.defaultAgentSettingsScope;
|
|
42134
|
+
const effectiveScope = getEffectiveAgentSettingsDefaultScopeSync();
|
|
42135
|
+
logger.info(`Effective default agent settings scope: ${cyan(effectiveScope)}`);
|
|
42136
|
+
if (configuredScope) {
|
|
42137
|
+
logger.info(`Configured in user config: ${cyan(configuredScope)}`);
|
|
42138
|
+
} else {
|
|
42139
|
+
logger.info("No user-configured agent settings scope. Built-in default is global.");
|
|
42140
|
+
}
|
|
42141
|
+
if (process.env.AGENTINIT_AGENT_DEFAULT_SCOPE !== undefined) {
|
|
42142
|
+
try {
|
|
42143
|
+
logger.info(`Environment override: ${cyan(normalizeAgentSettingsDefaultScope(process.env.AGENTINIT_AGENT_DEFAULT_SCOPE))}`);
|
|
42144
|
+
} catch {
|
|
42145
|
+
logger.info(`Invalid environment override ignored: ${cyan(process.env.AGENTINIT_AGENT_DEFAULT_SCOPE)}`);
|
|
42146
|
+
}
|
|
42147
|
+
}
|
|
42148
|
+
return;
|
|
42149
|
+
}
|
|
42150
|
+
const scope = normalizeAgentSettingsDefaultScope(scopeArg);
|
|
42151
|
+
const configState = await readUserConfig();
|
|
42152
|
+
configState.defaultAgentSettingsScope = scope;
|
|
42153
|
+
await writeUserConfig(sortConfig(configState));
|
|
42154
|
+
logger.success(`Set default agent settings scope to ${green(scope)}.`);
|
|
42155
|
+
} catch (error) {
|
|
42156
|
+
failConfigCommand(error);
|
|
42157
|
+
}
|
|
42158
|
+
});
|
|
42159
|
+
agentSettings.command("clear-scope").description("Clear the user-configured default scope used by `agentinit agent`").action(async () => {
|
|
42160
|
+
logger.titleBox("AgentInit Configuration");
|
|
42161
|
+
const configState = await readUserConfig();
|
|
42162
|
+
if (!configState.defaultAgentSettingsScope) {
|
|
42163
|
+
logger.info("No user-configured agent settings scope to clear.");
|
|
42164
|
+
return;
|
|
42165
|
+
}
|
|
42166
|
+
delete configState.defaultAgentSettingsScope;
|
|
42167
|
+
await writeUserConfig(sortConfig(configState));
|
|
42168
|
+
logger.success("Cleared the user-configured default agent settings scope.");
|
|
42169
|
+
});
|
|
42091
42170
|
const verifiedRepos = config.command("verified-repos").description("Manage exact verified GitHub repositories");
|
|
42092
42171
|
verifiedRepos.command("list").description("List verified GitHub repositories").action(async () => {
|
|
42093
42172
|
logger.titleBox("AgentInit Configuration");
|
|
@@ -45131,6 +45210,859 @@ Dry run \u2014 no changes made.`));
|
|
|
45131
45210
|
});
|
|
45132
45211
|
}
|
|
45133
45212
|
|
|
45213
|
+
// dist/core/agentSettings/settingsManager.js
|
|
45214
|
+
init_fs();
|
|
45215
|
+
init_userConfig();
|
|
45216
|
+
|
|
45217
|
+
// dist/core/agentSettings/valueParser.js
|
|
45218
|
+
var parseJsonValue = function(raw, key) {
|
|
45219
|
+
try {
|
|
45220
|
+
return JSON.parse(raw);
|
|
45221
|
+
} catch (error) {
|
|
45222
|
+
throw new Error(`Value for "${key}" is not valid JSON.`);
|
|
45223
|
+
}
|
|
45224
|
+
};
|
|
45225
|
+
function parseAgentSettingValue(definition, raw, parseJson = false) {
|
|
45226
|
+
switch (definition.valueType) {
|
|
45227
|
+
case "string":
|
|
45228
|
+
return raw;
|
|
45229
|
+
case "boolean": {
|
|
45230
|
+
const normalized = raw.trim().toLowerCase();
|
|
45231
|
+
if (TRUE_VALUES.has(normalized)) {
|
|
45232
|
+
return true;
|
|
45233
|
+
}
|
|
45234
|
+
if (FALSE_VALUES.has(normalized)) {
|
|
45235
|
+
return false;
|
|
45236
|
+
}
|
|
45237
|
+
throw new Error(`Value for "${definition.key}" must be one of: on, off, true, false, yes, no, 1, 0.`);
|
|
45238
|
+
}
|
|
45239
|
+
case "number": {
|
|
45240
|
+
const value = Number(raw);
|
|
45241
|
+
if (!Number.isFinite(value)) {
|
|
45242
|
+
throw new Error(`Value for "${definition.key}" must be a finite number.`);
|
|
45243
|
+
}
|
|
45244
|
+
return value;
|
|
45245
|
+
}
|
|
45246
|
+
case "enum": {
|
|
45247
|
+
if (!definition.allowedValues?.includes(raw)) {
|
|
45248
|
+
throw new Error(`Value for "${definition.key}" must be one of: ${definition.allowedValues?.join(", ")}.`);
|
|
45249
|
+
}
|
|
45250
|
+
return raw;
|
|
45251
|
+
}
|
|
45252
|
+
case "array": {
|
|
45253
|
+
if (parseJson) {
|
|
45254
|
+
const value = parseJsonValue(raw, definition.key);
|
|
45255
|
+
if (!Array.isArray(value)) {
|
|
45256
|
+
throw new Error(`JSON value for "${definition.key}" must be an array.`);
|
|
45257
|
+
}
|
|
45258
|
+
return value;
|
|
45259
|
+
}
|
|
45260
|
+
return [raw];
|
|
45261
|
+
}
|
|
45262
|
+
case "object": {
|
|
45263
|
+
if (!parseJson) {
|
|
45264
|
+
throw new Error(`Value for "${definition.key}" must be valid JSON. Use --value-json when setting it from the CLI.`);
|
|
45265
|
+
}
|
|
45266
|
+
const value = parseJsonValue(raw, definition.key);
|
|
45267
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
45268
|
+
throw new Error(`JSON value for "${definition.key}" must be an object.`);
|
|
45269
|
+
}
|
|
45270
|
+
return value;
|
|
45271
|
+
}
|
|
45272
|
+
}
|
|
45273
|
+
}
|
|
45274
|
+
var TRUE_VALUES = new Set(["true", "on", "yes", "1"]);
|
|
45275
|
+
var FALSE_VALUES = new Set(["false", "off", "no", "0"]);
|
|
45276
|
+
|
|
45277
|
+
// dist/core/agentSettings/adapters/claude.js
|
|
45278
|
+
init_paths();
|
|
45279
|
+
import {join as join12} from "path";
|
|
45280
|
+
var setting = function(key, valueType, title, description, options2 = {}) {
|
|
45281
|
+
const definition = {
|
|
45282
|
+
agent: "claude",
|
|
45283
|
+
key,
|
|
45284
|
+
nativePath: key.split("."),
|
|
45285
|
+
title,
|
|
45286
|
+
description,
|
|
45287
|
+
valueType,
|
|
45288
|
+
scopes: options2.scopes ?? ALL_SCOPES,
|
|
45289
|
+
defaultScope: options2.defaultScope ?? "global",
|
|
45290
|
+
category: options2.category ?? "settings",
|
|
45291
|
+
risk: options2.risk ?? "safe"
|
|
45292
|
+
};
|
|
45293
|
+
if (options2.allowedValues) {
|
|
45294
|
+
definition.allowedValues = options2.allowedValues;
|
|
45295
|
+
}
|
|
45296
|
+
if (options2.deprecated !== undefined) {
|
|
45297
|
+
definition.deprecated = options2.deprecated;
|
|
45298
|
+
}
|
|
45299
|
+
if (options2.replacement) {
|
|
45300
|
+
definition.replacement = options2.replacement;
|
|
45301
|
+
}
|
|
45302
|
+
return definition;
|
|
45303
|
+
};
|
|
45304
|
+
var ALL_SCOPES = ["global", "project", "local"];
|
|
45305
|
+
var PERSONAL_SCOPES = ["global", "local"];
|
|
45306
|
+
var claudeSettingsAdapter = {
|
|
45307
|
+
agent: "claude",
|
|
45308
|
+
displayName: "Claude Code",
|
|
45309
|
+
definitions: [
|
|
45310
|
+
setting("model", "string", "Model", "Override the default Claude Code model.", {
|
|
45311
|
+
defaultScope: "global",
|
|
45312
|
+
category: "model"
|
|
45313
|
+
}),
|
|
45314
|
+
setting("agent", "string", "Agent", "Run the main thread as a named Claude subagent.", {
|
|
45315
|
+
category: "model"
|
|
45316
|
+
}),
|
|
45317
|
+
setting("env", "object", "Environment", "Environment variables applied to every Claude Code session.", {
|
|
45318
|
+
category: "runtime"
|
|
45319
|
+
}),
|
|
45320
|
+
setting("permissions.allow", "array", "Allowed permissions", "Permission rules to allow.", {
|
|
45321
|
+
category: "permissions"
|
|
45322
|
+
}),
|
|
45323
|
+
setting("permissions.deny", "array", "Denied permissions", "Permission rules to deny.", {
|
|
45324
|
+
category: "permissions"
|
|
45325
|
+
}),
|
|
45326
|
+
setting("permissions.ask", "array", "Ask permissions", "Permission rules that require confirmation.", {
|
|
45327
|
+
category: "permissions"
|
|
45328
|
+
}),
|
|
45329
|
+
setting("permissions.defaultMode", "enum", "Default permission mode", "Default permission mode when opening Claude Code.", {
|
|
45330
|
+
allowedValues: ["default", "acceptEdits", "plan"],
|
|
45331
|
+
category: "permissions",
|
|
45332
|
+
risk: "security-sensitive"
|
|
45333
|
+
}),
|
|
45334
|
+
setting("permissions.additionalDirectories", "array", "Additional directories", "Additional working directories for file access.", {
|
|
45335
|
+
category: "permissions"
|
|
45336
|
+
}),
|
|
45337
|
+
setting("worktree.symlinkDirectories", "array", "Worktree symlink directories", "Directories to symlink into Claude Code worktrees.", {
|
|
45338
|
+
category: "worktree"
|
|
45339
|
+
}),
|
|
45340
|
+
setting("worktree.sparsePaths", "array", "Worktree sparse paths", "Paths to check out via sparse checkout in Claude Code worktrees.", {
|
|
45341
|
+
category: "worktree"
|
|
45342
|
+
}),
|
|
45343
|
+
setting("plansDirectory", "string", "Plans directory", "Directory where Claude Code stores plan files.", {
|
|
45344
|
+
category: "runtime"
|
|
45345
|
+
}),
|
|
45346
|
+
setting("autoMemoryDirectory", "string", "Auto memory directory", "Custom directory for Claude Code auto memory storage.", {
|
|
45347
|
+
scopes: PERSONAL_SCOPES,
|
|
45348
|
+
defaultScope: "global",
|
|
45349
|
+
category: "memory"
|
|
45350
|
+
}),
|
|
45351
|
+
setting("alwaysThinkingEnabled", "boolean", "Always thinking", "Enable extended thinking by default for Claude Code sessions.", {
|
|
45352
|
+
defaultScope: "global",
|
|
45353
|
+
category: "model"
|
|
45354
|
+
}),
|
|
45355
|
+
setting("effortLevel", "enum", "Effort level", "Persist Claude Code effort level across sessions.", {
|
|
45356
|
+
allowedValues: ["low", "medium", "high", "xhigh"],
|
|
45357
|
+
defaultScope: "global",
|
|
45358
|
+
category: "model"
|
|
45359
|
+
}),
|
|
45360
|
+
setting("prefersReducedMotion", "boolean", "Reduced motion", "Reduce or disable Claude Code UI animations.", {
|
|
45361
|
+
defaultScope: "global",
|
|
45362
|
+
category: "ui"
|
|
45363
|
+
}),
|
|
45364
|
+
setting("attribution", "object", "Attribution", "Customize Claude Code git commit and pull request attribution.", {
|
|
45365
|
+
defaultScope: "global",
|
|
45366
|
+
category: "git"
|
|
45367
|
+
}),
|
|
45368
|
+
setting("includeGitInstructions", "boolean", "Git instructions", "Include built-in git workflow instructions in Claude Code context.", {
|
|
45369
|
+
defaultScope: "global",
|
|
45370
|
+
category: "git"
|
|
45371
|
+
}),
|
|
45372
|
+
setting("cleanupPeriodDays", "number", "Cleanup period", "Delete session files older than this many days at startup.", {
|
|
45373
|
+
defaultScope: "global",
|
|
45374
|
+
category: "runtime"
|
|
45375
|
+
}),
|
|
45376
|
+
setting("showThinkingSummaries", "boolean", "Thinking summaries", "Show extended thinking summaries in interactive sessions.", {
|
|
45377
|
+
defaultScope: "global",
|
|
45378
|
+
category: "ui"
|
|
45379
|
+
}),
|
|
45380
|
+
setting("spinnerTipsEnabled", "boolean", "Spinner tips", "Show or hide tips while Claude Code is working.", {
|
|
45381
|
+
defaultScope: "global",
|
|
45382
|
+
category: "ui"
|
|
45383
|
+
}),
|
|
45384
|
+
setting("autoUpdatesChannel", "enum", "Auto updates channel", "Claude Code release channel for automatic updates.", {
|
|
45385
|
+
allowedValues: ["stable", "latest"],
|
|
45386
|
+
defaultScope: "global",
|
|
45387
|
+
category: "runtime"
|
|
45388
|
+
}),
|
|
45389
|
+
setting("includeCoAuthoredBy", "boolean", "Include co-authored-by", "Deprecated Claude Code attribution toggle.", {
|
|
45390
|
+
defaultScope: "global",
|
|
45391
|
+
category: "git",
|
|
45392
|
+
risk: "deprecated",
|
|
45393
|
+
deprecated: true,
|
|
45394
|
+
replacement: "attribution"
|
|
45395
|
+
}),
|
|
45396
|
+
setting("enableAllProjectMcpServers", "boolean", "Enable all project MCP servers", "Automatically approve project .mcp.json servers.", {
|
|
45397
|
+
category: "mcp",
|
|
45398
|
+
risk: "security-sensitive"
|
|
45399
|
+
}),
|
|
45400
|
+
setting("enabledMcpjsonServers", "array", "Enabled MCP JSON servers", "Specific project .mcp.json servers to approve.", {
|
|
45401
|
+
category: "mcp"
|
|
45402
|
+
}),
|
|
45403
|
+
setting("disabledMcpjsonServers", "array", "Disabled MCP JSON servers", "Specific project .mcp.json servers to reject.", {
|
|
45404
|
+
category: "mcp"
|
|
45405
|
+
}),
|
|
45406
|
+
setting("skipDangerousModePermissionPrompt", "boolean", "Skip dangerous mode prompt", "Skip confirmation before bypass permissions mode.", {
|
|
45407
|
+
scopes: PERSONAL_SCOPES,
|
|
45408
|
+
defaultScope: "global",
|
|
45409
|
+
category: "permissions",
|
|
45410
|
+
risk: "security-sensitive"
|
|
45411
|
+
})
|
|
45412
|
+
],
|
|
45413
|
+
getSettingsPath(scope, projectPath) {
|
|
45414
|
+
switch (scope) {
|
|
45415
|
+
case "global":
|
|
45416
|
+
return expandTilde("~/.claude/settings.json");
|
|
45417
|
+
case "project":
|
|
45418
|
+
return join12(projectPath, ".claude", "settings.json");
|
|
45419
|
+
case "local":
|
|
45420
|
+
return join12(projectPath, ".claude", "settings.local.json");
|
|
45421
|
+
}
|
|
45422
|
+
}
|
|
45423
|
+
};
|
|
45424
|
+
|
|
45425
|
+
// dist/core/agentSettings/registry.js
|
|
45426
|
+
function getAgentSettingsAdapters() {
|
|
45427
|
+
return [...ADAPTERS];
|
|
45428
|
+
}
|
|
45429
|
+
function getAgentSettingsAdapter(agent) {
|
|
45430
|
+
return ADAPTERS.find((adapter) => adapter.agent === agent);
|
|
45431
|
+
}
|
|
45432
|
+
function getAgentSettingDefinition(agent, key) {
|
|
45433
|
+
return getAgentSettingsAdapter(agent)?.definitions.find((definition) => definition.key === key);
|
|
45434
|
+
}
|
|
45435
|
+
function toSchemaEntry(definition) {
|
|
45436
|
+
return {
|
|
45437
|
+
...definition,
|
|
45438
|
+
nativePath: definition.nativePath.join(".")
|
|
45439
|
+
};
|
|
45440
|
+
}
|
|
45441
|
+
var ADAPTERS = [
|
|
45442
|
+
claudeSettingsAdapter
|
|
45443
|
+
];
|
|
45444
|
+
|
|
45445
|
+
// dist/core/agentSettings/settingsManager.js
|
|
45446
|
+
var assertObject = function(value, path) {
|
|
45447
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
45448
|
+
throw new Error(`${path} contains JSON that is not an object.`);
|
|
45449
|
+
}
|
|
45450
|
+
return value;
|
|
45451
|
+
};
|
|
45452
|
+
var getNestedValue = function(config, path) {
|
|
45453
|
+
let current = config;
|
|
45454
|
+
for (const segment of path) {
|
|
45455
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) {
|
|
45456
|
+
return;
|
|
45457
|
+
}
|
|
45458
|
+
current = current[segment];
|
|
45459
|
+
}
|
|
45460
|
+
return current;
|
|
45461
|
+
};
|
|
45462
|
+
var setNestedValue = function(config, path, value) {
|
|
45463
|
+
let current = config;
|
|
45464
|
+
for (const segment of path.slice(0, -1)) {
|
|
45465
|
+
const next = current[segment];
|
|
45466
|
+
if (!next || typeof next !== "object" || Array.isArray(next)) {
|
|
45467
|
+
current[segment] = {};
|
|
45468
|
+
}
|
|
45469
|
+
current = current[segment];
|
|
45470
|
+
}
|
|
45471
|
+
current[path[path.length - 1]] = value;
|
|
45472
|
+
};
|
|
45473
|
+
var normalizeHookEvent = function(event) {
|
|
45474
|
+
const exact = event;
|
|
45475
|
+
if (HOOK_EVENTS.has(exact)) {
|
|
45476
|
+
return exact;
|
|
45477
|
+
}
|
|
45478
|
+
const normalized = event.trim().replace(/_/g, "-").toLowerCase();
|
|
45479
|
+
const mapped = HOOK_EVENT_ALIASES[normalized];
|
|
45480
|
+
if (mapped) {
|
|
45481
|
+
return mapped;
|
|
45482
|
+
}
|
|
45483
|
+
throw new Error(`Unsupported hook event: ${event}. Supported: ${[...HOOK_EVENTS].join(", ")}.`);
|
|
45484
|
+
};
|
|
45485
|
+
var assertHookMatchers = function(value) {
|
|
45486
|
+
if (value === undefined) {
|
|
45487
|
+
return [];
|
|
45488
|
+
}
|
|
45489
|
+
if (!Array.isArray(value)) {
|
|
45490
|
+
throw new Error("Existing hooks value is not an array.");
|
|
45491
|
+
}
|
|
45492
|
+
return value.map((entry) => {
|
|
45493
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
45494
|
+
throw new Error("Existing hook matcher is not an object.");
|
|
45495
|
+
}
|
|
45496
|
+
const entryObject = entry;
|
|
45497
|
+
const matcher = entryObject.matcher;
|
|
45498
|
+
const hooks = entryObject.hooks;
|
|
45499
|
+
if (matcher !== undefined && typeof matcher !== "string") {
|
|
45500
|
+
throw new Error("Existing hook matcher must be a string.");
|
|
45501
|
+
}
|
|
45502
|
+
if (!Array.isArray(hooks)) {
|
|
45503
|
+
throw new Error("Existing hook commands must be an array.");
|
|
45504
|
+
}
|
|
45505
|
+
return {
|
|
45506
|
+
...entryObject,
|
|
45507
|
+
...matcher !== undefined ? { matcher } : {},
|
|
45508
|
+
hooks: hooks.map((hook) => {
|
|
45509
|
+
if (!hook || typeof hook !== "object" || Array.isArray(hook)) {
|
|
45510
|
+
throw new Error("Existing hook command is not an object.");
|
|
45511
|
+
}
|
|
45512
|
+
const hookObject = hook;
|
|
45513
|
+
const type2 = hookObject.type;
|
|
45514
|
+
const command = hookObject.command;
|
|
45515
|
+
const name = hookObject.name;
|
|
45516
|
+
if (type2 !== undefined && typeof type2 !== "string") {
|
|
45517
|
+
throw new Error("Existing hook command type must be a string when present.");
|
|
45518
|
+
}
|
|
45519
|
+
if (command !== undefined && typeof command !== "string") {
|
|
45520
|
+
throw new Error("Existing hook command must be a string when present.");
|
|
45521
|
+
}
|
|
45522
|
+
if (name !== undefined && typeof name !== "string") {
|
|
45523
|
+
throw new Error("Existing hook name must be a string when present.");
|
|
45524
|
+
}
|
|
45525
|
+
return {
|
|
45526
|
+
...hookObject,
|
|
45527
|
+
...typeof type2 === "string" ? { type: type2 } : {},
|
|
45528
|
+
...typeof command === "string" ? { command } : {},
|
|
45529
|
+
...typeof name === "string" ? { name } : {}
|
|
45530
|
+
};
|
|
45531
|
+
})
|
|
45532
|
+
};
|
|
45533
|
+
});
|
|
45534
|
+
};
|
|
45535
|
+
var getHookMatchers = function(config, event) {
|
|
45536
|
+
const hooks = getNestedValue(config, ["hooks"]);
|
|
45537
|
+
if (hooks === undefined) {
|
|
45538
|
+
return [];
|
|
45539
|
+
}
|
|
45540
|
+
if (!hooks || typeof hooks !== "object" || Array.isArray(hooks)) {
|
|
45541
|
+
throw new Error("Existing hooks value is not an object.");
|
|
45542
|
+
}
|
|
45543
|
+
return assertHookMatchers(hooks[event]);
|
|
45544
|
+
};
|
|
45545
|
+
var setHookMatchers = function(config, event, matchers) {
|
|
45546
|
+
const hooks = getNestedValue(config, ["hooks"]);
|
|
45547
|
+
if (hooks !== undefined && (!hooks || typeof hooks !== "object" || Array.isArray(hooks))) {
|
|
45548
|
+
throw new Error("Existing hooks value is not an object.");
|
|
45549
|
+
}
|
|
45550
|
+
const hooksObject = hooks;
|
|
45551
|
+
const nextHooks = hooksObject ?? {};
|
|
45552
|
+
if (matchers.length === 0) {
|
|
45553
|
+
delete nextHooks[event];
|
|
45554
|
+
} else {
|
|
45555
|
+
nextHooks[event] = matchers;
|
|
45556
|
+
}
|
|
45557
|
+
if (Object.keys(nextHooks).length === 0) {
|
|
45558
|
+
deleteNestedValue(config, ["hooks"]);
|
|
45559
|
+
return;
|
|
45560
|
+
}
|
|
45561
|
+
setNestedValue(config, ["hooks"], nextHooks);
|
|
45562
|
+
};
|
|
45563
|
+
var buildHookCommand = function(command, name) {
|
|
45564
|
+
const trimmed = command.trim();
|
|
45565
|
+
if (!trimmed) {
|
|
45566
|
+
throw new Error("Hook command cannot be empty.");
|
|
45567
|
+
}
|
|
45568
|
+
return {
|
|
45569
|
+
type: "command",
|
|
45570
|
+
command: trimmed,
|
|
45571
|
+
...name ? { name } : {}
|
|
45572
|
+
};
|
|
45573
|
+
};
|
|
45574
|
+
var deleteNestedValue = function(config, path) {
|
|
45575
|
+
const parents = [];
|
|
45576
|
+
let current = config;
|
|
45577
|
+
for (const segment of path.slice(0, -1)) {
|
|
45578
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) {
|
|
45579
|
+
return false;
|
|
45580
|
+
}
|
|
45581
|
+
parents.push({ object: current, key: segment });
|
|
45582
|
+
current = current[segment];
|
|
45583
|
+
}
|
|
45584
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) {
|
|
45585
|
+
return false;
|
|
45586
|
+
}
|
|
45587
|
+
const finalKey = path[path.length - 1];
|
|
45588
|
+
if (!(finalKey in current)) {
|
|
45589
|
+
return false;
|
|
45590
|
+
}
|
|
45591
|
+
delete current[finalKey];
|
|
45592
|
+
for (let i = parents.length - 1;i >= 0; i--) {
|
|
45593
|
+
const { object, key } = parents[i];
|
|
45594
|
+
const value = object[key];
|
|
45595
|
+
if (value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0) {
|
|
45596
|
+
delete object[key];
|
|
45597
|
+
} else {
|
|
45598
|
+
break;
|
|
45599
|
+
}
|
|
45600
|
+
}
|
|
45601
|
+
return true;
|
|
45602
|
+
};
|
|
45603
|
+
var resolveProjectPath = function(projectPath) {
|
|
45604
|
+
return projectPath ?? process.cwd();
|
|
45605
|
+
};
|
|
45606
|
+
var resolveScope = function(definition, scope) {
|
|
45607
|
+
const resolvedScope = scope ?? getEffectiveAgentSettingsDefaultScopeSync();
|
|
45608
|
+
if (!definition.scopes.includes(resolvedScope)) {
|
|
45609
|
+
throw new Error(`"${definition.key}" does not support ${resolvedScope} scope. Supported scopes: ${definition.scopes.join(", ")}.`);
|
|
45610
|
+
}
|
|
45611
|
+
return resolvedScope;
|
|
45612
|
+
};
|
|
45613
|
+
async function readJsonObject(path) {
|
|
45614
|
+
const content = await readFileIfExists(path);
|
|
45615
|
+
if (!content) {
|
|
45616
|
+
return {};
|
|
45617
|
+
}
|
|
45618
|
+
try {
|
|
45619
|
+
return assertObject(JSON.parse(content), path);
|
|
45620
|
+
} catch (error) {
|
|
45621
|
+
if (error instanceof SyntaxError) {
|
|
45622
|
+
throw new Error(`${path} contains invalid JSON.`);
|
|
45623
|
+
}
|
|
45624
|
+
throw error;
|
|
45625
|
+
}
|
|
45626
|
+
}
|
|
45627
|
+
var HOOK_EVENT_ALIASES = {
|
|
45628
|
+
"pre-tool-use": "PreToolUse",
|
|
45629
|
+
"before-tool-use": "PreToolUse",
|
|
45630
|
+
"post-tool-use": "PostToolUse",
|
|
45631
|
+
"after-tool-use": "PostToolUse",
|
|
45632
|
+
"post-tool-use-failure": "PostToolUseFailure",
|
|
45633
|
+
notification: "Notification",
|
|
45634
|
+
"permission-request": "PermissionRequest",
|
|
45635
|
+
stop: "Stop",
|
|
45636
|
+
"session-start": "SessionStart",
|
|
45637
|
+
"session-end": "SessionEnd"
|
|
45638
|
+
};
|
|
45639
|
+
var HOOK_EVENTS = new Set(Object.values(HOOK_EVENT_ALIASES));
|
|
45640
|
+
|
|
45641
|
+
class AgentSettingsManager {
|
|
45642
|
+
getSupportedAgents() {
|
|
45643
|
+
return getAgentSettingsAdapters().map((adapter) => adapter.agent);
|
|
45644
|
+
}
|
|
45645
|
+
getSchema(agent) {
|
|
45646
|
+
const adapter = getAgentSettingsAdapter(agent);
|
|
45647
|
+
if (!adapter) {
|
|
45648
|
+
throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(", ")}`);
|
|
45649
|
+
}
|
|
45650
|
+
return {
|
|
45651
|
+
agent: adapter.agent,
|
|
45652
|
+
displayName: adapter.displayName,
|
|
45653
|
+
effectiveDefaultScope: getEffectiveAgentSettingsDefaultScopeSync(),
|
|
45654
|
+
settings: adapter.definitions.map(toSchemaEntry)
|
|
45655
|
+
};
|
|
45656
|
+
}
|
|
45657
|
+
async get(agent, key, options2 = {}) {
|
|
45658
|
+
const adapter = getAgentSettingsAdapter(agent);
|
|
45659
|
+
if (!adapter) {
|
|
45660
|
+
throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(", ")}`);
|
|
45661
|
+
}
|
|
45662
|
+
if (!key) {
|
|
45663
|
+
const scope2 = options2.scope ?? getEffectiveAgentSettingsDefaultScopeSync();
|
|
45664
|
+
const path2 = adapter.getSettingsPath(scope2, resolveProjectPath(options2.projectPath));
|
|
45665
|
+
return await readJsonObject(path2);
|
|
45666
|
+
}
|
|
45667
|
+
const definition = getAgentSettingDefinition(agent, key);
|
|
45668
|
+
if (!definition) {
|
|
45669
|
+
throw new Error(`Unknown ${agent} setting: ${key}.`);
|
|
45670
|
+
}
|
|
45671
|
+
const scope = resolveScope(definition, options2.scope);
|
|
45672
|
+
const path = adapter.getSettingsPath(scope, resolveProjectPath(options2.projectPath));
|
|
45673
|
+
const config = await readJsonObject(path);
|
|
45674
|
+
return getNestedValue(config, definition.nativePath);
|
|
45675
|
+
}
|
|
45676
|
+
async set(agent, key, rawValue, options2 = {}) {
|
|
45677
|
+
const adapter = getAgentSettingsAdapter(agent);
|
|
45678
|
+
if (!adapter) {
|
|
45679
|
+
throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(", ")}`);
|
|
45680
|
+
}
|
|
45681
|
+
const definition = getAgentSettingDefinition(agent, key);
|
|
45682
|
+
if (!definition) {
|
|
45683
|
+
throw new Error(`Unknown ${agent} setting: ${key}.`);
|
|
45684
|
+
}
|
|
45685
|
+
const scope = resolveScope(definition, options2.scope);
|
|
45686
|
+
const path = adapter.getSettingsPath(scope, resolveProjectPath(options2.projectPath));
|
|
45687
|
+
const config = await readJsonObject(path);
|
|
45688
|
+
const previousValue = getNestedValue(config, definition.nativePath);
|
|
45689
|
+
const value = parseAgentSettingValue(definition, rawValue, options2.parseJson);
|
|
45690
|
+
setNestedValue(config, definition.nativePath, value);
|
|
45691
|
+
if (!options2.dryRun) {
|
|
45692
|
+
await writeFile(path, `${JSON.stringify(config, null, 2)}\n`);
|
|
45693
|
+
}
|
|
45694
|
+
return {
|
|
45695
|
+
agent,
|
|
45696
|
+
key,
|
|
45697
|
+
scope,
|
|
45698
|
+
path,
|
|
45699
|
+
value,
|
|
45700
|
+
previousValue,
|
|
45701
|
+
dryRun: Boolean(options2.dryRun)
|
|
45702
|
+
};
|
|
45703
|
+
}
|
|
45704
|
+
async unset(agent, key, options2 = {}) {
|
|
45705
|
+
const adapter = getAgentSettingsAdapter(agent);
|
|
45706
|
+
if (!adapter) {
|
|
45707
|
+
throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(", ")}`);
|
|
45708
|
+
}
|
|
45709
|
+
const definition = getAgentSettingDefinition(agent, key);
|
|
45710
|
+
if (!definition) {
|
|
45711
|
+
throw new Error(`Unknown ${agent} setting: ${key}.`);
|
|
45712
|
+
}
|
|
45713
|
+
const scope = resolveScope(definition, options2.scope);
|
|
45714
|
+
const path = adapter.getSettingsPath(scope, resolveProjectPath(options2.projectPath));
|
|
45715
|
+
const config = await readJsonObject(path);
|
|
45716
|
+
const previousValue = getNestedValue(config, definition.nativePath);
|
|
45717
|
+
deleteNestedValue(config, definition.nativePath);
|
|
45718
|
+
if (!options2.dryRun) {
|
|
45719
|
+
await writeFile(path, `${JSON.stringify(config, null, 2)}\n`);
|
|
45720
|
+
}
|
|
45721
|
+
return {
|
|
45722
|
+
agent,
|
|
45723
|
+
key,
|
|
45724
|
+
scope,
|
|
45725
|
+
path,
|
|
45726
|
+
previousValue,
|
|
45727
|
+
dryRun: Boolean(options2.dryRun)
|
|
45728
|
+
};
|
|
45729
|
+
}
|
|
45730
|
+
async listHooks(agent, event, options2 = {}) {
|
|
45731
|
+
const adapter = getAgentSettingsAdapter(agent);
|
|
45732
|
+
if (!adapter) {
|
|
45733
|
+
throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(", ")}`);
|
|
45734
|
+
}
|
|
45735
|
+
if (agent !== "claude") {
|
|
45736
|
+
throw new Error(`Agent ${agent} does not support hook management.`);
|
|
45737
|
+
}
|
|
45738
|
+
const scope = options2.scope ?? getEffectiveAgentSettingsDefaultScopeSync();
|
|
45739
|
+
const path = adapter.getSettingsPath(scope, resolveProjectPath(options2.projectPath));
|
|
45740
|
+
const config = await readJsonObject(path);
|
|
45741
|
+
if (event) {
|
|
45742
|
+
return getHookMatchers(config, normalizeHookEvent(event));
|
|
45743
|
+
}
|
|
45744
|
+
const hooks = getNestedValue(config, ["hooks"]);
|
|
45745
|
+
if (hooks === undefined) {
|
|
45746
|
+
return {};
|
|
45747
|
+
}
|
|
45748
|
+
if (!hooks || typeof hooks !== "object" || Array.isArray(hooks)) {
|
|
45749
|
+
throw new Error("Existing hooks value is not an object.");
|
|
45750
|
+
}
|
|
45751
|
+
const result = {};
|
|
45752
|
+
for (const [hookEvent, value] of Object.entries(hooks)) {
|
|
45753
|
+
result[hookEvent] = assertHookMatchers(value);
|
|
45754
|
+
}
|
|
45755
|
+
return result;
|
|
45756
|
+
}
|
|
45757
|
+
async addHook(agent, event, command, options2 = {}) {
|
|
45758
|
+
const adapter = getAgentSettingsAdapter(agent);
|
|
45759
|
+
if (!adapter) {
|
|
45760
|
+
throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(", ")}`);
|
|
45761
|
+
}
|
|
45762
|
+
if (agent !== "claude") {
|
|
45763
|
+
throw new Error(`Agent ${agent} does not support hook management.`);
|
|
45764
|
+
}
|
|
45765
|
+
const hookEvent = normalizeHookEvent(event);
|
|
45766
|
+
const scope = options2.scope ?? getEffectiveAgentSettingsDefaultScopeSync();
|
|
45767
|
+
const path = adapter.getSettingsPath(scope, resolveProjectPath(options2.projectPath));
|
|
45768
|
+
const config = await readJsonObject(path);
|
|
45769
|
+
const hook = buildHookCommand(command, options2.name);
|
|
45770
|
+
const matchers = getHookMatchers(config, hookEvent);
|
|
45771
|
+
const matcher = options2.matcher ?? "*";
|
|
45772
|
+
const existingMatcher = matchers.find((entry) => (entry.matcher ?? "*") === matcher);
|
|
45773
|
+
if (existingMatcher) {
|
|
45774
|
+
existingMatcher.hooks.push(hook);
|
|
45775
|
+
} else {
|
|
45776
|
+
matchers.push({
|
|
45777
|
+
...matcher === "*" ? {} : { matcher },
|
|
45778
|
+
hooks: [hook]
|
|
45779
|
+
});
|
|
45780
|
+
}
|
|
45781
|
+
setHookMatchers(config, hookEvent, matchers);
|
|
45782
|
+
if (!options2.dryRun) {
|
|
45783
|
+
await writeFile(path, `${JSON.stringify(config, null, 2)}\n`);
|
|
45784
|
+
}
|
|
45785
|
+
return {
|
|
45786
|
+
agent,
|
|
45787
|
+
event: hookEvent,
|
|
45788
|
+
scope,
|
|
45789
|
+
path,
|
|
45790
|
+
hook,
|
|
45791
|
+
dryRun: Boolean(options2.dryRun)
|
|
45792
|
+
};
|
|
45793
|
+
}
|
|
45794
|
+
async removeHook(agent, event, commandOrName, options2 = {}) {
|
|
45795
|
+
const adapter = getAgentSettingsAdapter(agent);
|
|
45796
|
+
if (!adapter) {
|
|
45797
|
+
throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(", ")}`);
|
|
45798
|
+
}
|
|
45799
|
+
if (agent !== "claude") {
|
|
45800
|
+
throw new Error(`Agent ${agent} does not support hook management.`);
|
|
45801
|
+
}
|
|
45802
|
+
const hookEvent = normalizeHookEvent(event);
|
|
45803
|
+
const scope = options2.scope ?? getEffectiveAgentSettingsDefaultScopeSync();
|
|
45804
|
+
const path = adapter.getSettingsPath(scope, resolveProjectPath(options2.projectPath));
|
|
45805
|
+
const config = await readJsonObject(path);
|
|
45806
|
+
const matchers = getHookMatchers(config, hookEvent);
|
|
45807
|
+
let removed = 0;
|
|
45808
|
+
const nextMatchers = matchers.map((entry) => {
|
|
45809
|
+
if (options2.matcher !== undefined && (entry.matcher ?? "*") !== options2.matcher) {
|
|
45810
|
+
return entry;
|
|
45811
|
+
}
|
|
45812
|
+
const hooks = entry.hooks.filter((hook) => {
|
|
45813
|
+
const matches = hook.name === commandOrName || hook.command === commandOrName;
|
|
45814
|
+
if (matches) {
|
|
45815
|
+
removed++;
|
|
45816
|
+
}
|
|
45817
|
+
return !matches;
|
|
45818
|
+
});
|
|
45819
|
+
return { ...entry, hooks };
|
|
45820
|
+
}).filter((entry) => entry.hooks.length > 0);
|
|
45821
|
+
setHookMatchers(config, hookEvent, nextMatchers);
|
|
45822
|
+
if (!options2.dryRun) {
|
|
45823
|
+
await writeFile(path, `${JSON.stringify(config, null, 2)}\n`);
|
|
45824
|
+
}
|
|
45825
|
+
return {
|
|
45826
|
+
agent,
|
|
45827
|
+
event: hookEvent,
|
|
45828
|
+
scope,
|
|
45829
|
+
path,
|
|
45830
|
+
removed,
|
|
45831
|
+
dryRun: Boolean(options2.dryRun)
|
|
45832
|
+
};
|
|
45833
|
+
}
|
|
45834
|
+
}
|
|
45835
|
+
|
|
45836
|
+
// dist/commands/agent.js
|
|
45837
|
+
init_logger();
|
|
45838
|
+
var failAgentCommand = function(error) {
|
|
45839
|
+
logger.error(error instanceof Error ? error.message : "Agent settings command failed.");
|
|
45840
|
+
process.exitCode = 1;
|
|
45841
|
+
};
|
|
45842
|
+
var resolveScopeOption = function(options2) {
|
|
45843
|
+
const requested = [
|
|
45844
|
+
options2.global ? "global" : null,
|
|
45845
|
+
options2.project ? "project" : null,
|
|
45846
|
+
options2.local ? "local" : null
|
|
45847
|
+
].filter(Boolean);
|
|
45848
|
+
if (requested.length > 1) {
|
|
45849
|
+
throw new Error("Choose only one scope: --global, --project, or --local.");
|
|
45850
|
+
}
|
|
45851
|
+
return requested[0];
|
|
45852
|
+
};
|
|
45853
|
+
var printJson = function(value) {
|
|
45854
|
+
console.log(JSON.stringify(value === undefined ? null : value, null, 2));
|
|
45855
|
+
};
|
|
45856
|
+
var printValue = function(value) {
|
|
45857
|
+
if (value === undefined) {
|
|
45858
|
+
logger.info("Not set.");
|
|
45859
|
+
return;
|
|
45860
|
+
}
|
|
45861
|
+
if (typeof value === "string") {
|
|
45862
|
+
console.log(value);
|
|
45863
|
+
return;
|
|
45864
|
+
}
|
|
45865
|
+
printJson(value);
|
|
45866
|
+
};
|
|
45867
|
+
var buildSetOptions = function(options2) {
|
|
45868
|
+
const result = {};
|
|
45869
|
+
const scope = resolveScopeOption(options2);
|
|
45870
|
+
if (scope) {
|
|
45871
|
+
result.scope = scope;
|
|
45872
|
+
}
|
|
45873
|
+
if (options2.valueJson !== undefined) {
|
|
45874
|
+
result.parseJson = options2.valueJson;
|
|
45875
|
+
}
|
|
45876
|
+
if (options2.dryRun !== undefined) {
|
|
45877
|
+
result.dryRun = options2.dryRun;
|
|
45878
|
+
}
|
|
45879
|
+
return result;
|
|
45880
|
+
};
|
|
45881
|
+
var buildReadOptions = function(options2) {
|
|
45882
|
+
const result = {};
|
|
45883
|
+
const scope = resolveScopeOption(options2);
|
|
45884
|
+
if (scope) {
|
|
45885
|
+
result.scope = scope;
|
|
45886
|
+
}
|
|
45887
|
+
return result;
|
|
45888
|
+
};
|
|
45889
|
+
var buildHookAddOptions = function(options2) {
|
|
45890
|
+
const result = {};
|
|
45891
|
+
const scope = resolveScopeOption(options2);
|
|
45892
|
+
if (scope) {
|
|
45893
|
+
result.scope = scope;
|
|
45894
|
+
}
|
|
45895
|
+
if (options2.matcher !== undefined) {
|
|
45896
|
+
result.matcher = options2.matcher;
|
|
45897
|
+
}
|
|
45898
|
+
if (options2.name !== undefined) {
|
|
45899
|
+
result.name = options2.name;
|
|
45900
|
+
}
|
|
45901
|
+
if (options2.dryRun !== undefined) {
|
|
45902
|
+
result.dryRun = options2.dryRun;
|
|
45903
|
+
}
|
|
45904
|
+
return result;
|
|
45905
|
+
};
|
|
45906
|
+
var buildHookRemoveOptions = function(options2) {
|
|
45907
|
+
const result = {};
|
|
45908
|
+
const scope = resolveScopeOption(options2);
|
|
45909
|
+
if (scope) {
|
|
45910
|
+
result.scope = scope;
|
|
45911
|
+
}
|
|
45912
|
+
if (options2.matcher !== undefined) {
|
|
45913
|
+
result.matcher = options2.matcher;
|
|
45914
|
+
}
|
|
45915
|
+
if (options2.dryRun !== undefined) {
|
|
45916
|
+
result.dryRun = options2.dryRun;
|
|
45917
|
+
}
|
|
45918
|
+
return result;
|
|
45919
|
+
};
|
|
45920
|
+
function registerAgentCommand(program2) {
|
|
45921
|
+
const manager = new AgentSettingsManager;
|
|
45922
|
+
const agent = program2.command("agent").description("Manage native agent settings");
|
|
45923
|
+
agent.command("set <agent> <key> <value...>").description("Set an agent setting").option("--global", "Write global user settings").option("--project", "Write shared project settings").option("--local", "Write local project settings").option("--value-json", "Parse the value as JSON for arrays and objects").option("--json", "Print JSON output").option("--dry-run", "Preview the write without changing files").action(async (agentId, key, valueParts, options2) => {
|
|
45924
|
+
try {
|
|
45925
|
+
const value = valueParts.join(" ");
|
|
45926
|
+
const result = await manager.set(agentId, key, value, buildSetOptions(options2));
|
|
45927
|
+
if (options2.json) {
|
|
45928
|
+
printJson(result);
|
|
45929
|
+
return;
|
|
45930
|
+
}
|
|
45931
|
+
const verb = result.dryRun ? "Would set" : "Set";
|
|
45932
|
+
logger.success(`${verb} ${green(result.agent)} ${cyan(result.key)} in ${result.scope} settings.`);
|
|
45933
|
+
logger.info(`Path: ${result.path}`);
|
|
45934
|
+
} catch (error) {
|
|
45935
|
+
failAgentCommand(error);
|
|
45936
|
+
}
|
|
45937
|
+
});
|
|
45938
|
+
const hook = agent.command("hook").description("Manage native agent hooks with typed operations");
|
|
45939
|
+
hook.command("add <agent> <event>").description("Add a command hook without replacing existing hooks").option("--command <command>", "Shell command to execute for this hook").option("--matcher <matcher>", "Claude hook matcher, defaults to all matching tools/events").option("--name <name>", "Stable name used to identify this hook later").option("--global", "Write global user settings").option("--project", "Write shared project settings").option("--local", "Write local project settings").option("--json", "Print JSON output").option("--dry-run", "Preview the write without changing files").action(async (agentId, event, options2) => {
|
|
45940
|
+
try {
|
|
45941
|
+
if (!options2.command) {
|
|
45942
|
+
throw new Error("agent hook add requires --command <command>.");
|
|
45943
|
+
}
|
|
45944
|
+
const result = await manager.addHook(agentId, event, options2.command, buildHookAddOptions(options2));
|
|
45945
|
+
if (options2.json) {
|
|
45946
|
+
printJson(result);
|
|
45947
|
+
return;
|
|
45948
|
+
}
|
|
45949
|
+
const verb = result.dryRun ? "Would add" : "Added";
|
|
45950
|
+
logger.success(`${verb} ${green(result.agent)} ${cyan(result.event)} hook in ${result.scope} settings.`);
|
|
45951
|
+
logger.info(`Path: ${result.path}`);
|
|
45952
|
+
} catch (error) {
|
|
45953
|
+
failAgentCommand(error);
|
|
45954
|
+
}
|
|
45955
|
+
});
|
|
45956
|
+
hook.command("list <agent> [event]").description("List configured hooks").option("--global", "Read global user settings").option("--project", "Read shared project settings").option("--local", "Read local project settings").option("--json", "Print JSON output").action(async (agentId, event, options2) => {
|
|
45957
|
+
try {
|
|
45958
|
+
const hooks = await manager.listHooks(agentId, event, buildReadOptions(options2));
|
|
45959
|
+
if (options2.json) {
|
|
45960
|
+
printJson(hooks);
|
|
45961
|
+
return;
|
|
45962
|
+
}
|
|
45963
|
+
logger.titleBox(`AgentInit ${agentId} Hooks`);
|
|
45964
|
+
if (Array.isArray(hooks)) {
|
|
45965
|
+
hooks.forEach((entry, index) => logger.tree(`${cyan(entry.matcher ?? "*")} ${entry.hooks.map((hook2) => hook2.name ?? hook2.command ?? hook2.type ?? "hook").join(", ")}`, index === hooks.length - 1));
|
|
45966
|
+
return;
|
|
45967
|
+
}
|
|
45968
|
+
const entries = Object.entries(hooks);
|
|
45969
|
+
if (entries.length === 0) {
|
|
45970
|
+
logger.info("No hooks configured.");
|
|
45971
|
+
return;
|
|
45972
|
+
}
|
|
45973
|
+
entries.forEach(([hookEvent, matchers], index) => logger.tree(`${cyan(hookEvent)} ${matchers.length} matcher(s)`, index === entries.length - 1));
|
|
45974
|
+
} catch (error) {
|
|
45975
|
+
failAgentCommand(error);
|
|
45976
|
+
}
|
|
45977
|
+
});
|
|
45978
|
+
hook.command("remove <agent> <event> <commandOrName>").alias("rm").description("Remove hooks by command string or hook name").option("--matcher <matcher>", "Only remove hooks from this matcher").option("--global", "Write global user settings").option("--project", "Write shared project settings").option("--local", "Write local project settings").option("--json", "Print JSON output").option("--dry-run", "Preview the write without changing files").action(async (agentId, event, commandOrName, options2) => {
|
|
45979
|
+
try {
|
|
45980
|
+
const result = await manager.removeHook(agentId, event, commandOrName, buildHookRemoveOptions(options2));
|
|
45981
|
+
if (options2.json) {
|
|
45982
|
+
printJson(result);
|
|
45983
|
+
return;
|
|
45984
|
+
}
|
|
45985
|
+
const verb = result.dryRun ? "Would remove" : "Removed";
|
|
45986
|
+
logger.success(`${verb} ${result.removed ?? 0} ${green(result.agent)} ${cyan(result.event)} hook(s) from ${result.scope} settings.`);
|
|
45987
|
+
logger.info(`Path: ${result.path}`);
|
|
45988
|
+
} catch (error) {
|
|
45989
|
+
failAgentCommand(error);
|
|
45990
|
+
}
|
|
45991
|
+
});
|
|
45992
|
+
agent.command("get <agent> [key]").description("Get an agent setting or settings file").option("--global", "Read global user settings").option("--project", "Read shared project settings").option("--local", "Read local project settings").option("--json", "Print JSON output").action(async (agentId, key, options2) => {
|
|
45993
|
+
try {
|
|
45994
|
+
const value = await manager.get(agentId, key, buildReadOptions(options2));
|
|
45995
|
+
if (options2.json) {
|
|
45996
|
+
printJson(value);
|
|
45997
|
+
return;
|
|
45998
|
+
}
|
|
45999
|
+
printValue(value);
|
|
46000
|
+
} catch (error) {
|
|
46001
|
+
failAgentCommand(error);
|
|
46002
|
+
}
|
|
46003
|
+
});
|
|
46004
|
+
agent.command("unset <agent> <key>").description("Unset an agent setting").option("--global", "Write global user settings").option("--project", "Write shared project settings").option("--local", "Write local project settings").option("--json", "Print JSON output").option("--dry-run", "Preview the write without changing files").action(async (agentId, key, options2) => {
|
|
46005
|
+
try {
|
|
46006
|
+
const result = await manager.unset(agentId, key, buildSetOptions(options2));
|
|
46007
|
+
if (options2.json) {
|
|
46008
|
+
printJson(result);
|
|
46009
|
+
return;
|
|
46010
|
+
}
|
|
46011
|
+
const verb = result.dryRun ? "Would unset" : "Unset";
|
|
46012
|
+
logger.success(`${verb} ${green(result.agent)} ${cyan(result.key)} in ${result.scope} settings.`);
|
|
46013
|
+
logger.info(`Path: ${result.path}`);
|
|
46014
|
+
} catch (error) {
|
|
46015
|
+
failAgentCommand(error);
|
|
46016
|
+
}
|
|
46017
|
+
});
|
|
46018
|
+
agent.command("list [agent]").description("List supported agents or setting keys for one agent").option("--json", "Print JSON output").action((agentId, options2) => {
|
|
46019
|
+
try {
|
|
46020
|
+
if (!agentId) {
|
|
46021
|
+
const agents = manager.getSupportedAgents();
|
|
46022
|
+
if (options2.json) {
|
|
46023
|
+
printJson(agents);
|
|
46024
|
+
return;
|
|
46025
|
+
}
|
|
46026
|
+
logger.titleBox("AgentInit Agent Settings");
|
|
46027
|
+
agents.forEach((entry, index) => logger.tree(cyan(entry), index === agents.length - 1));
|
|
46028
|
+
return;
|
|
46029
|
+
}
|
|
46030
|
+
const schema2 = manager.getSchema(agentId);
|
|
46031
|
+
const keys = schema2.settings.map((setting2) => setting2.key);
|
|
46032
|
+
if (options2.json) {
|
|
46033
|
+
printJson(keys);
|
|
46034
|
+
return;
|
|
46035
|
+
}
|
|
46036
|
+
logger.titleBox(`AgentInit ${agentId} Settings`);
|
|
46037
|
+
schema2.settings.forEach((setting2, index) => logger.tree(`${cyan(setting2.key)} ${dim(setting2.category)}`, index === schema2.settings.length - 1));
|
|
46038
|
+
} catch (error) {
|
|
46039
|
+
failAgentCommand(error);
|
|
46040
|
+
}
|
|
46041
|
+
});
|
|
46042
|
+
agent.command("schema <agent>").description("Show the setting schema for an agent").option("--json", "Print JSON output").action((agentId, options2) => {
|
|
46043
|
+
try {
|
|
46044
|
+
const schema2 = manager.getSchema(agentId);
|
|
46045
|
+
if (options2.json) {
|
|
46046
|
+
printJson(schema2);
|
|
46047
|
+
return;
|
|
46048
|
+
}
|
|
46049
|
+
logger.titleBox(`AgentInit ${schema2.displayName} Schema`);
|
|
46050
|
+
logger.info(`Default omitted scope: ${cyan(schema2.effectiveDefaultScope)}`);
|
|
46051
|
+
for (const setting2 of schema2.settings) {
|
|
46052
|
+
const flags = [
|
|
46053
|
+
setting2.valueType,
|
|
46054
|
+
setting2.category,
|
|
46055
|
+
setting2.risk !== "safe" ? setting2.risk : null,
|
|
46056
|
+
setting2.deprecated ? `use ${setting2.replacement}` : null
|
|
46057
|
+
].filter(Boolean).join(", ");
|
|
46058
|
+
logger.tree(`${cyan(setting2.key)} ${dim(`[${flags}]`)} ${setting2.description}`, false);
|
|
46059
|
+
}
|
|
46060
|
+
} catch (error) {
|
|
46061
|
+
failAgentCommand(error);
|
|
46062
|
+
}
|
|
46063
|
+
});
|
|
46064
|
+
}
|
|
46065
|
+
|
|
45134
46066
|
// dist/cli.js
|
|
45135
46067
|
init_logger();
|
|
45136
46068
|
var program2 = new Command;
|
|
@@ -45141,6 +46073,7 @@ registerRulesCommand(program2);
|
|
|
45141
46073
|
registerPluginsCommand(program2);
|
|
45142
46074
|
registerConfigCommand(program2);
|
|
45143
46075
|
registerLockCommand(program2);
|
|
46076
|
+
registerAgentCommand(program2);
|
|
45144
46077
|
program2.command("init").description("Initialize agents.md configuration for the current project").option("-f, --force", "Overwrite existing configuration").option("-t, --template <template>", "Use specific template (web, cli, library)").action(initCommand);
|
|
45145
46078
|
program2.command("detect").description("Detect current project stack and existing agent configurations").option("-v, --verbose", "Show detailed detection results").action(detectCommand);
|
|
45146
46079
|
program2.command("sync").description("Sync agents.md with agent-specific configuration files").option("-a, --agent <agents...>", "Target specific agent(s)").option("-d, --dry-run", "Show what would be changed without making changes").option("-b, --backup", "Create backup before syncing").action(syncCommand);
|