This commit is contained in:
musistudio
2026-01-02 22:51:22 +08:00
parent 9309cc8655
commit 1579413f3d
16 changed files with 86 additions and 200 deletions

View File

@@ -185,7 +185,7 @@ Located in `packages/shared/src/preset/`:
- **sensitiveFields.ts**: Identify and sanitize sensitive fields
- Detects api_key, password, secret fields automatically
- Creates `requiredInputs` array for installation prompts
- Replaces sensitive values with environment variable placeholders
### Preset File Format
@@ -206,12 +206,6 @@ Located in `packages/shared/src/preset/`:
"label": "OpenAI API Key",
"prompt": "Enter your OpenAI API key"
}
],
"requiredInputs": [
{
"field": "Providers[0].api_key",
"placeholder": "Enter your API key"
}
]
}
```

View File

@@ -141,14 +141,14 @@ A preset is a directory containing a `manifest.json` file:
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "{{apiKey}}",
"models": ["gpt-4", "gpt-3.5-turbo"]
}
],
"Router": {
"default": "openai:gpt-4"
"default": "openai,gpt-4"
},
"schema": [
@@ -251,4 +251,4 @@ ccr preset export my-preset --include-sensitive
- [Configuration Guide](/docs/cli/config/basic) - Basic configuration
- [Project-Level Configuration](/docs/cli/config/project-level) - Project-specific settings
- [Server: Presets](/docs/server/advanced/presets) - Advanced preset topics
- [Presets](/docs/presets/intro) - Advanced preset topics

View File

@@ -370,7 +370,7 @@ Output: ` feature/auth 📝 +150/-25 ⏱️ 2m34s`
Statusline themes can be included in presets. When you install a preset with statusline configuration, it will automatically apply when you activate that preset.
See [Presets](/docs/server/advanced/presets) for more information.
See [Presets](/docs/presets/intro) for more information.
## Troubleshooting

View File

@@ -8,7 +8,7 @@ CLI uses the same configuration file as Server: `~/.claude-code-router/config.js
## Configuration Methods
You can configure Claude Code Router in three ways:
You can configure Claude Code Router in two ways:
### Option 1: Edit Configuration File Directly
@@ -26,20 +26,6 @@ Open the web interface and configure visually:
ccr ui
```
### Option 3: Interactive Configuration
Use the interactive command-line configuration:
```bash
ccr model
```
This will guide you through:
1. Select LLM provider
2. Configure API Key
3. Select model
4. Set routing rules
## Restart After Configuration Changes
After modifying the configuration file or making changes through the Web UI, you must restart the service:

View File

@@ -21,7 +21,7 @@ Edit `~/.claude-code-router/config.json`:
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "your-api-key-here",
"models": ["gpt-4", "gpt-3.5-turbo"]
}

View File

@@ -30,10 +30,6 @@ ccr preset install /path/to/preset-directory
ccr preset install my-preset
```
:::note Note
CLI mode **does not support** installing presets directly from URLs. To install from GitHub, clone to local first or use Web UI.
:::
#### Using Presets
After installing a preset, you can use the preset name to start Claude Code:
@@ -41,9 +37,6 @@ After installing a preset, you can use the preset name to start Claude Code:
```bash
# Start with a specific preset
ccr my-preset "your prompt"
# Background task with preset
ccr my-preset --background "your prompt"
```
The preset will:
@@ -89,13 +82,6 @@ Then open `http://localhost:3000` in your browser.
2. Select the preset you want to install from the list
3. Click the "Install" button
Or manually enter a GitHub repository URL:
```
Format: https://github.com/username/repo
Example: https://github.com/example/ccr-presets
```
#### Reconfigure Preset
1. Click the "View Details" icon next to the preset
@@ -309,13 +295,13 @@ For complex configuration needs, use `configMappings` to precisely control value
"Providers": [
{
"name": "{{primaryProvider}}",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "{{apiKey}}",
"models": ["{{defaultModel}}"]
}
],
"Router": {
"default": "{{primaryProvider}}/{{defaultModel}}"
"default": "{{primaryProvider}},{{defaultModel}}"
},
"PROXY_URL": "{{proxyUrl}}"
},
@@ -352,9 +338,6 @@ These fields describe basic information about the preset:
| `license` | string | - | License type |
| `keywords` | string[] | - | Keyword tags |
| `ccrVersion` | string | - | Compatible CCR version |
| `source` | string | - | Preset source URL |
| `sourceType` | string | - | Source type (`local`/`gist`/`registry`) |
| `checksum` | string | - | Content checksum (SHA256) |
Example:
@@ -382,6 +365,14 @@ These fields are directly merged into CCR's configuration. All fields supported
| `Router` | object | Routing configuration |
| `transformers` | array | Transformer configuration |
| `StatusLine` | object | Status bar configuration |
| `NON_INTERACTIVE_MODE` | boolean | Enable non-interactive mode (for CI/CD) |
**CLI-Only Fields** (these fields only work in CLI mode and are not used by the server):
| Field | Type | Description |
|-------|------|-------------|
| `noServer` | boolean | Skip local server startup and use provider's API directly |
| `claudeCodeSettings` | object | Claude Code specific settings (env, statusLine, etc.) |
Example:
@@ -390,14 +381,14 @@ Example:
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "${OPENAI_API_KEY}",
"models": ["gpt-4o", "gpt-4o-mini"]
}
],
"Router": {
"default": "openai/gpt-4o",
"background": "openai/gpt-4o-mini"
"default": "openai,gpt-4o",
"background": "openai,gpt-4o-mini"
},
"PORT": 8080
}
@@ -413,7 +404,6 @@ These fields are used to create interactive configuration templates:
| `template` | object | Configuration template (with variable references) |
| `configMappings` | array | Configuration mapping rules |
| `userValues` | object | User-filled values (used at runtime) |
| `requiredInputs` | array | Required input list (auto-generated) |
**Schema Field Types:**
@@ -483,24 +473,16 @@ cat > ~/.claude-code-router/presets/simple-openai/manifest.json << 'EOF'
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "${OPENAI_API_KEY}",
"models": ["gpt-4o", "gpt-4o-mini"]
}
],
"Router": {
"default": "openai/gpt-4o",
"background": "openai/gpt-4o-mini"
},
"requiredInputs": [
{
"id": "Providers[0].api_key",
"prompt": "Enter OpenAI API Key",
"placeholder": "OPENAI_API_KEY"
}
]
"default": "openai,gpt-4o",
"background": "openai,gpt-4o-mini"
}
}
EOF
@@ -584,14 +566,14 @@ cat > ~/.claude-code-router/presets/advanced-config/manifest.json << 'EOF'
"Providers": [
{
"name": "#{provider}",
"api_base_url": "#{provider === 'openai' ? 'https://api.openai.com/v1' : 'https://api.deepseek.com'}",
"api_base_url": "#{provider === 'openai' ? 'https://api.openai.com/v1/chat/completions' : 'https://api.deepseek.com/v1/chat/completions'}",
"api_key": "#{apiKey}",
"models": ["gpt-4o", "gpt-4o-mini"]
}
],
"Router": {
"default": "#{provider}/gpt-4o",
"background": "#{provider}/gpt-4o-mini"
"default": "#{provider},gpt-4o",
"background": "#{provider},gpt-4o-mini"
}
},
@@ -639,12 +621,6 @@ ccr preset export my-exported-preset \
--tags "production,openai"
```
:::tip Share Presets
Exported preset directories can be directly shared with others. Recipients can:
- **CLI Mode**: Place directory in `~/.claude-code-router/presets/`, then run `ccr preset install preset-name`
- **Web UI Mode**: Upload directory to GitHub, then install via repository URL
:::
## Preset File Location
Presets are stored in:

View File

@@ -141,14 +141,14 @@ ccr preset delete my-config
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "{{apiKey}}",
"models": ["gpt-4", "gpt-3.5-turbo"]
}
],
"Router": {
"default": "openai:gpt-4"
"default": "openai,gpt-4"
},
"schema": [
@@ -251,4 +251,4 @@ ccr preset export my-preset --include-sensitive
- [配置指南](/zh/docs/cli/config/basic) - 基础配置
- [项目级配置](/zh/docs/cli/config/project-level) - 项目特定设置
- [服务器:预设](/zh/docs/server/advanced/presets) - 高级预设主题
- [预设](/zh/docs/presets/intro) - 高级预设主题

View File

@@ -371,7 +371,7 @@ module.exports = async function(variables, options) {
Statusline 主题可以包含在 presets 中。当您安装带有 statusline 配置的 preset 时,激活该 preset 时会自动应用。
查看 [Presets](/docs/server/advanced/presets) 了解更多信息。
查看 [Presets](/zh/docs/presets/intro) 了解更多信息。
## 故障排除

View File

@@ -31,10 +31,6 @@ ccr preset install /path/to/preset-directory
ccr preset install my-preset
```
:::note 注意
CLI 方式**不支持**从 URL 直接安装预设。如需从 GitHub 安装,请先克隆到本地或使用 Web UI。
:::
#### 使用预设
安装预设后,可以使用预设名称启动 Claude Code
@@ -42,9 +38,6 @@ CLI 方式**不支持**从 URL 直接安装预设。如需从 GitHub 安装,
```bash
# 使用指定预设启动
ccr my-preset "your prompt"
# 后台任务使用预设
ccr my-preset --background "your prompt"
```
预设会:
@@ -90,13 +83,6 @@ ccr ui
2. 在预设列表中选择要安装的预设
3. 点击"安装"按钮
或手动输入 GitHub 仓库地址:
```
格式https://github.com/username/repo
示例https://github.com/example/ccr-presets
```
#### 重新配置预设
1. 在预设列表中点击"查看详情"按钮
@@ -310,13 +296,13 @@ CCR 引入了强大的动态配置系统,支持:
"Providers": [
{
"name": "{{primaryProvider}}",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "{{apiKey}}",
"models": ["{{defaultModel}}"]
}
],
"Router": {
"default": "{{primaryProvider}}/{{defaultModel}}"
"default": "{{primaryProvider}},{{defaultModel}}"
},
"PROXY_URL": "{{proxyUrl}}"
},
@@ -353,9 +339,6 @@ CCR 引入了强大的动态配置系统,支持:
| `license` | string | - | 许可证类型 |
| `keywords` | string[] | - | 关键词标签 |
| `ccrVersion` | string | - | 兼容的 CCR 版本 |
| `source` | string | - | 预设来源 URL |
| `sourceType` | string | - | 来源类型(`local`/`gist`/`registry` |
| `checksum` | string | - | 内容校验和SHA256 |
示例:
@@ -383,6 +366,14 @@ CCR 引入了强大的动态配置系统,支持:
| `Router` | object | 路由配置 |
| `transformers` | array | 转换器配置 |
| `StatusLine` | object | 状态栏配置 |
| `NON_INTERACTIVE_MODE` | boolean | 启用非交互模式(用于 CI/CD |
**CLI 专用字段**(这些字段仅在 CLI 模式下有效,服务器不使用):
| 字段 | 类型 | 说明 |
|------|------|------|
| `noServer` | boolean | 跳过本地服务器启动,直接使用 Provider 的 API |
| `claudeCodeSettings` | object | Claude Code 特定设置(环境变量、状态栏等) |
示例:
@@ -391,14 +382,14 @@ CCR 引入了强大的动态配置系统,支持:
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "${OPENAI_API_KEY}",
"models": ["gpt-4o", "gpt-4o-mini"]
}
],
"Router": {
"default": "openai/gpt-4o",
"background": "openai/gpt-4o-mini"
"default": "openai,gpt-4o",
"background": "openai,gpt-4o-mini"
},
"PORT": 8080
}
@@ -414,7 +405,6 @@ CCR 引入了强大的动态配置系统,支持:
| `template` | object | 配置模板(使用变量引用) |
| `configMappings` | array | 配置映射规则 |
| `userValues` | object | 用户填写的值(运行时使用) |
| `requiredInputs` | array | 必填输入项列表(自动生成) |
**schema 字段类型:**
@@ -484,24 +474,16 @@ cat > ~/.claude-code-router/presets/simple-openai/manifest.json << 'EOF'
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "${OPENAI_API_KEY}",
"models": ["gpt-4o", "gpt-4o-mini"]
}
],
"Router": {
"default": "openai/gpt-4o",
"background": "openai/gpt-4o-mini"
},
"requiredInputs": [
{
"id": "Providers[0].api_key",
"prompt": "Enter OpenAI API Key",
"placeholder": "OPENAI_API_KEY"
}
]
"default": "openai,gpt-4o",
"background": "openai,gpt-4o-mini"
}
}
EOF
@@ -585,14 +567,14 @@ cat > ~/.claude-code-router/presets/advanced-config/manifest.json << 'EOF'
"Providers": [
{
"name": "#{provider}",
"api_base_url": "#{provider === 'openai' ? 'https://api.openai.com/v1' : 'https://api.deepseek.com'}",
"api_base_url": "#{provider === 'openai' ? 'https://api.openai.com/v1/chat/completions' : 'https://api.deepseek.com/v1/chat/completions'}",
"api_key": "#{apiKey}",
"models": ["gpt-4o", "gpt-4o-mini"]
}
],
"Router": {
"default": "#{provider}/gpt-4o",
"background": "#{provider}/gpt-4o-mini"
"default": "#{provider},gpt-4o",
"background": "#{provider},gpt-4o-mini"
}
},
@@ -640,12 +622,6 @@ ccr preset export my-exported-preset \
--tags "production,openai"
```
:::tip 分享预设
导出的预设目录可以直接分享给他人。接收者可以:
- **CLI 方式**:将目录放到 `~/.claude-code-router/presets/`,然后运行 `ccr preset install 预设名`
- **Web UI 方式**:将目录上传到 GitHub然后通过仓库 URL 安装
:::
## 预设文件位置
预设保存在:

View File

@@ -55,7 +55,6 @@ Preset 是一个预定义的配置包,用于快速配置 Claude Code Router。
"schema": [...],
"template": {...},
"configMappings": [...],
"requiredInputs": [...],
"userValues": {...}
}
```
@@ -113,7 +112,7 @@ Provider 配置数组,定义 LLM 服务提供商。
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "${OPENAI_API_KEY}",
"models": ["gpt-4o", "gpt-4o-mini"],
"transformer": "anthropic",
@@ -159,7 +158,7 @@ Provider 配置数组,定义 LLM 服务提供商。
| 字段 | 类型 | 说明 |
|------|------|------|
| `default` | string | 默认路由(格式:`provider/model` |
| `default` | string | 默认路由(格式:`provider,model` |
| `background` | string | 后台任务路由 |
| `think` | string | 思考模式路由 |
| `longContext` | string | 长上下文路由 |
@@ -550,27 +549,6 @@ userValues 存储用户在安装时填写的值,运行时自动应用。
}
```
### requiredInputs必填输入
requiredInputs 是导出预设时自动生成的字段列表,用于提示用户需要填写哪些信息。
```json
{
"requiredInputs": [
{
"id": "Providers[0].api_key",
"prompt": "Enter api_key",
"placeholder": "OPENAI_API_KEY"
},
{
"id": "PROXY_URL",
"prompt": "Enter proxy URL",
"placeholder": "PROXY_URL"
}
]
}
```
## 敏感字段处理
CCR 会自动识别敏感字段(如 `api_key``secret``password` 等),并将其替换为环境变量占位符。
@@ -617,13 +595,6 @@ $VARIABLE_NAME
"name": "openai",
"api_key": "${OPENAI_API_KEY}"
}
],
"requiredInputs": [
{
"id": "Providers[0].api_key",
"prompt": "Enter api_key",
"placeholder": "OPENAI_API_KEY"
}
]
}
```
@@ -642,7 +613,7 @@ $VARIABLE_NAME
"Providers": [
{
"name": "openai",
"api_base_url": "https://api.openai.com/v1",
"api_base_url": "https://api.openai.com/v1/chat/completions",
"api_key": "${OPENAI_API_KEY}",
"models": ["gpt-4o", "gpt-4o-mini"]
}
@@ -651,15 +622,7 @@ $VARIABLE_NAME
"Router": {
"default": "openai/gpt-4o",
"background": "openai/gpt-4o-mini"
},
"requiredInputs": [
{
"id": "Providers[0].api_key",
"prompt": "Enter OpenAI API Key",
"placeholder": "OPENAI_API_KEY"
}
]
}
}
```
@@ -806,7 +769,7 @@ $VARIABLE_NAME
"Providers": [
{
"name": "#{primaryProvider}",
"api_base_url": "#{primaryProvider === 'openai' ? 'https://api.openai.com/v1' : 'https://api.deepseek.com'}",
"api_base_url": "#{primaryProvider === 'openai' ? 'https://api.openai.com/v1/chat/completions' : 'https://api.deepseek.com/v1/chat/completions'}",
"api_key": "#{apiKey}",
"models": [
"#{defaultModel}",

View File

@@ -106,11 +106,21 @@ const sidebars: SidebarsConfig = {
},
items: [
'server/advanced/custom-router',
'server/advanced/presets',
],
},
],
},
{
type: 'category',
label: 'Presets',
link: {
type: 'generated-index',
title: 'CCR Presets',
description: 'Predefined configurations for quick setup',
slug: 'category/presets',
},
items: ['presets/intro'],
},
],
};

View File

@@ -51,7 +51,7 @@ async function listPresets(): Promise<void> {
const manifest = JSON5.parse(content);
// Extract metadata fields from manifest
const { Providers, Router, PORT, HOST, API_TIMEOUT_MS, PROXY_URL, LOG, LOG_LEVEL, StatusLine, NON_INTERACTIVE_MODE, requiredInputs, ...metadata } = manifest;
const { Providers, Router, PORT, HOST, API_TIMEOUT_MS, PROXY_URL, LOG, LOG_LEVEL, StatusLine, NON_INTERACTIVE_MODE, ...metadata } = manifest;
const name = metadata.name || dirName;
const description = metadata.description || '';

View File

@@ -234,7 +234,7 @@ export const createServer = async (config: any): Promise<any> => {
const manifest = JSON.parse(content);
// Extract metadata fields
const { Providers, Router, PORT, HOST, API_TIMEOUT_MS, PROXY_URL, LOG, LOG_LEVEL, StatusLine, NON_INTERACTIVE_MODE, requiredInputs, ...metadata } = manifest;
const { Providers, Router, PORT, HOST, API_TIMEOUT_MS, PROXY_URL, LOG, LOG_LEVEL, StatusLine, NON_INTERACTIVE_MODE, ...metadata } = manifest;
presets.push({
id: dirName, // Use directory name as unique identifier

View File

@@ -26,7 +26,6 @@ export interface ExportResult {
presetDir: string;
sanitizedConfig: any;
metadata: PresetMetadata;
requiredInputs: any[];
sanitizedCount: number;
}
@@ -41,8 +40,7 @@ export function createManifest(
presetName: string,
config: any,
sanitizedConfig: any,
options: ExportOptions,
requiredInputs: any[] = []
options: ExportOptions
): ManifestFile {
const metadata: PresetMetadata = {
name: presetName,
@@ -55,7 +53,6 @@ export function createManifest(
return {
...metadata,
...sanitizedConfig,
requiredInputs: options.includeSensitive ? undefined : requiredInputs,
};
}
@@ -81,13 +78,12 @@ export async function exportPreset(
};
// 2. Sanitize configuration
const { sanitizedConfig, requiredInputs, sanitizedCount } = await sanitizeConfig(config);
const { sanitizedConfig, sanitizedCount } = await sanitizeConfig(config);
// 3. Generate manifest.json (flattened structure)
const manifest: ManifestFile = {
...metadata,
...sanitizedConfig,
requiredInputs: options.includeSensitive ? undefined : requiredInputs,
};
// 4. Create preset directory
@@ -114,7 +110,6 @@ export async function exportPreset(
presetDir,
sanitizedConfig,
metadata,
requiredInputs,
sanitizedCount,
};
}

View File

@@ -2,7 +2,7 @@
* Sensitive field identification and sanitization functionality
*/
import { RequiredInput, SanitizeResult } from './types';
import { SanitizeResult } from './types';
// Sensitive field pattern list
const SENSITIVE_PATTERNS = [
@@ -88,17 +88,15 @@ function extractEnvVarName(value: string): string | null {
* Recursively traverse object to identify and sanitize sensitive fields
* @param config Configuration object
* @param path Current field path
* @param requiredInputs Required inputs array (cumulative)
* @param sanitizedCount Sanitized field count
*/
function sanitizeObject(
config: any,
path: string = '',
requiredInputs: RequiredInput[] = [],
sanitizedCount: number = 0
): { sanitized: any; requiredInputs: RequiredInput[]; count: number } {
): { sanitized: any; count: number } {
if (!config || typeof config !== 'object') {
return { sanitized: config, requiredInputs, count: sanitizedCount };
return { sanitized: config, count: sanitizedCount };
}
if (Array.isArray(config)) {
@@ -107,14 +105,12 @@ function sanitizeObject(
const result = sanitizeObject(
config[i],
path ? `${path}[${i}]` : `[${i}]`,
requiredInputs,
sanitizedCount
);
sanitizedArray.push(result.sanitized);
requiredInputs = result.requiredInputs;
sanitizedCount = result.count;
}
return { sanitized: sanitizedArray, requiredInputs, count: sanitizedCount };
return { sanitized: sanitizedArray, count: sanitizedCount };
}
const sanitizedObj: any = {};
@@ -126,15 +122,6 @@ function sanitizeObject(
// If value is already an environment variable, keep unchanged
if (isEnvPlaceholder(value)) {
sanitizedObj[key] = value;
// Still need to record as required input, but use existing environment variable
const envVarName = extractEnvVarName(value);
if (envVarName && !requiredInputs.some(input => input.id === currentPath)) {
requiredInputs.push({
id: currentPath,
prompt: `Enter ${key}`,
placeholder: envVarName,
});
}
} else {
// Sanitize: replace with environment variable placeholder
// Try to infer entity name from path
@@ -161,20 +148,12 @@ function sanitizeObject(
const envVarName = generateEnvVarName('global', entityName, key);
sanitizedObj[key] = `\${${envVarName}}`;
// Record as required input
requiredInputs.push({
id: currentPath,
prompt: `Enter ${key}`,
placeholder: envVarName,
});
sanitizedCount++;
}
} else if (typeof value === 'object' && value !== null) {
// Recursively process nested objects
const result = sanitizeObject(value, currentPath, requiredInputs, sanitizedCount);
const result = sanitizeObject(value, currentPath, sanitizedCount);
sanitizedObj[key] = result.sanitized;
requiredInputs = result.requiredInputs;
sanitizedCount = result.count;
} else {
// Keep original value
@@ -182,7 +161,7 @@ function sanitizeObject(
}
}
return { sanitized: sanitizedObj, requiredInputs, count: sanitizedCount };
return { sanitized: sanitizedObj, count: sanitizedCount };
}
/**
@@ -198,7 +177,6 @@ export async function sanitizeConfig(config: any): Promise<SanitizeResult> {
return {
sanitizedConfig: result.sanitized,
requiredInputs: result.requiredInputs,
sanitizedCount: result.count,
};
}

View File

@@ -147,6 +147,15 @@ export interface PresetConfigSection {
transformers?: TransformerConfig[];
StatusLine?: any;
NON_INTERACTIVE_MODE?: boolean;
// CLI-only fields (not used by server)
noServer?: boolean; // CLI: Whether to skip local server startup and use provider's API directly
claudeCodeSettings?: { // CLI: Claude Code specific settings
env?: Record<string, any>; // CLI: Environment variables to pass to Claude Code
statusLine?: any; // CLI: Status line configuration
[key: string]: any;
};
[key: string]: any;
}
@@ -244,7 +253,6 @@ export enum MergeStrategy {
// Sanitization result
export interface SanitizeResult {
sanitizedConfig: any;
requiredInputs: RequiredInput[];
sanitizedCount: number;
}