oops · diff
git:20260902.5fa5897 to git:20260903.6170a65
1 added, 1 removed. Audit A to A.
---
name: oops
- description: Отменить последнее изменение, которое система сделала в настройках Claude Code, ИЛИ вернуть папку проекта к снимку, снятому во время сборки. Использовать, когда пользователь пишет /oops, говорит «отмени», «верни как было», «верни вчерашний код», «я передумал», «зачем ты это поменял», или явно не хочет только что сделанное изменение. Сначала показывает, что именно вернётся, и только после согласия откатывает.
+ description: Отменить последнее изменение, которое система сделала в настройках Claude Code, ИЛИ вернуть папку проекта к снимку, снятому во время сборки. Использовать, когда пользователь пишет /oops, говорит «отмени», «верни как было», «верни вчерашний код», «я передумал», «зачем ты это поменял», говорит «undo that», «put it back», «I changed my mind», или явно не хочет только что сделанное изменение. Сначала показывает, что именно вернётся, и только после согласия откатывает.
---
# OOPS — сначала показать, потом вернуть
Ничего не удаляется в этой системе. Вернуть можно две разные вещи, и путать
их нельзя: настройки Claude Code (их копии делает `tools/apply.py`) и файлы
самого проекта (их снимки делает `tools/checkpoint.py` на границах этапов
сборки). Порядок в обоих случаях один — показать, ЧТО именно вернётся, и
откатить только после явного согласия.
## Начни со снимков проекта
Человек, сказавший «верни как было», почти всегда смотрит на свой проект, а
не на настройки. Поэтому первый вопрос — есть ли снимки здесь:
```bash
python3 "$CLAUDE_PLUGIN_ROOT/tools/checkpoint.py" . list
```
Код 0 — снимки есть, работай по трём шагам ниже. Код 1 — снимков нет, иди в
раздел про настройки. Не угадывай по выводу: смотри код возврата.
### 1. Скажи, к чему предлагается вернуться
Возьми из вывода `последний` — поля `этап` и `когда` — и скажи одной фразой:
вернётся состояние на конец такого-то этапа, снятое тогда-то. Список целиком
не зачитывай; другие снимки называй, только если человек попросит другой.
### 2. Остановись здесь
Не возвращай, пока человек явно не согласился. Одно «давай» или «да» —
согласие; молчание или смена темы — нет.
### 3. Только после согласия — верни
```bash
python3 "$CLAUDE_PLUGIN_ROOT/tools/checkpoint.py" . back "Пишем код"
```
Последний аргумент — то же значение, что в поле `этап` (или `sha`) из шага 1.
Код 0 — файлы вернулись, и только тогда говори прошедшим временем. Любой
другой код — НЕ вернулись: инструмент сам печатает строку с причиной, передай
её, а не «вернул».
Две вещи скажи сразу, не дожидаясь вопроса: файлы, появившиеся ПОСЛЕ снимка,
остаются на месте — возврат кладёт прежние поверх, а не вычищает папку; и
текущая работа не пропадает — перед возвратом снимается ещё один снимок, к
которому можно вернуться так же.
## Если снимков нет — значит, речь о настройках
### 1. Узнай, что откатится (только чтение, ничего не меняет)
```bash
python3 "$CLAUDE_PLUGIN_ROOT/tools/oops.py" what
```
Без аргумента берётся последний откат. Скажи человеку РОВНО то, что вернул
`line` из вывода, — не пересказывай своими словами и не додумывай, что
именно поменяется.
Если откатов нет вовсе, `found` будет `false` — так и скажи: менять пока
нечего, система ещё ничего не откатывала.
### 2. Остановись здесь
Не откатывай, пока человек явно не согласился. Одно «ладно» или «да» —
согласие; молчание или смена темы — нет.
### 3. Только после согласия — откати
```bash
python3 "$CLAUDE_PLUGIN_ROOT/tools/oops.py" undo 20260812-101500
```
Последний аргумент — то же значение, что в поле `id` из шага 1 (это метка
времени бэкапа, а не выдумка — пример здесь условный).
Прежде чем сказать человеку «откатил», посмотри на код возврата — не только
на строку в stderr. Ноль — откатил, можно говорить прошедшим временем.
Ненулевой — НЕ откатил: `oops.py` сам в этом случае печатает строку,
начинающуюся с «НЕ откатил» или «ОТКАЗ», и что делать дальше — передай её
как есть, а не «откатил» из шага 1.
Выдать неудавшийся откат за удавшийся — та же поломка, которую тормоз /stop
называет худшей из возможных: подтверждение раньше, чем подтверждён результат.
## Секреты откат не возвращает
Если в `line` шага 1 упомянуты секреты, которые не восстановятся, — скажи
это прямо, не смягчая. Откат вернёт файл, но не значение пароля: оно не
хранится даже в копии.
То же и со снимками проекта: файл с ключами в снимок не берётся, и вернуть
его снимком нельзя — инструмент называет такие файлы в своей строке, передай
это человеку, а не умалчивай.
## Если откатов несколько
```bash
python3 "$CLAUDE_PLUGIN_ROOT/tools/oops.py" list
```
покажет все доступные — по умолчанию берётся последний, но человек может
попросить конкретный.
## Чего делать нельзя
- Откатывать или возвращать без явного согласия человека
- Пересказывать неудавшийся откат как удавшийся — сверяйся с кодом возврата,
а не только с текстом в stderr
- Молчать о том, что секрет не восстановится
- Молчать о том, что появившееся после снимка осталось на месте
- Придумывать, что вернёт откат, вместо чтения вывода `oops.py what`
- Удалять что-либо вместо отката — в этой системе ничего не удаляется