Inspiration

I moved countries, and my life became paperwork: residence permits, leases, payslips, tax forms, appointment letters. They were scattered across email, Downloads and photos on my phone. An AI assistant could have answered "when does my permit expire?" in seconds, but only if I uploaded my passport, my address and my salary to it. I wanted the help without handing over the papers.

What it does

Voidcat is smart storage for your life. Drop in any document and it is read on your Mac, filed into folders, and its facts (dates, IDs, amounts, addresses) go to an inbox for you to approve, with the value highlighted on the page.

  • Download and go. A free, open-source Mac app (Apple silicon) from voidcat.io. Reading, filing and facts run on your Mac, offline.
  • Encrypted at rest. The library (SQLCipher) and every file (AES-256-GCM) are locked with a key in the macOS Keychain. A recovery key is the only other way in.
  • Ask any AI, safely. A local model sees real values and nothing leaves. A cloud model only gets masked text: names, IDs and addresses become placeholders like [PERSON_1], and the real values are put back on your Mac. You see exactly what will be sent before it goes.
  • Calendar and reminders for expiries, appointments, renewals and monthly payments.
  • MCP server, so Claude Desktop, Cursor or Claude Code can use your library with the same masking and per-app access levels.
  • Voidcat Cloud (optional). End-to-end encrypted sync to Google Cloud: open your library in any browser, choose per document what syncs, drop in new files, read them with "Read now" and ask Gemini, still masked. Google stores only locked bytes.

How we built it

  • Mac app: Tauri 2 with a Rust core (SQLCipher with FTS5 search, AES-GCM, Apple Vision OCR, Keychain) and a React front end. Filing runs on a local 9B model through Ollama, set up from inside the app.
  • Privacy layer: a masker that learns from approved facts plus patterns (IBAN, NIE, passport, phones, dates), and OpenAI's privacy-filter model running locally to catch names the rules miss.
  • Cloud: Cloud Run (web on nginx, API on Bun), Firestore and Cloud Storage holding only sealed records, Firebase Auth, Gemini 2.5 Flash on Vertex AI in Belgium. Browser keys are derived from the recovery key and kept non-exportable with WebCrypto.
  • GitLab: every stage of the lifecycle is automated, and Duo agents do the work while a person approves (next section).

Challenges

  • Same keys, two worlds. Rust and the browser had to derive identical keys and seal identical bytes. We pinned shared test values in both test suites so any drift fails CI.
  • Masking that still answers. Placeholders have to stay consistent across a whole conversation, and dates need a relative note ("about 5 months from now") or the AI can't answer deadline questions.
  • A 9B model filing documents. Showing it the folder list first made it put everything in the first folder. Splitting filing into two calls (what is it, then where does it go) fixed it.
  • OCR noise. Low-confidence scan text was garbage that leaked into prompts; pages under confidence 60 are now dropped, and the Mac re-reads scans with Apple Vision.

Accomplishments

  • Real end-to-end encryption: Google Cloud never sees a document, a fact or a file name in clear.
  • A working agent loop on GitLab: an issue was triaged, implemented, tested, scanned, merged and deployed by Duo flows, with a person approving each step.
  • Carbon measured per document with the SCI standard: about 0.06 gCO₂e to read and file one document locally.

What we learned

  • Privacy is a product feature people can see: showing the masked prompt before sending builds more trust than any promise.
  • Agents work best on small, well-scoped issues with a plan and clear rules (AGENTS.md).
  • A privacy guard in CI is worth it: it blocks real-looking personal values before they reach a public repo, and prints them redacted because job logs are public.

What's next

  • Paid plans (€4 a month) with Stripe, keeping the Mac app free forever.
  • Saved chats and the zip tool in the browser.
  • Firebase App Check, and showing each document's energy in the app.

GitLab and Duo

Supervised autonomy: agents do the steps, a person approves the outcomes. The loop ran for real on issue #4 → MR !13, merged and deployed on 18 Oct 2026.

  1. Plan: the custom Triage flow reads AGENTS.md, labels the issue (type, area, priority), checks for duplicates and comments a plan with tests and privacy risks.
  2. Create: assigning the issue to Duo Developer opens a draft merge request that follows the plan.
  3. Verify: verify (typecheck, lint, tests) and rust-test; Pipeline Doctor explains failures and pushes small fixes.
  4. Secure: SAST, secret detection and dependency scanning on every MR.
  5. Govern: the privacy-guard job blocks personal data; the Privacy Guard flow reviews changes to masking.
  6. Review: Duo Code Review with Voidcat's own rules (mr-review-instructions.yaml).
  7. Deploy: on merge, the web app and API deploy to Cloud Run and voidcat.io to Firebase Hosting, all through Workload Identity Federation, with no stored keys.
  8. Release and monitor: the Release flow picks the next version from the merged changes, bumps it and writes the changelog in a merge request. Merging is the approval; a release job on main then tags it and publishes the MCP builds and a GitLab release (v0.1.0 shipped this way). Agents never push tags. Health Reporter posts each pipeline's numbers to an issue.

Duo also reviews the automation itself. On the merge request that made releases automatic, it found five problems: a deprecated release tool, a tag check that could release twice, fragile version parsing, a race between merges, and releasing after a failed deploy. All five were fixed before merging.

Flow sources are versioned in .gitlab/duo/flows/.

Built With

  • apple-vision
  • bun
  • cloud-run
  • cloud-storage
  • firebase-auth
  • firebase-hosting
  • firestore
  • gitlab
  • gitlab-duo
  • google-cloud
  • mcp
  • ollama
  • openrouter
  • react
  • rust
  • sqlcipher
  • sqlite
  • tailwindcss
  • tauri
  • typescript
  • vercel-ai-sdk
  • vertex-ai
  • vite
  • webcrypto
Share this project:

Updates

Submission history