{
  "markdown": "# Kemb\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/downloads/)\n[![Claude Code plugin](https://img.shields.io/badge/Claude%20Code-plugin-8A2BE2.svg)](https://claude.ai/code)\n[![Cowork compatible](https://img.shields.io/badge/Cowork-compatible-1f6feb.svg)](https://claude.ai)\n[![Changelog](https://img.shields.io/badge/changelog-keepachangelog-orange.svg)](./CHANGELOG.md)\n\n> Comb document corpora into agent-ready form. One CLI, one Claude skill,\n> two LlamaCloud-backed facets — parse and classify — plus a local,\n> zero-credit `probe` for triaging a directory before you spend a thing.\n\n**Kembing** is the discipline of preparing document corpora for agents: survey\nthe pile, plan the pass, then comb each document into a structured markdown\nmirror that an LLM can actually use. Today `kemb` ships the two single-file\ndocument facets that make up a pass, plus a local `probe` that surveys and\ntriages a directory before you process it — the first shipped step of that\narc. The rest of the orchestration (plan → execute → mirror with hash-stamped\nprovenance) is in active development — see [`docs/goal.txt`](./docs/goal.txt).\n\n| Facet       | What it does                                                    | API                 |\n|-------------|-----------------------------------------------------------------|---------------------|\n| **parse**   | Document → clean markdown / text (tables, multi-column, scans)  | LlamaParse v2       |\n| **classify**| Document + categories → matched label + confidence              | LlamaClassify v2    |\n| **probe**   | Directory → per-file inventory + text samples for triage         | local, zero credits |\n\n**Why only two API facets?** Because the third party in the room is an LLM.\nOnce `parse` has produced clean markdown, the consuming agent extracts fields\nto a schema, classifies, and splits sections itself — zero LlamaCloud credits,\nzero extra plumbing, full conversation context. The former `extract` and\n`split` facets were removed for exactly that reason; `classify` stays for\nrouting documents *before* parsing (scans and layout-heavy files an agent\ncan't read locally).\n\n`probe` and `doctor` are local, zero-credit tools — `probe` scopes a directory\nand `doctor` runs a preflight check — neither uploads a document or starts a job.\n\n## 30-second quickstart\n\n```bash\n# 1. Install\npipx install git+https://github.com/acrosley/kemb\n\n# 2. Set your key (get one at https://cloud.llamaindex.ai/api-key)\nexport LLAMA_CLOUD_API_KEY=\"llx-...\"\n\n# 3. Parse anything\nkemb parse ./contract.pdf      # → contract.md\n```\n\nThat's it. `classify` follows the same shape — see\n[Real examples](#real-examples) below.\n\n## What this is for\n\n- **Knowledge workers and analysts** drowning in PDFs, scans, and Office docs\n  who want one tool that goes from \"file on disk\" to \"usable text or JSON\" —\n  no per-format glue code.\n- **Teams already using Claude Code or Cowork** who want LlamaCloud's parsing\n  quality available as one native skill, with corpus-level orchestration on\n  the roadmap.\n- **Legal, research, and analyst teams** prepping large document collections\n  for agent retrieval — the next phase of kemb (probe → plan → pass → mirror)\n  targets exactly this workflow.\n- **Anyone tempted to write `requests.post(...)` against LlamaCloud yourself**\n  — kemb handles upload, polling, retries, REST/SDK fallback, error surfacing,\n  and output paths so you can focus on the result.\n\n## Two ways to use it\n\n| Mode   | What you run                                                                                                  | What you get                                                                                                                                                            |\n|--------|---------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Plugin | `/plugin install kemb@kemb` in Claude Code (or \"Add marketplace from GitHub\" in Cowork)                       | One orchestrating skill that routes by facet, with per-facet reference docs that load on demand.                                                                        |\n| CLI    | `pipx install git+https://github.com/acrosley/kemb`                                                           | A `kemb` command on your PATH with `parse`, `classify`, and `probe` subcommands and a preflight `doctor`.                                                               |\n\nYou only need a LlamaCloud API key — grab one at\n<https://cloud.llamaindex.ai/api-key>.\n\n## Prerequisites (one-time)\n\nExport your API key as a persistent environment variable.\n\n**macOS / Linux** (bash/zsh):\n\n```bash\necho 'export LLAMA_CLOUD_API_KEY=\"llx-...\"' >> ~/.zshrc   # or ~/.bashrc\nsource ~/.zshrc\n```\n\n**Windows** (PowerShell):\n\n```powershell\nsetx LLAMA_CLOUD_API_KEY \"llx-...\"\n```\n\nRestart your terminal (and Claude Code / Cowork) so the new env var\npropagates.\n\n## Install — CLI\n\n```bash\npipx install git+https://github.com/acrosley/kemb\n```\n\nor, without pipx:\n\n```bash\npip install git+https://github.com/acrosley/kemb\n```\n\nYou'll get a `kemb` command:\n\n```bash\nkemb --help                                    # top-level help\nkemb parse     --help\nkemb classify  --help\nkemb probe     --help                          # scan a directory (zero credits)\nkemb doctor                                    # preflight checks (zero credits)\n```\n\nAfter install, run `kemb doctor` to confirm your Python, deps, and\n`LLAMA_CLOUD_API_KEY` are all set up — it makes one non-billable auth probe\nagainst LlamaCloud and never starts a job. Add `--offline` to skip the\nnetwork check.\n\n`llama-cloud`, `requests`, and `pypdf` install automatically as dependencies.\n\n### parse — document → markdown / text\n\n```bash\nkemb parse ./contract.pdf                       # → contract.md\nkemb parse ./scan.pdf --tier agentic            # agentic tier\nkemb parse ./report.pdf --output ./out.md       # explicit output path\nkemb parse ./report.pdf --result-type text      # → report.txt\nkemb parse ./report.pdf --strip-noise           # drop layout-hint comments\nkemb parse ./report.pdf --rest                  # force REST path (no SDK)\n```\n\n**Shortcut:** `kemb ./file.pdf [...]` (no subcommand) dispatches as `parse`.\n\n### classify — document + categories → label + confidence\n\n```bash\nkemb classify ./doc.pdf --rules @rules.json\nkemb classify ./doc.pdf --rules '[{\"type\":\"invoice\",\"description\":\"A bill requesting payment\"}]'\nkemb classify ./doc.pdf --mode multimodal       # vision for scans / layout-heavy\n```\n\n`--rules` is a JSON list of `{type, description}` objects. The classifier\nreturns `{type, confidence, reasoning}`. Output defaults to\n`<input>.classify.json`.\n\n### probe — recursively inventory a directory (zero credits)\n\n```bash\nkemb probe ./inbox                              # human-readable table\nkemb probe ./inbox --ext pdf,docx               # filter by extension\nkemb probe ./inbox --max-depth 2                # cap recursion depth\nkemb probe ./inbox --supported-only             # only LlamaCloud-friendly files\nkemb probe ./inbox --json > inventory.json      # machine-readable\n```\n\n`probe` walks the target directory recursively and reports per-file size,\nmtime, extension, mime type, and whether LlamaCloud is likely to accept the\nformat. It never makes a network call — use it to preview a batch before\nrunning `parse` / `classify` over a directory. Hidden\nfiles and directories are skipped unless `--include-hidden` is passed.\n\n#### probe --sample — corpus triage in one text file (zero credits)\n\n```bash\nkemb probe ./cases --sample                            # XML-tagged corpus sample\nkemb probe ./cases --sample --output corpus_sample.txt # write it to a file\nkemb probe ./cases --sample --sample-words 200         # more words per doc\nkemb probe ./cases --sample --sample-budget 20000      # tighter corpus-wide cap\nkemb probe ./cases --sample --json                     # samples embedded in the JSON\n```\n\n`--sample` extracts the first words of every document **locally** — PDFs via\n`pypdf`, Office/OpenDocument files via their XML, text/HTML directly — and\nrenders one text file of XML-tagged blocks (the structure LLMs parse most\nreliably): a `<document>` tag per file carrying labeled metadata attributes\n(`path`, `size`, `pages`, `modified`, `type`, `text` status), with up to\n`--sample-words` words of content as the body. An agent can read that single\nfile and weigh an entire multi-directory case corpus — what each document is,\nwhich are scans (PDFs with no text layer collapse to a self-closing tag with\na `note` flagging them for OCR-capable parse tiers), what to parse now versus\ndefer — without uploading anything or running a per-file model pass.\n\n```xml\n<corpus_sample generated=\"2026-06-10T01:52:23Z\" files=\"4\" total_size=\"4.3 KB\"\n               sampled_words=\"69\" status=\"no-text: 1, ok: 3\">\n<document path=\"smith/complaint.pdf\" size=\"2.2 KB\" pages=\"4\" modified=\"...\" type=\".pdf\" text=\"ok\">\nIN THE DISTRICT COURT Plaintiff John Smith alleges breach of contract and fraud ...\n</document>\n<document path=\"smith/exhibit-a.pdf\" size=\"1.7 KB\" pages=\"12\" modified=\"...\" type=\".pdf\"\n          text=\"no-text\" note=\"no text layer — likely a scan; needs an OCR-capable parse tier\"/>\n...\n</corpus_sample>\n```\n\n`--sample-budget` caps total sampled words corpus-wide so the output stays\nreadable in one context window; files past the budget keep their inventory\nline but skip the text. PDFs also gain page counts — the input you need to\nestimate parse cost (pages × tier) before committing to a batch.\n\n### --dry-run — preview a job without spending credits\n\n```bash\nkemb parse    ./contract.pdf --dry-run\nkemb classify ./doc.pdf      --rules @rules.json   --dry-run\n```\n\nAdds a `--dry-run` mode to every job subcommand. It validates the inputs\n(file exists, rules parse, mutually-exclusive flags\naren't combined), resolves the output path, and prints the configuration\nthat *would* be sent — without uploading the document or starting a job.\nPair it with `probe` to scope a batch run before any credits are spent.\n\n## Real examples\n\nConcrete recipes. Rule files referenced below ship in\n[`examples/`](./examples/) so you can copy and run them as-is.\n\n### Route incoming docs by type\n\n```bash\nfor f in inbox/*.pdf; do\n    kemb classify \"$f\" --rules @examples/rules/document_routing.json\ndone\n```\n\nEach call writes `<file>.classify.json` with the matched label (contract,\ninvoice, receipt, correspondence, other) plus a confidence score — wire that\ninto a shell loop and `mv` files into per-type folders.\n\n### Parse a multi-column scan to markdown\n\n```bash\nkemb parse ./scanned-deposition.pdf --tier agentic --strip-noise\n```\n\n`agentic` handles the multi-column OCR; `--strip-noise` drops repeating\nheader/footer artifacts so the resulting markdown is paste-ready.\n\n### Triage a multi-directory case corpus before spending credits\n\n```bash\nkemb probe ./case-files --sample --output corpus_sample.txt\n```\n\nOne zero-credit command produces an XML-tagged sample of the whole tree —\nfirst words, page counts, and scan flags for every document.\nHand `corpus_sample.txt` to Claude (or read it yourself) to decide doc types,\nparse tiers, and priorities, then run `parse` over only the files that earn\nit — and extract or split from the resulting markdown yourself.\n\n### Scope a directory, then run the batch\n\n```bash\n# 1. See what's in the folder and which files LlamaCloud will accept (free)\nkemb probe ./inbox --supported-only\n\n# 2. Confirm the config one file would send — no upload, no credits\nkemb parse ./inbox/sample.pdf --tier agentic --dry-run\n\n# 3. Run the batch once the inventory and config look right\nfor f in inbox/*.pdf; do kemb parse \"$f\" --tier agentic; done\n```\n\n`probe` and `--dry-run` together let you understand cost and scope before a\nsingle credit is spent — survey the pile, preview the job, then commit.\n\n## Install — Claude Code plugin\n\n```\n/plugin marketplace add acrosley/kemb\n/plugin install kemb@kemb\n```\n\nUpdates / removal:\n\n```\n/plugin marketplace update kemb\n/plugin uninstall kemb@kemb\n/plugin marketplace remove kemb\n```\n\nOne orchestrating skill (`kemb`) loads on demand. Its routing table sends\neach request to a facet under `references/`:\n\n| Request                                                                                                                  | Facet doc                |\n|--------------------------------------------------------------------------------------------------------------------------|--------------------------|\n| \"Parse this PDF with LlamaParse.\" / \"OCR this scan.\" / \"Convert this Excel to markdown.\"                                 | `references/parse.md`    |\n| \"Classify this document — is it a contract, invoice, or receipt?\" / \"Route incoming docs by type.\"                       | `references/classify.md` |\n| \"What's in this folder? / triage this corpus / scope a batch before parsing.\"                                            | `references/probe.md`    |\n\nRequests to extract fields or split sections route through `parse` first;\nClaude then does the structured work from the markdown directly — no extra\nAPI call, no extra credits.\n\nInvoke the skill explicitly via the slash menu: `/kemb:kemb`.\n\nThe first time the skill runs in a fresh sandbox it `pip install`s `llama-cloud`\nautomatically (the bundled shim passes `--auto-install`), so you don't need\nto set anything up beyond the API key.\n\n## Install — Claude Cowork plugin\n\nCowork manages plugins through the **Customize** menu (there's no `/plugin`\nslash command in Cowork).\n\n1. Open Claude Desktop → **Cowork** tab.\n2. Click **Customize** in the left sidebar.\n3. Click **+** → **Add marketplace from GitHub**.\n4. Enter `acrosley/kemb`.\n5. Find `kemb` in the marketplace and click **Install**.\n6. Fully quit Cowork from the system tray and relaunch.\n\n### Network allowlist (Cowork only)\n\nThe Cowork sandbox uses an HTTPS allowlist. If you see `403 Forbidden` /\n`Host not in allowlist` from the proxy when calling\n`api.cloud.llamaindex.ai`, add the host under **Settings → Capabilities →\nnetwork allowlist** (Team/Enterprise plans require an org owner to do this\nin Admin settings), then fully restart Cowork. Claude Code has no such\nrestriction.\n\n### Local-folder install (plugin development)\n\nIf you've cloned the repo and want to test changes without pushing:\n\n1. **Customize** → **+** → **Add marketplace from local folder**\n2. Point it at the cloned `kemb` directory\n3. Install as above\n\n## Cost\n\nThe two document facets bill per page processed. Parse exposes a tier knob;\nclassify has a single per-page rate. `probe` and `doctor` are local and\nfree — they never spend a credit. Post-parse extraction and splitting happen\nin your agent, so they add no LlamaCloud cost at all.\n\n**Parse tiers:**\n\n| Tier             | Approx multiplier | Best for                                       |\n|------------------|-------------------|------------------------------------------------|\n| `fast`           | ~1 cr/page        | Plain text, simple layouts                     |\n| `cost_effective` | ~3 cr/page        | Default; balanced quality                      |\n| `agentic`        | ~15 cr/page       | Tables, multi-column, mixed media              |\n| `agentic_plus`   | ~30+ cr/page      | Dense tables, charts, the hardest documents    |\n\n`fast` returns plain text only; the other three tiers also expose a\nstructured markdown expansion. The CLI handles this transparently — pass\n`--tier fast` and you'll get text saved to your chosen output path (with a\none-line note if you asked for markdown). Verify current pricing at\n<https://cloud.llamaindex.ai> before committing to large batches.\n\n**Classify** offers two `--mode` settings: `fast` (text-only, cheap) and\n`multimodal` (reads images and layout — better for scans).\n\n## What's inside\n\n```\nkemb/\n├── .claude-plugin/\n│   ├── marketplace.json            — marketplace manifest\n│   └── plugin.json                 — plugin manifest\n├── pyproject.toml                  — packaging for the `kemb` CLI\n├── src/kemb/\n│   ├── __init__.py                 — public exports\n│   ├── _core.py                    — subcommand dispatcher (parse / classify / probe / doctor)\n│   ├── _common.py                  — shared helpers (auth, SDK loader, REST poller, file upload)\n│   ├── _parse.py                   — LlamaParse v2\n│   ├── _classify.py                — LlamaClassify v2\n│   ├── _probe.py                   — local directory scan + corpus text sampling\n│   ├── _sample.py                  — per-format local text extractors (pypdf, zip/XML)\n│   └── _doctor.py                  — zero-credit preflight\n├── skills/kemb/                    — single orchestrating skill\n│   ├── SKILL.md                    — routes requests to facets\n│   ├── scripts/kemb_cli.py         — shim into src/kemb/\n│   └── references/\n│       ├── parse.md                — parse facet (LlamaParse v2)\n│       ├── classify.md             — classify facet (LlamaClassify v2)\n│       ├── probe.md                — probe facet (local scan + triage sample)\n│       ├── rest_api.md             — LlamaCloud v2 REST reference\n│       └── troubleshooting.md      — common failure modes\n├── examples/                       — copy-pasteable classifier rules\n├── docs/\n│   └── goal.txt                    — corpus-curation north star\n├── tests/                          — pytest suite\n├── CHANGELOG.md                    — version history\n├── CONTRIBUTING.md                 — dev setup and PR guide\n└── README.md\n```\n\nThe plugin skill and the standalone CLI both shell into the same `kemb`\npackage, so the two invocation paths never drift.\n\n## Contributing\n\nBug reports, feature requests, and PRs welcome. See\n[CONTRIBUTING.md](./CONTRIBUTING.md) for dev setup, the test workflow, and\nthe pattern to follow when adding a new facet.\n\n## Changelog\n\nSee [CHANGELOG.md](./CHANGELOG.md) for the release history (Keep a Changelog\nformat).\n\n## License\n\nMIT — see [LICENSE](./LICENSE).\n",
  "bytes": 18287,
  "sha": "20cc7460887a4dff0b6b706e4d84b1f45fe4584473c4a02fb858f08def713f15",
  "repo_slug": "acrosley/llamaparse-plugin",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_acrosley_llamaparse_plugin_llamaparse_pl_010788ea/readme"
}