feat(agents): прокси для Codex и Claude задаётся в их настройках

- Зачем: прокси из окружения запуска до API не доходил. Запросы Codex
  отправляет общий демон app-server, и маршрут зависел от того, кто запустил
  демон первым. Нужно было и обратное: Codex и Claude должны работать без
  прокси, даже если запускающее приложение его задало.
- Что: шаблоны codex/proxy.env (копируется в ~/.codex/.env) и
  claude/proxy-settings.json (блок env добавляется в ~/.claude/settings.json).
  По умолчанию прокси 127.0.0.1:12334. install.sh не трогает выбор, уже
  сделанный на машине. В README описано, как переключить машину на работу
  без прокси.
- Проверка: tests/test_install.sh и tests/test_proxy_env_sync.py проходят.
  Вручную: значения из ~/.codex/.env и из env в настройках Claude перекрывают
  унаследованные переменные; codex doctor проходит через Xray; очищенные
  адреса вместе с NO_PROXY=* дают прямое подключение.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ddadminandClaude Opus 5.5 committed 2026-10-14 18:00:55 +02:00
1 parent d19239bf31
commit d65403efb5
5 files changed
+213 -4

No files matched your search

+69
View File
@@ -497,12 +497,81 @@ if [ -d "$SKILLS_SRC" ]; then
ensure_symlink "$SKILLS_SRC" "$HOME/.claude/skills"
fi
# Прокси для Claude Code: блок env из claude/proxy-settings.json добавляется в
# ~/.claude/settings.json. Значения из env перекрывают унаследованное окружение.
# Если в env уже есть хоть одна proxy-переменная, файл не трогаем: машинный
# выбор (свой адрес или очищенные значения) важнее шаблона.
CLAUDE_PROXY_SRC="$DOTFILES_DIR/claude/proxy-settings.json"
CLAUDE_SETTINGS="$HOME/.claude/settings.json"
if [ -f "$CLAUDE_PROXY_SRC" ]; then
if [ -L "$CLAUDE_SETTINGS" ]; then
warn "~/.claude/settings.json — симлинк, прокси не добавляю"
elif ! command -v python3 &>/dev/null; then
warn "python3 не найден, прокси в ~/.claude/settings.json не добавлен"
else
claude_proxy_status=0
python3 -I - "$CLAUDE_PROXY_SRC" "$CLAUDE_SETTINGS" <<'PY' || claude_proxy_status=$?
import json
import os
import sys
import tempfile
src, dst = sys.argv[1:3]
with open(src, encoding="utf-8") as f:
template = json.load(f)["env"]
settings = {}
if os.path.exists(dst):
try:
with open(dst, encoding="utf-8") as f:
settings = json.load(f)
except ValueError:
sys.exit(2)
if not isinstance(settings, dict) or not isinstance(settings.get("env", {}), dict):
sys.exit(2)
env = settings.setdefault("env", {})
if any(key.lower() in ("http_proxy", "https_proxy", "all_proxy", "no_proxy") for key in env):
sys.exit(3)
env.update(template)
mode = os.stat(dst).st_mode & 0o777 if os.path.exists(dst) else 0o600
fd, tmp = tempfile.mkstemp(dir=os.path.dirname(dst), prefix=".settings.json.")
with os.fdopen(fd, "w", encoding="utf-8") as f:
json.dump(settings, f, indent=2, ensure_ascii=False)
f.write("\n")
os.chmod(tmp, mode)
os.replace(tmp, dst)
PY
case "$claude_proxy_status" in
0) info "В ~/.claude/settings.json добавлен прокси 127.0.0.1:12334" ;;
3) info "В ~/.claude/settings.json прокси уже задан, оставляю как есть" ;;
2) warn "~/.claude/settings.json не разобран как JSON-объект, прокси не добавлен" ;;
*) warn "Не удалось добавить прокси в ~/.claude/settings.json" ;;
esac
fi
fi
# ── Codex ────────────────────────────────────────────────────────────
# Пакета в репозитории нет: ~/.codex — обычный каталог, его заполняет Codex.
# Миграция раскрывает старый свёрнутый симлинк и переносит рантайм-данные.
migrate_folded_symlink "$HOME/.codex" .gitkeep
# ~/.codex/.env Codex читает при старте, и его значения перекрывают
# унаследованное окружение. По умолчанию кладём прокси на 127.0.0.1:12334.
# Готовый файл на машине не трогаем: где прокси не нужен, его очищают вручную.
CODEX_ENV_SRC="$DOTFILES_DIR/codex/proxy.env"
if [ -f "$CODEX_ENV_SRC" ]; then
mkdir -p "$HOME/.codex"
if [ -e "$HOME/.codex/.env" ] || [ -L "$HOME/.codex/.env" ]; then
info "~/.codex/.env уже есть, оставляю как есть"
else
cp "$CODEX_ENV_SRC" "$HOME/.codex/.env"
info "Создан ~/.codex/.env: Codex работает через прокси 127.0.0.1:12334"
fi
fi
# ── Bash: .bashrc ────────────────────────────────────────────────────
BASHRC="$HOME/.bashrc"