Build FUSE userspace filesystems on the BEAM.
Wick has two layers and deliberately stops there — it does not impose a filesystem abstraction. You drive the protocol loop yourself; the Writing a filesystem guide walks through a complete read-only example.
Transport
Wick.Native— opens/dev/fuse, armsenif_selectreadiness notifications, and does boundedread_frame/1/write_frame/2of protocol frames.Wick.Fusermount— mounts and unmounts via the setuidfusermount3helper.
Codec
Wick.Protocol— a pure-Elixir codec for the Linux FUSE kernel protocol (FUSE_KERNEL_VERSION 7.31).decode_request/1turns a kernel frame into an opcode, aWick.Protocol.InHeader, and a request struct;encode_response/3builds the reply frame.
The request/response loop
A FUSE server is an event loop over a single mounted fd:
Wick.Fusermount.mount/2returns a handle.Wick.Native.select_read/1arms one read-readiness notification; the owning process then receives{:select, handle, :undefined, :ready_input}when a request is waiting.Wick.Native.read_frame/1reads one request frame.Wick.Protocol.decode_request/1decodes it.- You build a reply and write it with
Wick.Protocol.encode_response/3andWick.Native.write_frame/2(orWick.Protocol.encode_error/2for an errno). - Re-arm with
select_read/1and repeat — the notification is one-shot.
The INIT handshake
The kernel's first request after a mount is :init, and nothing
else works until you answer it with a Wick.Protocol.Response.Init
carrying a compatible version (clamp the minor to 31) and your
negotiated max_write. See the guide for the full handshake.
Linux only
The transport binds the Linux FUSE ABI, so Wick.Native and
Wick.Fusermount only run on Linux. Wick.Protocol is pure
Elixir and runs anywhere.