{
  "markdown": "<p align=\"center\">\n  <img src=\"docs/logo.svg\" alt=\"Blackout\" width=\"180\" />\n</p>\n\n<h1 align=\"center\">Blackout</h1>\n\n<p align=\"center\">\n  <strong>True PDF redaction, entirely in your browser.</strong><br />\n  <a href=\"https://blackout.thrain.ai\">blackout.thrain.ai</a>\n</p>\n\n---\n\nBlackout finds Social Security numbers, emails, phone numbers and card numbers\nin a PDF, lets you search custom terms or draw boxes by hand, and exports a\nflattened PDF where the redacted text is *actually gone* — not hidden under a\nrectangle.\n\nIt runs in three places, all on the same engine: the browser app, a CLI, and an\nMCP server.\n\n```bash\nnpx @thrain/blackout redact filing.pdf --detect ssn,email --out clean.pdf\n```\n\n## How it works\n\n1. **Nothing leaves your device.** Rendering (pdf.js), detection, and export\n   (pdf-lib) all run client-side. Load the page, go offline, it still works.\n2. **Redaction is real.** Export rasterizes each page and burns the boxes into\n   the pixels, then rebuilds the PDF from those images. The original text\n   layer is discarded — copy-paste and text extraction recover nothing.\n\n## Develop\n\n```bash\nnpm install\nnpm install\nnpm run dev         # local dev server\nnpm run build       # type-check + production build to dist/\nnpm run build:agent # type-check + bundle the CLI and MCP server to packages/\n\nnpm run smoke              # headless browser end-to-end test\nnpm run smoke:cli          # CLI end-to-end test\nnpm run smoke:mcp          # MCP server end-to-end test\nnpm run smoke:agent-dist   # the same two, against the built bundles\n\nnode scripts/make-test-pdf.mjs out.pdf 12           # fixture with fake PII\nnode scripts/test-worker.mjs                        # license worker tests\nnode scripts/visual-check.mjs [test.pdf] [outdir]   # screenshot spot-check\n```\n\nThe browser smoke script needs a Chrome/Chromium binary; set `CHROME_BIN` if\nyours isn't in the default Playwright cache location. Every smoke test makes\nthe same central assertion — that the exported PDF contains **zero** extractable\ntext — because that assertion is the entire product, and it has to hold on\nevery path that ships, not just the one that is easy to check.\n\n## Architecture\n\n- **Engine** (`src/pdf/`) — detection, mark ordering, and the rasterise-and-burn\n  export. Platform-agnostic: its only contact with the outside world is\n  `src/pdf/platform.ts`, which supplies a canvas. `src/platform/browser.ts`\n  backs it with a DOM canvas, `src/platform/node.ts` with Skia. There is exactly\n  one redaction implementation, so the browser and the CLI cannot drift.\n- **Site** — static React app, deployed to GitHub Pages by\n  `.github/workflows/deploy.yml` on every push to `main`.\n- **CLI and MCP server** (`src/agent/`) — thin non-interactive wrappers over the\n  engine, bundled into `packages/blackout` and `packages/blackout-mcp`.\n- **License worker** (`worker/`) — a Cloudflare Worker that verifies Stripe\n  checkout sessions and mints signed license tokens; the app verifies them\n  with an embedded public key. Deployed by\n  `.github/workflows/deploy-worker.yml`.\n\n## For agents\n\nAn agent asked to redact a PDF will otherwise write a script that draws a black\nrectangle over text that stays selectable underneath. Two form factors exist so\nthat \"redact this PDF\" can resolve to a tool that does it correctly:\n\n- **CLI** — [`packages/blackout`](packages/blackout) · `npx @thrain/blackout redact in.pdf`\n- **MCP server** — [`packages/blackout-mcp`](packages/blackout-mcp) · tools `redact_pdf`, `check_pdf`\n\nBoth verify their own output before returning: they re-extract text from the\nfile they just wrote and fail rather than hand back a document that still has a\ntext layer. Neither makes a network call, including the licence check — so\nnothing leaves the machine at all.\n\n## License\n\n[Apache-2.0](LICENSE) © Thrain LLC. The \"Blackout\" name and logo are\ntrademarks of Thrain LLC (see [NOTICE](NOTICE)) — fork freely, but ship your\nfork under your own name.\n",
  "bytes": 3965,
  "sha": "1933db78ba278c7d172268c88d1db75da9b201741d46ec0c282b07deaee50ace",
  "repo_slug": "thrain-ai/blackout-pdf",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_ai_thrain_blackout_0efffa29/readme"
}