AgentStack
SKILL unreviewed MIT Self-run

Doc2kb

skill-zevtos-agentpipe-doc2kb · by zevtos

Converts a heterogeneous corpus of raw documents (PDF, DOCX, DOC, PPTX, IPYNB, RTF, MD, TXT, HTML, etc.) into a structured, LLM-optimized knowledge base — per-source Markdown + manifest.json + INDEX.md + AGENTS.md + a built-in BM25 search index (`query.sh`, citation-first), ready for ingestion in a separate Claude / Codex session. USE WHEN the user asks to ingest, index, preprocess, search, or bu…

No reviews yet
0 installs
8 views
0.0% view→install

Install

$ agentstack add skill-zevtos-agentpipe-doc2kb

Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

1 finding(s); flagged for manual review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures
  • high Possible prompt-injection directive.

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Doc2kb? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

doc2kb — Document Corpus → LLM Knowledge Base

⛔ Правила, которые важнее всего остального

  1. NEVER summarize. Контент сохраняется verbatim. Допустима только структурная очистка через normalize_md.py (дедупликация header/footer, whitespace, boilerplate-regex). Никакого rewriting, paraphrasing, перевода, "улучшения стиля". Пользователь хочет эквивалент того, что человек прочитал бы все файлы — потерянный при суммаризации факт не вернуть.
  2. NEVER silently skip a scanned PDF. Если scout помечает PDF как image_only или encrypted — обязательно спросить пользователя одним сообщением (batch). См. references/batch-questions.md.
  3. NEVER bulk-extract без scout. Сначала всегда фаза 2 (scout_corpus.py), потом фаза 3 (решения пользователя), и только потом фаза 4 (extract). Это нужно для оценки стоимости и для безопасного диалога с пользователем.
  4. NEVER touch binary files inside the kb output. Картинки заменяются на placeholder (см. extract_docx.py), а не сохраняются как base64 в Markdown — base64-блобы катастрофически раздувают токены и бесполезны для LLM.
  5. NEVER bypass the venv. Все скрипты запускаются через ensure_env.py (он находит venv в глобальном state-dir вне кода — ADR-008). Никогда не вызывайте extract-скрипты системным python3 — зависимости не установятся в системный Python.

When to use

Скилл триггерится, когда пользователь хочет:

  • превратить папку с документами в knowledge base для Claude / Codex / другого LLM-агента;
  • подготовить смешанный корпус (PDF + DOCX + PPTX + MD + …) к ingestion во второй сессии;
  • получить per-source Markdown с manifest для последующего grep/read-навигатора;
  • "обработать папку", "сделать базу знаний", "построить корпус", "feed files to Claude".

НЕ используй для:

  • одиночных PDF операций (есть Anthropic'овский pre-built pdf skill — лучше для single-file);
  • генерации новых документов (это docx/pptx/xlsx skills);
  • RAG-векторизации с эмбеддингами (skill не строит vector store, только корпус для in-context-окна);
  • кодовых репозиториев (используй repomix / gitingest).

Workflow (5 phases)

Canonical invocation pattern. Every script in /scripts/ is run through ensure_env.py as a wrapper. It handles venv bootstrap on first call (idempotent, ~30 ms on warm runs) and execs the target script inside the skill's .venv:

python3 /scripts/ensure_env.py  [args ...]

` is the folder containing SKILL.md — typically ~/.claude/skills/doc2kb/ or ~/.codex/skills/doc2kb/. Never invoke extract scripts directly with system python3 — they import _common.py` from the venv site-packages.

Phase 1: Bootstrap (один раз)

python3 /scripts/ensure_env.py

(No target script → bootstrap only, prints venv-python path.) Creates the venv in a global state dir outside the code (ADR-008 — $DOC2KB_HOME or ${XDG_DATA_HOME:-~/.local/share}/agentpipe/doc2kb/venv) and installs the lightweight tier: pymupdf4llm, pdfplumber, pypdf, pikepdf, python-magic, python-docx, mammoth, python-pptx, openpyxl, trafilatura, markdownify, charset-normalizer, striprtf, tiktoken.

Системные зависимости (macOS): brew install libmagic — обязательно, иначе python-magic не импортируется. На Linux: apt install libmagic1. На WSL то же. Без libmagic scout всё равно работает (fallback на расширение файла), но mime_confidence будет всегда "high" без перекрёстной проверки.

Опциональная зависимость для DOCX с математикой: pandoc (brew install pandoc / apt install pandoc). Если установлен, extract_docx.py автоматически переключается на него для документов, помеченных scout'ом как has_equations: true, и сохраняет OOXML math как $...$ LaTeX. Без pandoc такие документы извлекаются через mammoth и теряют формулы (warning будет в JSON output). pandoc также используется как предпочтительный маршрут для .rtf (extract_rtf.py): он сохраняет таблицы/картинки/структуру. Без pandoc .rtf всё равно извлекается через pure-Python striprtf (plain text), так что rtf никогда не падает.

Системный конвертер для legacy .doc: бинарный формат .doc (OLE2) не читается чистым Python, поэтому extract_doc.py шеллится во внешний конвертер по убыванию точности: soffice/libreoffice (brew install --cask libreoffice / apt install libreoffice-writer) → конвертит в .docx и переиспользует весь DOCX-пайплайн (таблицы, картинки, OOXML math); на macOS — textutil (встроен) тем же путём; иначе antiword (apt install antiword) — только plain text. Ни один из конвертеров не ставится в venv (как и opt-in mineru CLI). Если ни одного нет на PATH, extract_doc.py выходит с кодом 2 и install-hint — главный цикл должен трактовать это как «нужна установка конвертера», а не как corrupt-файл, и залогировать в _logs/errors.json. Scout заранее предупреждает (no .doc converter on PATH ...), когда в корпусе есть .doc, а конвертера нет.

Phase 2: Scout

python3 /scripts/ensure_env.py scout_corpus.py  

Производит /_scout.json с классификацией каждого файла. Никогда не пропускайте эту фазу. Schema файла зафиксирована в references/format-spec.md. Ключевые поля: files[].extraction_strategy, files[].action_required, user_decisions_needed.

Опциональный флаг --enable-mineru. Если установлен mineru tier (см. ниже «Optional heavy tier» / references/mineru.md), scout_corpus.py --enable-mineru автоматически роутит image_only PDF на extractor mineru вместо surfacing'а как ask_user_ocr_strategy. Без флага поведение не меняется — heavy ML deps никогда не активируются по-умолчанию.

Phase 3: Decide

  1. Прочитайте /_scout.json.
  2. Если user_decisions_needed пуст — переходите к Phase 4.
  3. Иначе — соберите одно сообщение пользователю по шаблону из references/batch-questions.md. Всегда батчите вопросы. Не задавайте по одному.

Возможные группы решений:

  • encrypted — зашифрованные файлы (Office/PDF); опции: password, skip.
  • scanned_pdf — image-only PDF; опции: skip, ocr_tesseract, vlm_mlx, claude_pagewise. MVP поддерживает только skip.
  • huge_file — >50 MB или >500 страниц; опции: skip, proceed, split.
  • corrupt — не открывается; опции: skip.
  • unsupported_format — XLSX/EPUB/ODT/IMAGE (не в MVP); опции: skip. (.doc и .rtf теперь поддержаны — см. Phase 4.)

Применение решений (важно для Phase 4). Разрешив группу, обновите каждый файл в _scout.json: проставьте итоговый extraction_strategy (skip для отказа, либо рабочую стратегию для proceed) и обнулите action_required (null). extract_corpus.py (Phase 4) откажется стартовать (exit 2), пока хоть у одного файла остался непустой action_required — это и есть гейт, гарантирующий, что Phase 3 пройдена.

Phase 3.5: Apply overrides (опционально, вместо ручной правки _scout.json)

Чтобы прогнать пару файлов через другой extractor (например mineru) или задать per-file настройки MinerU — не редактируйте _scout.json руками. Опишите правила в /_overrides.json и примените их детерминированно:

python3 /scripts/ensure_env.py apply_overrides.py  [--dry-run]
{
  "version": 1,
  "overrides": [
    { "match": "papers/*.pdf",          // glob по source_path, ЛИБО точный doc-id, ЛИБО точный source_path
      "strategy": "mineru",
      "mineru": { "backend": "vlm-auto-engine", "lang": "cyrillic", "keep_raw": true },
      "popo": true },                    // per-file Popo opt-in/out (перекрывает env)
    { "match": "doc-012", "strategy": "skip" }
  ]
}

Гарантии: конфиг валидируется (неизвестный ключ / неверная strategy / backend → exit 2, запись не происходит); _scout.json валидируется после применения и пишется атомарно (.tmpos.replace) — он никогда не останется полузаписанным или со сломанной схемой. На runnable-стратегии action_required обнуляется (override и есть Phase-3 решение). Правило, совпавшее с 0 файлов, — это ошибка (exit 1, типичная опечатка); --dry-run показывает diff без записи; --allow-unmatched понижает 0-match до warning. Блок mineru хранится структурно на записи файла — extract_corpus.py сам рендерит из него безопасные CLI-флаги (никаких сырых arg-строк). Лупа после этого: scout → applyoverrides → (решить остаток) → extractcorpus.

Phase 4: Extract

Запускайте один батч-диспетчер — не парсите файлы вручную. extract_corpus.py читает _scout.json и сам прогоняет весь механический Phase-4 цикл: диспатчит каждую extraction_strategy на нужный extractor через ensure_env.py, пишет docs/-.md, копит _logs/errors.json, и печатает один JSON-summary последней строкой stdout. Это заменяет ручной цикл «построить команду → запустить → распарсить JSON → залогировать» по каждому файлу.

python3 /scripts/ensure_env.py extract_corpus.py 
# опции: --timeout 600 (на файл), --normalize (прогнать normalize_md после каждого), --quiet

Exit codes: 0 — все файлы дошли до терминального состояния (needs_attention это НЕ ошибка); 2 — отказ старта (нет _scout.json, либо у какого-то файла остался непустой action_required — вернитесь в Phase 3); 3 — был хотя бы один файл в error-бакете (см. _logs/errors.json).

Каждый файл попадает ровно в один бакет counts: extracted / unchanged (sha совпал, переэкстракция пропущена) / skipped_by_decision / error / needs_attention (= число needs_install). Идемпотентность по source_sha256: повторный запуск переэкстрактит только изменившиеся файлы — безопасно гонять много раз (например, после установки конвертера для .doc).

Разберите needs_attention[] после диспетчера — это файлы, требующие ВАШЕГО суждения (диспетчер их НЕ решает сам, только surface'ит):

  • reason: "needs_install" — extractor вышел с кодом 2: .doc без системного конвертера, либо mineru CLI не установлен. install_hint подскажет, что поставить. Это НЕ ошибка и НЕ corrupt — поставьте инструмент и перезапустите extract_corpus.py (идемпотентность доделает только этот файл).
  • reason: "visual_transcription"ok:true PDF с warning'ом mangled_visual_layout: body извлечён, но позиционная математика рассыпана. Перечитайте исходный PDF через Read и перепишите body docs/-*.md вручную (см. pitfalls #13), затем extraction_method: claude-pagewise-manual@1.
  • reason: "dropped_pictures_residual"ok:true PDF с остаточными dropped_pictures: поле pages (список номеров страниц, восстановленный из тела документа) подскажет, какие страницы догнать через mineru page-patch (extract_pdf_mineru.py --pages … --patch-into …) или ручную транскрипцию.

Файлы visual_transcription/dropped_pictures_residual помечены extracted_but_flagged: true — считаются в extracted И присутствуют в needs_attention[] (body уже на диске, но требует доводки). unclassified_warnings[] эхо-ит любые нераспознанные warning'и дословно — ничего не глотается молча. После разбора needs_attention[] переходите к Phase 5 (build_manifest.py подхватит _logs/errors.json).

> Диспетчер использует таблицу стратегий ниже внутри себя. Прямой вызов одного extractor'а нужен только для адресных доводок (mineru page-patch, ручная переэкстракция одного файла):

| extraction_strategy | script | |---|---| | pymupdf4llm | extract_pdf_pymupdf4llm.py | | mineru | extract_pdf_mineru.py (opt-in tier, see below) | | mammoth | extract_docx.py | | doc | extract_doc.py (legacy .doc; needs system converter) | | rtf | extract_rtf.py | | python-pptx | extract_pptx.py | | passthrough-md | extract_md_txt.py --mode md | | passthrough-txt | extract_md_txt.py --mode txt | | trafilatura | extract_html.py | | ipynb | extract_ipynb.py |

python3 /scripts/ensure_env.py extract_pdf_pymupdf4llm.py \
    "" \
    "/docs/-.md" \
    --doc-id  \
    --source-rel ""

Каждый extract-скрипт пишет один .md в /docs/ и возвращает JSON {ok, out, tokens_estimated, warnings, ...} в stdout (диспетчер парсит его за вас). warnings непустые означают, что extraction прошёл с deficiency (пустой результат, charts dropped, и т.д.).

DOCX с математикой (автоматический pandoc-маршрут). Если scout пометил DOCX как has_equations: true и pandoc есть на PATH, extract_docx.py автоматически переключается с mammoth на pandoc — он сохраняет OOXML math (`) как $...$/$$...$$ LaTeX. Mammoth по-тихому дропает math элементы, и body после него ссылается на "формулу (1)", у которой нет содержимого. JSON extractor поле сообщит, какой маршрут был использован (pandoc или mammoth+markdownify). Если pandoc недоступен на машине с math-документом — будет warning с инструкцией установить (brew install pandoc / apt install pandoc`).

PDF с поломанными лигатурами fi / ff / fl (автоматическое восстановление). pymupdf4llm ≤ 1.27.x теряет одну букву из ASCII-смаппленных лигатур в его spans→markdown сборке, давая Ofcial вместо Official, fexible вместо flexible, trafc вместо traffic, Diffculty вместо Difficulty, quantifers вместо quantifiers, и т.д. Raw pymupdf.Page.get_text отдаёт буквы корректно — баг локален в pymupdf4llm. extract_pdf_pymupdf4llm.py автоматически прогоняет recover_ligatures из _common.py на body и эмитит warning ligatures_recovered: N word(s) ... с количеством исправлений. recover_ligatures идемпотентен (повторный вызов даёт 0 правок), регистр первой буквы сохраняется (OfcialOfficial, ofcialofficial). Если в новом корпусе встретится незнакомый broken pattern, эмитится дополнительный warning ligature_residual: ... с sample — расширьте _LIGATURE_FIXES в scripts/_common.py. Восстановление безопасно: lookbehind (? picture [WxH] intentionally omitted /assets/.

  1. Заменяет плейсхолдеры на Markdown image links ``.
  2. Подавляет dropped_pictures warning для тех плейсхолдеров, которые удалось заменить.

Дефолтное место для assets — .parent.parent / "assets", что соответствует стандартному layout /docs/*.md/assets/. Override: --assets-dir и --assets-rel . Отключить: --no-extract-images (вернёт исходное поведение с loud warning).

Warnings mangled_visual_layout / dropped_pictures (PDF only). Это два варианта одной и той же поломки — PDF использует визуальный layout для математики (формулы набраны позиционно: дроби как стек символов, штрихи отдельными glyph'ами). pymupdf4llm не может это восстановить и либо рассыпает выражения в `-цепочки одиночных символов внутри markdown-таблиц (mangledvisuallayout), либо выкидывает математические участки как ==> picture [WxH] intentionally omitted /scripts/ensureenv.py extractpdf_mineru.py \ "" "" \ --doc-id --source-rel "" \ --pages "2,18-19,35,221,243-244,588" \ --patch-into "/docs/.md" \ --lang cyrillic ```

Расценки на M-серии: ≈10 c/страница на vlm-mlx, то есть 9 страниц ≈ полторы минуты. Frontmatter автоматически обновляется (mineru_patched_pages: [...], extraction_method_supplementary: mineru-vlm@x.y.z), и ассеты для патчей сохраняются под именем -page-mineru-imgN. — pymupdf4llm-вые имена не затрагиваются. Установка tier и детали page-patching — в references/mineru.md (секция «Optional heavy tier» ниже — краткий обзор).

  1. Ручная транскрипция через Read tool (fallback). Если mineru

tier не установлен или его VLM не справляется (специфичные нотации, рукописные диаграммы):

  • Прочитайте исходный PDF напрямую через инструмент Read (Claude

умеет читать PDF — рендерит страницы и видит математику визуально). Для уже извлечённых картинок в assets/ Read тоже работает.

  • Перепишите body соответствующего /docs/-*.md

вручную (или добавьте транскрипцию таблиц/формул из картинок рядом со ссылками), сохранив YAML frontmatter, но обновив:

  • extraction_method: claude-pagewise-manual@1
  • заменив warning

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.