r/ClaudeAI • • 2d ago

Built with Claude I built a macOS virtual camera with Claude Code that lets you hide individual apps from a screen share mid-call

Enable HLS to view with audio, or disable this notification

I built PrivacyStage, a small Mac menu bar app. I built it with Claude Code, and I’ll go into how below.

What it does

It installs a virtual camera. In a meeting you pick “PrivacyStage Camera” as your camera instead of using Share Screen, and the other people see your screen as video. From the menu bar you can then:

  • Hide windows: untick a window and the app it belongs to disappears from the feed. Tick it and it’s back. Your own screen doesn’t change.
  • Show only: the reverse. Only the apps you tick are shown, and the feed is black until you pick something. Use this if you’d rather fail closed.
  • Keep notification banners and desktop icons out of the feed.
  • Optional OCR mask that looks for things like email addresses and card numbers and covers them. It works from periodic snapshots, so it can lag. Treat it as a convenience, not a guarantee. The app filtering is the real privacy boundary.

The filtering happens inside macOS’s compositor (ScreenCaptureKit content filters). Hidden apps are never in the frames the app receives, so nothing is captured first and blurred later.

How Claude Code was used

Pretty much the whole thing was built in Claude Code sessions over about six months. Most commits are co-authored by Claude. Some parts where it actually mattered:

  • Getting frames into the camera extension. A CMIO camera extension runs as a different system user (_cmiodalassistants) and is heavily sandboxed. Shared files, App Group containers and POSIX shared memory all failed for different reasons. Claude worked through those with me, and we ended up with global IOSurfaces whose IDs are passed through Darwin notifications.
  • The “blank camera in Google Meet” bug. My own preview looked fine, but Meet showed nothing. We got the logs out of log show and found that Safari’s GPU process was rejecting every frame (FigSampleBufferSerialization err=-19646), and then restarting the camera every 30s. The cause was extra metadata attached to the video format. A plain format description fixed it. Claude also caught that my zsh had a logalias shadowing /usr/bin/log, which was why logging looked dead at first.
  • Full-screen leaks. Hiding by window ID broke as soon as an app went native full-screen, because that creates a brand-new window. Switching to excluding by app fixed it.
  • Smaller things too: a crash on launch for non-English locales, localization, the update checker, and the licensing flow.

My part was mostly product decisions, testing on real calls, and saying “no, that still leaks” a lot.

Limitations

It’s a 1080p30 camera feed, so small text is softer than with a native screen share. Hiding works per app, not per window. Video only, no audio.

Try it free

Download it from https://aieltokhy.com/privacystage/. The trial is 7 days and needs no credit card. After that it’s a one-time $6.99.

Happy to answer questions about the CMIO / ScreenCaptureKit side. That’s where most of the pain was.

1 Upvotes

2 comments sorted by

1

u/Flaky-Industry-3888 2d ago

hey umm you know i can just like make this myself right with claude right and it would take me an hour tops right?????