5 releases

Uses new Rust 2024

new 0.2.4 May 14, 2026
0.2.3 May 14, 2026
0.2.2 May 14, 2026
0.2.1 May 14, 2026
0.2.0 May 13, 2026

#251 in macOS and iOS APIs


Used in heddle-cli

Apache-2.0

2MB
41K SLoC

mount

Heddle's content-addressed mount. The crate exposes virtualized threads as a directory tree backed by the object store.

Architecture

PlatformShell trait         ← thin platform adapters
  (FuseShell, FSKitShell)     (one per OS)
        ↓
ContentAddressedMount       ← pure Rust core
        ↓
crates/repo + crates/objects

The trait is in src/shell.rs. The core is in src/core.rs. Each adapter is its own cfg-gated module.

Cargo features

Feature Platform Effect
fuse Linux Compiles fuser and the FuseShell adapter.
fskit macOS Compiles the Swift adapter and the FSKitShell.

Both are off by default. The default build of the workspace runs on every OS and produces a crate with the trait + core only — no mountable shell.

# Linux dev box
cargo build -p mount --features fuse

# macOS dev box
cargo build -p mount --features fskit

macOS install requirements (FSKit)

The FSKit shell needs:

  1. macOS 15.4+ at runtime. The Swift adapter compiles against the 14.0 SDK and weak-links FSKit, so the build works on older SDKs too — but mount_background will fail at runtime on anything below 15.4. Use FSKitShell::is_runtime_available() to probe.

  2. Xcode command line tools (xcode-select --install). The build.rs invokes swiftc to compile swift/HeddleFSKit/HeddleFSKit.swift into a static library. Override the path via HEDDLE_SWIFTC=/path/to/swiftc and the Swift runtime location via HEDDLE_SWIFT_RUNTIME=/path/to/usr/lib/swift/macosx.

  3. The com.apple.developer.fskit.fsmodule entitlement on the binary that loads the FSKit module. Apple gates this entitlement to apps with a paid Developer account; the binary must be code-signed with a provisioning profile that grants it. For distribution, that means a Developer ID certificate + the FSKit entitlement attached to the heddle CLI binary.

  4. A code-signed build. codesign --entitlements heddle.entitlements --sign "Developer ID Application: ..." target/release/heddle. For local development you can self-sign with an ad-hoc identity, but the kernel will refuse to load an FSKit module from an unsigned binary on production macOS configurations.

  5. (Optional) Disable SIP for local development if you want to skip the entitlement requirement. Not recommended; only useful for proof-of-concept work on a dev VM.

Running the FSKit tests locally

The unit tests in src/fskit/mod.rs and the smoke test in tests/fskit_smoke.rs are all #[ignore] by default. To run:

# Unit lifecycle test (no real mount; just constructor + drop)
cargo test -p mount --features fskit fskit::tests -- --ignored

# Full mount smoke test (requires macOS 15.4 + entitlements)
HEDDLE_FSKIT_AVAILABLE=1 \
  cargo test -p mount --features fskit --test fskit_smoke -- --ignored

The integration test will skip itself unless HEDDLE_FSKIT_AVAILABLE=1 is set, so a generic CI runner won't fail on it accidentally.

Status

  • Linux FUSE shell: production. Used by the heddle CLI when --features mount is enabled.
  • macOS FSKit shell: scaffolded. The C ABI between the Swift adapter and the Rust trampolines is wired end-to-end; the PlatformShell dispatch is exercised by the unit test. The FSModuleHost.register(...) step that publishes the volume to the kernel is stubbed — the Swift mount(at:) returns ENOSYS today. Finishing this needs a .fsmodule bundle and the FSKit entitlement, which are release-engineering tasks.
  • Windows ProjFS / CfAPI shell: not started.

CLI integration

The CLI's mount lifecycle (crates/cli/src/cli/commands/mount_lifecycle.rs) currently dispatches through FuseShell only — it's gated on #[cfg(all(target_os = "linux", feature = "mount"))]. Adding FSKit dispatch is a follow-up:

  1. Add a #[cfg(all(target_os = "macos", feature = "mount"))] sibling module that mirrors the existing linux module but uses FSKitShell and FSKitSession.
  2. Re-export MountHandle / spawn_mount_for_thread / unmount_thread_if_mounted from whichever module is compiled in.
  3. Add the fskit feature to the CLI's mount feature propagation in crates/cli/Cargo.toml.

The trait layer means the dispatch site stays one line per backend; nothing in mount_lifecycle.rs's consumer code needs to change.

Dependencies

~59–87MB
~1.5M SLoC