sed -i правит не задумываясь, а поиск с заменой в редакторе не помнит, что сделал. sr 7.0.1 занимает нишу между ними: это замена по дереву файлов, где каждая правка записывается в сессию, которую можно посмотреть, сравнить и откатить одной командой. Ниже — что умеет утилита, что показал прогон на живых файлах, где проходит граница поддерживаемых платформ и какие грабли ждут на Windows.

TL;DR: что это и как проверить
- Что это. Один файл Python без сторонних зависимостей: сканирует дерево, находит, показывает диф, правит, ведёт журнал.
- Сопоставление литеральное по умолчанию. Регулярные выражения — по флагу, а не «как получится».
- Ничего не пишется до полного скана. Сначала подсчёт по всему дереву, потом запись.
- Журнал в
.sr. Каждый прогон — сессия с идентификатором; откат по нему. - Проверка.
sr doctor— 13 проверок установки, иsr replace ... --dry-run.
sr find "old_api" -p '*.py' # где встречается
sr diff "old_api" "new_api" -p '*.py' # что изменится
sr replace "old_api" "new_api" -p '*.py'
sr rollback <id> # откат
Проблема, которую это решает
Массовая замена в большом проекте — операция, где легко потерять контроль. Классический сценарий: устаревший вызов API встречается в двухстах файлах, его надо переименовать. sed -i справится, но у него три беды.
Первая: нет предпросмотра. Вы не видите, что именно изменится, пока не изменилось. Опечатка в шаблоне стоит часа работы с git.
Вторая: нет памяти. Через неделю никто не скажет, какой прогон что правил: останется только история коммитов, где все двести файлов в одном.
Третья: нет точечного откатa. git checkout вернёт всё, включая правки, сделанные после.
Утилита закрывает все три: diff показывает план, sessions хранит журнал, rollback отменяет конкретный прогон. Плюс отдельная деталь, которая экономит нервы — сопоставление литеральное по умолчанию, то есть точка в строке поиска остаётся точкой, а не «любым символом».
Что такое sr-search-replace
flowchart TB
FIND["find: где встречается"] --> DEC{"менять?"}
DIFF["diff: что изменится"] --> DEC
DEC -- да --> REP["replace: правка и сессия"]
DEC -- нет --> STOP["стоп"]
REP --> SESS["sessions: журнал прогонов"]
SESS --> RB["rollback: откат"]
DOC["doctor: проверка установки"] --> REP| Свойство | Значение |
|---|---|
| Версия в разборе | 7.0.1 |
| Рантайм | Python 3.10 или новее |
| Зависимости | нет сторонних на рантайме |
| Форма поставки | sr.pyz, wheel, sdist |
| Платформы | Linux, macOS, WSL2 |
| Журнал | каталог .sr внутри целевого дерева |
| Лицензия (тег 7.0.1) | MIT в LICENSE и pyproject.toml |
Отдельно про поставку: в релизе лежат три артефакта — sr.pyz на 495 680 байт с файлом контрольной суммы, wheel на 184 817 байт и исходник на 242 704 байта. pyz удобен тем, что не требует установки пакетов: скачал, проверил сумму, запустил.
Возможности
Поиск и предпросмотр
| Команда | Что делает |
|---|---|
find (он же search, grep) |
показывает совпадения: файл, строка, колонка |
diff |
печатает унифицированный диф без изменения файлов |
replace --dry-run |
считает и показывает сводку, ничего не записывая |
--json, --porcelain |
машиночитаемый вывод для конвейеров |
Правка
| Команда | Что делает |
|---|---|
replace (r) |
заменяет в файлах, создаёт сессию |
rename (mv) |
переименовывает файлы и каталоги по шаблону |
-p, --include, --exclude, --exclude-dir |
отбор файлов |
--max-size, --min-size, --newer-than, --older-than |
отбор по размеру и возрасту |
--gitignore, --hidden, --symlinks |
поведение обхода |
Журнал и откат
flowchart LR SCAN["скан всего дерева"] --> COUNT["подсчёт совпадений"] COUNT --> WRITE["запись изменений"] WRITE --> JOURNAL["сессия в .sr"] JOURNAL --> UNDO["откат по идентификатору"] UNDO --> CLEAN["очистка старых сессий"]
| Команда | Что делает |
|---|---|
sessions |
список прогонов с числом файлов и замен |
sessions show <id> |
подробности одной сессии |
rollback |
откат последней или указанной сессии |
sessions size |
сколько занимает журнал на диске |
--keep, --keep-age |
сколько сессий хранить (по умолчанию 20) |
Служебное
| Команда | Что делает |
|---|---|
doctor |
проверка установки и возможностей файловой системы |
update --check |
есть ли новая версия |
completions |
генерация дополнений для оболочки |
help options |
полный список флагов |
Как это работает
Порядок подчинён одной идее: сначала узнать, потом менять.
Скан собирает совпадения по всему дереву и только после этого начинается запись. Это значит, что ошибка в отборе файлов обнаруживается до того, как что-то испорчено: сводка показывает число файлов и замен, и неверная цифра — повод остановиться.
Каждая изменяющая команда оставляет сессию: идентификатор вида 20261113T030219Z-5b3ed3, число файлов, число замен, текст шаблона. Сессии лежат в .sr внутри целевого дерева — то есть журнал путешествует вместе с проектом и попадает в .gitignore, а не в домашний каталог пользователя.
Откат восстанавливает исходное содержимое файлов сессии. Это не «отмена последнего действия в редакторе»: откатывается весь прогон целиком, что для массовой замены как раз и нужно.
Замеры и цифры
Проверено 13.11.2026, двумя проверками.
| Что | Значение | Как |
|---|---|---|
Архив тега v7.0.1 |
7 458 640 байт, SHA-256 4081f9a5…a692e84 |
скачивание тега и подсчёт хеша |
| Файлов в дереве | 116, из них 18 файлов тестов | разбор tar |
| Артефакты релиза | sr.pyz 495 680 Б + .sha256, wheel 184 817 Б, sdist 242 704 Б |
просмотр релиза |
find по трём файлам |
3 совпадения в 3 файлах, скан 3 файлов, 8 мс | прогон |
diff |
унифицированный диф по трём файлам, «3 файла изменятся, 3 замены» | прогон |
replace --dry-run |
3 файла, 3 замены, прочитано 57 байт, 3 мс, предупреждение «файлы не изменены» | прогон |
replace (реально) |
3 файла, 3 замены, записано 57 байт, 24 мс, сессия 20261113T030219Z-5b3ed3 |
прогон |
sessions |
одна сессия, 3 файла, 3 замены, шаблон 'old_api' → 'new_api' |
прогон |
sessions size |
2 записи, журнал 7,3 КБ | прогон |
doctor |
13 проверок: 10 пройдено, 2 предупреждения, 0 отказов, 307 мс | прогон |
rollback без терминала |
отказ: «not a terminal, assuming ‘no’», файлы не тронуты | прогон |
rollback --yes на Windows |
восстановил первый файл и упал на os.chown |
прогон |
| PyPI, GitHub, вики проекта | 200 / 200 / 200 | curl |
| npm-страница пакета | 403 — защита от автоматических запросов | curl |
Главное из этих чисел — про откат. На Linux и macOS он штатный, а на Windows всё ломается: утилита восстанавливает первый файл и падает на os.chown, потому что в Windows такой функции нет. Дерево остаётся в смешанном состоянии: часть файлов откачена, часть — нет. Это не случайность, а следствие платформенной границы, и ниже она описана отдельно.
Сильные стороны продукта
- Журнал вместо памяти. Каждый прогон записан, и через месяц видно, что и когда менялось.
- Точечный откат. Отменяется конкретная сессия, а не всё подряд через git.
- Литеральное сопоставление по умолчанию. Регулярки включаются осознанно, а не по умолчанию.
- Предпросмотр на трёх уровнях.
find— где,diff— что,--dry-run— сколько. - Ноль зависимостей. Python 3.10 и всё;
sr.pyzзапускается без установки пакетов. - Встроенная самопроверка.
doctorпроверяет не только версию, но и возможности файловой системы. - Машиночитаемый вывод.
--jsonи--porcelainдля конвейеров. - Защита от опасных прогонов. Отказ работать от root и в системных каталогах без явного флага.
Установка
# из релиза: pyz с контрольной суммой
curl -LO https://github.com/paulmann/sr-search-replace/releases/download/v7.0.1/sr.pyz
sha256sum -c sr.pyz.sha256
python3 sr.pyz doctor
# из PyPI
pipx install sr-search-replace
# из клона
git clone https://github.com/paulmann/sr-search-replace.git
cd sr-search-replace && python3 sr.py doctor
| Требование | Значение |
|---|---|
| Python | 3.10 или новее |
| Файловая система | POSIX: Linux, macOS, WSL2 |
| Права | не root (иначе нужен --allow-root) |
| Каталог | не /, не /etc, не домашний без явного -C |
| git или бэкап | желательны: правка идёт на месте |
Настройка
| Что настроить | Как |
|---|---|
| Отбор файлов | -p, --include, --exclude, --exclude-dir, --gitignore |
| Пределы | --max-size, --min-size, --max-depth, --newer-than |
| Режим сопоставления | --regex, --ere, --pcre, -i, -w |
| Хранение журнала | --keep N, --keep-age |
| Конфигурация | --config KEY=VALUE, --config-file FILE |
| Автоматизация | --yes для прогонов без терминала |
flowchart TD
R1["не root или --allow-root"] --> G{"все проверки пройдены?"}
R2["каталог не / и не домашний"] --> G
R3["есть TTY или --yes"] --> G
R4["POSIX-файловая система"] --> G
G -- да --> GO["прогон разрешён"]
G -- нет --> NO["отказ без записи"]Про --yes стоит сказать отдельно: без терминала утилита не делает необратимых действий и сообщает об этом. Это правильное поведение — но в cron-скрипте отсутствие флага выглядит как «команда ничего не сделала», а не как ошибка. Именно поэтому --yes требуется указывать явно, а не «по умолчанию соглашаться».
Что показывает журнал сессий
Сессия — это не лог на память, а рабочий инструмент. У неё есть идентификатор, время, число файлов, число замен и текст шаблона; в каталоге .sr лежат данные, достаточные для восстановления содержимого.
Практическая ценность в трёх сценариях.
Первый: разбор через неделю. Вы помните, что «что-то меняли в конфигах», но не помните что. sessions показывает список прогонов с шаблонами — по строке 'old_api' → 'new_api' картина восстанавливается мгновенно.
Второй: откат одного прогона. Обычный git revert отменит все правки коммита, а сессия — ровно свой набор файлов. Это спасает, когда после замены успели сделать другие изменения.
Третий: контроль объёма. sessions size показывает, сколько журнал занимает: у нас на трёх файлах это 7,3 КБ, а на большом дереве счёт пойдёт на мегабайты. По умолчанию хранится двадцать сессий, лишние удаляются автоматически — и это же означает, что откатить правку месячной давности не получится.
Есть и обратная сторона: журнал лежит внутри целевого дерева. Если проект под git, каталог .sr надо добавить в .gitignore — иначе он попадёт в коммит и будет мусорить в диффах.
Почему POSIX — не формальность
Требование POSIX-файловой системы в документации выглядит как перестраховка, но за ним стоит конкретная механика.
Утилита сохраняет права и владельца файлов, чтобы правка не меняла метаданные. Для этого она обращается к os.chown — функции, которой в Windows просто нет. Она использует атомарное переименование POSIX, блокировки через O_CREAT|O_EXCL и сохранение inode: без этого «восстановить ровно то, что было» не получится.
Отсюда и наблюдаемое поведение на Windows: поиск, диф и предпросмотр работают, потому что ничего не пишут. А откат, который восстанавливает файлы и затем пытается выставить владельца, падает на первой же попытке — уже после того, как первый файл возвращён.
Правильный вывод не «обойти», а «не запускать запись»: на Windows использовать find и diff, а саму замену делать в WSL2 или на сервере. Кстати, doctor на неподходящей платформе честно предупреждает — 13 проверок показывают, что доступно, а что нет.
Альтернативы и когда они лучше
Честный обзор обязан назвать, чем ещё это делают.
| Инструмент | Сильная сторона | Слабое место |
|---|---|---|
sed -i |
есть везде, нулевой порог | нет предпросмотра и журнала |
| Замена в редакторе | удобный интерфейс, видно контекст | не помнит прогон, зависит от машины |
git grep + правка |
встроено в git, быстрый поиск | правку и откат делаете руками |
| Кодмоды (ast-grep, comby) | понимают структуру кода, а не текст | сложнее настроить, больше зависимостей |
sr выигрывает там, где нужна не «умная» правка по синтаксису, а массовая текстовая с проверяемым следом: переименование ключа конфигурации, смена адреса API, нормализация кодировки, переименование файлов по шаблону.
Кодмоды лучше, когда правка должна учитывать структуру: заменить вызов, не тронув одноимённую строку в комментарии. Но за это платят настройкой — и для задачи «переименовать вызов в двухстах файлах» разница обычно не окупается.
Подводные камни
- Windows не поддерживается для записи. В документации прямо сказано:
findи--dry-runработают, путь записи — нет. - Откат на Windows падает на
os.chown. Проверено: первый файл восстановлен, дальше исключение, дерево в смешанном состоянии. - Без
--yesпрогон без терминала не пишет. Сообщение «assuming ‘no’» легко принять за успех. - Журнал лежит в целевом дереве. Каталог
.srнадо добавить в.gitignore, иначе он попадёт в коммит. - Сессии обрезаются. По умолчанию хранится 20; старые удаляются после каждого прогона, и откатить давнюю правку не получится.
- Литеральный поиск — не регулярка. Точка и звёздочка в шаблоне означают себя, а не шаблон.
- Подсчёт по вхождениям, а не по строкам. Одна строка с тремя совпадениями даст три замены.
- Параллельности нет. Журнал ведётся последовательно намеренно; ускоряются прогоном по каталогам через
-C. - Лицензия требует сверки. В теге 7.0.1
LICENSEиpyproject.tomlговорят MIT, а вAGENTS.md(ветка main) есть замечание о расхождении с PolyForm Noncommercial — перед распространением надо проверять. - npm-страница отвечает 403. Это защита от ботов, а не отсутствие пакета; ставить лучше через PyPI или pyz.
- Права root. Прогон от root отвергается, и обходить это флагом
--allow-rootстоит только понимая последствия.
Как выглядит безопасный рефакторинг
Общая процедура для любой массовой замены, независимо от инструмента.
Первое: зафиксировать исходное состояние. Коммит в git или копия каталога. Не «я помню, как было», а точка, к которой можно вернуться.
Второе: измерить объём. find даёт число совпадений и файлов; если цифра удивляет — значит, шаблон шире, чем кажется. Частая ошибка — искать короткое имя, которое встречается ещё и в посторонних местах.
Третье: сузить отбор. Расширения, каталоги, исключения. Лучше три узких прогона, чем один широкий: узкий проще проверить и проще откатить по отдельности.
Четвёртое: прочитать диф целиком. Не «пролистать» — прочитать. Диф на двести файлов читается за десять минут и почти всегда показывает одну-две неожиданные правки.
Пятое: выполнить замену и сразу проверить. Сборка, тесты, git diff — что угодно, что даёт объективный сигнал. Если сигнала нет, замена не проверена.
Шестое: записать идентификатор сессии в задачу или в журнал работ. Через месяц он будет единственным способом быстро понять, что произошло.
Седьмое: не смешивать. Если в одном прогоне переименование ключа и нормализация отступов, откат одного без другого невозможен. Одна сессия — одна логическая правка.
Коды выхода и автоматизация
У утилиты есть отдельный документ с контрактом кодов выхода — он заморожен и генерируется из кода, а не пишется руками. Это правильный подход: конвейер опирается на числа, а не на разбор текста сообщений.
| Что важно для автоматизации | Как |
|---|---|
| Прогон без терминала | обязателен флаг --yes |
| Машиночитаемый вывод | --json или --porcelain |
| Проверка установки | doctor до работы |
| Проверка обновлений | update --check |
| Отбор файлов | те же фильтры, что в find |
| Хранение журнала | --keep, --keep-age |
Практическое замечание: в CI массовую замену обычно не запускают — её делают один раз локально и коммитят результат. Утилита полезна именно как инструмент разовой аккуратной правки, а не как постоянный шаг сборки.
Что было бы в статье про версию
Это обзор продукта, а не заметка о релизе, но одно уточнение уместно: 7.0.1 — текущая версия, и в ней закрыты ошибки шестой ветки. Полный список изменений — в CHANGELOG.md репозитория; пересказывать его здесь смысла нет, потому что ценность утилиты не в последней правке, а в модели работы: скан, предпросмотр, журнал, откат.
Чек-лист
- [ ] Проверить версию Python: 3.10 или новее.
- [ ] Прогнать
doctorи прочитать предупреждения. - [ ] Убедиться, что дерево чистое в git или есть бэкап.
- [ ] Найти совпадения:
findс нужным шаблоном и фильтрами. - [ ] Посмотреть
diffи прочитать его глазами. - [ ] Сделать
replace --dry-runи сверить число файлов и замен. - [ ] Запустить реальную замену и запомнить идентификатор сессии.
- [ ] Проверить результат: сборка, тесты,
git diff. - [ ] При проблеме —
rollback <id>(на POSIX). - [ ] Добавить
.srв.gitignore. - [ ] На Windows — не запускать запись, использовать
findиdiff.
Где утилита не нужна
Границы полезны не меньше достоинств.
Не нужна, когда правка одна. Открыть файл и заменить — быстрее, чем набирать команду.
Не нужна, когда нужна структурная правка. Заменить вызов функции, не тронув одноимённую строку в комментарии, текстовым инструментом не выйдет — здесь нужны кодмоды или ручная работа с пониманием кода.
Не нужна для бинарных файлов: утилита про текст, а не про произвольные данные.
Не нужна как замена системы контроля версий. Журнал сессий — страховка на уровне прогона, а не история проекта; git остаётся обязательным.
И не нужна на Windows для записи. Там её место — поиск и предпросмотр, а сама правка идёт на POSIX-системе.
FAQ
Чем это лучше sed -i?
Предпросмотром (diff, --dry-run), журналом сессий и точечным откатом. sed этого не умеет.
Где хранится журнал?
В каталоге .sr внутри целевого дерева, а не в домашнем каталоге. Старые сессии обрезаются по --keep.
Работает ли на Windows?
Поиск и предпросмотр — да. Запись официально не поддерживается: нужна POSIX-файловая система (Linux, macOS, WSL2).
Что будет без --yes в cron?
Утилита откажется писать и сообщит «not a terminal, assuming ‘no'». Для автоматизации флаг обязателен.
Как откатить не последнюю, а конкретную правку?
sessions покажет список с идентификаторами, rollback <id> откатит нужную.
Нужны ли сторонние пакеты?
Нет: только Python 3.10+. sr.pyz вообще не требует установки.
Можно ли заменить по регулярному выражению?
Да, флагами --regex, --ere или --pcre. По умолчанию сопоставление литеральное.
Что осталось за кадром
Три вещи, которые стоило бы проверить отдельно и которые в этом разборе не проверялись.
Первая: поведение на большом дереве. Замер шёл на трёх файлах — этого достаточно, чтобы убедиться в логике, но не чтобы судить о скорости на десятках тысяч файлов. В документации упоминается отсутствие параллельности по умолчанию; на практике это значит, что большой прогон лучше делить по каталогам.
Вторая: переименование файлов по шаблону. Команда rename в прогоне не участвовала, а у неё свои риски: конфликт имён на регистронезависимых файловых системах, потеря расширений при неаккуратном шаблоне.
Третья: совместимость сессий между версиями. Журнал лежит файлами внутри дерева, и вопрос «прочитает ли новая версия сессию старой» в разборе не закрыт.
Общее правило для читателя: то, что не проверено, надо помечать, а не додумывать. В статье про инструмент это особенно важно — доверие к утилите строится на воспроизводимых прогонах, а не на описании её же документации.
Итог
sr 7.0.1 решает узкую, но частую задачу: массовая правка дерева с возможностью посмотреть, что изменится, и отменить сделанное. Прогон подтвердил основные обещания — 3 совпадения в 3 файлах за 8 мс, предпросмотр на 3 замены, сессия с идентификатором, doctor с 13 проверками без отказов. Границы честные: запись только на POSIX, на Windows откат падает на os.chown, сессии обрезаются, лицензию перед распространением стоит сверить. Для рефакторинга на Linux это заметно спокойнее, чем sed -i, и честнее, чем верить в память.
Цитата: Массовая замена страшна не тем, что меняет много файлов, а тем, что не помнит, какие.
Связанные материалы
- ctf-collect-to-file: весь код в один документ — обход дерева для контекста модели, соседняя задача.
- github-wiki-llm-writer: вики репозитория с проверкой фактов — ещё один инструмент с правилом «источник или не утверждение».
- Bash WP-CLI Update: обслуживание парка WordPress — bash-утилита с контрактом кодов выхода.
- MD.Scribe 3.1.0: переименование и починка обновлятора — пример проекта, где переименование затрагивает всё дерево.
- Релиз v7.0.1 — артефакты и заметки.
LLM Summary
- Тема:
sr7.0.1 — утилита замены по дереву файлов с журналом сессий и откатом. - Команды:
find(он жеsearch,grep),diff,replace(r),rename(mv),rollback,sessions,doctor,update --check,completions. - Требования: Python 3.10+, POSIX-файловая система (Linux, macOS, WSL2), не root без
--allow-root, не системный каталог и не домашний без-C. - Безопасность: сопоставление литеральное по умолчанию, регулярки по флагам
--regex/--ere/--pcre; запись только после полного скана; без TTY требуется--yes. - Журнал: каталог
.srв целевом дереве, сессии обрезаются по--keep(по умолчанию 20) и--keep-age. - Проверено 13.11.2026: архив тега — 7 458 640 байт, SHA-256
4081f9a5…a692e84, 116 файлов (18 тестов); артефакты —sr.pyz495 680 Б, wheel 184 817 Б, sdist 242 704 Б. - Прогон:
find— 3 совпадения в 3 файлах за 8 мс;diff— «3 файла изменятся, 3 замены»;replace --dry-run— 3 файла / 3 замены / 3 мс; реальная замена — 3 файла / 3 замены / 24 мс, сессия20261113T030219Z-5b3ed3;sessions size— 7,3 КБ;doctor— 13 проверок, 10 пройдено, 2 предупреждения, 0 отказов. - Граница Windows: запись не поддерживается;
rollback --yesвосстановил первый файл и упал наAttributeError: module 'os' has no attribute 'chown', оставив дерево в смешанном состоянии. - Живые адреса: PyPI, GitHub и вики проекта — 200; npm-страница — 403 (защита от ботов).
- Лицензия: в теге 7.0.1
LICENSEиpyproject.toml— MIT; вAGENTS.mdветки main есть замечание о PolyForm Noncommercial — требует проверки перед распространением. - Ссылки: https://github.com/paulmann/sr-search-replace, https://pypi.org/project/sr-search-replace/
Промт для агента (установка и настройка)
Готовый промт: скопируйте блок целиком. Источник шагов — AGENTS.md репозитория (есть в ветке main, в архив тега 7.0.1 не входит) и README.md; сверено с прогоном на живых файлах.
Задача: выполнить массовую замену по дереву файлов утилитой sr так, чтобы результат можно было проверить и откатить.
Материалы:
- репозиторий: https://github.com/paulmann/sr-search-replace
- AGENTS.md: https://github.com/paulmann/sr-search-replace/blob/main/AGENTS.md
- README: https://github.com/paulmann/sr-search-replace/blob/main/README.md
- релиз: https://github.com/paulmann/sr-search-replace/releases/tag/v7.0.1
Шаг 1. Проверить предпосылки: python3 --version (нужен 3.10+), id -u (не root), файловая система POSIX (Linux/macOS/WSL2).
Шаг 2. Установить: скачать sr.pyz и sr.pyz.sha256, проверить сумму, либо pipx install sr-search-replace.
Шаг 3. Прогнать sr doctor и прочитать предупреждения (13 проверок).
Шаг 4. Убедиться, что дерево чистое: git status --short, либо сделать бэкап.
Шаг 5. Найти совпадения: sr find "<шаблон>" -p '<маска>' — оценить число файлов.
Шаг 6. Посмотреть diff и прочитать его: sr diff "<старое>" "<новое>" -p '<маска>'.
Шаг 7. Сделать предпросмотр: sr replace "<старое>" "<новое>" --dry-run — сверить числа.
Шаг 8. Выполнить замену: sr replace "<старое>" "<новое>" -p '<маска>' — записать идентификатор сессии.
Шаг 9. Проверить результат: git diff, сборка, тесты.
Шаг 10. При проблеме откатить: sr rollback <id> (только POSIX; для cron добавить --yes).
Шаг 11. Добавить каталог .sr в .gitignore.
Запрещено:
- запускать запись на Windows: платформа не поддерживается, откат падает на os.chown;
- работать от root без --allow-root;
- запускать замену без предварительного diff и --dry-run;
- рассчитывать на --yes по умолчанию: без TTY прогон не пишет;
- хранить сессии бесконечно: по умолчанию остаётся 20;
- считать шаблон регулярным выражением: по умолчанию сопоставление литеральное;
- распространять копию, не сверив лицензию: в теге MIT, в AGENTS.md упомянут PolyForm.
Что считать успехом: число файлов и замен в --dry-run совпало с ожиданием, реальный прогон дал ту же сводку, идентификатор сессии записан, diff после правки содержит только ожидаемые строки, откат проверен на пробном каталоге.