API среды выполнения сеанса (официальные CLI)
Плоскость управления запускает CLI поставщика. Она не заменяет Claude Code, Codex или Grok Build. Сеансы и терминалы — один модуль этого продукта, а не продукт.
Эта страница описывает Community operate-маршруты под /v1/m/sessions/runs.
Они уже есть в бета-документе OpenAPI. Выпуск 26.10
добавляет контракт драйвера, транспорт, который нужен каждой форме запуска, и
сценарии J01–J08 как тесты.
Граница редакции
Заголовок раздела «Граница редакции»| Редакция | Что делает | Чего не делает |
|---|---|---|
| Community (эта страница) | Собственный локальный потомок: запуск, stdin/stdout/stderr, attach с курсором, возобновление точного разговора, повторное подключение живого потока, остановка с наблюдаемым кодом выхода. Строки сессий и доказательства остаются в модуле II. | Движок Identity & Scale с несколькими панелями, слушатель mTLS, ввод в панели cockpit, чанк интерфейса xterm |
| Оверлей Identity & Scale | Коммерческий движок session-cockpit (слушатель, панели, журнал записей). Маршруты находятся под /v1/m/session-cockpit/, когда модуль присутствует. |
Не заменяет /v1/m/sessions/runs |
Сборка Community отвечает на пространство имён оверлея отсутствием (404). Она не монтирует заглушку 501.
Путь hook Claude Code остаётся olivares claude-hook (PreToolUse PEP). Это
наблюдение и принуждение, а не замена CLI.
Существующее принуждение на маршрутах модуля:
| Право | Маршруты |
|---|---|
sessions:run:read |
GET /runs, GET /runs/{ref}, GET /runs/{ref}/events, GET /runs/{ref}/attach, GET /runs/{ref}/handoff, GET /runs/{ref}/activity, GET /runs/{ref}/activity/agents/{agent}, GET /runs/{ref}/messages, POST /runs/{ref}/pin, DELETE /runs/{ref}/pin |
sessions:run:write |
POST /runs, POST /runs/{ref}/input, POST /runs/{ref}/interrupt, POST /runs/{ref}/stop, POST /runs/{ref}/resume, POST /runs/{ref}/move, POST /runs/{ref}/handoff, PUT /runs/{ref}/name, POST /runs/{ref}/archive, DELETE /runs/{ref}/archive |
sessions:run:admin |
POST /runs/{ref}/cleanup, DELETE /runs/{ref} |
Viewer может читать список и закреплять сессии для себя. Создание, ввод и остановка требуют write. Authorizer маршрута — точка принуждения; отсутствующее право даёт 403.
Маршруты, которые читает консоль
Заголовок раздела «Маршруты, которые читает консоль»База: /v1/m/sessions. Аутентифицируйтесь. Отправьте X-Olivares-Tenant.
| Метод | Путь | Результат |
|---|---|---|
GET |
/runs |
Страница управляемых запусков. Необязательные state, live_ref, claude_session_id (legacy) |
GET |
/runs/{ref} |
Один запуск. state выводится. exit_code наблюдается. Нет выдуманного поля успеха. archived_at (RFC 3339, UTC) присутствует, пока сессия в архиве |
GET |
/runs/{ref}/events |
Строки доказательств жизненного цикла |
GET |
/runs/{ref}/attach?from={seq} |
SSE: кадры output, lag, если кольцо вытеснило ниже курсора, end или notice, что сессия не жива. Сессия Grok, OpenCode или Gemini CLI, возобновлённая после запуска, которому переданы секреты хранилища (vault), учётные данные репозитория, управляемые учётные данные или токен реестра пакетов, не передаёт разговор, который её инструмент воспроизводит при возобновлении, и сообщает об этом одним кадром olivares_notice (history_withheld) |
POST |
/runs/{ref}/input |
stdin. Stream-json использует line/message. Codex/Grok — text. 202 {accepted:true} |
POST |
/runs/{ref}/stop |
SIGTERM, затем SIGKILL группы процессов. Наблюдаемый код выхода в строке |
POST |
/runs/{ref}/resume |
Новое поколение процесса. Точный сохранённый разговор. Тихого отката к новому разговору нет |
POST |
/runs/{ref}/interrupt |
Отменяет активный ход. Процесс остаётся |
POST, DELETE |
/runs/{ref}/pin |
Закрепляет сессию за вызывающим или открепляет её. Закрепление принадлежит вызывающему и следует за ним в другой браузер или на другую машину; оно никогда не меняет список другого человека. Оба вызова идемпотентны и отвечают 200 {run_ref, pinned, pinned_at}. За одним человеком закреплено не более 20 сессий: при закреплении 21-й самая старая открепляется. Освобождение или удаление сессии снимает все закрепления на ней. GET /runs и GET /runs/{ref} несут собственные pinned и pinned_at вызывающего, а GET /runs также возвращает закреплённые сессии вызывающего, которые выходят за пределы его страницы (не более 20 строк сверх limit; pagination=cursor ничего не добавляет, поскольку один раз охватывает все сессии). Закрепление принадлежит учётным данным, которыми оно сделано: консоль человека и сессии olivares login делят свои закрепления, а токен API хранит собственные. Освобождённая сессия отвечает 409 |
POST, DELETE |
/runs/{ref}/snooze |
Откладывает сессию для вызывающего до момента или снимает отложение. POST принимает {until}, время RFC 3339 в будущем (иначе 400); второй POST переносит его. Отложение принадлежит вызывающему, как и закрепление: консоль убирает сессию из списка этого человека до until, списки других людей не меняются. Оба запроса отвечают 200 {run_ref, snoozed_until?, done}. GET /runs и GET /runs/{ref} несут snoozed_until вызывающего только пока действует отложение. Освобождение или удаление сессии снимает все отложения на ней. Освобождённая сессия отвечает 409 |
POST, DELETE |
/runs/{ref}/done |
Отмечает сессию как готовую для вызывающего или снимает отметку. Консоль помещает готовую сессию в «Ранее» в списке этого человека. Оба вызова идемпотентны и отвечают 200 {run_ref, snoozed_until?, done}. GET /runs и GET /runs/{ref} несут done вызывающего. Освобождение или удаление сессии снимает все отметки на ней. Освобождённая сессия отвечает 409 |
PUT |
/runs/{ref}/name |
Тело {name}. Переименовывает сессию. Имя обрезается по краям; пустое имя стирает его, и клиенты возвращаются к собственному именованию. Больше 200 символов, управляющий или невидимый символ (форматирования, разделитель строк или абзацев: пробелы нулевой ширины, переопределения направления) или отсутствующее name дают 400. 200 run. Имя принадлежит сессии, поэтому его видит каждый читатель. Записывается в журнал аудита как sessions.run.renamed со ссылкой на запуск, а не с именем; имя, которое уже принадлежит сессии, ничего не меняет и ничего не записывает |
POST, DELETE |
/runs/{ref}/archive |
Архивирует сессию или возвращает её из архива. Без тела. 200 run, с archived_at, пока сессия в архиве. Архивация не останавливает и не удаляет сессию. Отметка принадлежит сессии, а не вызывающему: сессия архивирована для всех. GET /runs ею не сужается; каждый клиент сам исключает архивированные сессии из своего списка. Оба вызова идемпотентны: архивация уже архивированной сессии сохраняет её archived_at и ничего не записывает. Записывается в журнал аудита как sessions.run.archived и sessions.run.unarchived |
POST |
/runs/{ref}/move |
Тело {provider_profile_ref}. Привязывает остановленную или завершившуюся сбоем сессию Claude Code к другому профилю того же инструмента и переносит её разговор. Ничего не запускает. 200 run |
GET |
/runs/{ref}/handoff |
Сводка, с которой начиналась бы передача: summary, source_driver, turns, transcript_bytes. Только чтение, записывается в журнал аудита. Работающая сессия читается как есть; сессия, которая ещё не запустилась, отвечает 409 |
POST |
/runs/{ref}/handoff |
Тело {provider_profile_ref, summary?, name?}. Запускает новую сессию в этом профиле, связанную с данной. 201 run плюс summary_state (и first_turn, когда он не delivered); 202, пока запуск ожидает одобрения |
GET |
/runs/{ref}/activity |
Что делает инструмент сессии Claude Code или Codex, читается из его собственной нативной записи при каждом запросе: agents, tasks (команды и фоновая работа), files (путь, added, removed, created), todos, skills, mcp_servers, model, context_tokens, обнуляемое context_window, когда его сообщает инструмент, и context_percent (процент для Claude Code, null, когда значение неизвестно), compactions и transcript (read, pending до того, как инструмент его записал, missing, когда он должен быть на месте). Агенты и задачи имеют состояние running, completed, failed, stopped или scheduled. Codex использует свой файл rollout, не запуская ещё один app-server; context_tokens описывают последний запрос, а не суммарное использование. Только чтение; записывается в журнал аудита один раз на читателя и сессию каждые 15 минут. Неподдерживаемый инструмент отвечает 422; сессия, которой выданы секреты хранилища (vault), учётные данные репозитория или управляемые учётные данные, отвечает 409, как и сессия, использовавшая токен реестра пакетов, когда она остановлена или работает после resume, который следует за запуском с таким токеном |
GET |
/runs/{ref}/activity/agents/{agent} |
Транскрипт одного субагента Claude Code простыми ходами (role, text). Только чтение, записывается в журнал аудита. 404 для неизвестного агента. Codex сообщает состояние дочерних агентов в корневом ответе Activity; чтение транскриптов дочерних агентов не предлагается |
GET |
/runs/{ref}/messages |
Сообщения сессии Claude Code или Codex, читаются при каждом запросе из собственного транскрипта инструмента, страницами: items (id, role user или assistant, at, first_line), total, next, transcript (read, pending, missing). По умолчанию только то, что отправил человек; role=all добавляет ответы инструмента. q оставляет сообщения, содержащие эту фразу в любом месте (без учёта регистра, не более 256 байт); at (RFC 3339) оставляет сообщения не раньше этого времени, так что первый элемент является якорем; order — asc (по умолчанию) или desc, limit — не более 200, а cursor — id, с которого продолжается страница (next); элементы всегда идут от старых к новым. id читает одно сообщение целиком (text и later_same — сколько более поздних сообщений того же отправителя повторяют его первую строку; фильтры не применяются, а total — число сообщений сессии). text=1 добавляет text к каждому элементу страницы с тем же пределом 64 KiB на сообщение, что и при чтении по id, и без later_same; текст, обрезанный на этом пределе, заканчивается на [...], а его элемент несёт clipped: true, в том числе при чтении по id; такая страница содержит не более 50 сообщений; чтобы скопировать весь разговор, следуйте next. id сообщения — его позиция среди сообщений сессии, и он не меняется по мере роста транскрипта. Только чтение; записывается в журнал аудита один раз на читателя, сессию и окно в 15 минут, как sessions.run.messages, а чтение с text=1 — как sessions.run.messages.text. Неподдерживаемый инструмент отвечает 422; сессия, которой выданы секреты хранилища (vault), учётные данные репозитория или управляемые учётные данные, отвечает 409; неизвестный id — 404; недопустимый параметр — 400 |
DELETE |
/runs/{ref} |
Требует sessions:run:admin. Удаляет запись освобождённой сессии. Неосвобождённая сессия отвечает 409 session must be cleaned before delete (state=…). Записывается в журнал аудита как sessions.run.deleted в транзакции удаления |
GET |
/runs/{ref}/diff |
Ветка сессии worktree относительно её исходной точки: branch, base, head и изменённые files (path, status). Без worktree — 404 |
GET |
/runs/{ref}/diff/file?path= |
Текст одного пути на base и на head (original, modified, каждый не больше меньшего из max_read_bytes workspace и 64 КиБ) |
Для вызовов Codex Code Mode, аргументы плана которых не сохраняются в rollout,
Activity также читает последнее уведомление turn/plan/updated, уже полученное
живым мостом. Перезагрузка в браузере использует ту же серверную сессию; для
обновления никакой app-server не запускается. После того как живой дескриптор
исчез, можно прочитать только данные, которые сохранил сам Codex.
Для Claude Code окно берётся из нативного поля результирующего кадра
modelUsage[model].contextWindow, которое сохраняется при остановке и повторном
подключении. Совпадающий однозначный отчёт задаёт context_percent как
100 × context_tokens / context_window; иначе оба поля равны null, а CLI и
консоль показывают токены с пометкой о неизвестном окне. Новый запуск инструмента
очищает предыдущий отчёт об окне.
Задачи workflow могут включать workflow: run_id, name, duration_ms,
agents_total, agents_done, agents_failed и phases. Каждая фаза имеет
index, title, необязательные detail и state и те же счётчики агентов.
Счётчики описывают агентов, наблюдавшихся к настоящему моменту. Пока сессия
жива, состояние фазы описывает наблюдаемых работающих или завершившихся сбоем
агентов. Завершение агента не доказывает, что скрипт покинул свою фазу, поэтому
оно не помечает фазу завершённой и не указывает текущий шаг скрипта. Завершённые
состояния фаз задаёт итоговая сводка workflow.
Живые снимки workflow берутся из вывода system/task_progress Claude Code, общего
с потоком attach. Завершённый workflows/<runId>.json инструмента заполняет
итоговую сводку по правилам транскрипта о домашнем каталоге, ссылках и размере.
Чтение сводки ограничено 8 МиБ на файл и 64 МиБ на запрос; более крупные нативные
журналы или результаты делают сводку нечитаемой, сохраняя доступный живой прогресс.
Нечитаемые сводки и пропуски в ограниченном живом буфере вносят вклад в unreadable.
Перенос сессии и передача
Заголовок раздела «Перенос сессии и передача»Сессия продолжается в другой учётной записи одним из двух способов, и консоль, а
также olivares session move / olivares session handoff предлагают оба. Перенос
(move) передаёт сохранённый разговор сессии Claude Code в другой профиль того же
инструмента, поэтому переносить можно только сессии Claude Code. Передача
(handoff) запускает новую сессию из разговора сессии Claude Code, Codex, Gemini
CLI или OpenCode.
Запуск несёт limit, когда его инструмент завершил последний ход на лимите:
{kind, resets_at, account_ref}. kind — usage (исчерпан лимит тарифного плана
учётной записи) или rate (провайдер ограничивает запросы). resets_at — RFC 3339;
присутствует, когда инструмент сообщает, когда лимит снимется, и отсутствует в
остальных случаях, а account_ref — профиль, под которым выполнялся ход. Claude
Code сообщает факт в собственном результате (api_error: usage_limit_reached или
HTTP 429), а время сброса — в своём rate_limit_event; Codex сообщает факт в
неудавшемся ходе с типом usageLimitExceeded или rateLimitExceeded, а время
сброса — в окнах своего account/rateLimits/updated; когда исчерпаны два окна,
записывается более позднее время сброса, а время сброса более чем через год от
текущего момента опускается. Журнал получает одно событие limit_reached, когда
факт записан впервые; повторная встреча того же факта не добавляет ни одного.
Следующий успешный ход очищает limit, как и перенос в другую учётную запись.
Результат любого другого вида никогда его не задаёт.
POST /runs/{ref}/move сохраняет ту же сессию. Ему нужна сессия в состоянии
stopped или failed, чей разговор находится в домашнем каталоге её учётной
записи, и целевой профиль того же инструмента, который принял бы запуск под ним
(активный, среда этого узла, авторизованный источник). Движок копирует этот один
разговор — транскрипт и файлы его субагентов и результатов инструментов — в
целевой домашний каталог, но никогда не копирует вход, настройку или другой
разговор, и перепривязывает строку запуска, живую строку и журнал в одной
транзакции. Запуск сохраняет свой run_ref и id разговора у провайдера; журнал
получает событие moved, в деталях которого оба профиля названы по ссылке и
указано число перенесённых файлов, а сессия, завершившаяся сбоем, сохраняет свою
reason. Исходный домашний каталог только читается. Отказ ничего не записывает и
удаляет то, что создал перенос:
- 409 для работающей сессии, сессии, которой выданы секреты хранилища (vault), учётные данные репозитория, управляемые учётные данные или токен реестра пакетов (нельзя доказать, что то, что она вывела, их не содержит), строки, чей домашний каталог не принадлежит её профилю, id разговора, уже привязанного к другой сессии под целевым профилем, цели, в которой хранится другая версия разговора, цели другого инструмента или файла, изменившегося во время копирования (повторите);
- 422 для ссылки, второго имени файла или специального файла внутри разговора, а также для сессии другого инструмента.
Копия того же разговора, оставленная в цели предыдущим переносом, заменяется более
новой. Ничего не запускается: следующий POST /runs/{ref}/resume — обычный, поэтому
к нему применяются политика, бюджеты и одобрения целевого профиля. Сессия, у
которой ещё нет разговора, переносится без чего-либо для переноса и запускается
заново в цели.
GET /runs/{ref}/handoff и POST /runs/{ref}/handoff продолжают работу в другом
инструменте, где нативного resume нет. Они читают сохранённый разговор сессии
Claude Code, Codex, Gemini CLI или OpenCode (сессия Grok отвечает 422). Сессия
может быть в состоянии stopped, failed, running или idle; ещё не
запустившаяся отвечает 409. Предварительный просмотр читает работающую сессию как
есть. POST сначала останавливает работающую сессию так же, как POST /runs/{ref}/stop, и читает её разговор после завершения её инструмента; каждый
отказ, которому остановка не нужна (целевой профиль, секреты хранилища (vault),
учётные данные репозитория), наступает до неё, а отказ после неё сообщает, что
сессия была остановлена и её можно возобновить. Codex читается из его rollout,
Gemini CLI — из его журнала чата, а OpenCode — через его собственную команду
opencode export, запущенную один раз и офлайн под профилем сессии.
Предварительный просмотр создаётся из сохранённого разговора без модели, чтобы
человек мог просмотреть и изменить его, и каждое его чтение записывается в журнал
аудита как sessions.run.handoff_preview. POST запускает новую сессию в выбранном
профиле, в том же workspace и по тому же шаблону, первым ходом которой становятся
просмотренные summary (создаются, если отсутствуют) и путь к транскрипту,
записанному в домашний каталог конфигурации целевого профиля под собственным
именем. Транскрипт несёт сообщения целиком до 256 КиБ каждое, вызовы и результаты
инструментов сокращены, и он сообщает, сколько записей не смог прочитать. Новый
запуск сообщает handoff_of, а журнал оригинала получает событие handed_off.
Ответ несёт summary_state:
summary_state |
Значение |
|---|---|
delivered |
Первый ход дошёл до новой сессии. |
not_delivered |
Он не дошёл. first_turn содержит текст для отправки. |
unknown |
Отправка была предпринята, результат не подтверждён; проверьте, прежде чем снова отправлять first_turn. |
waits_for_approval |
Запуск удерживается для человека (202); первый ход автоматически не отправляется. |
first_turn присутствует, только когда состояние не delivered, потому что он
называет путь вложения. Исходный разговор отклоняется с 409, если его сессии
выданы секреты хранилища (vault), учётные данные репозитория, управляемые учётные
данные или токен реестра пакетов, потому что передача отправляет его другому
провайдеру, и с 422 при размере более 256 МиБ или когда в нём есть одна запись
крупнее 32 МиБ.
Опция worktree
Заголовок раздела «Опция worktree»POST /runs принимает необязательное логическое поле worktree. Если оно true и
workspace_ref указывает зарегистрированный workspace, который является корневой
папкой репозитория git, сессия работает в новом git worktree на новой ветке этого
репозитория (workspace_path — worktree, а запуск сообщает worktree_branch).
Отсутствие поля, null или false сохраняют прежнее поведение. Движок возвращает 422
для workspace, который не является git worktree или не является корневой папкой
репозитория, не имеет коммита, доступен только для чтения или имеет папки только
для чтения, чья конфигурация git задаёт фильтр или включает файл; для изоляции,
отличной от native, и для запуска без workspace; и 503, если на узле нет каталога
worktree. POST /runs/{ref}/resume возвращается в тот же worktree.
POST /runs/{ref}/cleanup принимает необязательное тело {"discard_worktree": true};
без тела вызов работает как раньше, и сервер по-прежнему принимает любое тело:
подтверждением является только явное true. Сессия с worktree освобождается,
если её ветка слита в текущую ветку workspace, worktree находится на этой ветке и
не имеет незакоммиченных файлов; иначе вызов отклоняется с 409 (неслитая работа,
отсоединённый HEAD, worktree, недоступный узлу), а запуск остаётся остановленным.
Вызов можно повторить с discard_worktree, чтобы всё равно удалить worktree и
ветку, либо — для worktree, недоступного узлу, — освободить сессию и оставить
worktree на месте. Событие журнала cleaned сообщает, что произошло с worktree,
и вершину ветки.
Одобрение команды настройки папки
Заголовок раздела «Одобрение команды настройки папки»Команда настройки принадлежит зарегистрированной папке и хранится в хранилище движка. Файлы репозитория и переменные окружения не могут её изменить. Ничто пока не выполняет эту команду в этих операциях или при запуске сессии.
PUT /workspaces/{ref}/setup-commandпринимает{"command":"npm ci"}. Точный текст UTF-8 сохраняется, включая пробельные символы; не более 8192 байт, без NUL. Пустая строка очищает команду. Требует администрирования workspace.GET /workspaces/{ref}возвращаетsetup_command,setup_command_sha256и, после одобрения,setup_approvalсsha256,actorиat.setup_approvedравно true только пока это одобрение покрывает текущий текст. После правкиsetup_approvalостаётся как свидетельство, поэтому проверяйтеsetup_approved, а не наличиеsetup_approval.POST /workspaces/{ref}/setup-command/approveпринимает{"sha256":"<reviewed hash>"}. Требует администрирования workspace и отклоняет идентичность агента. Хеш должен совпадать с текущим сохранённым текстом; параллельная правка возвращает 409. Одобрение и его запись аудитаsessions.workspace.approve-setupфиксируются вместе.
Запуск worktree возвращает 409, если у команды нет соответствующего одобрения, до
создания worktree. Его сообщение называет команду и шаг одобрения. Изменение одного
символа, включая пробельный, требует нового одобрения. Последнее одобрение остаётся
как свидетельство; чтобы применяться, его хеш должен равняться setup_command_sha256,
поэтому возврат команды к тексту, который был одобрен раньше, снова применяет то
одобрение. Любой, кто может читать папку, может прочитать команду, поэтому не
помещайте в неё секреты. POST /runs с "no_setup":true пропускает настройку
только для этого запуска. Передача сессии, у которой есть worktree, запускает новый
worktree и требует такого же одобрения; варианта пропуска у неё нет. Остальные
запуски и resume сохраняют своё прежнее поведение.
В CLI задайте команду так: olivares agent workspace setup <ref> --command 'npm ci',
прочитайте её так: olivares agent workspace setup <ref>, а показанный хеш
одобрите так: olivares agent workspace approve-setup <ref> --sha256 <hash>.
olivares session start --worktree --no-setup один раз пропускает настройку.
Запуск worktree от коммита или ветки
Заголовок раздела «Запуск worktree от коммита или ветки»С worktree вызов POST /runs также принимает необязательный worktree_from:
полный id коммита (40 или 64 строчных шестнадцатеричных цифры) или локальную ветку
репозитория workspace. Новый worktree и его собственная новая ветка начинаются там
вместо текущего коммита workspace; названная ветка и checkout workspace не
перемещаются. Так получатель открывает работу, указанную в передаче, содержимое
которой может иметь необязательные branch и sha. Git разрешает значение в полный
id коммита; используется только этот id. Движок возвращает 422 до создания чего-либо
для коммита, которого нет в репозитории, ветки, которой в нём нет, выражения
ревизии, диапазона, опции, а также worktree_from без worktree. Если поле
отсутствует, запуск, как и прежде, начинается от текущего коммита workspace.
GET /runs/{ref}/diff перечисляет пути, изменённые веткой worktree сессии с момента
отделения от текущего коммита workspace (base — их база слияния, head — вершина
ветки, оба полные id коммитов; максимум 200 путей, truncated сообщает о
превышении), а GET /runs/{ref}/diff/file?path= возвращает текст одного пути на
base и на head, пустой там, где файла нет. Он читает закоммиченные объекты git
через низкоуровневые команды, поэтому незакоммиченные изменения в него не попадают;
требуется то же разрешение, что и на чтение запуска. Он соблюдает файловые правила
workspace: путь вне разрешённых подпутей не перечисляется и возвращает 404;
запрещающая DLP-политика workspace даёт 403 (чтение аудируется, как чтение файла
workspace), а файл больше 16 МиБ — 413. Сессия без worktree и запуск другого
тенанта возвращают 404; исчезнувшая ветка или отсутствие общей истории с workspace
— 409. worktree_from также возвращает 422 для id коммита, на который не указывает
ни одна ветка, тег или удалённая ветка репозитория.
Повторное подключение после оборванного attach — GET …/attach?from={last+1} к
тому же живому процессу. После потери процесса attach сообщает, что сессия не
жива. Resume начинает новое поколение. Reconnect не выдумывает процесс-замену
(SDD R04).
Конфигурация агента, которую несёт репозиторий
Заголовок раздела «Конфигурация агента, которую несёт репозиторий»Клонированный репозиторий может нести конфигурацию агента, которая запускает
программу или перенаправляет трафик. Движок считает её недоверенным вводом, когда
сессия запускается в папке. Он читает перечисленные ниже файлы, никогда не
выполняет их и собирает только перечисленные ключи. Пустое значение ({}, [],
"", false, null) ничего не настраивает и не помечается.
| Инструмент | Файл | Помечается |
|---|---|---|
| Claude Code | settings.json и settings.local.json в папке .claude |
hooks, apiKeyHelper, statusLine, mcpServers, enableAllProjectMcpServers, enabledMcpjsonServers, awsAuthRefresh, awsCredentialExport, otelHeadersHelper, fileSuggestion, enabledPlugins, extraKnownMarketplaces и записи env с именем из последней строки |
| Claude Code | .mcp.json |
mcpServers |
| Codex | .codex/config.toml |
hooks, notify, mcp_servers, model_providers, otel, любой *_base_url верхнего уровня и записи shell_environment_policy.set с именем из последней строки; те же ключи в profiles.<name> |
| Gemini CLI | .gemini/settings.json |
hooks, mcpServers, toolDiscoveryCommand, toolCallCommand, proxy, tools.discoveryCommand, tools.callCommand, mcp.serverCommand, telemetry.otlpEndpoint |
| Gemini CLI | .gemini/.env, .env |
записи с именем из последней строки |
| Имена окружения | NODE_OPTIONS, NODE_EXTRA_CA_CERTS, NODE_TLS_REJECT_UNAUTHORIZED, LD_PRELOAD, LD_LIBRARY_PATH, LD_AUDIT, DYLD_INSERT_LIBRARIES, BASH_ENV, PATH, PYTHONPATH, GIT_SSH_COMMAND, GIT_EXTERNAL_DIFF, SSL_CERT_FILE, CLAUDE_CODE_SHELL_PREFIX, ANTHROPIC_CUSTOM_HEADERS, AWS_ENDPOINT_URL* и любое имя, оканчивающееся на _BASE_URL, _API_BASE, _ENDPOINT или _PROXY (NO_PROXY только сужает прокси и не помечается) |
Файл, который существует, но не читается в своём формате (недопустимый JSON или
TOML, больше 1 МиБ, вложенность глубже 64 уровней, не обычный файл), считается
помеченным, потому что его безопасность нельзя показать. В TOML каждый сегмент
точечного ключа или заголовка таблицы — один уровень, как в разобранном документе,
и прибавляется к скобкам вокруг него: заголовок из 30 сегментов над 35 вложенными
встроенными таблицами — это 65 уровней. Когда в файле есть заголовок [[array]],
сегменты заголовка считаются дважды, потому что каждый может называть массив и его
элемент. Файл слишком большого размера хешируется целиком при каждой проверке. Папка,
в которой ничего не помечено, запускается как прежде.
GET /workspaces/{ref}/project-configперечисляет помеченные ключи по файлам с их значениями (пароль внутри URL маскируется) иsha256ровно этой помеченной части по файлам всех трёх инструментов, плюсapprovedи последнееapproval. Он читает саму папку; worktree, запущенный от другого коммита, может нести другие отслеживаемые файлы, и его отказ называет собственный хеш.POST /workspaces/{ref}/project-config/approveпринимает{"sha256":"<reviewed hash>"}, требует администрирования workspace и отклоняет идентичность агента. Одобрение сохраняет, кто, когда и какой хеш, вместе с записью аудитаsessions.workspace.approve-project-configв той же транзакции.
Запуск или resume инструмента, который читает помеченный файл, возвращает 409, если сохранённое одобрение не равно текущему хешу. Изменение одного символа помеченного значения либо добавление или удаление помеченного ключа требует нового одобрения; изменение ключей, которые не помечаются, — нет. Варианта пропуска проверки нет.
Сессия Claude Code, несущая hook движка, запускается с --setting-sources ""; в
Claude Code 2.1.299 такая сессия не загружает ни файл настроек проекта или
локальный, ни проектный .mcp.json, поэтому такой запуск не отклоняется. Запуск
Claude Code без hook движка (удалённое управление или движок без эндпоинта hook)
читает эти файлы и проверяется. Codex учитывает .codex/config.toml только для
проекта, которому доверяет домашний каталог его учётной записи, и игнорирует файл
недоверенного проекта; движок не может спросить инструмент, поэтому проверяет этот
файл, и человек одобряет его один раз. Gemini CLI 0.64.0, запущенный так, как его
запускает движок (gemini --acp), игнорирует .gemini/settings.json и .gemini/.env
папки, которой не доверяет его домашний каталог учётной записи, а в доверенной папке
выполняет tools.discoveryCommand, hooks и команды mcpServers и берёт базовый
URL из .gemini/.env; движок проверяет эти файлы по той же причине. Он также
загружает файлы родительских папок, которые эта проверка не читает.
В CLI используйте olivares agent workspace project-config <ref>, чтобы прочитать
это, и olivares agent workspace approve-project-config <ref> --sha256 <hash>, чтобы
одобрить.
Транспорт (Community)
Заголовок раздела «Транспорт (Community)»Каждая официальная CLI запускается на том транспорте, который нужен её собственной
форме operate; какой именно, объявляет cliruntime.LaunchTransport. Сегодня все
три формы — протоколы поверх stdio, поэтому корень композиции подключает
sessions.NewProcRunner(): stdin, stdout и stderr — каналы и остаются раздельными
потоками.
Claude Code отклоняет терминал на stdin. Форма --print со stream-json отвечает
Error: Input must be provided either through stdin or as a prompt argument when using --print
и выходит с кодом 1, не выдав ни одного кадра протокола. Сервер приложений Codex и
stdio-агент Grok говорят по JSON-RPC через те же потоки. Терминал нужен интерактивной
форме; sessions.NewPTYRunner() остаётся доступен для неё в Linux, с stdin/stdout
на сыром локальном PTY и stderr на канале. Ни один из них не запускает изоляцию
container или sandbox. Хост с podman или Docker добавляет контейнерный раннер для
isolation=container в stdio-форме; sandbox по-прежнему отклоняется (см.
Топология 4).
Контракт драйвера находится в modules/sessions/cliruntime. Виды: claude, codex,
grok. Соответствие всегда проверяется против внутрипроцессного fake и локального
пира на обоих транспортах. Если claude / codex / grok есть в PATH, отдельный набор тестов
прогоняет весь контракт на настоящем двоичном файле — запуск, attach, ввод, вывод,
повторное подключение, остановка, resume — и не отправляет ни одного хода модели:
каждое рукопожатие является протокольным, а каждый запуск получает свежий HOME и
свой каталог конфигурации.