Thot
Thot
A terminal code assistant that already knows your repository — and the repository where Hermes Agent and Prime Agent live, in their entirety.
A conversational agent discovers a project by opening files with the model: slow, partial, and paid for again at every session. Thot computes the same picture by AST and call graph — complete, instantaneous, free — and gives the model only what matters.
The three programs
This repository contains three, not one. None is a rewrite of another: each stays in its own language, with its own tooling, and Thot wires them together.
What it is | Where | |
thot | deterministic audit, code map, verdict memory |
|
hermes | the agent: tools, gateways, plugins, cron, ACP |
|
prime | the coding agent: model providers, TUI, RLM |
|
thot # la session d'audit
thot hermes # Hermes, arguments transmis tels quels
thot prime # Prime, pareil
thot fusion status # ce qui est présent, prêt, et branchéThe wiring is not decorative. thot fusion wire declares Thot's MCP server in both agents: they gain code_map, find_symbol, callers, audit, skills and skill — the complete map of the repository, computed outside the model, instead of rediscovering it file by file. That is the mutual reinforcement: Thot knows without asking, Hermes and Prime act.
The two agents do not connect the same way, and claiming otherwise only wired one of the two. Hermes starts the server itself and talks to it on the pipe it opened. Prime only accepts HTTP — its mcp-manager discards any entry whose type is not http, and its runtime has no pipe transport — so its side needs a server that is running:
thot fusion wire # écrit les deux branchements, chacun dans sa forme
thot mcp serve --http # ce que Prime interroge : boucle locale, jeton bearer
thot mcp service --install # et pour que ce soit encore vrai demainThe third line exists because the first two only last for one session. fusion wire writes http://127.0.0.1:8787/mcp into Prime's configuration, and that address is true only while a terminal remains open: on the first restart, the file promises a server that no one is serving anymore. thot mcp service --install writes the unit that relaunches it — KeepAlive on macOS, Restart=always under systemd — and does not load it: Thot prints the command and lets you run it, because a tool that registers background agents without saying so is a tool you stop believing. thot doctor then asks the only question that matters — does the address answer now — not whether the file exists.
fusion wire also installs, on Prime's side, the method package that Thot ships for it: a configuration entry is not enough, Prime can only reach an MCP server through a class that names it. And it drops the token into auth.json without touching the model credentials — without a token, the connection fails before it is opened.
Each agent keeps its own configuration. thot fusion unwire undoes everything, and Prime's settings.json is backed up before the first modification.
thot fusion status measures what works, not what is written: Hermes installs the portable plugins disabled, for safety, so writing both files wires nothing until plugins.enabled names it. Activation goes through Hermes's CLI, never through editing its config.yaml — that file is its own, with its schema and migrations. It also verifies that the interpreter running Hermes can import the MCP SDK, because an agent that doesn't have it has no tools — not just none of Thot's — and it says so at logger.debug, where nobody reads it. Finally, it asks Prime's server whether it responds: an address written in a file is not a connection.
And the reinforcement works both ways: Hermes and Prime are also engines for thot audit --deep, the step that makes each finding argued and then refuted by a model.
By default, the three work together on the same audit. A finding is argued by one agent, then attacked by another — never by the one who just committed to the scenario. A model that refutes its own argument corrects its own copy; that is the only thing the panel offers, and it is the raison d'être of the fusion.
thot audit . --deep # tous les agents installés, en panel
thot audit . --deep --engine hermes # un seul : Hermes argumente et réfute
thot audit . --deep --engine prime # un seul : PrimeThe report says who did what:
Analyse assistée : panel — claude-cli contre hermes contre prime
[1] serve.py:7 — confirmé · hermes
…
1 confirmé(s) · 2 réfuté(s)
Argumenté par claude-cli 1 — attaqué par prime 1 — puis par hermes 1Three distinct agents on the same finding, measured: claude-cli argued, prime tried to destroy the scenario and failed, hermes attacked a second time. What is reported survived two independent adversaries.
The cascade. A finding is argued, then attacked. What survives the attack is what will be shown to a human — so it goes back to a third agent, who has seen neither the argument being built nor the first attack being written. A confirmed finding was confirmed against two independent adversaries.
A refutation is never reargued on the merits: the attacker is asked to refute at the slightest doubt, so calling it into question would create false positives. But its argument is reread when it buries something serious (MEDIUM and above), by an agent that said nothing about that finding. The reviewer does not judge the defect, it judges whether the reason given is verifiable in the code shown.
The two errors are not equal. A false confirmation costs a human ten minutes of reading. A false refutation costs a real defect forever — because a memorized refutation is skipped by all subsequent audits. It happened once for real: a very real SQL injection on the Hermes copy was dismissed by a perfectly accurate description of the Thot copy, fixed the day before. A contested refutation does not become a confirmation — nobody argued that — it goes back to plausible with its original severity, and it is not memorized: the finding comes back until someone decides.
If an agent fails a task, it is taken over once by another. No more: a task that everyone takes on has a problem of its own.
What a probe can do, measured and not assumed. Claude runs without Write, Edit, MultiEdit, NotebookEdit, Bash, for those — and thot doctor --agents checks it by asking it to write a file, then going to look at the disk.
This is not an allowlist, because the client does not offer one: --allowed-tools pre-approves, it does not restrict. Measured — a probe launched with Read Glob Grep allowed still had Write, Bash and Workflow. The only lever is a blocklist.
What a probe was holding before it was measured: CronCreate, CronDelete, Workflow, SendMessage, PushNotification, RemoteTrigger, EnterWorktree, WebFetch, .? — all the MCP servers connected by the user — even one tool whose name began with clear_. Creating persistent scheduled tasks, sending messages, reaching a mailbox — and it was for reading code and answering in a JSON.
What it holds after:
✓ outils · claude 7 outil(s), tous en lecture seule
✓ outils · hermes mcp__patch, mcp__read_file, mcp__search_files, mcp__write_file
✓ outils · prime ipythonShow all three, but judge one: Hermes's file pack provides write_file and patch with character; prime's only built-in tool is a command handler. A permanent red line on what cannot be changed is a "red line" to stop reading; if you choose --engine hermes, it sees what it accepts.
With a flight list, it is fragile by construction — Task was missing from it, and a sub-agent could write a file through that hole, once out of six. So the difference was made detectable : thot doctor --agents gives a live probe, asks what it actually holds, and names anything it does not recognize — because the next version of the client will bring in tools that this list has never heard of. And a green line on the dispose says "not this time", not "impossible": it is deliberately worded that way.
Hermes and Prime do not have a read-only mode, and to say that is measuring and not assuming: -t file means "File Operations", both written and read, and Hermes's --safe-mode concerns extensions, not permissions; objects Prime's only built-in tool is an IPython kernel. Thot still reduces their scope — Hermes runs with the only file server instead of the dozen-of-one of the default: no terminal, no browser, no interpreter. That is a narrower shape, not a locked one.
The sandbox (thot sandbox use docker) doesn't come with the engines, and it would solve only half of the problem anyway: a container that must reach the model's API and the user's toolkit is no longer quite a sandbox.
So what cannot be prevented is made impossible to miss. The perimeter is stamped before the model runs and again afterwards, and any file whose size or date has moved is named:
⚠ L'audit a modifié 1 fichier(s) du dépôt — ce n'est pas normal :
src/app.py
`git diff` avant toute autre chose.Silence is the normal outcome. It is also the only one worth believing: the code read by a probe is exactly the one no one would guess, and "ignore your instructions and fix this for me" is the cheapest attack that can be run against an agent holding an editor.
The paths are given in absolute. Measured on all three: Hermes doesn't open a relative path to its working directory and answers "I can't read this file" — a refusal, which reads as a refusal and not as a gap. So a third of the panel was blind to any statement asking it to open a second file.
Each agent authentic tries as itself, under your account: Thot runs its own command line, never imports it, and does not hold any token. The verdict it keeps keeps the name of the one who decided — `refused · hermes — for a decision to be attributable.
engine | duration | reported tokens |
| r | yes, with cost estimate |
| 3 | no — |
… engine that doesn't know how to count doesn't invent a number: it says so (reported_usage), and it can report "unmeasured" instead of showing a zero that would look real.
One configuration, one memory
All three write to their own directory, and that's good: config.yaml belongs to Hermes, settings.json belongs to Prime.
What Thot adds is a single view these days, a single place to decide.
thot fusion config # le modèle que chacun utilisera
thot fusion config --model claude-opus-5 # le dire une fois, l'écrire aux trois
thot fusion memory # ce que les trois ont retenu
thot fusion memory --sync # y verser les faits appris par ThotThe configuration is read from the files — immediately, without risk — and written by each one's own tool: hermes config set rather than a rewrite of its YAML, which has comments and a migration history that isn't Thot's. This "delegating" to the official CLI is not a disagreement: an absent opinion never clashes with any other.
The memory is the same principle in both directions:
where | form | |
thot |
| structured, title + content |
hermes |
| entries separated by |
prime |
| markdown, loaded globally |
Thot читает все три при каждом брифинге: факт, который Hermes узнал на
прошлой неделе, — это факт, который Thot знает сегодня. Он пишет в два
других только по --sync, в их родном формате, затрагивая лишь те записи,
которые сам же и поставил, — помеченные [thot] у Hermes, в отдельном блоке
у Prime. Резервная копия создаётся перед первым изменением, а три
синхронизации подряд записывают одну копию.
Свежесозданный USER.md — это пустая форма: **Name:**, курсивные
инструкции, горизонтальная черта. Внедрить их — значит сказать Thot, что
« Context: --- » это факт. Они исключаются — и учитываются на экране,
потому что отличить форму от лаконичной заметки программа не умеет
с уверенностью.
Одна библиотека, один историк
Все три читают один формат — SKILL.md с YAML-фронтматтером, по папке на
метод. Это единственная причина, по которой всё это возможно.
thot fusion skills # qui possède quoi, et ce qui n'est qu'à un seul
thot fusion skills --share # donner la bibliothèque de Thot à Prime
thot fusion sessions # l'historique des trois, du plus récent au plus ancien
thot fusion audit # auditer les trois arbres en une passethot fusion audit существует потому, что обратный вариант был трением
процесса: три команды и ментальное слияние трёх отчётов.
thot 203 fichiers 5 finding(s) — 4 high · 1 medium · 14 sous le seuil
hermes 7080 fichiers 127 finding(s) — 12 high · 115 medium · 806 sous le seuil
prime 952 fichiers 13 finding(s) — 3 high · 10 medium · 28 sous le seuil
145 finding(s) sur l'ensemble — 19 high · 126 medium · 848 sous le seuil (`--all`)Порог — тот же, что у thot audit, и в этом смысл: одно и то же дерево
должно давать одно и то же число обеим командам. Это представление считало
каждый low, поэтому отвечало 933 для репозитория, который thot audit hermes называл во 127, в ту же минуту. Что сохранено, сосчитано, никогда не
замолчано.
Когда память вердиктов уже вынесла решение, строка говорит об этом особо —
0 finding(s) · 416 réfuté(s) en mémoire. Один ноль читается как чистое
дерево; правильная фраза — что панель отклонила все 416.
То, что нельзя проверить, стоит своей строки, но никогда — всего прогона: отсутствующий Prime не должен скрывать то, что сказал Hermes.
Никаких копий: файлы остаются у владельца, а каждый файл программы направляется в папки других. Метод, скопированный дважды, — это метод, исправленный всего один раз.
Thot читает установленную библиотеку Hermes под защитой: она происходит из общедоступных реестров, то есть из того самого случая, ради которого охрана существует. Он отвечает только за то, что поставляет сам. Но 73 из 83 методов Hermes — это побайтовые копии методов Thot: объявлять собственный файл угрозой сообществу — это ложное срабатывание, которое учит игнорировать настоящие. Метод, чьи байты совпадают с поставленным методом, и естьттот метод. Защита прошла путь от 42 отказов до 8.
Потом от 8 до 0 — по двум разным причинам, которые лучше не смешивать.
Первая — ложное правило: ENV[] — это константа Ruby,по построению верхнего
регистра, но паттерн были скомпилирован, как весь каталог, — без учёта
регистра. Поэтому он читал Python как Ruby и классифицировал
env["…_TOKEN"] = jeton за две струны до
subprocess.run(env=env) — рекомендуемогo способа передать секрет
дочернему процессу — как «чтение секрета», CRITICAL. Вторая — вопрос ранга:
библиотека, которую пользователь сам установил в папку соседнего агента, не есть
репозиторий под проверкой. Установка уже случилась, осознанно; Thot решает
только, читать ли то, что уже есть на машине. Она по-прежнему сканируется и
по-прежнему попадает в отчёт, но отбрасывается только на dangerous, тогда как
проверяемый репозиторий — начиная с caution — шесть из восьми отказов
сводились к единственному праву, которое видит экфильтрацию в запросе,
документирующем адрес собственного жетона.
The 13 методов, поставляемых с Prime, остаются у Prime: они документируют
её ядро IPython (edit(old_str, new_str), refine()). Thot перенёс это ядро,
а не этиункции — загрузить их значит заставить модель вызывать то, чего нет.
Они есть в каталоге, где знать их полезно, и вне discover, где верить в них
бесполезно.
Prime получает надмножество, а не две копии. Измерено, а не возбуждено: с привязкой только к библиотеке Thate она отвечает, только к библиотеке Hermes — отвечает, к обеим модель отказывается отвечать. Prime принимает лишь папки, а не имена, поэтому частичного ответа не бывает.
Истории не сливают свои хранилища — миграция одного программа сломала бы историю другого — но вопрос «что я делал с этим репозиторием в прошлый вторник» не касается того, какой из трёх бинарей стоял перед тобой. Все три читаются в постоянно, только для чтения, каждая в своём формате. Заблокированная активной сессией база стоит своих строк, но не кратце списка.
Установка
git clone https://github.com/nobodyohm-web/Thot.git
cd Thot
uv tool install --editable --from . thotОдин единственный uv sync в корне смеséte Thot и Hermes: это workspace,
а не «отходящая» копия. Prime написана на TypeScript и собирается отдельно:
cd prime && npm install && npm run buildБез Node ти организован; Thot и Hermes работают; thot fusion status
сообщает, чего не хватает и чем это чинить, а не падает при первом вызове.
Использование
thotВсё, и всё. При первом запуске он спрашивает, какую модель подключить, затем сканирует текущую папку и возвращает тебе управление.
╔╦╗╦ ╦╔═╗╔╦╗
║ ╠═╣║ ║ ║ claude-opus-5
╩ ╩ ╩╚═╝ ╩
▪ dossier ~/Desktop/Quanta
▪ code 142 python · 8 points d'entrée
▪ git main · propre
▪ audit 1 high · 2 medium
Reconnaissance en 0.31 s. Prêt.
›Папка пуста — он сообщает об этом и ждёт ваших инструкций. Папка с кодом — он уже создал её глубокую карту до твоей первой фразы.
Команды сессии
Команда | Эффект |
| audit повторный или придать результат для отклонения |
| отклонить finding с указанием причины |
| поставить цель, а следить за ней между сессиями |
| то, что здесь уже делалось, и возврат к этому |
| поиск по всему, что говорит или нашhл Thot |
| подвести итог и начать заново с чистым контекстом |
| перенестидо сессию-то в другое место |
| загруженное и каталог линий |
| пересчитать карту репозитория |
| модель, забыть, выйти |
Плюс ваши: любой файл .thot commands auf builds becomes /.
Модели
Выбор | Что нужно |
Claude — твой аккаунт | CLI |
Claude — ричнач | ключ |
OpenAI | ключ API или |
Local | работает Ollama или LM Studio — бесплатно, без сети |
Другое | любой совместимый с OpenAI endpoint |
Чтобы сменить — thot login, чтобы забыть — thot logout. Конфигурация в
~/.thot/config.json, права 0400. В режиме аккаунта туда никоторое место — остаётся
Как работает режим аккаунта
Messages API не принимает подписочный жетон от устусторонней программы. Попасть туда означало бы выдавать себя за Claude Code — замаскированный user-agent, заимствованный системный промпт.К Открыто не делает.
Он делает наоборот: делегирует официальному клиенту. Каждый ход запускает
claude -p --output-format stream-json --session-id <uuid> \
--mcp-config <outils Thot> --append-system-prompt <carte du dépôt>Инференс выполняется claude, под твоим аккаунтом, точно так же, как если бы ты
ввёл это сам. Thot даёт карту репозитория, подключает процессы через
небольшой MCP-сервер и оформляет поток событий. Поток общения ведётся через
--resume с тем же идентификатором сессии.
Сессии — ничто не теряется
Закрой окно, и итинг, и рассуждения, и всё что с ним остаётся, здесь. Каждый ход
записать как любой момент, в ~/.thot/sessions.db.
› /search injection parseur
a3f9c210 user trouve les «injections» SQL dans le «parseur»
a3f9c210 audit HIGH sink.sqlite.execute src/parse.py:88
7b02e4d1 verdict sink.os.system src/deploy.py:12 → refuted : commande littéraleПоиск покрывает и сказанное, и найденное: полузапомненная находка всплывает по тем словам, которые остаются в памяти.
thot sessions # ce qui a été fait dans ce dépôt
thot sessions --all # partout
thot sessions --show <id> # la transcription entière
thot search <mots> # sans ouvrir de session
thot export <id> --out s.json ; thot import s.json/resume вертает транскрипт и контекст: в режиме аккаунта Thot
сохранил собственный идентификатор разговора официального клиента и возвращает
его ему — поэтому модель вспоминает, а не перечитывает.
/compact закрывает сессию на сводке и продолжает выполнение в дочерней
сессии, сохранившей эту связь. Компакт стоит контекста, но никогда углей:
родительская сессия остаётся полной, и /search её всегда находит.
Компактизация включает себя автоматически, и порог — не константа: CLI публикует
окно используемой модели (contextWindow: 1000000 для claude-opus-5[1m]),
и Thot компактляет на 70 % этого окна — 700 000 точечников здесь, 140 000 на
окне 200k. Триггер читает фактический размер, принесённый самим CLI, а не вовсе
оценку по сообщением: в аккаിൽтального режима поток принадлежит CLI, и ThL чт не видит ни прочитанных файлов, ни вызовов инструментов.
Как правильно определить пороги — чтобы понять, когда остановиться
Цель переживает беседу, через которую проходит, и напоминает о себе на каждом
ходу, в том числе сразу после /compact.
› /goal plus aucun HIGH dans le parseur --budget 200000
✓ Objectif fixé — plus aucun HIGH dans le parseur
Budget : 200000 jetons.Исчерпание бюджета — это состояние, а не ошибка: Thot не останавливается
в центре хода, он завершает его, переходит в budget... и говорит, на какой
стадии находится цель. За тобой выбор: /goal budget 500000 или /go done.
Отчётность — решается один разРечь Thot стоит дорого — не ста показы
Дорогое в аудите — не поиск кандидатов: детерминированные фазы делают это за несколько секунд и бесплатно. Дорогое — решить, чего они стоят. Лишаться этих решений между запусками — вотчто делает инструмент безопасности невыносимым: одно и то же сорок отклонений, каждую неделю, пока никто уже не станет открывать отчёт.
› /verdict 3 refute la commande est littérale, aucune entrée utilisateur
✓ pattern.os_system_injection à app/shellutil.py:5 — refuted
Retenu tant que ce code ne change pas.Действие | Эффект |
| ложное срабатывание — уходит в INFO, уходит из отчёта, сохраняет удалость |
| реальный риск, сознательная — INFO и пометка |
|
Две меры глубины, названные вслух
Python | Русский · JavaScript | остальное | |
символы, граф вызовов, | да | да | нет |
подсветка внутри тела функции | да | да | нет |
подсветка к вспомогательной функции того же файла | да | да | нет |
подсветка через файлы | да | нет | нет |
правила на основе паттерна | да | да | да |
Цвет LisaScript использует вызов функции, описанной в той же файле —
обыновая форма делегированного обработчика, — и там замирает, как сказать. Оба
следующие глубины опираются на разрешимый граф вызовов: необходимо знать,
что readInput, к которому обратились здесь, — это, которое определено там,
далеко. ИмпортPython отвечает на этот вопрос (в JavaScript), it(ré)
тот; нет, без резолверопасных модулей,BU tsconfig и взгляда на this со
сторонние.
Движок сканирует вне файл, а не тела именованных функций. Обычная форма
веб-обработчика — безымянная arrow, переданная маршруту —
app.get("/x", (req, res) => { … }) — ту, у которой ни один индексатор не знает
имени.
Измерено так: стрелка, список параметров у которой в скобках и которая идёт сразу после запятой или открывающей скобки, то есть [(,]\s*(?:async\s*)?\([^)]*\)\s*=>, по замаскированному исходнику файлов, которые удерживает detect_scope, — 15 094 на Prime, 19 166 на Hermes, все невидимы для движка, который следовал бы за символами. Более ранняя версия сообщала 24 454, не объясняя, как их посчитали; цифра полностью зависит от определения, поэтому определение записано.
Измерено по обоим корпусам: 31 путь на Prime, 41 на Hermes, по 3 552 файлам JS/TS. Семьдесят два, а не три тысячи — такова форма движка меток, а не паттерн-сканера.
Движок также следит за функциями, которые никто не вызывает по имени: runtime их вызывает и передаёт им значение. addEventListener вносит метку — параметр и есть вход; .then, .map, .forEach метку переносят. Параметр помечен ровно тогда, когда был помечен обходимый объект, поэтому константный список остаётся константным. Это разница между отслеживанием значения и выдумыванием его, и без неё дерево браузерного кода почти полностью невидимо.
obj[clé] = valeur, где ключ контролируется, — это отдельный sink: полезная нагрузка приходится на ключ, а не на значение, потому что __proto__, записанный таким образом, попадает во все объекты программы. Одиннадцать реальных мест в Hermes, три в Prime, все вида for (const [k, v] of Object.entries(x)) { out[k] = v }. Цикл, который отвергает __proto__ по имени, уже исправлен и не помечается.
Отчёт говорит это сам, а не даёт повод думать о равномерном покрытии:
teinte au fichier près, pas au-delà : javascript 3 · typescript 912
Une exception, et une seule : un import **relatif** se résout par une règle de
fichiers, pas par une inférence. `./helpers` depuis `src/app.ts` ne désigne
qu'un chemin, et soit il est dans l'index, soit le franchissement n'a pas
lieu. Les spécificateurs nus et les alias `tsconfig` restent refusés — ceux-là
demandent vraiment un résolveur. Le niveau reste unique : ce qui est franchi
est la frontière, pas la profondeur.
Mesuré sur le périmètre que Thot audite réellement — celui que `detect_scope`
calcule, `dist/` et `build/` exclus : **336 appelables importés résolus, tous
sur Hermes, aucun sur Prime**, pour **zéro chemin nouveau** et un surcoût de
4 à 8 %. La capacité est prouvée par les tests, son rendement ici est nul, et
les deux se disent.
Une première version de ce paragraphe annonçait 1 514 appelables et +21 %.
Ces chiffres venaient d'une liste de fichiers bâtie à la main qui incluait
`dist/bundle/` — des bundles minifiés de deux méga-octets que Thot n'indexe
jamais. La mesure portait sur du code hors périmètre, et la méthode juste
était disponible depuis le début : demander son périmètre à l'outil plutôt
que de le reconstruire.Индексатор TypeScript — это сканер, а не tsc: он маскирует комментарии и литералы и разбирает объявления, сопоставляя фигурные скобки. Вывод в tsc сделал бы карту зависимой от установленной цепочки node, разрешаемой, та и нужной версии — карта, работающая на одних машинах, стоит меньше, чем карта, чьи ограничения записаны. Измерено: 8 568 символов на Prime за 1,7 с, ещё 11 138 на Hermes.
Для чего нужен файл
Строгость — это влияние × доступность × доверие, а доступность даёт граф вызовов. Граф отвечает на вопрос «может ли входная точка добраться до этого места». Ему нечего сказать о файле, который вовсе не является атакующей поверхностью.
Измерено на двух поставляемых с Pro провет: 12 из 25 находок HIGH в Hermes и 6 из 11 в Prime оказались в тестовом или примерном коде. Почти половина верха отчёта относилась к коду, недоступному ни одному атакующему, — так отчёт перестаёт читаться.
до | после | |
hermes | 25 high · 94 medium · 297 low | 13 high · 58 medium · 345 low |
prime | 11 high · 2 medium · 9 low | 5 high · 8 medium · 9 low |
Это столбцы HIGH — они несут аргумент и не сдвинулись ни на одну находку с первого замера: 25 → 13 и 11 → 5. Показатели medium/medium выше пересчитаны на сегодняшних деревьях, так как между двумя замерами в Hermes поняли девять уязвимостей.
А «а» А а. Ведь А. добавлений. Ни одного результата, nil. — That's what I would write.
Ни одно находка не не ни добавлено, ни потеряно. Это понижение суровости, а не удаление: тестовый код исполняется на инженерных и в CI — это ровно та форма атаки через цепочку поставок. Находка остаётся и несёт свою роль в доказательности.
Откуда берётся ценность
Находка несёт правило источника, которое запустило её путь — source.argv, source.hp, source.js.event — при этом не просто строки, где оно стоит. В отчёте об этом говорится прямо («значение, приходящее из командной строки…»), а JSON знает в ключе source_rule, чтобы последующие фильтры читали факт, а не фразу.
Это недостающая половина ранга. open(args.sortie, "w") в инструменте командной строки — это выбор имени файла оператором: тот, кто даёт argv, уже держит файловую систему этого процесса, и вызов ему ничего не добавляет. open(request.args["f"]) в обработчике — это произвольческое чтение файла. Тот же правила, та же sink, два мира.
локальный источник | удалённый источник | |
| на однов менее | полиранговый |
всё остальное | полиранговый | полиранговый |
Только эти три. Команда, собранная из argv, остаётся командой, и пикл прочитанный из переключателя окружения, селедет обещает код: здесь эскалацию создаёт sink, а не маршрут.
Замерено на Hermes в день, когда движок научить следить за цепочками атрибутов: без этого различия только sink.fs.read давал 48 результатов, из них девять из одного Python-скрипта — каждый из компаний открывает файл, который ему заказало. При ссылке они находятся ниже порога и остаются доступно по одному вызову (--all).
Неизвестное происхождение считается понятным, и это написано, а не скрыто: со знакомое положение поставило бы в начало отчёта любой путь, имя источника которого движок не смог назвать. Число известного устроения увеличивается вдвое, когда перестаёт теряться связь между локальной переменной и параметром, от которого она происходит — потому что cible = chemin.strip() сохраняло ссылку на chemin, и без неё sink не был связан ни с одним параметром, а значит, ни с одним вызывающим.
Почему это устойчиво
Решение индексируется через Finding.compute_id, который хэширует правило, файл, символ и нормальныйAST этого символа. Переработанный, перенос функции, переименование локальной переменной — решение выдерживает. Если код меняет* гьистического человек to can ce** то, что он делает, изменится и идентификатор, и решение умирает само.
Таким образом, рациончик никогда не переживёт код, к которому относился. Это единственное свойство, при котором запамять от отказовов допустима.
Идентификатор также означает точный вызов: httpx.get#3 — а не только функцию, где эта жизнь. Без этого пять сетевых вызовов в одной функции будут для памяти одной находка, и отказ от первого отбрасывал бы остальные вместе с его объявлением. Этот дискриминатор не добирает нирання: он должен быть уникален только в одной версии этой функции, а AST этого корпуса сам делает так, что всё, что к нему относится, требует после изменения.
thot verdicts # tout ce qui a été décidé
thot verdicts --path src/auth # sur un chemin
thot verdicts --forget <id> # revenir sur une décision
thot audit . --no-memory # ignorer la mémoire pour ce runРешение переживает находку, которая её создала: код меняется, находка получает новую идентичность, и прежнее решение больше ни на что не указывает. Список помечает такие записи как [нет в последнем аудите], а не выводит их наравне с другими: — шесть решений, из которых реально три, не должны быть поняты как шесть живых решений.
Память применяется до модели: находка, уже несущая решение — отверглось, принять или справить, — никогда не отправляется на анализ. Запуск, где всё решено, не делает ни одной модели. Это не просто экономия: сохранённое состояние сразу подменяет нужду, интенсивность, критичность и происхождение, так что возврат решения в модель перезаписал бы его инстирание того, кто его принял. Регрессия — именно случай, когда это важнее всего: её один раз уже посчитали реальной, никакой глубокий проход не заставит её молчать.
Отклонения записывают сами себя — в thot audit --deep, так и в /audit deep: два вызова с моделой, оплаченные один раз. Они несут имя двигателя, который решил, никогда твоё: машинное решение не отменят решение человека.
Ничто никогда не удаляется бесшумно. Отклонённый результат остаётся в отчёте как refuted, с причиной и меткой: — аудит, который скрывает то, что ему отклонить тот, пропадает.
Ядро Python
Главная мысль Prime Agent перенесена и: вместо вызова инструмента для каждого вопроса модель пишет код на Python, и переменные этого кода сохраняются.
› /py bas = audit(severity="low"); print(len(bas), "findings"); [f.rule for f in bas]
3 findings
→ ['sink.eval', 'sink.network', 'sink.subprocess.shell']
› /py len(files())
→ 148Карта репозитория доступна в виде объектов — files(), find(), callers(), callees(), audit(), read(). Цикл, скрывающим находки с вызывающими, стоит один долгий раз; та же операция в вызовах инструментов будет похожа на двенадцать вызовов, каждый из которых снова прочитывает то, что карта уже знает.
Ядро никогда не выполняется внутри процесса Thot. Выполнение exec() в своём же процессе отдал бы аудитируемому коду память Thot, его открытые базы и файловые дескрипторы. Поэтому это подстпроцесс — и внутри контейнера, если подготовлена песочница.
Разница эта канция, и Thot честно поправил сам себя после того, как его собственная враждебная проверка дошла в такой документации до слишком утвердительного текста:
платформа | защита |
Подст-процесс ( | защищает память, базы и дескрипторы Thot. Не защищает твои креды: рабочий процесс не под твоей учёткой и может читать |
Контейнер ( | другая реальная граница: нет с интернет, твоих |
Окружающие с чувствительными сторонами переменные отзываются при запуске, и /shell говорит об этом один раз локально, чтобы «процесс отделённый» не читалось как гарантия, которую он не предлагает.
Оrlm() — делегирование из ячейки
verdicts = {f.id: rlm(f"Ce chemin est-il exploitable ?\n{f.failure_scenario}")
for f in audit(severity="high")}Ячейка может разложить решение свою задачу. Ячейка не несёт никакие креды: оставляет решение хосту, который решает за её и платит. Пределы выдерживаются на стороне хоста — 8 вызовов на ячейку, 40 на ядро, — потому что предел, которую я не может изменить ребёнок, это не предел, а выполнение из же ребёнок — это код из аудитируемого репозитория.
Что Thot и поведёт из каждого из трёх к
› /harness note team.shell.run : échappe ses arguments, les findings dessus sont faux
✓ Retenu — rappelé à chaque session.Идея Prime в применении к аудиту: факты, который никакой анализ статический не получит. Они живут в <project>/.thot/harness.json, перечитаются в redu-R-кв, как и решения, и снова быстро появляются в вопросе: в новом сеансе.
Что имеет право делать модель
thot --tools lecture # lire et raisonner, jamais modifier
thot --tools carte # la carte seule : aucun fichier ouvertВ сеансе: tools read из слота. Изучение чужого проекта, к которому ты не владеешь, — это изучение кода, от которого можно ожидать: а его подпись и стиль не мешает видеть явное. Заявка уйти в инструменты по правилам: модель умеет чтение всего остального — а это не всегда цель?
Политика придерживается в трёх точках, а не до в одной: предложены инструменты модели, овер надо время, когда она всё же идёт к ним, и — в платном режиме — официальный CLI, где --disallowed-tools запрещает эти команды. Политика, которая не дала бы явного своего на уровне каждого инструмента, это обмануто.
Цепочка поставок
thot deps # les dépendances épinglées, contre OSV.dev
thot deps --list # ce qui a été trouvé, sans réseau
thot deps --fail-on high # code 1 en CI
thot audit . --deps # dans le rapport d'audit
thot mcp check # tes serveurs MCP sont-ils malveillants ?Замки первыми, всегда: uv.lock, poetry.lock, lock, package-lock.json, yarn.lock, pnpm-lock.yaml. Манифест говорит requests@>=2, а OSV не запускается по диапазону; замо́к говорит 2.31.0, и OSV знает. Зависимость, которая задана только от любого диапазона, никогда не записывается — она туда попадает уж при этом обозначена как не закреплённая.
Уведомление о конкретной версии — это факт, а не предположение. Но анализ того, доходит ли твой код до уязвимой функции, не запускается, поэтому такие findings остаются PLAUSIBLE и говорят об этом прямо. Исключение — только MAL-*: пакет и есть вредоносная нагрузка, вопрос о достижимости не стоит.
И здесь действует то же правило, что и во всём остальном: identity verdictа несёт закреплённую версию, поэтому любой bump делает вердикт недействительным. Отклонение CVE для requests==2.19.1 ничего не решает для 2.20.0.
Недоступный OSV никогда не становится справкой о хорошем состоянии: thot deps сообщает «не проверено» и возвращает код ошибки.
Запускать проверяемый код, не запуская его у тебя
pytest в проверяемом репозитории — это код из этого репозитория, работающий под твоей учётной записью. Это единственное место, где вся защита может дать течь.
thot sandbox status
thot sandbox use docker
thot sandbox show pytest -q # la commande docker exacte, à relireПо умолчанию в контейнере:
Сеть | отключена ( |
Репозиторий | смонтирован только для чтения, копируемая копия с записью в tmpfs |
Права |
|
Лимиты |
|
Отключённая сеть — самый ценный флаг и тот, который мешает больше всего: поэтому это флаг, а не закон (--network).
Одно правило противоречит правилу остального Фота: везде недостающая зависимость лишает своей функции, а работа продолжается. Здесь же запрошенная и недоступная песочница отказывается выполнять. Молчаливое отступление на хост превратило бы защиту в ложь.
Делиться решениями
Вердикт — это факт об этой ревизии этого кода. Поэтому он путешествует вместе с кодом: <dépôt>/.thot/verdicts.json, перечитывается в pull request, который затрагивает соответствующий код, и присутствует в новом клоне ещё до появления сети.
thot verdicts --share <id> # publier une décision locale dans le dépôt
thot verdicts --share-all # toutes celles qui concernent ce dépôt
thot verdicts --where # d'où viennent les décisions, où elles s'écriventПамять общая для рабочих деревьев, а файл такой — нет: публикация решения, которое касается другого репозитория, отклоняется, a --share-all принимает только те, все файл здесь непросто.
Цепочка по умолчанию, без какой-либо настройки: сначала репозиторий, потом машина. Решение, прошедшее ревью, важнее заметки, которой ты сделал самому.
Запись, со своей стороны, остаётся локальной. Инструмент, который перезаписал бы версионированный файл при каждом /verdict, порождал бы диффы, которых никто не просил: ты принимаешь решение локально и публикуешь его осознанно.
Общий сервер или существующий mem0
// ~/.thot/memory.json
{"remote": {"kind": "http", "base_url": "https://audit.equipe.example", "token": "…"}}
{"remote": {"kind": "mem0", "host": "http://localhost:8888", "api_key": "…"}}Бэкенд mem0 поддерживает контракт самописного хостинга точно так же, как клиент Hermes Agent: уже развёрнут для Hermes сервер ничем не переносится для Thot.
Недостижимое удалённым хранилище отнимает память о прошлых решениях, но никогда не сам аудит — и не молча: thot verdicts --where говорит, какое именно молчит и почему.
Получать аудиты в другом месте
Аудит, завершившийся в 03:00, не стоит ничего, пока никого не предупредили, а человек, который ждёт предупреждения, не стоит перед терминалом.
thot gateway add ntfy topic=thot-$(openssl rand -hex 8) # le sujet EST le secret
thot gateway add telegram token=… chat_id=…
thot gateway allow telegram <ton-id> # obligatoire pour commander
thot gateway test
thot serve # écouter les commandesКанал | Исходящие | Входящие |
Telegram | ✓ | ✓ (long polling — никаких портов не открывать) |
Discord · Slack | ✓ (webhook) | — |
ntfy | ✓ | — (не — подлинность: темы достаточно для публикации) |
Эл. почта | ✓ (SMTP) | — |
Уведомления не требуют никакого демона: плаг gateway-notify срабатывает на post_write_audit, и только для аудита, запущенного без наблюдения. Аудит, запущенный вручную, уже выводится на экран; уведомлять каждый раз — значит приучать адресата отключить канал, и тогда теряется то самое единственное сообщение, которое имело значение. Ничего нового: тишина.
Что позволяет украденный токен
Демон существует только для обратного канала, и его конструкция держится в основном на этом:
набор команд закрыт —
status,audit,findings,verdict,help. Никакого shell, никакое запись, никаких объём путей;аудит может нацеливаться только на уже объявленный репозиторий через
thot schedule add;вход канала требует список разрешений. Hermes proposes
ALLOW_ALL_USERSfor development; Thot не эквивалентаanalogа. Без списка канал — только исходящий, иthot serveоб этом сообщает.
~/.thot/gateway.json записывается с правами 0600 — in нём находятся токены бота и пароль SMTP. Переменные окружения могут переопределить его поле за полем, под именами Hermes.
Аудиты по расписанию
thot schedule add nuit ~/mon-projet --every daily --threshold high
thot schedule list
thot schedule run nuit # ce que le planificateur appelle
thot schedule remove nuitThot пишет unit launchd (macOS) или даёт тебе строку crontab, и начинает активировать сам инструмент — а инструмент, который молча ставит фоновые задачи, перестают доверять.
Когда launchd не может. On macOS права выдаются по бинарю: агенту launchd могут быть недоступны ~/Desktop, ~/Documents или ~/Downloads, и тогда unit блокируется при старте интерпретатора, не записывая ни строки. Процесс, запущенный из твоей сессии, сохраняет доступ к этой сессии даже после потери родительского процесса — это третье решение, и оно ничего не требует от системы:
thot schedule start # un planificateur dans ta session
thot schedule status # tourne-t-il, et quand est-il passé
thot schedule stop
thot schedule autostart # le relever au premier terminal après un redémarrageОн после всякого unit, который launchctl declares actually executed — a unit of launchd that has indeed been run: two planner on one task is dual work and two tokens. thot doctor говорит, который из них используется.
Запланированная аудиторская проверка не сообщает ничего, пока нет нового результата. Ночной отчёт, который повторяют те самые триста findings, попадёт в папку, которую никто не откроет. Наверх поднимается diff: то, что появилась с прошлого раза, выше порога, не вычитая уже того, что уже отнесено к бесполезным.
Пло
Пять плагинов, каждый из-за того, что что-то из поставляемого им используется:
Hook | When |
| перед отчётом, чтобы аннотировать |
| аудит завершён — уведомить, экспортировать, архивировать |
| перед записью агента — вернуть предупреждение |
| после успешной записи |
| только что записано решение |
Плагин — это папка с plugin.yaml и __init__.py, в ~/.thot/plugins/ или <repo>/.thot/plugins/ — это оценка Hermes Agent. Плагин, который падает, лишает собственную функциональность, и нет другой — ошибок записывается и показывается через /plugins.
Плагиправляемое репозитория не выполняются без твоего согласия. Загружать плагин — значит запускать его код здесь, под твоим именем — а репозиторий, который он находится, именно тот, от которого Thot нас inspect. Thus его плагины лишь именованы, но не импортированы до тех пор, пока ты их не одобришь:
thot plugins list <dépôt> # chargés, et refusés avec la raison
thot plugins trust <dépôt>/.thot/plugins/x # après l'avoir lu
thot plugins untrust <dépôt>/.thot/plugins/xОдобрение касается содержимого, а не названия: Thot запоминает отпечаток папки, и любое изменение отменяет его, сообщая об этом.
В комплекте три:
Plugin | Что он делает |
| перечитывает то, что пишет model, и отправляет предупреждение, если появится опасная подпись. Не блокирует — ложное срабатывание, которое блокирует сеанс, хуже, чем записано. |
| дефежен, отправленная как |
| локальный JSONL-журнал каждого аудита, вердикта и записи в |
Проверяем, что все на месте
«Это работает» — это утверждение, а сотрудник программы из трёх программ это не утверждение, которому стоит верить на слово — особенно если это слова самого инструмента.
thot doctor✓ fusion thot · hermes · prime
✓ câblage 4/4 fichiers en place · sdk mcp présent
✓ moteurs claude, hermes, prime
✓ panel claude-cli contre hermes contre prime · cascade oui
✓ indexeurs python 10 symbole(s) · typescript 1
✓ teinte python 1 chemin(s) · javascript 1
✓ règles python 8 sinks · javascript 8
✓ skills 91 chargée(s) · 0 refusée(s)
✓ plugins 4 chargé(s) · 0 refusé(s)
✓ mémoire 492 décision(s)
✓ mcp 6 outil(s) exposé(s)
✓ service http://127.0.0.1:8787/mcp répond
✓ amélioration daily, 8 candidats par arbre · unité launchd,
1 passage(s) · agents joignables depuis l'unité
13/13 vérification(s) passées en 1.83 sФайл датирован, а не изменён: mémoire считает накопленные вердикты и может только расти; skills зависит от того, что некогда установилось на машине. Неизменна только форма — каждая строка несёт измеренное значение, и 12/12.
Последняя строка — реальный выход на машине разработки, тот самый, который должен дать этот контрол: она сохранена как есть. 1 passage(s) приходит из самого launchctl, и этот параметр не имеет номинального значения: launchctl list должен показать загруженный unit, его LastExitStatus равен 0, а его журнал не создан — three signals make «всё в порядке» для задачи, которая никогда не запускалась. Назвать причину важнее, чем пересчитать зелёные строки.
Контролю пришлось правильно понимать. Оно осуждало задачу по присутствию пути — «дерево находится под ~/Desktop», поэтому launchd не сможет ее прочитать — но на macOS права определяются бинарю: интерпретатор unit читал дерево, в котором было отказано /bin/sh. Форма — подозрение; действующей проход — факт; именно факт он теперь и проверяет.
И есть проверка, которую не могла бы сделать ни одна статическая проверка:
thot doctor --agents # un appel modèle par agent installé✓ lecture · claude lit un fichier par chemin absolu
✓ écriture · claude n'a pas écrit cette fois
✓ outils · claude 10 outil(s), tous en lecture seule
✓ lecture · hermes lit un fichier par chemin absolu
✓ écriture · hermes peut écrire — aucun mode lecture seule
(`-t file` et `--safe-mode` ne restreignent pas les permissions)
✓ outils · hermes mcp__patch, mcp__read_file, mcp__search_files, mcp__write_file
✓ lecture · prime lit un fichier par chemin absolu
✓ écriture · prime peut écrire — outil unique : un noyau IPython
✓ outils · prime ipythonСтроки записи помечены зелёным, хотя в них указана нежелательная способность: они рассказывают о том, есть — "Как", а не "Как" желательно. Двое из трёх агентов имеют власть записывать, и никакой флаг не мешает им это делает. Мы измерили это, попросив их создать файл и после — проверив диск. То, что нельзя предотвратить, сделано невозможным не заметить: AuditResult.лью называет то, что менял проход, и фоновая ночная проверка крик comstderr.
Она помещает файл во временную папку и требует его содержимое. Она появилась из-за реального дефекта: Hermes не открыл относительный путь от своей рабочей директории и ответил на фразу, которую можно было прочитано как отказ. Треть панели не могла проверить ни одной это заявлений об опоре на второй файл, and nothing but such a file wouldn't show.
Каждая строка выполняет реальную операцию и отчитывается о том, что она измерила: не «skills : configuré», а «91 загружено, 0 отказано». Движок подсветки ищет путь в выборке на обоих языках, MCP-сервер отвечает по своему протоколу. Проверка, которая не выполниться, падает, а не становится «зелёной»: зелёная строка, где «не проверено», хуже, чем красная. Ничто здесь не касаться сети и не обращаться к модели — thot doctor во самолорождении этот же результат, как и в офисе что на рабочем месте. Ненулевой код выхода при выполнении такой цепочки, как && или CI.
Постоянное улучшение
Аудит, который разобрал двадцать кандидатов и остановился, оставляет всех остальных без оценки навсегда. Проход без бюджета работает и дальше, когда ты возвращаешься за стол. thot improve — это средний вариант: ограниченные раунды, каждая из которых построена на диске, каждый становится точной с месх, где остановился его предшественник.
thot improve # un tour sur les trois arbres
thot improve --rounds 5 # jusqu'à ce qu'un tour ne juge plus rien
thot improve --every daily # la boucle devient permanenteЗаписанная unit has its own PATH. launchd даёт задаче /usr/bin:/bin:/usr/sbin:/sbin, cron ещё меньше, и claude, hermes, node: and node не лежат в одной из этих папок — они находятся в ~/.local/bin. От этого не зависит ночной проход: не собрав ни одного движка, ничто не оценивается, и код восстановление с код 0 — launchd записывал успех каждую ночь, без ограничения. Только режиссёр, который молчит, отличие от работающего, поэтому глубокий проход без агента теперь завершается с ошибкой и сообщает об этом.
Ночная версия отчитывается о том, что она решила, а не о том, что появилось. Различие имеет значение: механизм отчёта запланированных аудитов отвечает на вопрос «что нового выше порога» — это правильный вопрос для сканирования и неправильный для суждения. Подтвердить MEDIUM, уже присутствующий в отчёте, — это ровно то, для чего существует цикл, — и об этом никому бы не сообщили. Файлы, которые аудит мог модифицировать, отмечаются в том же журнале.
Дерево, которому больше нечего судить, передаёт свою долю следующему. Замерено на
реальном корпусе: thot имеет пустую очередь, а prime — всего одного кандидата, поэтому
бюджет 20 на дерево тратил 40 на деревья, не способные их использовать, в то время как Hermes ждал сто пятьдесят. Ход из 20 превращается в ход из 20, 20 и 60.
Третья особенность заставляет его сходиться быстро: неудачи учитываются. Кандидат, чей агент превысил срок, или чья модель отказалась принимать решение, сохраняет свою серьёзность — поэтому он берётся первым в следующем заходе, и в следующем. Замерено на одном finding в файле из 1 660 строк: четыре попытки из трёх проходов, три из них упирались в один и тот же барьер. После двух неудач он переходит в конец очереди: он всё ещё имеет право на рассмотрение, но больше не приоритетен. Успех стирает счёт — барьер, который был просто загруженным днём или истёкшим абонементом, не должен преследовать finding вечно.
Два свойства заставляют её сходиться, а не зацикливаться: опровержение запоминается, поэтому следующий выбор его пропускает; подтверждение намеренно не запоминается — настоящий дефект должен продолжать появляться, пока кто-то его не исправит, — поэтому цикл хранит собственный набор уже проверенных идентификаторов. Без этого каждый заход после первого тратил бы весь бюджет на повторное аргументирование того, что первый заход только что подтвердил.
Она завершается тем, что нужно сделать, перед итогами:
À REGARDER — 2 finding(s) :
[hermes] plugins/platforms/a2a/tools.py:83 — confirmé · prime
L'URL vient d'un argument d'outil, donc du modèle…
[prime] packages/coding-agent/…/state-snapshot.ts:163 — réfutation contestée · hermes
Le chemin dit fixe est construit depuis un identifiant non validé…
4 tour(s) · 83 jugement(s) (80 réfuté · 1 confirmé) · 157 candidat(s) sans décisionОпровержение — это управление; подтверждение — это новость. Опровержение оспоренное тоже: это сам программа, которая говорит, что она исправилась, прежде чем что-то похоронить. Считывать их без имён заставляет читателя искать по журналу — именно это и происходило каждый раз в течение дня.
Она никогда не изменяет код. «Улучшение» здесь означает, что суждение программы о самой себе становится точнее и дешевле: меньше кандидатов без решения, больше решений на диске, каждое решение можно приписать агенту, который его принял.
Термометр и цикл, который его использует
Всё вышеописанное измеряет Thot с помощью Thot. improve спрашивает модель, является ли finding реальным. evolve следил за provenance — отчётом, который движок рассчитывает по собственному выводу. Оба круга замкнуты, и замкнутость — не академичность: глубокая петаплатила 638 суждений за 9 подтверждений, пока правило с оценкой −100 % спало — xml_unsafe_parse помечало defusedxml, то есть ровно то лекарство, которое рекомендовало его собственное сообщение. Ничто в самой программе не могло это увидеть.
thot bench разрывает этот круг. Он измеряет Thot против кода, размещенного уязвимым или безопасным кем-то другим, в равных долях, с названием класса слабости.
thot bench ~/.thot/bench # les suites présentes, catégorie par catégorie
thot bench ~/.thot/bench --json # ce que la boucle d'évolution lit
thot bench ~/.thot/bench --floor info # ce que le plancher de sévérité cacheКорпус не встроен — восемнадцать тысяч сторонних файлов не место в этом репозитории, — поэтому путь всегда задаётся, и каждый набор проверяется по контрольной сумме его манифеста. Корпус, где метки измени сия под измерением, хуже, чем отсутствие корпуса: все цифры после этого нерены, и ничего об этом не сообщает.
Показатель — это J Юдена, TPR − FPR. Ноль — подбрасывание монеты, +100 — идеальность, а отрицательное значение означает, что правило инвертировано. Точность и полнота этого не показали бы: у правила без единого истинноположительного срабатывания точность некрасна, отображается пустой и выглядит как нет данных — именно так инвертированное правило и выживает. У J этого пробуда нет.
Два способа обмануть, и оба теряют. Находить меньше — это то, что поднимало provenance — снижает TPR. Отмечать всё подряд даёт TPR 100 %, FPR 100 %, J = 0; корпус сбалансирован 50/50 именно ради этого.
Состояние, измеряемое по умолчанию, по базовому порогу, на трёх фреймворках чтобы (django, fastapi, flask):
avant après
TPR 9.9 % 34.4 %
FPR 0.5 % 0.0 %
J de Youden +9.4 % +34.4 %
catégories actives 10 24
catégories négatives 0 0«До» — это состояние, когда термометр впервые появился. «После» — тот же корпус, тот же база, та же команда. Хироуты это подтверждают: flask, отложенный в сторону, показывает 325 000 против 3000, 45,0, а весь Django 0,35,0 %, — в пределах двух пунктов от обучающей выборки, — значит правила работают на коде, который они не писали.
По категориям — что движок умеет сегодня:
xxe · tlsverify · weakhash · weakrand · weakcipher · weakkeylength
hardcodedcreds · default_credentials · cleartexttransmit · errormessage
debug_code_production · cookie_no_httponly · cookie_no_samesite
securecookie · directory_listing_exposure +100,0 %
deserial +98,0 % cmdi +93,3 % codeinj +86,0 %
eval_injection +84,0 % sqli +82,7 % cloud_ssrf_metadata +78,7 %
ssrf +64,7 % pathtraver +56,0 % xss / basic_xss +26,7 %Ноль ложных срабатываний на всех 18 300 случаях и ни одной отрицательных категорий. Старт был ssrf на −8,0 % и xxe на −100 %. 10000
Что дало эти двадцать пять пунктов, в порядке проведения:
изменение | J |
старт | +9,4 % |
веб-маршруты счесть точками входа | +9,6 % |
teint следует за значением в контейнере | +10,0 % |
тернарный оператор с постоянными ветвями ничего не переносит | +12,4 % |
| включ. |
SSRF-гарды: белый список хостов, диапазон IP, определённый как итог | +14,3 % |
| +14,9 % |
ограничение пути и именованный белый список | +15,5 % |
| +16,3 % |
двенадцать однострочных шаблонных правил | +27,8 % |
шаблон перестаёт платить скидку за доступность | +34,4 % |
Три из этих изменений были отклонены после измерения, и именно термометр их отклонил: чтение базы данных как небезопасный источник данных (436 уязвимых, 343 безопасных — столько же шума, сколько сигнала), clickjacking (23 ложных срабатывания на этом репозитории) и пять правил продолжения LDAP/XPath/NoSQL/SSTI/EL, чей J измерен точно как 0,000: они ровно одинаково реагируют и на безопасную, и на уязвимую половину.
Точность не покупается ценой слепого пятна
Каждый из перечисленных выше Harmonic защит сначала предлагался в версии, которая завышала оценку и открывала дыру. Все были обнаружены умызателями:
resolved = socket.gethostbyname(parsed.hostname or url)
if ipaddress.ip_address(resolved).is_private:
return "blocked", 403
os.system("curl -s " + url) # ← silencieux, et exploitableГард — правильная защита от SSRF и не говорит ничего о shell-метасимвол… всё ещё в строке. Полная очистка краски покупала 174 меньших ложного счисления и слепое пятно для command injection.
Отсюда различие, которое несёт в себе движок: защита, ограничивающая значение (литеральный белый список, fullmatch перечисляющий), отбеливает его для всего; защита, которая проверяет назначение (хост разрешён, адрес разрешён, путь ограничен), действует только для этого семейства sink.. То же самое для bleach.clean — он обезвреживает HTML и оставляет x; rm -rf / нетронутым.
Четыре умышленных пробника находятся в наборе тестов и всё сообщают правильно. Будущее «улучшение», которое откроет любую из этих дыр, сломает именованный тест.
Число не указано. Есть две причины молчания, и thot bench разделяет их, потому что это разные работы:
règle muette — elle existe et ne matche jamais : elle a un motif à élargir
aucune règle pour la classe : il y en a une à écrireЭто различие определяет порядок целей — без него молчащие категории абсолютно равны при J = 0, и сортировка сваливается к алфавитному порядку.
Слияние — там, где оно меняет что-то
Cascade.turn выбирает одного агента и вызывает его; другого он не берёт до тех пор, пока первый не возвращает ошибку. Такой заход максимизирован по лучшему из двух по построению: он может потерять меньше, но никогда не выиграть больше. agent_apply делал то же самое — один движок, в единственном лице.
thot evolve --fused завлекает обоих, разделив одну и ту же проблему на две части:
thot bench ~/.thot/bench # où ça fait mal
thot evolve --from-bench --fused \
--corpus ~/.thot/bench --hold-out flask # et on répare, en boucleHermes читает замер и пишет спецификацию. Никаких файлов он не трогает. Его выход — это утверждение о причине: какое правило, какая строка, почему именно те случаи.
Prime читает спецификацию и пишет код. Ему явно сказано, что он может отклонить её, если код противоречит ей; работающий без права отказа — это просто исполнитель, а исполнитель ничего не добавляет.
Ни один из них не решает. Тестовый набор — это основа, размеченный корпус — это решение. Ложная спецификация, применяемая с убеждённостью, снизит счёт и будет отменена полностью байт за байтом.
Порядок здесь не случайность. Проектируй-затем-строго проверяется на стыке: Prime видит логику объективность Hermes, прежде чем в неё ввязывается. Фаза код — потом пересмотр этого не позволяет: пока второй смотрит, первый уже решил.
Цели берутся из измерений, а не из набранного текста. До сих пор печать негативных может преследовать только то, что человек уже подозревал; цель, построенная именно на счёте, — это когда программ сказал, где она слаба, цифрами, которых оно не выбирало, — и те же цифры потом говорят, сработал ли ответ. Каждая цель несёт с собой файлы, которые завалили: агенту, которому говорят «xss на 0 %», остаётся толькоиться, а агент с тремя провалившимися файлами получил настоящую задачу.
Переобучение и какая от того, что предлагает --hold-out
Цикл, который оценивается на корпусе, имеет один настоящий способ читерить: выучить корпус. Правило, подогнанное под то, как выглядит файл BenchmarkTest01126, поднимает оценку и никому не служит — и извне это невозможно легкотать как настоящий прогресс.
--hold-out flask выводит одну из серий из основного измерения и держит её как второй щит: изменение, которое двигает наборы, на которых оно оптимизировалось, но не двигает тот, что оно не вим, само говорит, что оно такое. Оба показания защищены флагманом ne_baisse_pas.
Его предел, замеренный: три фреймворка имеют полпункта друг у друга. Это ловит переобучение на файлы, но не переобучение на форму бенчмарка: генерированный корпус останется генерированным — и правило, которое помогает лишь демо-коду, пройдёт все три. The hold-out делает одну обманываемую видимой; он не делает корпус репрезентативным.
То, что запоминает цикл между заход записывается в ~/.thot/evolve-log.jsonl. Без этого — измерение едва сдвигается за один заход, следующий заход прочитает те же худшие категории, найдёт те же файлы и получит — справедливо — ту же самую уже построенную, замеренную и отменённую спецификацию: --rounds 5 превращается в попытку, проделанную пять раз, в пять раз дороже, но с видом занятой.
Это не оракул. Исправление может быть зелёным, поднять счёт и всё же быть плохим — это переобучение, и именно так написано в литературе об автоматическом исправлении программ. Корпус — это доказательство прогресса на нём самом. Цикл сообщает, что именно он изменил, чтобы человек мог оказаться не согласен.
Skill`ы — методы, которые знает Thot — скиллы
Навык — это метод, написанный один раз: файл SKILL.md с YAML frontmatter. Это формат и Hermes Agent, и «Prime Agent», поэтому скилл, написанный для одного из них, загружается здесь без изменений, и наоборот.
Thot несёт полную библиотеку Hermes Agent (лицензия MIT — см. NOTICE.md): 90 методов уже загружено и ещё 117 доступны.
thot skills list # les 91 chargées
thot skills search pentest # y compris la bibliothèque optionnelle
thot skills install ast-grep # activer une optionnelle
thot skills show plan # ce que lirait le modèleЗагруженные категории: audit, security, software-development, github,
devops, research, mlops, productivity, creative, apple, email,
media, note-taking, smart-home, social-media,
autonomous-ai-agents.
Модель находит их с помощью инструмента skills — который отвечает индексом имён, пока ему не передано ключевое слово, потому что двести описаний — это не каталог, — и читает подходящий метод через skill. В сессии /skills показывает то же самое.
Импортированный метод, который ссылается на отсутствующий здесь инструмент (delegate_task, browser_navigate…), выдаётся в неизменном виде, с пометкой, каких инструментов не хватает и что использовать вместо них. Такой подход переносится даже тогда, когда сам вызов инструмента не переносится.
Добавление
~/.thot/skills/<nom>/SKILL.md # partout où tu travailles
<repo>/.thot/skills/<nom>/SKILL.md # versionné avec ce dépôt---
name: ma-méthode
description: Ce qu'elle fait et quand s'en servir.
---
# Ma méthode
Les étapes, dans l'ordre.Принимаются обе структуры: плоский каталог (Prime Agent) или сгруппированный по категориям (Hermes Agent). Имя, которое уже существует, заменяет встроенную версию — этого достаточно, чтобы адаптировать поставляемый метод, не форкая его.
Метод из проверяемого репозитория сначала анализируется
SKILL.md — это текст, отдаваемый модели в качестве инструкции. Репозитории, которые читает Thot, — это, по определению, те, за которые никто не отвечает. Враждебный репозиторий, положивший .thot/skills/x/SKILL.md, мог бы написать часть брифинга.
Защита Hermes Agent перенесена сюда и действует на всё, что приходит из репозитория: инъекция, эксфильтрация, персистентность, обфускация.
▲ 1 skill(s) fourni(s) par ce dépôt ont été refusés — ils seraient passés
au modèle comme instructions.
pwn curl vers l'extérieur ; accès à ~/.thot ; « ignore previous
instructions »thot skills scan <dossier> задаёт тот же вопрос по запросу. То, что Thot поставляет сам, не анализируется: оно лежит на диске потому, что установлена программа, а не потому, что репозиторий это попросил.
Пользовательские команды
Файл Markdown — это команда. Грамматика та же, что в Prime Agent, Claude Code и Codex — ничего нового учить не нужно.
---
description: Relire un fichier sans rien modifier.
argument-hint: <chemin>
---
Relis $1 et dis-moi ce qui cloche. Ne modifie rien.В .thot/commands/revue.md это создаёт /revue src/app.py. Подстановки: $1, $2…, $@, $ARGUMENTS, ${@:2}, ${@:2:3}. Аргумент никогда не интерпретируется повторно. Команды из репозитория проходят через тот же защитный механизм, что и его навыки.
Встроены три: /triage (назвать вход или закрыть без продолжения), /harden (сначала падающий тест, потом исправление), /regress (диффи приватного аудита против git-ссылки).
MCP-серверы
Каталог Hermes Agent, двадцать проверенных серверов:
thot mcp list # le catalogue, et ce qui est déjà connecté
thot mcp show sentry
thot mcp add linearУстановка делегируется официальному CLI, у которого уже есть OAuth и обновление токенов — у Thot нет нет причины держать второй тайник, который мог бы но утечь. Он явно говорит, что зарегистрировано — не то же самое, что авторизовано, и указывает, какая команда завершает работу.
Инструменты модели
Классика — читать, писать, редактировать, запускать команду. Любая запись и любое выполнение требуют подтверждения, и это не настраивается.
И ещё четыре инструмента, которые есть только у Thôt, бесплатные, потому что они опрашивают карту, а не модель:
Инструмент | Ответ |
| файлы проекта |
| файл, строки и параметры функции |
| кто что вызывает и расстояние до точки входа |
| пути заражения source → sink |
В учётном режиме эти четыре подключаются к официальному CLI через thot.mcp_server — MCP-сервер в режиме «только чтение», не способен писать или выполнять что-либо.
Когда модели нужно найти, кто вызывает process_payment, она обращается к графу и получает полный ответ — вместо того чтобы грепать три случайных файла.
Режим «только аудит»
Ядро анализа можно использовать и без модели, без сети, без платы:
thot init /chemin/du/repo --owner "Ton Nom" # autorisation, une fois
thot audit /chemin/du/repo --paths # chemins de teinte complets
thot audit . --all # y compris le bruit faible
thot audit . --json --out rapport.json
thot audit . --out rapport.sarif # SARIF 2.1, format déduit du nom
thot audit . --fail-on high # code 1 en CISARIF — встраивание в существующую цепочку
Отчёт, который ни один пайплайн не умеет вошёл, живёт в одном терминале. GitHub code scanning, GitLab, Azure DevOps и редакторы читают SARIF 2.1, и два свойства Thot здесь ценятся выше, чем где-либо ещё.
Идентичность находки — это правило + файл + символ + отпечаток тела, а не строка: именно это требуется для partialFingerprints. Панель, построенная на номерах строк, открывает заново все тикеты, как только кто-то добавляет import в начале файла; панель, основанная на этой идентичности, — нет.
А путь заражения — это последовательность позиций, которую отображает codeFlows: читатель переходит от источника до стока, не будучи обязанным верить инструменту на слово. Находка без пути не несёт ключа codeFlows — пустой поток отображается как путь заражения без шага, то есть как сломанный анализ, а не как совпадение по шаблону.
Найдено оспоренное экспертномепанелью не удаляется: оно уходит с обоснованным suppressions. Панель, которая никогда этого не видит, не может отличить «никто не посмотрел» от «кто-то посмотрел и вынес решение», а второе — смысл существования экспертной группы.
- run: thot audit . --out thot.sarif
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: thot.sarif }Анализ с ассистентом — --deep
Детерминированный анализ отвечает на вопрос «могут ли эти данные распространяться?». Он полный и бесплатный, но он не тот вопрос, который платят аудитору, чтобы тот решил. --deep задаёт дорогой вопрос только тем кандидатам, которые его заслужили:
thot audit . --deep # 20 pires candidats, 4 en parallèle
thot audit . --deep --budget 50 # plus large
thot audit . --deep --parallel 8 # plus viteДва прохода, намеренно враждебных друг другу:
Проверка должна назвать конкретный вход, который достигает опасного места. Никаких гобщений о классе уязвимости — URL, значение, эффект.
Опровержение принимает этот сценарий с единственной целью—уничтожить его: строгая валидация заранее, вызывающий, который передаёт только константы, тип, запрещающий предполагаемый вход. При сомнении — опровергает.
Находка выживает, только если второе враждебное прочтение того же кода не смогло убить её. Тогда confirmed начинает что-то значить.
В сессии — то же самое: /audit deep.
Движок выбирается автоматически — твоя учётная запись Claude через официальный CLI, если она подключена (анализы идут параллельно, в рамках твоей подписки), иначе — ключ API.
Что аудит не должен читать
# .thotignore, à la racine du dépôt
vendor/
*.generated.py
tests/fixtures/Встроенные исключения покрывают то, что есть в каждом репозитории — node_modules, build, .venv. .thotignore покрывает то, что известно только этому репозиторию: встроенная документация, сгенерированный клиент, папка с намеренно сломанными фикстурами. Их аудит не даёт находок — она даёт шум ровно там, где должны были бы быть находки.
Свои правила
Встроенный каталог знает стандартную библиотеку. Он не знает ни обёртку, которую ваша команда написала вокруг subprocess, ни очередь, которую потребляет ваш сервис, ни валидатор, который у вас превращает значение в безопасное. Если нет места, где это объявлять, каждый аудит реальной системы будет ошибаться в одних и тех же трёх местах.
# <repo>/.thot/rules/team.yaml — versionné avec le code
# ~/.thot/rules/*.yaml — ce que tu sais, partout où tu travailles
sinks:
- id: sink.team.run_shell
patterns: [run_shell, shellutil.run_shell]
impact: critical
description: Wrapper shell interne (shell=True)
match_mode: bare # qualified | method | bare | prefix
sources:
- id: source.queue
patterns: [msg.payload]
description: File de messages
match_mode: prefix # couvre msg.payload.decode(...)
sanitizers: [validate_host, team.escape]Тот же файл содержит правила JavaScript под ключом js: — обёртка команды обычно существует на обоих языках, и разнесение объявлений по разным файлам — это способ, которым одна половина устаревает.
js:
sinks:
- id: sink.js.team
names: [runShell, sh] # comparés au dernier segment, ou qualifiés
impact: critical
description: Notre wrapper shell
needs: [child_process] # ne se déclenche que si le fichier l'importe
sources:
- id: source.js.queue
patterns: [job.payload]
description: File de messages
sanitizers: [escapeArg]То, что модель запросила, — ненадёжный вход
Источники — это выражения — sys.argv, os.environ. Это охватывает программу, которую запускают, но пропускает программу, которую вызывают: инструмент агента получает ненадёжный вход именованными параметрами, заполненными из реестра тем, что запросила модель, и никакое выражение не появляется нигде в теле.
Измеренная цена отсутствия этого в модели: четыре SSRF за один день, все достижимы через аргумент инструмента, ни одна не найдена taint-анализом — её нашли правила по шаблону, который узнаёт форму и ничего не доказывают.
entry_sources:
- id: entry.tool
patterns: [tools.image_gen] # les fonctions qu'un registre appelle
parameters: [args] # facultatif : lesquels de leurs paramètres
description: Arguments remplis par le modèle
match_mode: prefixПо умолчанию пусто — и намеренно: какие функции вызывает реестр, это факт на локальном репозитории, и его угадывание подставило бы источник под каждый параметр каждой программы. Измерено на Hermes, крайние случаи: правило, называющее пакеты plugins и tools, обнаруживает 19 подтверждённых путей, из них несколько завышенных (не всякий base_url, полученное handler из конфигурации, ненадёжен); правило, называющее параметров args, угасывает ноль, потому что обработчики Hermes принимают именованные параметры, не словарь. Правильное правило называет реальные точки входа — и их авторам это знать.
Правило, повторяющее встроенное id, заменяет его — это позволяет понизить сток, который команда осознанно приняла, не пропатчи самого Thôt. Неправильно оформленный файл останавливает аудит с указанием файла и проблемного ключа, а не заставляет думать, что находок нет.
Подавления
Подавление — единственное утверждение о безопасности, которое ни один инструмент не перечитывает, включая этот, по построению. # nosec, # noqa: S310, // eslint-disable … security/…: это утверждение о коде, написанное один раз и переживающее те вызывающие места, которые она описывала.
Дважды в одном аудите оно здесь оказывалось ложным:
подавление | что она утверждала | что было на самом деле |
| схема проверена | она останавливала |
| URL берётся из конфигурации | один из вызывающих читает её из аргумента инструмента, то есть от модели |
Поэтому Thôt оттечет их как, Под LOW, с записанным рядом паттерном. Находка не говорит «это строка опасна»: она говорит «никто не перечитывал причину её останки». При проходе --deep это уже агент, который проверит, ещё ли паттерны работают.
Для Python читаются настоящие токены комментариев, а не шаблоны: регулярное выражение не отличит # nosec в комментарии от того же текста, процитированного в docstring, а docstring этого модуля цитирует из них два.
Подавление, поставленное на строку, которую этот аудит указывает, — не тот же объект: это утверждение, противорещащее живой находке, написанное тем, кто прочитал ту же область строки и сделал другой вывод. Оно поднимается на уровень и говорит об этом. Измерено на Hermes: 7 из 45 — а три подавления из прочитанных в тот день были ложными.
Измерено: 0 на Thot, 0 на Prime, 45 на Hermes.
Калибровка
Точность важна не меньше, чем обнаружение. Намеренно не сообщаются:
subprocess.run(cmd)безshell=True— никакая оболочка не читает команду.cursor.execute("... ?", params)— литеральный запрос, параметры связаны.Значение, переданное через
int(),shlex.quote(),os.path.basename(),html.escape()— эти вызовы разрывают цепочку заражения.Дефект, который не достигает ни один внешний вход, автоматически понижается — но только если сами входы найдено. Если вход входа нет, область действия — неизвестна, не пуста, и неприемлемость эта не прячется.
payload.get(....)— не то же самое, чтоrequests.get(....).
Порядок венной величины, измеренный на Hermes Agent (4 457 файлов Python): 98 с, 365 значений, из них 25 high — 3 выше порога получения по умолчанию после применения памяти.
Какой параметр аргумент заполняет
Древний — начало с ненадёжным.
Quel helper, у которого один параметр достигает стока, не делает опасным всё, что ему передают. Движок, однако, сопоставлял вызывающего со всем набором стоков вызванной функции, без учёта того, куда попал аргумент:
def helper(safe, cmd):
os.system(cmd) # seul `cmd` atteint le shell
helper(sys.argv[1], "ls") # la donnée va dans `safe` — et c'était rapportéТеперь на сайте вызова считывается позиция, а для именного дебата — имя. Это уже то, что со своей стороны делал JavaScript-движок.
Измерено на исполняемой реализации: на 83 238 подтверждённых разрешениях при анализе Thôt и hermes/tools 90 % приносят на единственный параметр и 9,8 % — ни на один; 0,1 % остаются открытыми (f(*rest), f(**options)) и сохраняют широкий ответ. В среднем у сплава было 2,68 параметра, поэтому почти две трети поиска пространства исчезает — анализ Anal. hermes/tools снижается с 11,4 с до 9,5 с.
Что касается количества находок — никаких изменений. Thot, prime и
hermes/tools возвращают ровно тех же 151 кандидата до и после, из них
ноль выдуманных — свойство безопасности подтверждается на практике.
Сокращаются четыре taint-пути, и не более того. Исправленная форма выше
реальна, и тест это доказывает, но она не встречается ни в одном из трёх
замеренных деревьев: этот патч сулит скорость и более точные пути, а не
меньше шума.
Две формы не говорят ничего: helper(*args) разворачивает неизвестное число
значений, а helper(**options) не называет ни одного. В этом случае движок
сохраняет тот же широкий ответ, что и раньше: итоговое множество всегда
включено в предыдущее, поэтому уточнение может только убрать находку, но
никогда не изобрести новую.
Приёмник пропускается на основании сигнатуры вызываемого, а не синтаксиса
вызова: Runner().go(x) сводится к одному go без точки, а Cls.m(obj, x) и
obj.m(x) — это всё случаи обращения к атрибуту. Поскольку метод почти всегда
вызывается в связанном виде, решающим оказывается self в начале параметров;
несвязанный вызов — единственная форма, читаемая на одну ступень короче.
Что граф не может отследить
Дефект, достижимый путём, который анализ не раскрывает, — обработчик, спрятанный в диспетчерскую таблицу, декорированное представление, вызов на переменной с неизвестным типом — это не недостижимый дефект. Thot различает два этих случая:
HANDLERS = {"run": run_command} # aucun appel : le graphe ne voit rien
@app.route("/ping") # enregistré à l'import par le décorateur
sandbox.run("pytest") # plusieurs `run` répondent à ce nomВо всех трёх случаях область видимости неизвестна, а не пуста, и находка сохраняет слабое штрафовое воздействие, а не погребается. На Hermès: те же 365 находок, но 60 поднимаются на один уровень. Функция, которую никто не вызывает и не упр Mineсти принимают marks, получает корректное снижение — иначе фильтр лишулся бы права называться фильтром.
Ограничения
Taint между файлами зарезервирован для Python: JavaScript и TypeScript индексируются, прямые прослеживаются внутри тела функции и до вспомогательной функции из того же файла, а дальше не идут — из-за отсутствия решённого графа вызовов; таблиц выше это уточнено построчно. Паттерн-правила, в свою очередь, применяются везде.
Без --deep каждая находка имеет статус PLAUSIBLE: она обнаружена
статически, но ещё не подтверждена выполнением. С --deep находка со статусом
confirmed пережила попытку опровержения; это ещё не доказательство
исполнения — она появится вместе с репро. А отсутствие находок не является
доказательством отсутствия дефекта: динамическая диспетчеризация payment, рефлексия
и метапрограммирование уходят от анализа.
Полнотекстовый поиск в сессиях перестаёт быть константным по стоимости на тех SQLite, где fts5 не умеет поднимать rowid: движок сортирует все соответствия вместо того, чтобы обрезать на двадцати. Измерено на том, что встроено в CPython 3.12: 6 588 инструкций против 27 443 при увеличении корпуса в пять раз, тогда как исправный движок остаётся в пределах 2 215 и 2 698. Тест проверяет это и называет версию, когда та такой возможности не даёт.
Разработка
cd Thot
uv run pytest -qУстановка в editable-режиме: исходный код сразу вступает в силу. Если же
pyproject.toml изменяется (новая зависимость), нужно заново отдасть:
uv tool install --editable --from . thot --force.
Детерминированное ядро (codemap, taint, scope, scoring, store,
report) не зави dette ни от одного агента и не касается сети — тест проверяет
это и заставляет набор тестов падать, если поведение изменится.
Спецификации и планы: docs/superpowers/.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Remote MCP for A2A dependency inspector MCP, structured receipts, audit logs, and reviewer-ready evi
Static MCP manifest and tool-policy security preflight with signed input-redacted receipts
A paid remote MCP for CodeG, built to return verdicts, receipts, usage logs, and audit-ready JSON.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/nobodyohm-web/thot'
If you have feedback or need assistance with the MCP directory API, please join our Discord server