feat: support configurable provider config dirs
This commit is contained in:
1 parent
2e97513e60
commit
aab3f567f1
7 files changed
+105
-25
No files matched your search
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Xi Xu
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
会自动完成以下操作:
|
会自动完成以下操作:
|
||||||
|
|
||||||
- 写入 `~/.codex/config.toml`
|
- 写入 Codex 配置文件
|
||||||
- 设置 provider 为 `xixu`
|
- 设置 provider 为 `xixu`
|
||||||
- 配置 `XIXU_API_KEY` 环境变量
|
- 配置 `XIXU_API_KEY` 环境变量
|
||||||
|
|
||||||
@@ -16,20 +16,18 @@
|
|||||||
|
|
||||||
会自动完成以下操作:
|
会自动完成以下操作:
|
||||||
|
|
||||||
- 写入 `~/.claude/settings.json`
|
- 写入 Claude Code 配置文件
|
||||||
- 配置 `ANTHROPIC_AUTH_TOKEN`
|
- 配置 `ANTHROPIC_AUTH_TOKEN`
|
||||||
- 配置 `ANTHROPIC_BASE_URL`
|
- 配置 `ANTHROPIC_BASE_URL`
|
||||||
- 配置默认模型为 `gpt-5.4`
|
- 配置默认模型为 `gpt-5.4`
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Codex
|
## Codex
|
||||||
|
|
||||||
### Linux/macOS
|
### Linux/macOS
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash <(curl -fsSL https://github.com/xixu-me/provider-setup/raw/refs/heads/main/codex.sh)
|
bash <(curl -fsSL https://github.com/xixu-me/provider-setup/raw/refs/heads/main/codex.sh)
|
||||||
````
|
```
|
||||||
|
|
||||||
### Windows PowerShell
|
### Windows PowerShell
|
||||||
|
|
||||||
@@ -37,8 +35,6 @@ bash <(curl -fsSL https://github.com/xixu-me/provider-setup/raw/refs/heads/main/
|
|||||||
powershell -ExecutionPolicy Bypass -Command "& ([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://github.com/xixu-me/provider-setup/raw/refs/heads/main/codex.ps1').Content))"
|
powershell -ExecutionPolicy Bypass -Command "& ([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://github.com/xixu-me/provider-setup/raw/refs/heads/main/codex.ps1').Content))"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Claude Code
|
## Claude Code
|
||||||
|
|
||||||
### Linux/macOS
|
### Linux/macOS
|
||||||
@@ -53,8 +49,6 @@ bash <(curl -fsSL https://github.com/xixu-me/provider-setup/raw/refs/heads/main/
|
|||||||
powershell -ExecutionPolicy Bypass -Command "& ([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://github.com/xixu-me/provider-setup/raw/refs/heads/main/claude.ps1').Content))"
|
powershell -ExecutionPolicy Bypass -Command "& ([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://github.com/xixu-me/provider-setup/raw/refs/heads/main/claude.ps1').Content))"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 配置内容
|
## 配置内容
|
||||||
|
|
||||||
### Codex
|
### Codex
|
||||||
@@ -72,7 +66,7 @@ env_key = "XIXU_API_KEY"
|
|||||||
|
|
||||||
### Claude Code
|
### Claude Code
|
||||||
|
|
||||||
写入到 `~/.claude/settings.json` 的 `env`:
|
写入到目标 `settings.json` 的 `env`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -88,16 +82,19 @@ env_key = "XIXU_API_KEY"
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 说明
|
## 说明
|
||||||
|
|
||||||
* 脚本默认会提示输入 API Key
|
### 路径规则
|
||||||
* 若对应配置文件已存在,会在保留其他配置的基础上更新目标字段
|
|
||||||
* Windows 下用户级环境变量会持久化保存
|
|
||||||
* Linux/macOS 下会写入当前 shell 配置文件以便后续生效
|
|
||||||
|
|
||||||
---
|
- Codex 使用 `CODEX_HOME/config.toml`;若未设置 `CODEX_HOME`,则回退到 `~/.codex/config.toml`
|
||||||
|
- Claude Code 使用 `CLAUDE_CONFIG_DIR/settings.json`;若未设置 `CLAUDE_CONFIG_DIR`,则回退到 `~/.claude/settings.json`
|
||||||
|
|
||||||
|
### 其他说明
|
||||||
|
|
||||||
|
- 脚本默认会提示输入 API Key
|
||||||
|
- 若对应配置文件已存在,会在保留其他配置的基础上更新目标字段
|
||||||
|
- Windows 下用户级环境变量会持久化保存
|
||||||
|
- Linux/macOS 下会写入当前 shell 配置文件以便后续生效
|
||||||
|
|
||||||
## 验证
|
## 验证
|
||||||
|
|
||||||
@@ -106,14 +103,14 @@ env_key = "XIXU_API_KEY"
|
|||||||
#### Linux/macOS
|
#### Linux/macOS
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cat ~/.codex/config.toml
|
cat "${CODEX_HOME:-$HOME/.codex}/config.toml"
|
||||||
echo $XIXU_API_KEY
|
echo $XIXU_API_KEY
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Windows PowerShell
|
#### Windows PowerShell
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
Get-Content ~/.codex/config.toml
|
Get-Content (Join-Path $(if ($env:CODEX_HOME) { $env:CODEX_HOME } else { Join-Path $HOME ".codex" }) "config.toml")
|
||||||
$env:XIXU_API_KEY
|
$env:XIXU_API_KEY
|
||||||
[System.Environment]::GetEnvironmentVariable("XIXU_API_KEY","User")
|
[System.Environment]::GetEnvironmentVariable("XIXU_API_KEY","User")
|
||||||
```
|
```
|
||||||
@@ -123,11 +120,24 @@ $env:XIXU_API_KEY
|
|||||||
#### Linux/macOS
|
#### Linux/macOS
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cat ~/.claude/settings.json
|
python3 -c "import json, os, pathlib; config_dir = pathlib.Path(os.environ.get('CLAUDE_CONFIG_DIR', str(pathlib.Path.home() / '.claude'))); settings_file = config_dir / 'settings.json'; data = json.loads(settings_file.read_text(encoding='utf-8')); env = data.get('env', {}); keys = ['ANTHROPIC_AUTH_TOKEN', 'ANTHROPIC_BASE_URL', 'ANTHROPIC_DEFAULT_HAIKU_MODEL', 'ANTHROPIC_DEFAULT_OPUS_MODEL', 'ANTHROPIC_DEFAULT_SONNET_MODEL', 'CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC', 'CLAUDE_CODE_SUBAGENT_MODEL']; print(settings_file); [print(f'{key}={env.get(key)}') for key in keys]"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Windows PowerShell
|
#### Windows PowerShell
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
Get-Content ~/.claude/settings.json
|
$settingsFile = Join-Path $(if ($env:CLAUDE_CONFIG_DIR) { $env:CLAUDE_CONFIG_DIR } else { Join-Path $HOME ".claude" }) "settings.json"
|
||||||
|
$envConfig = (Get-Content $settingsFile -Raw | ConvertFrom-Json).env
|
||||||
|
$settingsFile
|
||||||
|
"ANTHROPIC_AUTH_TOKEN=$($envConfig.ANTHROPIC_AUTH_TOKEN)"
|
||||||
|
"ANTHROPIC_BASE_URL=$($envConfig.ANTHROPIC_BASE_URL)"
|
||||||
|
"ANTHROPIC_DEFAULT_HAIKU_MODEL=$($envConfig.ANTHROPIC_DEFAULT_HAIKU_MODEL)"
|
||||||
|
"ANTHROPIC_DEFAULT_OPUS_MODEL=$($envConfig.ANTHROPIC_DEFAULT_OPUS_MODEL)"
|
||||||
|
"ANTHROPIC_DEFAULT_SONNET_MODEL=$($envConfig.ANTHROPIC_DEFAULT_SONNET_MODEL)"
|
||||||
|
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=$($envConfig.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC)"
|
||||||
|
"CLAUDE_CODE_SUBAGENT_MODEL=$($envConfig.CLAUDE_CODE_SUBAGENT_MODEL)"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT. See [LICENSE](LICENSE).
|
||||||
+5
-1
@@ -13,7 +13,11 @@ if ([string]::IsNullOrWhiteSpace($ApiKey)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$SettingsDir = Join-Path $HOME ".claude"
|
$SettingsDir = if ([string]::IsNullOrWhiteSpace($env:CLAUDE_CONFIG_DIR)) {
|
||||||
|
Join-Path $HOME ".claude"
|
||||||
|
} else {
|
||||||
|
$env:CLAUDE_CONFIG_DIR
|
||||||
|
}
|
||||||
$SettingsFile = Join-Path $SettingsDir "settings.json"
|
$SettingsFile = Join-Path $SettingsDir "settings.json"
|
||||||
|
|
||||||
New-Item -ItemType Directory -Force -Path $SettingsDir | Out-Null
|
New-Item -ItemType Directory -Force -Path $SettingsDir | Out-Null
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ if [[ -z "$API_KEY" ]]; then
|
|||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SETTINGS_DIR="$HOME/.claude"
|
SETTINGS_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
|
||||||
SETTINGS_FILE="$SETTINGS_DIR/settings.json"
|
SETTINGS_FILE="$SETTINGS_DIR/settings.json"
|
||||||
|
|
||||||
mkdir -p "$SETTINGS_DIR"
|
mkdir -p "$SETTINGS_DIR"
|
||||||
|
|||||||
@@ -13,7 +13,11 @@ if ([string]::IsNullOrWhiteSpace($ApiKey)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$ConfigDir = Join-Path $HOME ".codex"
|
$ConfigDir = if ([string]::IsNullOrWhiteSpace($env:CODEX_HOME)) {
|
||||||
|
Join-Path $HOME ".codex"
|
||||||
|
} else {
|
||||||
|
$env:CODEX_HOME
|
||||||
|
}
|
||||||
$ConfigFile = Join-Path $ConfigDir "config.toml"
|
$ConfigFile = Join-Path $ConfigDir "config.toml"
|
||||||
|
|
||||||
New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null
|
New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ if [[ -z "$API_KEY" ]]; then
|
|||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CONFIG_DIR="$HOME/.codex"
|
CONFIG_DIR="${CODEX_HOME:-$HOME/.codex}"
|
||||||
CONFIG_FILE="$CONFIG_DIR/config.toml"
|
CONFIG_FILE="$CONFIG_DIR/config.toml"
|
||||||
|
|
||||||
mkdir -p "$CONFIG_DIR"
|
mkdir -p "$CONFIG_DIR"
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import pathlib
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
REPO_ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigDirTests(unittest.TestCase):
|
||||||
|
def test_codex_ps1_prefers_codex_home(self) -> None:
|
||||||
|
content = (REPO_ROOT / "codex.ps1").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
self.assertIn('$ConfigDir = if ([string]::IsNullOrWhiteSpace($env:CODEX_HOME))', content)
|
||||||
|
self.assertIn('$env:CODEX_HOME', content)
|
||||||
|
self.assertIn('Join-Path $HOME ".codex"', content)
|
||||||
|
|
||||||
|
def test_codex_sh_prefers_codex_home(self) -> None:
|
||||||
|
content = (REPO_ROOT / "codex.sh").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
self.assertIn('CONFIG_DIR="${CODEX_HOME:-$HOME/.codex}"', content)
|
||||||
|
|
||||||
|
def test_claude_ps1_prefers_claude_config_dir(self) -> None:
|
||||||
|
content = (REPO_ROOT / "claude.ps1").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
self.assertIn('$SettingsDir = if ([string]::IsNullOrWhiteSpace($env:CLAUDE_CONFIG_DIR))', content)
|
||||||
|
self.assertIn('$env:CLAUDE_CONFIG_DIR', content)
|
||||||
|
self.assertIn('Join-Path $HOME ".claude"', content)
|
||||||
|
|
||||||
|
def test_claude_sh_prefers_claude_config_dir(self) -> None:
|
||||||
|
content = (REPO_ROOT / "claude.sh").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
self.assertIn('SETTINGS_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"', content)
|
||||||
|
|
||||||
|
def test_readme_documents_environment_overrides(self) -> None:
|
||||||
|
content = (REPO_ROOT / "README.md").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
self.assertIn("`CODEX_HOME`", content)
|
||||||
|
self.assertIn("`CLAUDE_CONFIG_DIR`", content)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Reference in new issue
Block a user