Repository navigation
FAQ
Removes. That is the whole product. A PDF page carrying an accepted redaction is rasterised with the boxes burned in and rebuilt from that raster; DOCX and PPTX text runs are edited in place; spreadsheet cells are rewritten and dependent formulas dropped; email byte ranges are replaced; image pixels are replaced and the file re-encoded.
And it is checked, not promised: every export is re-opened and read the way an adversary would, and a surviving value fails the export. See Security Model.
No, and it does not claim to. No detector finds everything. The reviewer is the control, which is why the interface never implies completeness and accepting is a deliberate act. Verification proves the absence of the accepted strings, not of the information: "the CEO of the company on Elm Street" still identifies someone.
The pattern detectors alone reach 20.1% covered recall at 94.1% precision on the labelled synthetic corpus. They are deliberately precise and do not look for names, which is the model's job. Numbers for models are what #153 will publish. See Testing and Benchmarks.
No. Without a model, pattern detection, manual redaction, search, rules, learned rule offers and export all work. Only the contextual pass (names, prose addresses, roles) and Hush are unavailable, and the document says the model pass did not run.
Twenty-five: the Vercel AI Gateway, OpenAI, Anthropic, Google, Mistral, xAI, Groq, Cerebras, DeepSeek, DeepInfra, Together, Cohere, Fireworks, Perplexity, Baseten, Azure, Bedrock, Vertex, OpenRouter, Synthetic, Ollama, LM Studio, llama.cpp, any OpenAI-compatible URL, and a ChatGPT subscription sign-in. Every one is verified before use. See AI Providers.
Yes. Ollama, LM Studio or llama.cpp, with a vision model such as Qwen3-VL for images. Local providers have zero spend and run one request at a time by default. CI tests against a real local Qwen3-VL model weekly.
Technically yes (pnpm ai login --provider openai), with a clear caveat. It uses Codex CLI's public OAuth client, OpenAI's terms decide whether that is allowed, and the backend is undocumented. Use an API key for anything deployed or shared. There is no Claude subscription sign-in, because Anthropic's terms reserve it for Anthropic's own apps.
In the fully local setup (Postgres, RustFS, Tesseract, optionally a local model), nothing. There is no telemetry in any configuration: usage counters are rows in your own database. If you configure a hosted OCR or AI provider, the content those steps need goes to that provider, as it must. Hush asks before it reads a document.
Hush is a review assistant (Ctrl/⌘+K) that searches, reads and scans with tools and proposes rules and redactions. It cannot change anything without you pressing Approve on a card showing what it will do. Approvals are signed by the server and re-checked before they run. See Hush Assistant.
Ctrl/⌘+F, type it (optionally as a RegEx), then Redact all. That opens a rule with a live preview and the exact count before anything is written. Rules can apply to the document, the whole batch, or everything you upload from now on. See Search and Rules.
A preset called "HIPAA" that somebody applies and then believes their document is compliant is a worse outcome than having no presets at all. Presets are named for what they search for, and the rule is enforced: a preset naming a regulation or claiming an outcome fails validation at import. See Redaction Presets.
The page was rasterised, which is what makes the removal real. Pages without redactions keep their text. Preserving the text layer is #40.
No, and the export dialog says so. Solid fill is the default, text is always filled solid, and the report records which style was used.
Alternatives to masking. Pseudonymize replaces a value with a stable surrogate (PERSON_014) and keeps no mapping. Tokenize does the same and gives you a vault to reverse it. Encrypt writes ciphertext with the key in the vault. IDs, account numbers, API keys and faces can only be masked, and addresses and birth dates cannot be pseudonymised. None of these is anonymisation in the regulatory sense. See Export and Anonymisation.
No, by design. The vault is shown once and stored nowhere. You can restore yourself with the file and its vault at /restore, which stores nothing either.
Each attachment in a supported format becomes a document of its own: reviewed, redacted, and substituted back into the message (verified by checksum). A message with attachments arrives as a batch. Unreadable formats are carried through and the report says so, per attachment.
An .mbox expands into one document per message, and your decisions carry across all of them. Since 1.10.0 you download it back as a mailbox: rebuilt from the verified exports, with separator lines written fresh (no envelope senders), and verified again as a whole. Or download the processed files in folders. See Batches and Mailboxes.
1 h, 6 h, 24 h or 3 days, chosen at upload, extendable to at most 72 h from upload. A scheduled sweep then deletes everything. If you self-host, you have to run that sweep yourself (Deployment).
For the fully local path, yes: it runs Postgres and RustFS. Without Docker, leave STORAGE_DRIVER unset (files go to .anonify-storage/), but you still need a Postgres somewhere.
The MinIO server repository was archived in April 2026 and its client in July 2026. RustFS is actively released under Apache-2.0, speaks the same S3 operations, and imports the existing volume in place. That import is one-way, so back up first (Upgrading).
Much less since 1.6/1.7. Documents are read in 1 MiB authenticated chunks, a page at a time, and the budget is chunk × chunks in flight × concurrent documents. For example, six concurrent 50 MiB decks fall from roughly 900 MiB to roughly 100 MiB. See Streaming IO.
Not casually. A new key makes everything already stored permanently unreadable, including a stored ChatGPT sign-in. There is no recovery.
It should not be: self-hosted has no daily quotas. Check ANONIFY_PROFILE.
Yes, with real limits (300 s steps, a daily cron, a 1 GB Blob store, 50k workflow events a month). Add the sweep.yml Action for frequent expiry. See Deployment.
Tesseract: per-word boxes, no account. Mistral: better on difficult scans, but per-block boxes, so a redaction covers a paragraph.
OCR does (OCR_TESSERACT_LANGUAGE). Detection mostly does not: detectors and prompts are English-shaped, and the failure is silent (#43). A contribution for one language you speak is welcome.
Export them as JSON from the Rules panel. They are tied to your browser session and expire 30 days after last use. Import the file on another instance or browser.
v1 was Flask + React: pdfminer.six extraction, a spaCy NER model fine-tuned on a Kaggle PII dataset, and a rebuild with reportlab. It got the hardest thing right (rebuilding meant the redacted text really was gone), and v2 inherits that principle.
| v1 | v2 | |
|---|---|---|
| Formats | PDF, DOCX, XLSX, PPTX, EML, MBOX, CSV, TSV, TXT, RTF, images | |
| Fidelity | rebuilt as plain text | format-native; only redacted PDF pages rasterised |
| Who decides | High / Med / Low, globally | every suggestion, individually; rules and an assistant, all under your approval |
| Manual control | none | click a word, drag, regions, cells, search and Redact all, RegEx rules |
| Detection | fixed NER labels | validated patterns + a contextual pass on any of 25 providers + local expansion |
| Proof | trusted by construction | every export re-opened adversarially; a surviving value fails it |
| Processing | in-request, Socket.io | durable workflow, paced retries, resumable stream, admission queue |
| At rest | files on disk | per-document AES-256-GCM in authenticated chunks, TTL, scheduled purge |
| Access | path-based | session ownership on every read; signed, short-lived, checksum-verified downloads |
They are better at different things. A model is genuinely better at contextual judgement ("Customer: Apple Inc. / Account manager: John Smith"). It is worse at everything a regex does well: it is non-deterministic, it costs money per token, and it can invent values. So patterns run first (Luhn-checked cards, structurally valid SSNs, label-gated accounts and birth dates), the model is asked only what they cannot settle, and its answers are located, never trusted.
The tooling now exists: a 534-document labelled corpus, a scorer, and pnpm bench:models, which compares each model with and without the pattern pass. The pattern-only baseline is measured. A model run has not been published yet; that is #153.
By labels. A merged PR's labels decide the version bump, a workflow tags and publishes it, and the release notes come from changelog.d/ fragments written in each PR. See Contributing.
Apache-2.0, chosen for its explicit patent grant. Read Section 7: no warranty that any particular value was removed from any particular file. Anonify verifies every export against what you accepted, but the decision about what to accept was yours. Check the file before you send it.
Report it privately: the Security tab → Report a vulnerability. Do not publish a bypass before there is a fix. See Security Model §13.
Anonify: AI proposes, the application applies, and only what a person accepted is removed.
Repository · Report a bug · Request a feature · Security policy · Apache-2.0
This wiki describes v1.10.0 and summarises and links the in-repo documentation. Where the two disagree, the files under docs/, CHANGELOG.md and SECURITY.md are canonical.
Getting going
Using it
- Supported Formats
- Review Workspace
- Search and Rules
- Hush Assistant
- Redaction Presets
- Export and Anonymisation
- Batches and Mailboxes
How it works
- Architecture
- Processing Workflow
- Redaction Engine
- Storage and Encryption
- Streaming IO
- Data Model
- API Reference
- Security Model
When it breaks
Contributing
Repository · Issues · Releases · Changelog