# proxy-client `proxy-client` — переносимый Linux/Bash-интерфейс для запуска команд через внешний прокси или через управляемый пользовательский Xray. Он добавляет команды `proxy_on`, `proxy_off`, `pclaude` и `pcodex`, но не подменяет обычные `claude` и `codex`. CLI требует Python 3.8+ и использует только стандартную библиотеку. Он не запускает Xray и не переключает режим прокси без явной команды пользователя. ## Установка ### Только пакет `proxy-client` Скопируйте каталог в постоянное место и запустите пакетный установщик. Текущий рабочий каталог не важен: ```bash ~/src/proxy-client/install.sh ``` Установщик создаёт три ссылки на исходный каталог: CLI, Bash-модуль и каталог шаблонов. Поэтому исходный каталог после установки нельзя перемещать. Если какой-то из путей уже занят чужим файлом или ссылкой, установщик ничего не меняет и перечисляет все такие пути. Повторный запуск безопасен. По умолчанию установщик дописывает в `~/.bashrc` блок между строками `# >>> proxy-client >>>` и `# <<< proxy-client <<<`: он добавляет `~/.local/bin` в `PATH` и подключает Bash-модуль. Если блок уже есть, файл не меняется. После установки откройте новый Bash или примените блок в текущей сессии: ```bash source ~/.bashrc ``` Чтобы оставить `~/.bashrc` без изменений, запустите: ```bash ~/src/proxy-client/install.sh --no-shell-setup ``` В этом случае подготовьте только текущую сессию вручную: ```bash export PATH="$HOME/.local/bin:$PATH" source ~/.config/proxy-client/shell.bash ``` Для следующих сессий добавьте эти строки в подходящий Bash-конфиг сами. Установщик не создаёт машинный `config` и закрытый `default.url`, не устанавливает Xray и не проверяет сеть. После подключения команд выберите режим по разделу [«Настройка режима»](#настройка-режима). Без машинного конфига действует режим Hiddify по умолчанию. ### В составе dotfiles Корневой установщик dotfiles подключает тот же пакет через Stow и загружает Bash-функции в новых интерактивных сессиях: ```bash cd ~/dotfiles ./install.sh ``` Он заранее создаёт `~/.local/bin` и `~/.config/proxy-client`, чтобы Stow размещал ссылки внутри них, а не превращал сами каталоги в ссылки на репозиторий. После установки откройте новый Bash или выполните: ```bash export PATH="$HOME/.local/bin:$PATH" source ~/.bash_custom ``` Если `~/.local/bin` отсутствует в `PATH` и в новых сессиях, добавьте ту же строку `export` в свой Bash-конфиг: корневой установщик dotfiles его не изменяет. ## Как выбирается прокси Режим определяется только машинным файлом `~/.config/proxy-client/config`: | Машинный конфиг | Используется | Что запускать | |-----------------|-------------|---------------| | Файла нет | Hiddify на `hproxy.local:12334` | Ничего | | `type = external` | Указанный внешний прокси | Ничего | | `type = xray` | Управляемый локальный Xray | `proxy-client start` | Доступность процесса не меняет выбранный режим. Если в конфиге указан Xray, но он не запущен, `status`, `env`, `run`, `proxy_on`, `pclaude` и `pcodex` завершатся с ошибкой. Автоматического перехода на Hiddify или другой прокси нет. Текущий выбор и доступность проверяет команда: ```bash proxy-client status ``` ## Настройка режима ### Hiddify в Windows, команды в WSL Это режим по умолчанию. Если Hiddify доступен из WSL как `hproxy.local:12334`, создавать `config` не нужно: ```bash getent hosts hproxy.local proxy-client status pclaude --version ``` #### WSL NAT mode IP Windows-шлюза меняется при перезапуске WSL, поэтому `hproxy.local` нужно обновлять. В отдельно скопированном пакете системных помощников нет. Узнайте адрес шлюза: ```bash ip route show default | awk 'NR == 1 {print $3}' ``` Затем откройте `/etc/hosts` через `sudoedit` и оставьте одну отдельную строку с полученным адресом: ```bash sudoedit /etc/hosts ``` ```text <адрес-шлюза> hproxy.local ``` Не удаляйте другие имена на той же строке: при необходимости перенесите их на отдельную строку. Повторяйте обновление после перезапуска WSL. С полным dotfiles запустите корневой `~/dotfiles/install.sh` интерактивно: он предложит автоматическое обновление при старте WSL. Обновить адрес сразу можно так: ```bash sudo ~/dotfiles/scripts/setup-hproxy.sh # после настройки автозапуска и загрузки общих Bash-функций: update_hproxy ``` В NAT mode Hiddify должен слушать адрес, доступный через Windows-шлюз, а не только `127.0.0.1`. #### WSL mirrored mode В [mirrored mode](https://learn.microsoft.com/windows/wsl/networking#mirrored-mode-networking) (`networkingMode=mirrored`) Windows-сервисы доступны из WSL через `127.0.0.1`. Чтобы сохранить адрес по умолчанию, добавьте алиас в Windows hosts: ```text # C:\Windows\System32\drivers\etc\hosts 127.0.0.1 hproxy.local ``` Альтернатива — настройте внешний режим по следующему разделу и укажите `address = 127.0.0.1`. Алиас проверяйте через `getent hosts hproxy.local`, а активный конфиг — через `proxy-client status`. ### Другой внешний прокси Скопируйте пример и измените адрес, порт и локальные исключения: ```bash cp ~/.config/proxy-client/examples/config.external \ ~/.config/proxy-client/config ``` ```ini [proxy] type = external name = Office proxy address = proxy.example.internal port = 12334 no_proxy_extra = .example.internal,git.example.internal ``` Для внешнего прокси на той же Linux-машине можно указать `127.0.0.1` напрямую. ### Локальный Xray Создайте машинный конфиг: ```bash cp ~/.config/proxy-client/examples/config.xray \ ~/.config/proxy-client/config ``` Закрытый профиль должен содержать ровно одну VLESS-ссылку: ```bash cp ~/.config/proxy-client/examples/default.url \ ~/.config/proxy-client/default.url $EDITOR ~/.config/proxy-client/default.url chmod 600 ~/.config/proxy-client/default.url ``` Установите проверенную версию Xray без root: ```bash proxy-client install ``` Запустите Xray в отдельном терминале или панели tmux: ```bash proxy-client start ``` Другой закрытый профиль можно выбрать без замены `default.url`: ```bash proxy-client start -f ~/.config/proxy-client/work.url ``` Для переключения профиля сначала выполните `proxy-client stop`. Все файлы с настоящими VLESS-ссылками должны иметь права `600` и не должны попадать в Git. ## Ежедневное использование | Задача | Команда | Область действия | |--------|---------|------------------| | Запустить Claude через прокси | `pclaude [ARG...]` | Только дочерний процесс | | Запустить Codex через прокси | `pcodex [ARG...]` | Только дочерний процесс | | Запустить другую команду | `proxy-client run -- COMMAND ARG...` | Только дочерний процесс | | Включить прокси | `proxy_on` | Текущая Bash-сессия | | Выключить прокси | `proxy_off` | Текущая Bash-сессия | | Проверить прокси | `proxy-client status` | Без изменения окружения | | Получить proxy-переменные | `proxy-client env` | Машинный вывод в stdout | | Показать внешний IP | `myip` | С учётом текущего окружения | `run`, `pclaude` и `pcodex` передают дочернему процессу восемь вариантов `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY` и `NO_PROXY`, включая имена в нижнем регистре. После завершения команды переменные не остаются в оболочке. `proxy_on` применяет те же переменные к текущей Bash-сессии только после успешной проверки прокси. `proxy_off` удаляет их. Обычные `claude` и `codex` не обёрнуты и не выполняют предварительную проверку, но после `proxy_on` наследуют прокси-переменные, как и любой другой дочерний процесс. ### Жизненный цикл Xray ```bash proxy-client install [--replace] proxy-client start [-f PROFILE] proxy-client status proxy-client stop ``` `start` сначала проверяет версию и конфигурацию Xray, затем остаётся на переднем плане. Systemd, фоновый автозапуск и скрытый запуск из `run` не используются. Один loopback-порт принимает HTTP CONNECT и SOCKS5. Остановить Xray можно двумя способами: `Ctrl+C` в окне `start` или `proxy-client stop` из любого терминала. Оба гасят Xray и удаляют служебные файлы. Если процесс `start` был убит (например, закрыли окно tmux), Xray может остаться работать: `status` и `env` тогда сообщат об ошибке, а `stop` добьёт его и уберёт файлы. `stop` работает и после изменения машинного типа на `external`. Второй `start`, пока первый работает, завершится ошибкой. ## Диагностика Начните с проверки выбранного режима: ```bash proxy-client status ``` Для внешнего Hiddify в WSL проверьте имя и порт: ```bash getent hosts hproxy.local curl --proxy http://hproxy.local:12334 https://example.com curl --proxy socks5h://hproxy.local:12334 https://example.com ``` Для запущенного Xray можно дополнительно проверить созданный JSON: ```bash xray run -test -c \ "${XDG_STATE_HOME:-$HOME/.local/state}/proxy-client/client.json" ``` Если выбран `type = xray`, но процесс не запущен, запустите его отдельно — `proxy_on` и `run` этого не делают. Профиль XHTTP с ALPN `h3` требует доступного UDP-маршрута до сервера; автоматического перехода на H2 нет. Таймаут предварительной проверки по умолчанию равен двум секундам. Его можно изменить положительным числом: ```bash export PROXY_PREFLIGHT_TIMEOUT=5 ``` ## Справочник ### Ручное подключение без установщика Если пакетный установщик запустить нельзя, выберите постоянный абсолютный путь к исходному каталогу и создайте те же ссылки вручную. Команды предполагают, что назначения ещё не заняты: ```bash mkdir -p ~/.local/bin ~/.config/proxy-client ln -s /absolute/path/to/proxy-client/.local/bin/proxy-client \ ~/.local/bin/proxy-client ln -s /absolute/path/to/proxy-client/.config/proxy-client/shell.bash \ ~/.config/proxy-client/shell.bash ln -s /absolute/path/to/proxy-client/.config/proxy-client/examples \ ~/.config/proxy-client/examples chmod 755 /absolute/path/to/proxy-client/.local/bin/proxy-client ``` Подготовьте текущую Bash-сессию: ```bash export PATH="$HOME/.local/bin:$PATH" source ~/.config/proxy-client/shell.bash ``` Для следующих сессий добавьте эти две строки в свой Bash-конфиг. Исходный каталог после этого нельзя перемещать: созданные ссылки зависят от его пути. ### Машинный конфиг Формат строгий: одна секция `[proxy]` и пять обязательных ключей без повторов и неизвестных полей: - `type` — `external` или `xray`; - `name` — имя для диагностики; - `address` — IPv4, IPv6 без квадратных скобок или ASCII DNS-имя без схемы и порта; - `port` — TCP-порт локального входа; - `no_proxy_extra` — IP и домены через запятую, значение может быть пустым. Список **замещает** встроенный `DEFAULT_NO_PROXY_EXTRA` целиком, а не дополняет его: домены, нужные постоянно, придётся перечислить здесь заново. Поддержка CIDR в `NO_PROXY` различается между программами, поэтому надёжнее указывать точные IP и домены. Без машинного файла внешний режим дополнительно включает `.concept-software.ru`, `dementev.space` и `.dementev.space` в `NO_PROXY`. Для `type = xray` адрес обязан быть адресом обратной петли, например `127.0.0.1` или `::1`. ### Поддерживаемые профили Поддерживаются VLESS TCP/RAW с REALITY и VLESS XHTTP с TLS. Неизвестные, повторные и несовместимые query-параметры отклоняются. XHTTP поддерживает ALPN `http/1.1`, `h2` и `h3`; `extra` должен быть JSON-объектом, его содержимое проверяет `xray run -test`. Кроме `encryption=none`, принимается VLESS-шифрование `encryption=mlkem768x25519plus.…` из новых ссылок Hiddify; остальную часть значения проверяет сам Xray. Только с таким шифрованием XHTTP допускает `flow=xtls-rprx-vision`. Косая черта перед параметрами (`…:443/?type=…`) допустима, другой путь в ссылке — нет. Xray 26.3.27 использует `pcs` и `vcn`. Устаревшие `allowInsecure` и `insecure` принимаются с любым значением, но не переносятся: при значении `1` или `true` выводится предупреждение, а сертификат проверяется обычным способом. Последняя версия Xray, где `allowInsecure` ещё применяется, — [25.12.8](https://github.com/XTLS/Xray-core/releases/tag/v25.12.8); опция удалена в [26.2.6](https://github.com/XTLS/Xray-core/releases/tag/v26.2.6). `proxy-client` эти версии не поддерживает и не устанавливает. ### Проверяемая установка Xray `proxy-client install` устанавливает Xray 26.3.27 в `~/.local/bin/xray`. Для `x86_64`/`amd64` используется `Xray-linux-64.zip`, для `aarch64`/`arm64` — `Xray-linux-arm64-v8a.zip`; остальные архитектуры отклоняются. CLI скачивает официальный архив и файл `.dgst`, сверяет SHA-256 и фактическую версию бинарника, а затем атомарно заменяет назначение. При любой ошибке старый файл остаётся на месте. Если нужная версия уже установлена, сеть не нужна и ничего не меняется. Другой файл или симлинк не заменяется без `--replace` (симлинк заменяется сам, файл по ссылке не трогается); каталог не заменяется никогда. Если после установки `PATH` находит другой `xray`, `install` сообщает об ошибке и подсказывает команду. Устанавливать можно и при работающем Xray: он продолжит работу со старым файлом, а `install` напомнит перезапустить `start`. `start` использует первый `xray` из `PATH` и принимает только версию 26.3.27. ### Файлы и безопасность | Путь | Назначение | |------|------------| | `~/.config/proxy-client/config` | Несекретный машинный выбор режима | | `~/.config/proxy-client/default.url` | Закрытая VLESS-ссылка, права `600` | | `~/.config/proxy-client/examples/` | Синтетические примеры без секретов | | `$XDG_STATE_HOME/proxy-client/` или `~/.local/state/proxy-client/` | Состояние и сгенерированный JSON | Сводка скрывает UUID и ключи, а для XHTTP показывает только длину `path`. Если файл профиля доступен другим пользователям, `start` не запустится и покажет готовую команду `chmod 600` для конечного файла (у симлинка — для файла, на который он указывает). Служебный каталог закрыт для других пользователей (`700`, файлы в нём — `600`) и очищается после остановки Xray. Сбой определения внешнего IP показывается как предупреждение и не останавливает уже готовый процесс. ## Изменение кода Перед правкой proxy-client прочитайте [спецификацию](../docs/specs/2026-07-15-proxy-client-design.md): там сказано, от чего клиент защищается, от чего нет и почему, и где живут тесты. Все тесты пакета (из корня dotfiles): ```bash tests/test_proxy_client_full.sh ```