macOS has Screen Sharing built in and it works beautifully. You can reach your Mac from anywhere and drive it like you’re sitting there.
It leaves one gap. When you remote in, anyone at the physical desk sees everything on your screen and can move the mouse or type into your apps while you work. For a machine in a shared office, a lab, or a house with other people in it, that’s a real problem.
Why the obvious fix doesn’t work
Cover the local displays and ignore physical input. Simple enough, except your laptop and the desk share one login session. A naive overlay blocks you too, and then you’ve locked yourself out of your own machine from across the country.
That’s the actual engineering problem, and it’s why this isn’t just a black window.
Filtering by event source
The trick is that macOS tells you where an input event came from.
Events injected by Screen Sharing carry a different source identity than events generated by physical hardware at the desk. So you don’t block input, you block input by origin: drop events from the local hardware, pass injected remote events through untouched.
That one distinction is the whole product. It’s why Curtain needs no virtual display, no second user account, and no kernel extension. I looked at all three of those first. Every one is heavier, more fragile, and asks the user for more trust.
Detection works similarly. Rather than hardcoding assumptions about a particular remote protocol, it keys off a transport-independent capture flag plus the network signals Screen Sharing leaves behind. Transport-independent matters because it means the thing doesn’t break when Apple changes the implementation underneath.
The escape hatch is not optional
There’s a Carbon hotkey for emergency unlock, and it works even if you haven’t granted Accessibility permissions yet.
That’s deliberate and it’s the part I’d argue about if someone wanted to cut it. A security tool whose failure mode is locking the owner out of their own hardware is worse than no tool. Any mechanism that blocks input needs an unblock path that can’t itself be blocked, including during the window before setup is complete. Getting that ordering right was more of the work than the filtering was.
Why it’s free
This capability exists commercially. It tends to sit in the pricier tiers of paid remote-desktop suites.
Paying real money for one small, well-understood feature felt wrong when the hard ninety percent, the actual screen sharing, is already free and built into the OS. The gap is a hundred lines of event filtering, not a product.
First working version came together in about ninety minutes on June 1. A few days of polish followed, but the core was an afternoon.
The speed is a function of scope discipline rather than heroics. The problem had exactly one hard part, distinguishing event origin, and the operating system already provided everything else. Most of the engineering was deciding what not to build: no virtual display, no second account, no kernel extension, no reimplementation of screen sharing. The same instinct that keeps nSelf a thin orchestration layer over Docker rather than a container runtime of its own.
It’s a small Swift menu-bar agent, open source, and it exists so nobody has to pay rent on a feature the operating system almost already has.