(settingsFile: string)
| 430 | } |
| 431 | } |
| 432 | function loadSettingsFromFlag(settingsFile: string): void { |
| 433 | try { |
| 434 | const trimmedSettings = settingsFile.trim(); |
| 435 | const looksLikeJson = trimmedSettings.startsWith('{') && trimmedSettings.endsWith('}'); |
| 436 | let settingsPath: string; |
| 437 | if (looksLikeJson) { |
| 438 | // It's a JSON string - validate and create temp file |
| 439 | const parsedJson = safeParseJSON(trimmedSettings); |
| 440 | if (!parsedJson) { |
| 441 | process.stderr.write(chalk.red('Error: Invalid JSON provided to --settings\n')); |
| 442 | process.exit(1); |
| 443 | } |
| 444 | |
| 445 | // Create a temporary file and write the JSON to it. |
| 446 | // Use a content-hash-based path instead of random UUID to avoid |
| 447 | // busting the Anthropic API prompt cache. The settings path ends up |
| 448 | // in the Bash tool's sandbox denyWithinAllow list, which is part of |
| 449 | // the tool description sent to the API. A random UUID per subprocess |
| 450 | // changes the tool description on every query() call, invalidating |
| 451 | // the cache prefix and causing a 12x input token cost penalty. |
| 452 | // The content hash ensures identical settings produce the same path |
| 453 | // across process boundaries (each SDK query() spawns a new process). |
| 454 | settingsPath = generateTempFilePath('claude-settings', '.json', { |
| 455 | contentHash: trimmedSettings |
| 456 | }); |
| 457 | writeFileSync_DEPRECATED(settingsPath, trimmedSettings, 'utf8'); |
| 458 | } else { |
| 459 | // It's a file path - resolve and validate by attempting to read |
| 460 | const { |
| 461 | resolvedPath: resolvedSettingsPath |
| 462 | } = safeResolvePath(getFsImplementation(), settingsFile); |
| 463 | try { |
| 464 | readFileSync(resolvedSettingsPath, 'utf8'); |
| 465 | } catch (e) { |
| 466 | if (isENOENT(e)) { |
| 467 | process.stderr.write(chalk.red(`Error: Settings file not found: ${resolvedSettingsPath}\n`)); |
| 468 | process.exit(1); |
| 469 | } |
| 470 | throw e; |
| 471 | } |
| 472 | settingsPath = resolvedSettingsPath; |
| 473 | } |
| 474 | setFlagSettingsPath(settingsPath); |
| 475 | resetSettingsCache(); |
| 476 | } catch (error) { |
| 477 | if (error instanceof Error) { |
| 478 | logError(error); |
| 479 | } |
| 480 | process.stderr.write(chalk.red(`Error processing settings: ${errorMessage(error)}\n`)); |
| 481 | process.exit(1); |
| 482 | } |
| 483 | } |
| 484 | function loadSettingSourcesFromFlag(settingSourcesArg: string): void { |
| 485 | try { |
| 486 | const sources = parseSettingSourcesFlag(settingSourcesArg); |
no test coverage detected