- Зачем: - claude/codex CLI должны гарантированно ходить через hproxy.local, а ручной proxy_on легко забыть. - Что: - добавлен spec docs/superpowers/specs/2026-05-19-proxy-cli-launchers-design.md. - описаны команды pclaude/pcodex с fail-fast pre-flight для Linux (bash) и Windows (PowerShell). - честная формулировка цели (удобство + best-effort), зафиксировано проверенное допущение о proxy-env. - добавлены секция «Известные ограничения» (аддитивность, TOCTOU), PS-passthrough и регресс-тест proxy_on. - Проверка: - git show --stat HEAD.
12 KiB
Дизайн: pclaude / pcodex — явный запуск claude/codex CLI через прокси
Дата: 2026-05-19 Статус: утверждён (дизайн), ожидает плана реализации
Проблема
claude и codex CLI должны ходить в сеть через прокси
(hproxy.local:12334). Сейчас это обеспечивается ручным proxy_on в текущем
shell — легко забыть, и тогда трафик уходит мимо прокси.
Цель и подход
Цель — удобство и best-effort, а не сетевая гарантия: дать одну явную
команду, после которой не нужно помнить про proxy_on и которая не стартует
молча, если прокси недоступен. Это не fail-closed изоляция — голые
claude/codex по-прежнему могут уйти мимо прокси (см. «Известные
ограничения»).
Проверенное допущение: claude и codex уважают
HTTP(S)_PROXY/ALL_PROXY — подтверждено эмпирически (ежедневная работа в
этом режиме). На этом стоит весь env-подход; spike не требуется.
Ввести отдельные явные команды pclaude и pcodex. Бинарники
claude/codex не переименовываются и не перекрываются — явное p-имя
выражает намерение и исключает риск «где-то нет алиаса → запуск мимо прокси».
Подход — convenience-обёртка (не сетевая изоляция):
- выставить proxy-env только для дочернего процесса (не загрязняя родительский shell/сессию);
- fail-fast pre-flight: перед запуском быстро проверить, что
hproxy.local:12334доступен; если нет — не запускать, выдать понятную ошибку и ненулевой код возврата. Семантика проверки — reachability (порт прокси открыт), а не доказательство, что трафик реально проксируется; последнее покрывается проверенным допущением выше. Таймаут вынесен в переменную (PROXY_PREFLIGHT_TIMEOUT, дефолт 2 c).
Реализация на двух платформах:
- Linux/WSL bash;
- Windows native PowerShell.
Эндпоинт прокси один и тот же на обеих платформах (hproxy.local:12334) и
переиспользуется из уже существующих proxy_on.
Не входит в объём (YAGNI)
- Сетевая изоляция / firewall / network namespace (fail-closed).
- Перекрытие/переименование оригинальных
claude/codex. - Поддержка не-PowerShell оболочек на Windows (cmd.exe и т.п.).
- Изменение существующего поведения
proxy_on/proxy_off/myip.
Ключевой принцип: единый источник правды
Эндпоинт прокси сейчас захардкожен в proxy_on дважды (bash и PS-профиль).
Чтобы pclaude/pcodex не размножили константы ещё в нескольких местах,
значения выносятся в небольшой внутренний хелпер в каждом файле, и
существующий proxy_on рефакторится на этот же хелпер. Это единственный
сопутствующий рефактор, ограниченный задачей.
Компоненты — Linux
Файл: bash/.bash_functions (stow → ~/.bash_functions, уже подключается
через ~/.bash_custom). Новых установочных шагов нет.
_proxy_export()— внутренний. ЭкспортируетHTTP_PROXY,HTTPS_PROXY,ALL_PROXY,NO_PROXY(+ lower-case дубли) из единого набора локальных переменных.proxy_on()рефакторится так, чтобы вызывать_proxy_export; его эхо и проверка внешнего IP остаются без изменений._proxy_reachable()— TCP-connect кhproxy.local:12334с таймаутом${PROXY_PREFLIGHT_TIMEOUT:-2}c (timeout "$t" bash -c '... >/dev/tcp/hproxy.local/12334'). Возвращает 0/1, ничего не печатает. Таймаут покрывает и медленный DNS-резолвhproxy.local(при зависании резолва — false-negative и отказ запуска, что является безопасным направлением отказа)._proxy_run <cmd> [args…]:_proxy_reachable→ при неудаче печатает понятное сообщение (рус., стиль существующих❌/✅),return 1, бинарник не запускается;- проверка наличия
<cmd>в PATH (command -v) → при отсутствии отдельное понятное сообщение, ненулевой код; - запуск в subshell:
( _proxy_export; exec command "<cmd>" "$@" )— proxy-env виден только дочернему процессу, не протекает в родительский shell; код возврата пробрасывается.
pclaude() { _proxy_run claude "$@"; }pcodex() { _proxy_run codex "$@"; }
Компоненты — Windows
Файл: chezmoi/dot_config/powershell/profile.ps1 (уже доставляется chezmoi и
подключается через Microsoft.PowerShell_profile.ps1.tmpl). Новых
установочных шагов нет.
-
Set-ProxyEnv— внутренний. СтавитHTTP_PROXY,HTTPS_PROXY,ALL_PROXY,NO_PROXYиз единого источника.proxy_onрефакторится на него (его вывод/Get-PublicIpне меняются). -
Test-ProxyReachable—System.Net.Sockets.TcpClientкhproxy.local:12334с таймаутом ~2 c. Возвращает$true/$false. -
Invoke-WithProxy -Exe <name> -CmdArgs $args:- pre-flight
Test-ProxyReachable→ при неудачеWrite-Error+ return, не запускать; - проверка
Get-Command <name>→ при отсутствии понятная ошибка; - сохранить текущие значения 4 env-переменных;
Set-ProxyEnv;& $Exe @CmdArgs; вfinallyвосстановить прежние значения env (сессия не остаётся с включённым прокси — поведение симметрично subshell в bash); пробросить$LASTEXITCODE.
- pre-flight
-
function pclaude { Invoke-WithProxy claude @args }function pcodex { Invoke-WithProxy codex @args }Passthrough аргументов — known footgun PowerShell. Флаги вида
-p,--modelмогут перехватываться парсером PS как параметры обёртки. Требование:Invoke-WithProxyобъявляет[Parameter(ValueFromRemainingArguments)]на$CmdArgs, обёртки передают@args(splatting, не$args), внутри —& $Exe @CmdArgs. Обязательные тест-кейсы при реализации:pclaude -p "...",pclaude --model ...,pcodex --help, аргумент с пробелами и с--.
Обработка ошибок
| Ситуация | Поведение |
|---|---|
Прокси hproxy.local:12334 недоступен |
Понятное сообщение, ненулевой код, запуск не происходит |
claude/codex нет в PATH |
Отдельное понятное сообщение, ненулевой код |
| Аргументы с пробелами/спецсимволами | Сохраняются ("$@" / @args-splatting) |
NO_PROXY |
Берётся существующий список платформы как есть (bash: с ::1/[::1]; PS: без) — существующее поведение не меняется |
Известные ограничения
Принимаются осознанно (следствие выбранного convenience-подхода):
- Аддитивность. Голые
claude/codexостаются доступны и идут мимо прокси без предупреждения. Фича снижает вероятность ошибки, но не устраняет её — это удобство, не гарантия. - TOCTOU. Pre-flight проверяет доступность только в момент старта.
Для долгой интерактивной сессии
claudeпрокси может упасть позже — обёртка этого не отследит. - Pre-flight ≠ доказательство проксирования. Проверяется открытость порта, не факт, что инструмент использует прокси (закрыто проверенным допущением о поведении claude/codex, не самим preflight).
Деплой
Ноль новых установочных шагов. Оба целевых файла уже доставляются (stow /
chezmoi) и подключены в shell-профилях. run_-скрипты chezmoi не требуются.
Тестирование
Зеркалит существующий стиль (tests/test_install.sh — простой bash +
assert-хелперы, без bats).
Новый tests/test_proxy_launchers.sh:
_proxy_runпри недоступном прокси не вызывает бинарник и возвращает ненулевой код (мок проверки доступности + мокcommand/PATH);- proxy-env реально выставлены в дочернем процессе и не протекают в родительский shell;
- проброс кода возврата дочернего процесса;
- аргументы с пробелами и
--доходят до бинарника без искажений; - регресс
proxy_on: после рефактора на общий хелперproxy_onэкспортирует ровно тот же набор переменных (включая lower-case дубли и тот жеNO_PROXY), что и до рефактора — снимок до/после; shellcheckнаbash/.bash_functions.
Windows-часть — без авто-тестов (нет CI под Windows). Ручной чеклист в
плане: pclaude/pcodex запускаются; при остановленном прокси fail-fast
срабатывает; env не остаётся в сессии после выхода (в т.ч. после Ctrl-C —
если finally не отработал, прокси остаётся включённым: безопасное
направление отказа); passthrough-кейсы pclaude -p "...",
pcodex --help, аргумент с пробелами; proxy_on/proxy_off после
рефактора ведут себя как прежде.