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`
|
||||
- 配置 `XIXU_API_KEY` 环境变量
|
||||
|
||||
@@ -16,20 +16,18 @@
|
||||
|
||||
会自动完成以下操作:
|
||||
|
||||
- 写入 `~/.claude/settings.json`
|
||||
- 写入 Claude Code 配置文件
|
||||
- 配置 `ANTHROPIC_AUTH_TOKEN`
|
||||
- 配置 `ANTHROPIC_BASE_URL`
|
||||
- 配置默认模型为 `gpt-5.4`
|
||||
|
||||
---
|
||||
|
||||
## Codex
|
||||
|
||||
### Linux/macOS
|
||||
|
||||
```bash
|
||||
bash <(curl -fsSL https://github.com/xixu-me/provider-setup/raw/refs/heads/main/codex.sh)
|
||||
````
|
||||
```
|
||||
|
||||
### 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))"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Claude Code
|
||||
|
||||
### 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))"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 配置内容
|
||||
|
||||
### Codex
|
||||
@@ -72,7 +66,7 @@ env_key = "XIXU_API_KEY"
|
||||
|
||||
### Claude Code
|
||||
|
||||
写入到 `~/.claude/settings.json` 的 `env`:
|
||||
写入到目标 `settings.json` 的 `env`:
|
||||
|
||||
```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
|
||||
|
||||
```bash
|
||||
cat ~/.codex/config.toml
|
||||
cat "${CODEX_HOME:-$HOME/.codex}/config.toml"
|
||||
echo $XIXU_API_KEY
|
||||
```
|
||||
|
||||
#### Windows 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
|
||||
[System.Environment]::GetEnvironmentVariable("XIXU_API_KEY","User")
|
||||
```
|
||||
@@ -123,11 +120,24 @@ $env:XIXU_API_KEY
|
||||
#### Linux/macOS
|
||||
|
||||
```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
|
||||
|
||||
```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"
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $SettingsDir | Out-Null
|
||||
|
||||
@@ -13,7 +13,7 @@ if [[ -z "$API_KEY" ]]; then
|
||||
echo
|
||||
fi
|
||||
|
||||
SETTINGS_DIR="$HOME/.claude"
|
||||
SETTINGS_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
|
||||
SETTINGS_FILE="$SETTINGS_DIR/settings.json"
|
||||
|
||||
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"
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null
|
||||
|
||||
@@ -13,7 +13,7 @@ if [[ -z "$API_KEY" ]]; then
|
||||
echo
|
||||
fi
|
||||
|
||||
CONFIG_DIR="$HOME/.codex"
|
||||
CONFIG_DIR="${CODEX_HOME:-$HOME/.codex}"
|
||||
CONFIG_FILE="$CONFIG_DIR/config.toml"
|
||||
|
||||
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