Files
Jamie Pine 61dea60558 CI green on sources: runner toolchain, clippy, typecheck, tests compile (#3102)
* ci: install rustfmt and clippy components on every runner

Self-hosted runners have rustc preinstalled, so setup-rust skipped the
dtolnay/rust-toolchain step that added the components and the Rust
Formatting job died with 'cargo-fmt is not installed'. Add the components
to rust-toolchain.toml and run rustup component add unconditionally.

* setup: install FFmpeg development libraries on Linux and macOS

crates/ffmpeg is a default workspace member that links libav* through
ffmpeg-sys-next, so a fresh machine fails the first cargo build with
'libavutil.pc not found'. Install the libav dev packages and pkg-config
from scripts/setup.sh for every supported package manager, warn from
xtask setup when pkg-config cannot find them, and document the requirement
in the README build section.

* test: call the trash directly in delete_strategy_test

bcc7337 gave LocalDeleteStrategy::move_to_trash a JobContext parameter so
it can record where the item went; the integration test still passed one
argument and stopped every cargo test target from compiling. The two trash
cases now call ops::files::trash::trash with the same arguments the
strategy forwards, which is what they were asserting on.

* interface: clear the 30 Tauri typecheck errors

Remove the 23 unused imports and locals, apply the rename rules' serde
defaults (regex and whole_name false, start and step 1) where the modal
renders optional fields, drop the size prop ToggleGroup never accepted,
and type SourceCard on ts-client's SourceInfo so a filesystem source with
no adapter renders its data type instead. Register the /redundancy/duplicates
route the dashboard already navigates to, which is what the DuplicatesView
import was for.

* clippy: make cargo clippy --workspace -D warnings pass on Linux

sd-store names its sqlx row tuples with type aliases. sd-ffmpeg converts
with try_from and f32::from where the cast was lossless, takes raw
borrows for FFI out-pointers, resamples from an integer position, and
allows the pointer-alignment and s32-to-f32 precision casts with the
reason. sd-mobile-core sets DaemonRequest.device (None, local execution)
on the two envelopes it builds. file-opening-macos and file-opening-windows
pull their platform bindings only on that target and gate their sources,
matching sd-desktop-macos. The Tauri build script drops externalBin from
the config when no daemon sidecar exists, so a check or clippy run that
never built the daemon still passes, and the desktop binary's macOS-only
commands return on other hosts without unreachable code. Workspace
rust-version moves to 1.95, the floor gpui already imposes, so the MSRV
lint stops flagging APIs the pinned 1.97.1 toolchain uses.

* docs: make the stale doctests compile

sd-media-metadata examples still imported from the old image module and
asserted a plus code that belonged to the other example's coordinates (the
value is verified against the reference Open Location Code encoder);
MediaLocation has no Display, so the parse example compares coordinates.
The sd-task-system example unwraps dispatch and matches the (TaskId,
TaskOutput) pair Done now carries. The spacedrive-sdk sketch names types
that do not exist yet and the job-derive expansion only resolves inside
sd-core, so both are marked ignore with the reason beside them.

* build: pin bun to 1.3.4 everywhere

package.json said bun@1.3.0 while CI installed 1.3.4, and any newer bun
rewrites bun.lockb on install, so the lockfile churned on every machine.
Pin packageManager to the CI version, document it, and install with
--frozen-lockfile in the TypeScript job so a drifting lockfile fails
instead of being silently rewritten.

* status: register the CI green on sources work and the libav requirement

* docs: make the sd-core doctests compile too

Five sd-core examples referenced the crate by its old name, used an arrow
glyph in a rust fence, or called methods without the trait in scope; the
copy strategy sketch needs a running JobContext so it is marked ignore.

* ci: stop shrinking the runner's root disk before installing a toolchain

easimon/maximize-build-space moves the root filesystem's free space into an
LVM volume mounted at the workspace and leaves root with the reserve, which
on the Blacksmith runner came out at 100 MB after the swap file. rustup
installs the pinned 1.97.1 toolchain under /home/runner/.rustup on root, so
both Rust jobs died with 'No space left on device'. The runner has 82 GB
free on root, which is plenty for a clippy target directory, so the step
goes.

* ci: run clippy on the Ubuntu 24.04 Blacksmith runner; let sd-server check without bun

The Blacksmith migration wrote the runner label into the matrix's target
field and left runs-on at GitHub's ubuntu-22.04, whose FFmpeg 4.4 predates
the libav 6 API sd-ffmpeg uses (ch_layout, av_dict_iterate), so the job
could never compile sd-ffmpeg. It now runs on blacksmith-4vcpu-ubuntu-2404
with FFmpeg 6.1, the same as a developer machine on 24.04, and the target
field holds a target triple again.

sd-server's build script skipped the web build when bun was absent and
RustEmbed then failed on the missing apps/web/dist. A debug build now gets
an empty dist with a warning so check and clippy pass; a release build
without bun and without a prebuilt dist still refuses, so a server never
ships without its UI by accident.

* build: let the desktop crate compile without a built frontend

tauri::generate_context! panics when frontendDist is missing, which is how
every check or clippy run looks before bun run build. The build script now
creates an empty apps/tauri/dist for debug builds with a warning; a release
build without one still refuses.

* status: record the CI result for the sources green-up
2026-10-04 20:15:07 +00:00

12 KiB

Spacedrive

Spacedrive

Your data should not have to live on somebody else's computer to be useful.

Apache-2.0 license Rust and TypeScript Spacedrive Discord

Download • Docs • Discord • Build from source


Important

Spacedrive 2.0 Beta is planned for October 1, 2026.

Beta commits to Spacedrive's data model and to preserving your library as it evolves. The release makes self-owned storage practical across your devices. It brings portable source indexes, private remote access, mounts, history, extensions, and one API for people and software. Current builds.

Spacedrive is open personal data infrastructure. It turns the storage you control into one private filesystem across your devices, drives, servers, and the clouds you choose.

Bring your data home without giving up search, protection, intelligence, sharing, or access from anywhere. No hosted account, no vendor control plane, no telemetry.

Spacedrive browsing files across devices and locations

Own where your data lives

Cloud services made it feel normal for your files to live on someone else's computer. Personal files and behavioral data piled up on infrastructure whose security, policies, and future you do not control. Automated attacks increase the scale of that exposure. AI increases the value of accumulated data for training, inference, and profiling.

Owning the drive is the easy part. You still need to find files, reach them from another device, know what is backed up, recover earlier states, share on your terms, and notice when something changes.

Spacedrive does all of that while you decide where the bytes and metadata live. Local disks, removable media, NAS datasets, private servers, and offline archives are first-class homes. Cloud services remain optional sources and destinations.

Read the Product Direction for the complete product boundary.

One filesystem, every source

A source can be a folder, a complete drive, a dataset on your NAS, another Spacedrive node, a cloud bucket, or an external service. Every source uses the same record shape and the same operations.

Each source has a portable store with two kinds of knowledge: a generation that can be refreshed while the origin is available, and durable assertions that cannot be reconstructed from the files alone. Disconnect a drive and its catalog remains searchable. Move a source to another machine and its metadata can travel with it.

  • A live index. Watchers keep names, sizes, timestamps, and content state current, so opening a folder never rescans the disk.
  • Search across boundaries. One search runs across local, remote, cloud, and adapter sources.
  • Stable identity. Records survive moves. BLAKE3 content identities connect copies of the same bytes across sources and devices.
  • Fast duplicate detection. Sampled hashes find candidates quickly. Full-byte verification confirms equality before destructive cleanup.
  • History that stays useful. Freeze a source at a point in time, browse an offline snapshot, and inspect which operation changed it.
  • Provider exit. Move data away from a service without losing the organization, tags, history, and knowledge built around it.

Protection is part of the filesystem

Keeping files safe is filesystem work.

  • Track integrity, redundancy, backup state, capacity, and unexpected changes.
  • Distinguish independent copies using physical drives, pools, and failure domains.
  • Keep an inventory of drives that are offline, archived, lost, or retired.
  • Preserve unreadable records with their error instead of omitting them.
  • Run indexing, metadata extraction, previews, and search on infrastructure you control by default.
  • Name every external recipient before file content or derived metadata leaves your devices.

An index snapshot preserves evidence about the filesystem. Provider versions and backups preserve the bytes. Spacedrive connects the two so you can understand what existed, where it lived, and how to recover it.

See every change before it happens

The everyday threat to your files is an operation: a copy that overwrites the wrong folder, a cleanup that deletes the last copy, a merge that lands somewhere unintended. A durable filesystem protects your files from its own operations.

Every operation that changes files answers two questions before it runs. Validation answers whether it may run and how: permissions, capacity, safety rules, and the exact strategy, enforced by the daemon rather than the dialog. Preview answers what will exist afterward, projected from the index without touching a file.

  • Browse the result before it exists. A preview serves the same listings as the present filesystem, so you walk the outcome folder by folder before a byte moves.
  • Plan against offline storage. The index answers for a drive sitting in a drawer, so you can prepare a merge before you plug anything in.
  • Get warnings only an indexed filesystem can give. Three of these files are the last copy of their content anywhere in your library.
  • Skip duplicates on proof. A file is treated as a copy only after full-byte verification, never on a sampled hash.
  • Trust the execution. The daemon re-validates at dispatch, applies the same policy against the live filesystem, and reports any divergence from the plan.

Access anything from anywhere

Pair Spacedrive nodes to browse and operate their authorized sources through the same interface. A live node serves queries, snapshots, byte ranges, jobs, and logs. Other nodes can cache projections and content without claiming authority over the source.

Share a source or subtree with another person, device, or agent without merging libraries. The host decides what the recipient can see and do. The grant stays visible and revocable, while the recipient sees the shared data beside their own sources.

Mount any source or subtree into macOS, Windows, or Linux. Files stream on demand from a local disk, another device, or a cloud provider through one byte plane. Range reads power mounts, transfers, previews, media playback, and video scrubbing without copying the whole file first.

Peer connections use Iroh and QUIC with end-to-end encryption. Devices connect directly when they can and fall back to relays when they must.

One API for people and software

The desktop app, web interface, mobile clients, CLI, generated SDKs, skills, and MCP server all call the same registered operations. A copy has the same input, progress, conflicts, and result whether a person clicks it or software invokes it.

  • Operations return structured data and stable identifiers.
  • Validate, preview, and execute are the same three verbs for every operation and every client.
  • Long-running work becomes a durable job with progress, cancellation, restart recovery, and logs.
  • Remote clients can inspect the same job state through an authorized session.
  • Capabilities are explicit, scoped, visible, and revocable.

Spacedrive does not bundle an agent or choose a model for you. Use the CLI, skill, SDK, or MCP server with the agent you trust. Your agent gains a consistent filesystem interface without becoming the owner of your data. An agent validates first, shows you the plan, and commits the exact input it previewed. That is what makes destructive file operations safe to delegate.

Extend the filesystem

The default installation stays small. Extensions add specialized support only when you need it.

An extension can contribute:

  • A source adapter or storage backend.
  • File recognition through extensions, MIME types, UTTypes, magic bytes, and provider metadata.
  • Typed metadata and search fields.
  • Preview renderers, thumbnails, proxies, video thumbstrips, and persistent sidecars.
  • Registered jobs, actions, menus, settings, and focused views.

Platform bridges can discover handlers already registered with macOS, Windows, and Linux. Heavy codecs, provider SDKs, and models remain outside the default binary. Extensions install from explicit packages and declare the access they need.

Architecture

flowchart TB
    people[Desktop, web, mobile, CLI]
    software[SDKs, skills, MCP]
    operations[Typed operation registry]
    daemon[Spacedrive daemon]
    stores[Source stores, history, jobs]
    local[Local drives and NAS]
    remote[Remote Spacedrive nodes]
    cloud[Cloud providers]
    adapters[Adapters and extensions]

    people --> operations
    software --> operations
    operations --> daemon
    daemon --> stores
    daemon --> local
    daemon --> remote
    daemon --> cloud
    daemon --> adapters

The Rust daemon owns filesystem identity, indexing, operations, policy, and durable work. Clients connect through JSON-RPC over local sockets or WebSockets. Network protocols use Iroh and QUIC. OpenDAL provides cloud storage backends. SQLite gives each source a portable store and FTS5 index.

Core operations are registered at compile time with type-safe inputs and outputs. Specta generates the TypeScript and Swift clients from those Rust types, so every interface shares one contract.

Build from source

You need Rust 1.95 or newer (rust-toolchain.toml pins 1.97.1), Bun 1.3.4 (the version package.json and CI pin; a newer Bun rewrites bun.lockb), Node 20, and just.

git clone https://github.com/spacedriveapp/spacedrive
cd spacedrive

# Installs system dependencies on macOS, Linux, or Windows.
./scripts/setup.sh              # .\scripts\setup.ps1 on Windows

bun install
cargo run -p xtask -- setup

Run the daemon and your preferred client:

just dev-daemon     # Rust daemon
just dev-desktop    # Desktop client
just dev-server     # Headless server and web interface
just dev-mobile     # Mobile client

The sd-ffmpeg crate is a default workspace member and links the FFmpeg development libraries installed on the host (libavutil, libavformat, libavcodec, libavfilter, libavdevice, libswscale, libswresample) and uses libclang to generate its bindings. scripts/setup.sh installs them (libav*-dev and libclang-dev on Debian and Ubuntu, ffmpeg on Homebrew). Without them the first cargo build fails in ffmpeg-sys-next with libavutil.pc not found.

The default build can use FFmpeg installed on the host for video thumbnails and thumbstrips. Install the native codec bundle only when developing code that links the optional FFmpeg, libheif, or Pdfium libraries:

cargo run -p xtask -- setup --native-deps

Run the checks before submitting a change:

just test
just check

See the documentation for deployment, source, extension, and architecture guides.

Project history

Spacedrive began in 2021 as one interface over files scattered across devices and cloud accounts. The first public version proved the demand and exposed the cost of carrying two file models, fragile transfers, and too much product in the default build.

V2 rebuilds the project around sources, portable stores, durable jobs, and one typed operation surface. Read the project history for the full account.

Contributing

License

Apache-2.0.

Releases before 2026-03-24 were published under AGPL-3.0 and remain available under that license.