# CM в Codex и Claude Code Раньше CM подключалась к Codex и Claude Code только как MCP-сервер, и экономии не было: модель сама решала, вызывать ли CM, вызывала редко, а вызвав, всё равно читала файлы ([HISTORY.md](HISTORY.md#7-codex-и-claude-code-через-mcp)). Теперь в оба клиента CM подаёт контекст так же, как в Harness: до первого вызова модели, через хук `UserPromptSubmit`. ## Как подключается `cm-hook` ([src/hooks/cli.ts](../src/hooks/cli.ts)) получает от клиента событие с текстом задачи, выбирает контекст тем же сервисом, что и MCP-сервер, и возвращает `hookSpecificOutput.additionalContext`: инструкцию и блок `CM context`. Формат общий для Codex и Claude Code. Заголовок не утверждает, что файл «засчитан как прочитанный»: эти клиенты не регистрируют чтение по внешнему контексту. При ошибке хук ничего не добавляет и не мешает запросу. Codex, `~/.codex/config.toml` или `/.codex/config.toml`: ```toml [[hooks.UserPromptSubmit]] [[hooks.UserPromptSubmit.hooks]] type = "command" command = "node /path/to/dist/src/hooks/cli.js --project /path/to/project --retrieval-policy adaptive --auto-update true" timeout = 120 ``` Claude Code, `.claude/settings.json`: ```json { "hooks": { "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "node /path/to/dist/src/hooks/cli.js --project /path/to/project --retrieval-policy adaptive --auto-update true", "timeout": 120 } ] } ] } } ``` Аргументы те же, что у MCP-сервера ([MCP-SETUP.md](MCP-SETUP.md)): `--index`, `--vectors`, `--model-cache`, `--memory-dir`, `--embedding-cache`, `--source-scope`. Оба клиента требуют доверить хук: Codex — через `/hooks` (в автоматических прогонах `--dangerously-bypass-hook-trust`), Claude Code — как обычные настройки проекта. Переменная `CM_HOOK_LOG` пишет диагностику без исходного кода: маршрут, файлы, размер, время. ### Прогретый демон Каждый запуск хука — новый процесс. Без помощника он заново грузит индекс (JSON 92 МБ на Geo Dash), векторную модель и LanceDB — около 3,5 с на запрос. Поэтому хук работает через демон ([daemon.ts](../src/hooks/daemon.ts)), по той же идее, что у Netflix с движком IntelliJ ([HISTORY.md](HISTORY.md#10-демон-для-хука)): - для каждой конфигурации CM (проект, индекс, векторы, модель) — свой демон; он держит всё загруженным в памяти; - связь — Unix-сокет в каталоге `$TMPDIR/cm-hook-` с правами `0700`, на Windows — именованный канал; TCP-порт не открывается; - если демона нет, хук отвечает сам и запускает демон в фоне для следующих запросов; `CM_HOOK_DAEMON=off` это отключает; - демон не следит за файлами в фоне: перед каждым запросом через индекс он сверяет хеши исходников и при изменениях пересобирает индекс, как и без демона; - после 30 минут без запросов демон завершается; запустить заранее можно командой `cm-hook-daemon` с теми же аргументами. | Запрос хука на Geo Dash | Время | |---|---:| | Без демона (первый запрос) | 3,5 с | | Через прогретый демон, поиск места | 0,39–0,63 с | | Через прогретый демон, названный файл | 0,57 с | Контекст от демона побайтно совпадает с контекстом, который хук считает сам. ## Методика Те же шесть задач Geo Dash, рабочие копии, векторы и независимый грейдер, что в сериях Harness ([EFFICIENCY-AB.md](EFFICIENCY-AB.md)); раннер [native_ab.ts](../scripts/native_ab.ts). Три варианта, два повтора, порядок чередуется: - **без CM**; - **CM 0.8.1** — как его ставил прежний установщик: MCP-сервер и skill, модель решает сама; - **новый CM** — хук плюс MCP-сервер и skill из текущей сборки. Публичная проверка (`project_checks`) дана всем вариантам одинаково — как команда вне рабочей копии. Codex: `gpt-6-luna`, reasoning low, песочница workspace-write; расход — из событий `turn.completed`, цена — расчёт по тарифам Luna. Claude Code: Sonnet 5.5, `--permission-mode acceptEdits`, разрешены Read/Edit/Write/Grep/Glob и только команда проверки; загружаются лишь MCP и хук эксперимента (`--strict-mcp-config`, `--setting-sources project`), без переменных родительской сессии; расход и цена — из итогового события Claude Code. Активация хука подтверждается логом в каждой сессии нового CM, иначе серия останавливается. ## Результаты ### Codex 0.163.0, GPT-6 Luna, 36 сессий | | Без CM | CM 0.8.1 (MCP) | Новый CM (хук) | |---|---:|---:|---:| | Правильных правок | 11/12 | 12/12 | **12/12** | | Токены | 1 003 370 | 1 093 846 | **578 500** | | к без CM | — | +9,0% | **−42,3%** | | Расчётная цена | $0.0373 | $0.0391 | **$0.0289** | | к без CM | — | +4,8% | **−22,7%** | | Время, сумма | 175,9 с | 199,5 с | **167,8 с** | | к без CM | — | +13,4% | **−4,6%** | | Медиана сессии | 14,1 с | 17,6 с | **11,4 с** | | Команды чтения и поиска | 24 | 31 | **8** | | Вызовы CM через MCP | — | 0 | 0 | Меньше токенов, чем без CM, в 9 парах из 12; быстрее в 7. CM 0.8.1 модель не вызвала ни разу — skill и MCP без авто-контекста не используются. Слабое место — statistics-linear: 152К против 115К без CM. Неудача без CM — wallet-delta, второй повтор. [Данные](../evaluation/native/codex-results.json). ### Codex с прогретым демоном, 36 сессий Та же серия Codex, но демон запущен до сессии, как при обычной работе с проектом; его прогрев (3,6–6,0 с) в время сессии не входит. Все 12 сессий нового CM получили контекст через демон. | | Без CM | CM 0.8.1 (MCP) | Новый CM (хук + демон) | |---|---:|---:|---:| | Правильных правок | 12/12 | 12/12 | 11/12 | | Токены | 832 264 | 1 053 931 | **614 329** | | к без CM | — | +26,6% | **−26,2%** | | Расчётная цена | $0.0341 | $0.0393 | **$0.0302** | | к без CM | — | +15,1% | **−11,5%** | | Время, сумма | 170,8 с | 203,2 с | **164,0 с** | | к без CM | — | +19,0% | **−4,0%** | | Медиана сессии | 13,1 с | 17,9 с | **10,9 с** | | Время хука, сумма за 12 сессий | — | — | **4,8 с** (в первой серии 27,9 с) | Демон сделал своё: хук отвечал за 0,24–0,89 с вместо 0,3–9,1 с, суммарно на 23 с меньше на 12 сессий. На итоговом времени это почти не видно: разброс модели между сериями больше (вариант без CM — 175,9 с в первой серии и 170,8 с во второй). Экономия токенов в этой серии меньше, чем в первой (−26% против −42%), в основном потому, что вариант без CM потратил меньше (832К против 1 003К). Неудача нового CM — wallet-delta, первый повтор: та же ошибка смысла счётчика, что и раньше. [Данные](../evaluation/native/codex-daemon-results.json). ### Codex: хук с демоном и без, 90 сессий Прямое сравнение в одной серии: без CM, новый CM без демона (хук каждый раз грузит CM сам) и новый CM с демоном, запущенным до сессии. Шесть задач по пять повторов на вариант, порядок чередуется. | | Без CM | Хук без демона | Хук с демоном | |---|---:|---:|---:| | Правильных правок | 29/30 | 30/30 | 29/30 | | Токены | 2 390 735 | 1 841 853 | **1 634 540** | | к без CM | — | −23,0% | **−31,6%** | | Расчётная цена | $0.0917 | $0.0832 | **$0.0769** | | к без CM | — | −9,2% | **−16,1%** | | Время, сумма | 552,4 с | 563,8 с | **498,8 с** | | к без CM | — | +2,1% | **−9,7%** | | Медиана сессии | 19,1 с | 18,9 с | **12,2 с** | | Время хука, сумма | — | 66,6 с | **10,3 с** | | Команды чтения и поиска | 62 | 35 | **24** | Демон убрал около 1,9 с хука на сессию, и разница по времени сессий с хуком без демона того же размера: в среднем −2,2 с на пару задача/повтор, быстрее в 20 парах из 30. 95%-й интервал бутстрепа по парам (−5,1…+0,6 с) ещё захватывает ноль, поэтому выигрыш по времени — устойчивая тенденция, а не строго доказанный эффект. К варианту без CM с демоном: −1,8 с на пару (−4,3…+0,6 с), быстрее в 20 из 30. Разница токенов между вариантами с демоном и без (−11%) от демона не зависит — контекст одинаковый; это разброс модели. Слабое место прежнее — statistics-linear (339К с демоном против 233К без CM). Неудачи: wallet-delta по одному разу без CM и с демоном. Прогрев демона до сессии — медиана 3,7 с. [Данные](../evaluation/native/codex-daemon-ab-results.json). ### Claude Code 2.1.301, Sonnet 5.5, 36 сессий | | Без CM | CM 0.8.1 (MCP) | Новый CM (хук) | |---|---:|---:|---:| | Правильных правок | 12/12 | 12/12 | **12/12** | | Токены | 1 411 814 | 1 323 841 | **994 566** | | к без CM | — | −6,2% | **−29,6%** | | Цена по отчёту Claude Code | $0.697 | $0.704 | **$0.602** | | к без CM | — | +1,0% | **−13,6%** | | Время, сумма | 201,6 с | 217,5 с | 207,9 с | | к без CM | — | +7,9% | +3,1% | | Медиана сессии | 18,0 с | 17,7 с | **14,6 с** | | Read / Grep / Glob | 53 | 48 | **25** | | Вызовы CM через MCP | — | 0 | 0 | Меньше токенов в 8 парах из 12, быстрее в 7. Сильный выигрыш на поиске места и двух модулях: motion-envelope 92К против 317К, quota-receipts 116К против 307К. Проигрыш на circle-contact (158К против 128К) и wallet-delta (392К против 334К): хук отдал правильные файлы, но модель правила по нескольку раз, пока не проходила проверка. Суммарное время не лучше варианта без CM, медиана — лучше. [Данные](../evaluation/native/claude-results.json). ### Пробные прогоны Перед сериями — по одной сессии на задаче motion-envelope в каждом клиенте ([Codex](../evaluation/native/codex-pilot-results.json), [Claude Code](../evaluation/native/claude-pilot-results.json)): новый CM −65% и −57% токенов к варианту без CM. ## Ограничения - Codex — три серии (последняя по пять повторов), Claude Code — одна серия по два повтора; шесть задач одного проекта. - Claude Code проверен только с Sonnet 5.5; Codex — только с GPT-6 Luna. - Подмена повторного чтения из Harness здесь не используется: в Codex файлы читаются командами shell; для Read в Claude Code такая замена не проверялась. - В обоих клиентах экономия меньше, чем в Harness (−30…−42% против −45…−66% токенов), и выигрыш по суммарному времени не устойчив.