Спецификация 603 → 220 строк: без описаний снятых защит и без пересказа кода и README; остались задача, границы, решения с причинами и риски. В README раздел «Изменение кода» ведёт к спецификации и тестам. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
15 KiB
proxy-client для агентских CLI
Дата: 2026-07-15
Статус: реализовано; 2026-09-28 упрощено по принципу ниже
Точное поведение, форматы, сообщения и команды описаны в коде,
proxy-client --help и proxy-client/README.md.
Здесь — то, чего по коду не видно: задача, границы, выбор и его причины, риски.
Принцип: личный инструмент
proxy-client пользуются владелец и несколько друзей на своих машинах. Код
защищается от реальных ошибок и опасностей:
- скачанный Xray проверяется по SHA-256 и заменяется атомарно;
- секреты профиля не попадают в вывод, служебные файлы закрыты правами 600/700;
- локальный порт Xray слушает только loopback;
- чужие файлы не перезаписываются;
- сигнал уходит только процессам из
state.json: Xray — если его/proc/PID/exeсовпадает с запущенным файлом, супервизору — если Xray подтверждён и в командной строке супервизора естьproxy-client.
Пользователь и его собственные файлы — не противник. Сообщение об ошибке называет файл полным путём и подсказывает готовую команду.
Новая защита появляется вместе со сценарием, который реально случается у
пользователя, и этот сценарий записывается рядом с ней. Так же проверяется и
прежний код: в 2026-09-28 убраны защиты без такого сценария — повторное
использование PID, подложный state.json, zip-бомба в проверенном архиве,
гонка status с параллельным start.
Тесты проверяют поведение через команду proxy-client, разбор ссылки
(parse_vless + build_xray_config), установку Xray с подставным
скачивателем, функции Bash с поддельным PROXY_CLIENT_BIN и установщик пакета
во временном HOME.
Проблема
На удалённых Linux-серверах нет GUI-клиента Hiddify. Перед запуском Claude Code или Codex приходится вручную запускать Xray и выставлять proxy-переменные. Переменные легко забыть, и агент стартует без прокси.
Нужны привычные команды pclaude и pcodex, которые не запускают агента,
если явно настроенный прокси недоступен. Решение работает и в составе этого
репозитория, и отдельно от остальных dotfiles.
Контекст
Прежний дизайн
pclaude / pcodex
задаёт договор: proxy-переменные видны только дочернему процессу, аргументы и
код возврата сохраняются, недоступный прокси — отказ до запуска агента. Эта
спецификация заменяет его Linux-часть; Windows-часть не меняется.
Xray принимает конфигурационные файлы, а не vless://-ссылки. Его SOCKS-вход
принимает SOCKS и HTTP на одном порту, поэтому прежняя схема proxy-переменных
подходит локальному Xray без второго порта. См.
командную строку Xray и
SOCKS-вход.
Цели
- Управляемый пользовательский Xray на Linux-сервере без systemd и root.
- Явные
pclaudeиpcodex, которые нельзя случайно запустить через другой прокси или без прокси. - Одна VLESS-ссылка Hiddify превращается в клиентский JSON Xray.
- Внешний Hiddify работает, как раньше.
- Машинный
NO_PROXYнастраивается без правки файлов репозитория. - Каталог
proxy-client/можно скопировать отдельно и поставить своим установщиком, без остальных dotfiles и без Stow.
Не входит в объём
- Windows, PowerShell, Windows Codex launcher и VS Code Server.
- systemd, автозапуск, sudo, firewall, TUN и системная маршрутизация.
- Автоматический выбор между Xray и Hiddify или запасной прокси.
- Несколько одновременных профилей у одного Unix-пользователя.
- Импорт подписок или полного JSON-экспорта Hiddify.
- Протоколы за пределами двух поддержанных семейств VLESS.
- pip, venv и сторонние Python-библиотеки.
- Сетевая изоляция голых
claudeиcodex: намерение выражают команды с префиксомp.
Рассмотренные варианты
- Только Bash. URL-кодирование, JSON, контрольные суммы и управление процессом делают Bash хрупким и плохо тестируемым.
- Bash-контроллер и Python-преобразователь. Граница между двумя языками усложняет ошибки, тесты и единый источник настроек.
- Один Python CLI и тонкий Bash-модуль. Выбран. Python отвечает за данные, установку Xray, процессы и запуск дочерних команд. Bash нужен только там, где меняется окружение текущей shell-сессии.
- Без менеджера: готовые JSON и Xray вручную в tmux. Почти нет кода, но не
решает главного — безопасного
pclaude/pcodexиз ссылки Hiddify.
Для отдельно скопированного пакета рассматривались: только инструкция для
ручных ссылок (легко забыть шаги), копирование файлов в $HOME (сложно
обновлять), обязательный Stow (лишняя зависимость на серверах) и свой
установщик. Выбран свой установщик, который ставит прямые ссылки: один способ,
нет второй копии файлов.
Решение
Компоненты
proxy-client — один исполняемый файл на Python 3.8+ без внешних библиотек:
установка Xray, запуск и остановка, проверка доступности, разбор VLESS, запуск
дочерней команды через прокси. Команды: install, start, stop, status,
env, run. Без подкоманды ничего не делается.
shell.bash — единственный владелец proxy_on, proxy_off, pclaude,
pcodex и myip; в bash/.bash_functions их нет, чтобы не зависеть от
порядка source. Модуль сам конфиг не читает:
pclaudeиpcodexвызываютproxy-client run -- COMMAND ARG...;proxy_onберёт готовые переменные изproxy-client envи применяет их, только если команда завершилась успешно;evalне используется;proxy_offочищает переменные в обоих регистрах.
proxy_on/proxy_off больше не запрашивают внешний IP: это замедляло
переключение. Для проверки есть myip и proxy-client status.
Настройки
Два файла в ~/.config/proxy-client/:
config— несекретный машинный INI: типxrayилиexternal, имя, адрес, порт, добавка кNO_PROXY. Если файла нет, используется прежний Hiddify наhproxy.local:12334.default.url— секретная VLESS-ссылка с правами 600;start -fберёт другой файл.
Они разделены, потому что первый описывает политику машины, а второй — секрет,
который меняется независимо. Выбран INI, а не TOML: tomllib появился только
в Python 3.11.
Явный тип прокси
xray значит: нужен Xray, запущенный через proxy-client start. Если его нет,
агент не запускается. external значит: проверяется только доступность адреса
и порта. Ни один тип не переходит на другой сам — предсказуемость канала важнее
удобства.
start работает только при type=xray и loopback-адресе в конфиге. Поэтому
нельзя поднять локальный Xray, оставив pclaude направленным во внешний
Hiddify. stop от типа не зависит: после переключения на external старый
Xray всё равно можно остановить.
Один порт на HTTP и SOCKS, по умолчанию 12334; порт настраивается, чтобы
разные пользователи одной машины не мешали друг другу.
VLESS-ссылки
Поддержаны две семьи: TCP/RAW с REALITY и XHTTP с TLS. Неизвестный или
повторный query-параметр — отказ: он может менять смысл соединения, и его
нужно добавить в разбор явно. Остальное проверяет xray run -test.
Hiddify Manager добавляет allowInsecure/insecure даже к профилям с
нормальным сертификатом
(Hiddify-Manager#5438),
а Xray 26.2.6 эту
опцию удалил. Поэтому поля принимаются и игнорируются с предупреждением;
TLS-проверку задают pcs и vcn.
Сводка перед запуском не показывает UUID, ключи REALITY и содержимое XHTTP
path (там бывает токен). Ссылка не передаётся аргументом командной строки.
Установка Xray
proxy-client install ставит в ~/.local/bin/xray официальный архив одного
зафиксированного релиза (сейчас 26.3.27), проверяет SHA-256 по .dgst и
заменяет файл атомарно. Официальный установщик Xray не подходит: он требует
root и создаёт systemd-службы. start принимает только ту же версию и никогда
ничего не скачивает.
Жизненный цикл
start остаётся на переднем плане как небольшой Python-супервизор с одним
дочерним Xray; ожидаемое место — панель tmux. Отдельный журнал и команда logs
не нужны: хватает истории tmux. Второй start отсекает блокировка flock.
state.json хранит PID супервизора и Xray, чтобы stop работал из любого
терминала и мог добить Xray, если супервизор убит.
Перед запуском обязательны разбор ссылки, xray run -test и открытый порт
после старта. Проверка внешнего IP — только диагностика: её сбой даёт
предупреждение.
run никогда не запускает Xray, поэтому у pclaude и pcodex нет скрытого
автозапуска.
Доставка
Каталог proxy-client/ раскладывается в $HOME ссылками: CLI в
~/.local/bin/, shell.bash и examples/ в ~/.config/proxy-client/.
Машинный config и default.url пользователь создаёт сам; в Git они не
входят.
- Отдельно:
proxy-client/install.shставит эти три ссылки и по умолчанию дописывает блок в~/.bashrc. Чужие файлы не трогает. Режим прокси, Xray и сеть не настраивает — это делают отдельные команды по README. - В составе dotfiles: корневой
install.shподключает тот же пакет через Stow, а.bash_customзагружаетshell.bash.
Риски
- Формат ссылок Hiddify расширяется. Строгий отказ на неизвестном параметре лучше частично неверного JSON, но новые ссылки могут потребовать правки разбора.
- Открытый порт не доказывает, что маршрут работает. Проверка внешнего IP отделена от обязательных проверок.
- Loopback без аутентификации открыт другим пользователям того же узла. Пользователи машины считаются доверенными.
NO_PROXYпрограммы понимают по-разному, особенно CIDR. README советует точные IP и домены.- Ссылки установки зависят от пути исходного каталога: переносить его нельзя.
- Поддержка РЕД ОС, Astra Linux и Alt Linux заявляется только после проверки
версии Python и прогона
tests/test_proxy_client_full.shна них. - Шаблоны в
examples/содержат только вымышленные значения; настоящие ссылки, UUID и ключи в репозиторий не попадают.