{"slug": "squint-your-screenshots-have-secrets", "title": "Squint: your screenshots have secrets.", "summary": "A developer built Squint, a macOS menu bar app that scans every screenshot for passwords, API keys, tokens, emails, phone numbers and card numbers, then places a redacted copy on the clipboard. Text is read on-device with Apple's Vision framework, regex rules triage matches into tiers, and ambiguous candidates are classified by Gemma 3 4B running locally through Ollama with a JSON-schema-constrained output. The developer reports roughly 0.36 seconds per candidate after hand-writing the chat template and warming the prompt cache, down from about 3 seconds per screenshot in the first version.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady](https://dev.to/challenges/hacktoberfest-week3-2026-10-19)*\n\nWe almost do everything with AI now. A bug, an email, a form, a weird error in a dashboard: We just take a screenshot and paste it into a chat. It's the laziest, fastest way to explain anything.\n\nIt's also how we keep leaking things. An email address in the corner of a page. A phone number in a form. An API key sitting in a terminal we didn't bother to crop. By the time we notice, the screenshot is already on someone else's server.\n\nSo I built Squint: a small macOS menu bar app that checks every screenshot before it goes anywhere, using Gemma running on my own Mac.\n\nTake a screenshot the way you always do. If it contains a password, key, token, email, phone number or card number, a banner slides in:\n\nHid 3 things in your screenshot The redacted copy is on your clipboard\n\nThat's the whole interaction. The clipboard already holds the safe version, so ⌘V just works. No dialog, no export button, no new habit.\n\nIf you want to check what Squint did, click the banner. You see the screenshot exactly as it will be pasted. Click anything to show or hide it, or drag a box over something it missed.\n\nEverything happens on your Mac: reading the text, deciding what's private, and redacting it. The deciding is done by Gemma 3 (4B), running locally through Ollama.\n\nThe laziest privacy tool is the one you never think about. You don't open Squint, you don't drag files into it, and you don't change how you take screenshots. It squints at every screenshot so you don't have to.\n\nIt's lazy on the inside too. Gemma is the sloth of the pipeline. Fast pattern rules catch the obvious cases (a Stripe live key is always a Stripe live key), and Gemma only wakes up for the genuinely ambiguous ones, like \"is [support@acme.io](mailto:support@acme.io) private here, or is it a public address?\"\n\n🌐 **[mysquint.tech](https://mysquint.tech)**: download for macOS (Apple Silicon and Intel, macOS 14+)\n\nTry it:\n\n`.env` file with ⌃⇧⌘4.\nSquint checks every screenshot you take on your Mac for passwords, API keys, tokens and personal details, and puts a redacted copy on your clipboard. Nothing leaves your Mac text is read with Apple's Vision framework, and Gemma 3 runs locally through Ollama.\n\n`Squint.dmg` and drag Squint into Applications.\nWhen macOS asks whether Squint may access your Desktop, allow it: that's where screenshots are saved.\n\nTake a screenshot as usual (⇧⌘4 to save a file, ⌃⇧⌘4 to copy it). If…\n\nSquint watches two places: the screenshot folder (⇧⌘4) and the clipboard (⌃⇧⌘4).\n\nmacOS's floating thumbnail delays saving the file by a few seconds, so Squint turns it off while it runs and restores your setting when it quits. It does that even if the app is force-killed: the engine notices its parent process is gone and cleans up.\n\nA small Swift helper runs Apple's Vision OCR and returns every line with per-word boxes. It runs on device and takes about 0.3–0.4 s.\n\nRegex rules sort every match into three tiers:\n\n`password = …` assignments, high-entropy strings. These go to Gemma.`<YOUR_API_KEY>`, UUIDs, commit SHAs, dates, `noreply@`. These are dropped.\nEach ambiguous candidate goes to `gemma3:4b` with only the matched text and about one line of context, never the image. The output is constrained by a JSON schema to `{\"sensitive\": true|false}`.\n\nTwo design rules made this safe:\n\nWhy Gemma 3, not Gemma 4? I built and tuned everything on Gemma 3 4B, including the hand-written chat template and the prompt-cache warm up. I haven’t tested Gemma 4 yet. It’s the first thing I’ll try next, and I’ll re-run the same 24-screenshot eval before switching.\n\nMy first version took 3 seconds per screenshot. Here's what fixed it:\n\n`raw` mode with Gemma's chat template written by hand, and warm every slot with the shared prefix at startup. Now only the candidate itself is new work.\nResult: **about 0.36 s per candidate**, and about **1.5 s from screenshot to safe clipboard**. That kind of tuning is only possible because the weights and the runtime are open: I could change the template and the cache behaviour, not just the prompt.\n\nPixelation and blur can sometimes be reversed. Squint first replaces every hidden region with random noise tinted from the surrounding pixels, *then* pixelates it, so nothing of the original survives. A property test checks that two different secrets produce identical redacted pixels.\n\nOCR gives one box per word, and `STRIPE_KEY=sk_live_…` is one \"word\". Squint works out where the value sits inside that word, so the variable name stays readable and only the value is hidden. You can still tell *what* was there, just not *what it was*.\n\nI built an eval set of 24 generated screenshots: `.env` files, YAML, terminals, chat, git logs, dashboards and READMEs, in three fonts, light and dark themes, all with fake secrets. Because I render them myself, I know the exact pixel box of every secret. So the eval checks whether each secret is **fully covered**, not just detected. Five screenshots are held out and never tuned against.\n\n|  | Tuning set (19) | Held-out (5) | \n|---|---|---|\n| Secrets hidden | **100%** (39/39) | 92% (11/12) | \n| Fully covered, no visible edges | **100%** | 92% | \n| Variable names left readable | 100% | 100% | \n| Hidden items that were really secrets | 98% | 79% | \n\nThe eval earned its keep. It caught two bugs where part of a secret stayed visible:\n\n`.` in a JWT as a space, so only half of it was hidden. Squint now joins the pieces.\nRecall on the tuning set went from 74% to 100%. The held-out miss is a JWT in a proportional font that was 95% covered. That's next on the list.\n\nWith Gemma switched off, Squint has to hide every ambiguous match. Across all 24 screenshots:\n\n|  | Regex only | Regex + Gemma | \n|---|---|---|\n| False alarms | 10 | **4** | \n| Secrets hidden | 50 / 51 | 50 / 51 | \n| Extra time | — | about 1 s | \n\nSame recall, less than half the false alarms. Real screenshots are messier than my synthetic ones, and that's exactly where context matters most: `support@` versus a colleague's personal address.\n\n**Because the screenshot is the secret.** A cloud model would be a better OCR engine and a smarter classifier, and it would be useless here. You can't upload a screenshot to someone else's server to ask whether it's safe to upload screenshots to someone else's server. The only honest design is a model that runs where the screenshot already is, and open weights make that possible.\n\n**Because nothing leaves your Mac.** After the one-time model download, Squint makes no network calls except to Ollama on `127.0.0.1`. The review API is bound to localhost and needs a per-run token. There are no accounts, analytics or update checks; the only outside link is the Ollama download page, which the setup window opens in your browser.\n\n**Because it works offline.** On a plane, on a locked-down work laptop, anywhere.\n\n**Because you shouldn't need an API key to protect your API keys.** No account, no subscription, no usage bill. Set it up once and it's free forever.\n\nBefore Squint, a safe screenshot meant: take it, open it, scan every corner, crop or scribble over anything private, then paste. I usually skipped all of that, which is exactly how keys and emails leaked.\n\nWith Squint, the safe path and the lazy path are the same path. Take the screenshot, press ⌘V. About 1.5 seconds later, the clipboard already holds the redacted copy. Zero extra steps, zero new habits, and the check I used to skip now happens every time.", "url": "https://wpnews.pro/news/squint-your-screenshots-have-secrets", "canonical_source": "https://dev.to/sarthak_narula_5789cd042d/squint-your-screenshots-have-secrets-4fd0", "published_at": "2026-10-26 06:39:39+00:00", "updated_at": "2026-10-26 06:42:52.298240+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-tools", "ai-safety", "generative-ai"], "entities": ["Squint", "Gemma 3", "Ollama", "Apple", "Vision framework", "mysquint.tech", "Hacktoberfest"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/squint-your-screenshots-have-secrets", "markdown": "https://wpnews.pro/news/squint-your-screenshots-have-secrets.md", "text": "https://wpnews.pro/news/squint-your-screenshots-have-secrets.txt", "jsonld": "https://wpnews.pro/news/squint-your-screenshots-have-secrets.jsonld"}}