Skip to content
Subfile

FSKit, explained: a real drive in Finder without a kernel extension

For years, mounting a custom volume on macOS meant shipping code into the kernel. FSKit is the reason Subfile does not have to.

4 min readThe Subfile team

When you unlock a vault, Subfile mounts it in Finder as a drive. Not a folder that pretends to be a drive, and not a temporary directory that files get copied into — a real mounted volume with a mount point under /Volumes, which Finder, the Terminal, and any application that can open a file all treat identically. Getting that behaviour on macOS used to be genuinely difficult. FSKit is what changed.

The old answer, and why it was bad

A file system is a translator. The kernel asks questions — list this directory, read these bytes from that file, create an entry here — and something has to answer them. Historically on macOS, that something had to live inside the kernel, as a kernel extension. Kexts are effective and they are also the worst place to put third-party code.

  • A bug in a kext is not a crash, it is a kernel panic. Your whole machine goes down, not one app.
  • A kext runs with no meaningful boundary around it. There is no sandbox in the kernel.
  • Installing one requires user approval, sometimes a reboot, and on Apple silicon a reduction in the machine's security posture. That is a serious thing to ask of someone who just wants to open a file.
  • Kexts cannot be distributed through the Mac App Store, so any app that needed one also needed its own installer, its own updater and its own trust story.

The well-known workaround, macFUSE, is a kernel extension that forwards file system calls out to a userspace process. It works, and a generation of macOS tools were built on it, but it inherits the installation problem: the user still has to install a kext and, on modern hardware, still has to lower the security settings the machine shipped with. For a privacy tool that is a bad opening move. You are asking someone to weaken the operating system as the first step in protecting their files.

What FSKit changes

FSKit is Apple's framework for writing file systems that run entirely in userspace. Your implementation ships as an app extension inside a normal application bundle. macOS launches it as an ordinary sandboxed process, and the system handles the kernel side of the conversation for you. There is no kernel extension to install, nothing to approve at boot, and no reduced-security mode. On macOS 15.4 it became something an app could realistically ship on, and Apple's own FAT support moved onto it — a useful signal that the framework is meant to carry real file systems rather than toys.

The shape of the API is small and mostly what you would guess. Your extension declares itself as a file system module. When the system encounters a resource that might belong to you — a block device, a disk image, a container your app hands over — it probes your module, and you answer whether you recognise the contents. If you do, the system asks you to produce a volume, and from that point on you implement the operations a volume needs: enumerate a directory, look up a name, read a range, write a range, create, rename, remove, report attributes.

runs as
sandboxed userspace app extension
installs via
the containing app — nothing else to approve
failure mode
the extension dies, the Mac keeps running
distribution
Mac App Store, notarized like any app

Why this matters for an encrypted vault specifically

A vault has an awkward requirement: the plaintext must never exist as a file on disk, but it must behave like one. If unlocking meant extracting your files into a temporary folder, you would have a copy of everything in the clear, subject to Spotlight indexing, backup, and whatever the operating system decides to do with a directory it can see. That is not an encrypted vault. That is a zip file with extra steps.

A real file system solves this because the plaintext only ever exists in response to a specific request. An application asks for a range of bytes, the file system decrypts that range in memory, hands it back, and forgets it. Writes go the other way: encrypted before they are ever handed to the carrier file. Nothing is staged in the clear because there is no staging area.

FSKit is what makes that architecture available to a sandboxed, App Store-distributed app. Before it, you could have the correct design or a reasonable installation experience, but not both.

The trade-offs, honestly

Userspace file systems cross a process boundary for work that in-kernel code does inline, and that costs something. For the workload a vault sees — documents, archives, scans, project files, opened and saved by hand — the cost is not where you notice it. For workloads that hammer a volume with very small operations in a tight loop, a userspace file system will not match a native one, and it would be dishonest to pretend otherwise.

The other constraint is the floor it puts under the product. FSKit requires a recent macOS, which is a real limitation for anyone on older hardware or holding back on updates. We would rather have that limitation than ask you to install a kernel extension. A tool whose first instruction is to weaken your machine's defences has already lost the argument it is trying to make.

/Volumes/PRIVATE mounted · userspace · no kext · no reboot

next

Choosing a carrier file: why video beats photos for large vaults

A photo makes the better demo. A video makes the better vault. The difference is entirely about what size looks normal.

5 min read

An ordinary file. A private drive inside.

Subfile writes an encrypted volume into a file you already have and mounts it in Finder. Offline, no account, macOS.

See how it works