diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..958b047 --- /dev/null +++ b/LICENSE @@ -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. diff --git a/README.md b/README.md index 692bf87..8695361 100644 --- a/README.md +++ b/README.md @@ -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). diff --git a/claude.ps1 b/claude.ps1 index 69463e9..3523cf5 100644 --- a/claude.ps1 +++ b/claude.ps1 @@ -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 diff --git a/claude.sh b/claude.sh index fc16807..32bc3d1 100644 --- a/claude.sh +++ b/claude.sh @@ -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" diff --git a/codex.ps1 b/codex.ps1 index 79a508a..c154c81 100644 --- a/codex.ps1 +++ b/codex.ps1 @@ -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 diff --git a/codex.sh b/codex.sh index d60a242..72f77b8 100644 --- a/codex.sh +++ b/codex.sh @@ -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" diff --git a/tests/test_config_dirs.py b/tests/test_config_dirs.py new file mode 100644 index 0000000..f2cae29 --- /dev/null +++ b/tests/test_config_dirs.py @@ -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()