From 95f0c995843d5a015b6c65280fe6c233c581ea98 Mon Sep 17 00:00:00 2001 From: James Feng <47167674+GhostDragon124@users.noreply.github.com> Date: Sat, 6 Jun 2026 01:07:53 +0800 Subject: [PATCH] fix(settings): prevent ~/.claude/ localSettings from overriding userSettings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When CWD is the home directory, projectSettings and localSettings resolve to files inside ~/.claude/ (e.g. settings.local.json). These are not legitimate project-level files — they are user config files that should not take priority over explicit userSettings. Added a guard in loadSettingsFromDisk() that skips projectSettings and localSettings when their resolved path is under the user's claude config home directory. Fixes: CCP --settings flag and default settings loading not working when ~/.claude/settings.local.json contains model overrides. --- src/utils/settings/settings.ts | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/utils/settings/settings.ts b/src/utils/settings/settings.ts index 3bea04af2..61161795d 100644 --- a/src/utils/settings/settings.ts +++ b/src/utils/settings/settings.ts @@ -274,25 +274,31 @@ function getUserSettingsFilePath(): string { export function getSettingsFilePathForSource( source: SettingSource, ): string | undefined { + let result: string | undefined switch (source) { case 'userSettings': - return join( + result = join( getSettingsRootPathForSource(source), getUserSettingsFilePath(), ) + break case 'projectSettings': case 'localSettings': { - return join( + result = join( getSettingsRootPathForSource(source), getRelativeSettingsFilePathForSource(source), ) + break } case 'policySettings': - return getManagedSettingsFilePath() + result = getManagedSettingsFilePath() + break case 'flagSettings': { - return getFlagSettingsPath() + result = getFlagSettingsPath() + break } } + return result } export function getRelativeSettingsFilePathForSource( @@ -746,6 +752,21 @@ function loadSettingsFromDisk(): SettingsWithErrors { if (!seenFiles.has(resolvedPath)) { seenFiles.add(resolvedPath) + // Skip project and local settings when they resolve to the user's + // claude config directory (~/.claude/). These are not legitimately + // separate project-level files — the CWD just happens to be the same + // directory as the claude config home. Loading them would let a + // local override (e.g. settings.local.json) silently clobber the + // user's explicit global settings values. + if ( + (source === 'projectSettings' || source === 'localSettings') && + resolvedPath.startsWith( + resolve(getSettingsRootPathForSource('userSettings')), + ) + ) { + continue + } + const { settings, errors } = parseSettingsFile(filePath) // Add unique errors (deduplication)