gdocs
Skill9 starsChanged 3 months agoMITView on GitHub
Вести живой документ в Google Docs, который правится итеративно и его читает заказчик: \"поправь ТЗ в доке\", \"обнови документ у клиента\". Разовая сборка - `md-docx`/`md-pdf`.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- dewil/ai-toolkitword for word, first seen Aug 25, 2026
- 15yotsuka/claude-skillstheir own version, first seen May 22, 2026
Other versions2 projects use a version of this.
Word for word · 1
- dewil/ai-toolkit★ 9100% same
Edited · 0
None found.
Wrote their own version · 1
- 15yotsuka/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository37 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- agent-browserSkill
- android-apk-releaseSkill
- asana-blockersSkill
- asana-commentsSkill
- asana-projectSkill
- backlog-taskSkill
- canon-syncSkill
- csv-xlsxSkill
- estimate-calibrationSkill
- harvest-canonSkill
- implementSkill
- jev-decideSkill
- llm-ruSkill
- local-transcriptionSkill
- md-docxSkill
- md-pdfSkill
- md-pptxSkill
- memory-compactSkill
- memory-searchSkill
- migrateSkill
- minimal-codeSkill
- mymeet-snapshotSkill
- office-mdSkill
- pii-maskSkill
- proofreadSkill
- qa-browserSkill
- redmine-snapshotSkill
- repo-publicationSkill
- requirementsSkill
- reviewSkill
- sddSkill
- session-costSkill
- telegram-sendSkill
- telegram-snapshotSkill
- tutorSkill
- web-researchSkill
The file
Files
gdocs
Ведение живого документа в Google Docs: scripts/gdocs.py с четырьмя подкомандами. Только stdlib, авторизация общая с gsheets.py.
Зачем это поверх прямых вызовов API
Документ, который правится программно и его же читает заказчик, копит класс дефектов, невидимых для API: все вызовы возвращают успех, а поломку видит только человек, открывший документ (rules/silent-failure.md). Ни одна из граблей ниже не следует из документации Docs API - каждая стоила отдельного разбора на живом документе.
Пробел в каноне закрывается ровно этот: работа с Sheets есть (scripts/gsheets.py), сборка документа из markdown есть (md-docx, md-pdf), а ведения живого документа не было.
Когда применять
- Документ ведется итеративно: правки идут сериями, между ними его читают и правят люди.
- Документ имеет структуру с номерами - разделы, подпункты, перекрестные ссылки "см. 10.7".
- Документ уходит наружу: заказчику, на согласование, в приложение к договору.
Когда НЕ применять
- Разовая генерация документа из готового текста - это
md-docx(илиmd-pdf): собрал и отдал, вести нечего. - Документ без нумерации и структуры - заметка, черновик, произвольный текст:
normalizeиcheckтут проверяют то, чего нет, аblanksнавяжет чужое правило. - Таблица данных - это Sheets (
scripts/gsheets.py,rules/google-sheets-mcp.md), не Docs. - Чужой документ, который мы только читаем - хватит
snapshot;normalizeиblanksчужую разметку менять не должны.
Грабли Docs API
1. Вставленный текст наследует форматирование точки вставки. replaceAllText и insertText своего стиля не несут: результат перенимает оформление места, куда попал. Три наблюдавшихся исхода: заменил абзац-заголовок на "заголовок + тело" - все тело стало заголовком и уехало в структуру документа; вставил список строк вплотную к заголовку - каждая строка стала заголовком; заменил текст внутри бывшего заголовка - абзац остался обычным, но сохранил кегль 16pt вместо 11. Снаружи API все три - успешный ответ.
Лечится не аккуратностью, а проходом-нормализатором после каждой правки. Инвариант проверяемый: заголовок - это строка вида N. ЗАГЛАВНЫМИ или N.M. ЗАГЛАВНЫМИ, все остальное - обычный текст без явного fontSize. Опознается по тексту, а не по разметке - разметка и есть то, что врет. Ловится в обе стороны: и текст, ставший заголовком, и заголовок, потерявший разметку.
2. Удаления и вставки в одном batchUpdate ломают индексы. Операции применяются последовательно, и индексы, посчитанные по исходному документу, после первого же удаления смещаются; сортировка по убыванию спасает только внутри однородного набора. Наблюдалось: смешанный батч разорвал заголовок пополам - 5.9. О КОМПАНИИ превратился в 5.9. О плюс отдельный абзац КОМПАНИИ. Удаления и вставки - разными запросами, между ними документ перечитывается. Дороже на один запрос, зато не портит документ.
3. Оглавление API вставлять не умеет. Запроса нет. Ручной список разделов текстом - плохая замена: он не обновляется и, вставленный рядом с заголовком, сам становится набором заголовков (грабля 1). Правильно: разметить заголовки стилями и сказать пользователю, что оглавление вставляется штатно (Вставка - Оглавление) и дальше собирается само.
4. Нативные списки несовместимы с перекрестными ссылками. В нативном списке Docs номер живет в разметке, а не в тексте: сослаться на него нельзя, а при вставке пункта все ссылки "см. 10.7" начинают врать. В документе с перекрестными ссылками номера остаются частью текста. Цена - ручная перенумерация, она же дает контроль. Визуальную вложенность дают отступы абзаца, а не списки.
5. Удаление пункта оставляет три следа, и проверять надо все три сплошным проходом: осиротевшую пустую строку, дыру в нумерации (10.6 -> 10.8) и перекрестные ссылки в никуда.
6. Правило пустых строк зависит от типа раздела, единого нет - и в этом ловушка: приведешь весь документ к одному виду, испортишь половину. Раздел, где подпункты это заголовки блоков с телом, - перед каждым ровно одна пустая строка. Раздел, где подпункты это список коротких пунктов, - пустых строк между ними нет. Тип определяется автоматически: по тому, есть ли под подпунктом непустое тело.
7. Документ живет только в облаке. Его правят несколько человек, а история версий Google неудобна для сравнения. Снимок в markdown рядом с проектом дает обычный diff: видно, что изменилось между правками и что внес заказчик.
Порядок работы
Правку вносить заменой по точному фрагменту текста. Тогда чужая правка не будет затерта молча: замена просто не найдет фрагмент, и это видно по
occurrencesChanged: 0.Проверять надо
occurrencesChanged == 1, а не> 0. Двойка означает, что фрагмент встретился дважды и вторую копию мы затерли не глядя; API при этом отвечает успехом. Отсюда же вторая ловушка - цепочка замен, наступающая сама на себя: еслиnewодной пары окажется подстрокойoldдругой, вторая замена попадет в уже переписанный текст. Серию замен подавай так, чтобы фрагменты не пересекались, а после серии сверяй число затронутых мест с числом задуманных.Удалять пункт -
deleteContentRangeпо границам абзаца, с конца документа к началу, а не заменой на пустую строку: замена оставляет пустой абзац, который потом придется искать черезblanks, а сортировка от конца нужна по грабле 2 - индексы смещаются.- После каждой содержательной правки -
normalizeиblanks, а не в конце работы: дефект, найденный через десять правок, уже неотличим от исходного текста. - Перед отправкой наружу -
check(нумерация и ссылки) иsnapshot(копия рядом с проектом). - Заголовки размечать стилями сразу; оглавление текстом не вставлять.
- Пользователь видит в документе не то, что вернул API, - верить пользователю и смотреть фактическое состояние документа, а не свой предыдущий ответ. Именно так были найдены грабли 1 и 2.
CLI
python3 scripts/gdocs.py normalize <doc_id> # предпросмотр
python3 scripts/gdocs.py normalize <doc_id> --send # записать
python3 scripts/gdocs.py blanks <doc_id> --send
python3 scripts/gdocs.py check <doc_id> # только отчет
python3 scripts/gdocs.py snapshot <doc_id> -o тз.md # только чтениеdoc_id - из URL документа (.../document/d/<doc_id>/edit).
Дефолт у normalize и blanks - dry-run, как у остальных пишущих скриптов канона: показывает построчно, что изменится. Документ общий, и правка видна заказчику сразу - показывай вывод пользователю и получай "ок" перед --send. check и snapshot не пишут никогда.
check возвращает ненулевой код, когда что-то нашел: годится как гейт перед отправкой.
Идемпотентность и границы правки
- Повторный прогон
normalizeиblanksничего не делает - оба приводят документ к инварианту, а не накладывают правку. Проверено на живом документе: второй прогон дает "расхождений нет". normalizeне трогает пустые абзацы, аblanksне трогает стили - иначе две команды дрались бы за один абзац.- Смена стиля индексы не двигает, поэтому
normalizeидет одним батчем.blanksдвумя с перечитыванием между ними - по грабле 2. - Абзацы внутри таблиц видны всем командам: иначе
normalizeпропустил бы текст в таблицах, аcheck- ссылки в них. - Скрипт не переносит и не удаляет содержимое - только стили и пустые строки. Перенумерация, удаление пунктов и правка текста остаются за агентом и человеком.
Что скрипт не умеет, и это осознанно
Проверено состязательным ревью в два раунда; перечисленное ниже - остаточные ограничения, а не недосмотр.
- Намеренный кегль 14/16/20pt неотличим от унаследованного. Снимается размер, одинаковый во всем абзаце и совпадающий с кеглем заголовка Docs; цитата 12pt, подпись 9pt и цена 18pt переживают нормализацию, а намеренный 16pt - нет. Документ с перенастроенными named styles (унаследованный кегль не из этого набора)
normalizeне почистит. - Заголовок со строчной латинской буквой внутри слова не опознается (
ПРОЦЕСС cДАЧИс латинскойc). Промах безопасный: заголовок просто останется без разметки, а не текст уедет в структуру. - Перед первым подпунктом сразу после заголовка раздела пустая строка не ставится - там уже есть граница раздела. Правило "ровно одна пустая" действует между подпунктами.
- Абзацы до первого заголовка верхнего уровня
blanksне трогает: без раздела непонятно, какое правило применять. checkне различает контекст. Ссылка "см. 9.9" внутри примера кода или цитаты будет показана как битая. Это осознанно: различать контекст можно только по стилям, а стили и есть то, что врет. Команда ничего не правит, поэтому ложная тревога стоит одной строки в отчете.Но доля имеет значение. Первая редакция искала цели ссылок только среди размеченных заголовков, и на живом документе, где половина подпунктов разметку потеряла, получилось 16 ложных срабатываний из 16 - гейт красный всегда, то есть проверкой быть перестал (
rules/silent-failure.md). Теперь цель ищется шире: заголовок или абзац, начинающийся с номера. Найденная не в заголовке цель отмечается в отчете отдельно - это не битая ссылка, а работа дляnormalize.Обратная плата у этого своя, и ее надо знать: номер, живущий только в цитате или в тексте ("2.5. миллиона"), теперь засчитается как существующая цель, и ссылка на несуществующий пункт может проскочить. Меняли шило на мыло сознательно: сплошное ложное срабатывание обесценивает гейт целиком, единичный пропуск - нет.
blanksпишет двумя запросами и не является транзакцией. Между ними документ перечитывается, и правка привязана к ревизии; но если чужая правка придет между запросами, удаления окажутся применены, а вставки нет. Скрипт скажет об этом прямо - повторить надо весь прогон, с предпросмотра.snapshotвыгружает тело первой вкладки. Сноски, колонтитулы и остальные вкладки не попадают; оглавление, картинки и разрывы отмечаются комментарием, а многовкладочный документ получает пометку "НЕПОЛНЫЙ СНИМОК". Молча не теряется ничего.
Авторизация
Общая с gsheets.py: ~/.config/gsheets/auth.json (client_id, client_secret, refresh_token, token_uri, права 600). Модуль подгружается сбоку - два места, работающих с ключами, разошлись бы на первом же фиксе; нет gsheets.py рядом - скрипт скажет, что взять из канона.
Нужна область documents у того же OAuth-клиента. Ее нет - Docs API отвечает 403 insufficient, и скрипт печатает, что делать. Токен - секрет: в синкаемые папки, заметки и артефакты не класть (rules/secrets-handling.md).
Связанные файлы
scripts/gdocs.pyв корне проекта - движок (dry-run по умолчанию).scripts/gsheets.py- сосед по авторизации, он же для таблиц.rules/google-sheets-mcp.md- почему к Google ходим скриптами, а не только MCP.skills/md-docx,skills/md-pdf- разовая сборка документа из markdown, другой случай.
Модель и текущие назначения
Перед новым заданием и запуском применяй маршрутизацию моделей: свежий MODELS выше канонического дефолта. Границы данных и полномочий этого навыка сохраняются.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

