Sidebar lists indexed drives including detached ones, volume rows and overview
cards carry persisted entry counts, and the explorer gains a list view over
daemon ops with event-driven refresh.
- Add SHARE-000..011 task specs and docs/design/shares.md defining
the sd.app public sharing architecture and wire protocols
- Rework INDEX-010 to scope ephemeral UUID reconciliation per-library
instead of a single global map, since core can have multiple
libraries loaded at once
- Add sidecar serving and configurable bind host to apps/server, and
wire the web platform's daemon status to the server's own origin
- Add quick preview button to the file inspector, with a null-safe
useOptionalExplorer for use outside the explorer context
* feat: add redundancy awareness & cross-volume file comparison
Surface content redundancy data so users can answer "if this drive dies,
what do I lose?" — builds on existing content identity and volume systems.
Backend:
- New `redundancy.summary` library query with per-volume at-risk vs
redundant byte/file counts and a library-wide replication score
- Extend `SearchFilters` with `at_risk`, `on_volumes`, `not_on_volumes`,
`min_volume_count`, `max_volume_count` filters
- Add composite index migration on entries(content_id, volume_id)
Frontend:
- `/redundancy` dashboard with replication score, volume bars, at-risk callout
- `/redundancy/at-risk` paginated file list sorted by size
- `/redundancy/compare` two-volume comparison (unique/shared toggle)
- Sidebar ShieldCheck button linking to redundancy view
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* redundancy UI improvements + ZFS volume detection fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix ZFS pool capacity reporting and stats filtering
- ZFS: override total_capacity for pool-root volumes using zfs list
used+available. df under-reports pool-root Size because it only
counts the root dataset's own used bytes plus avail — on a 60 TB
raidz2 pool this shows as ~15 TB instead of ~62 TB. The pool root's
own used property includes descendants, so used+available is the
real usable capacity.
- Library stats: drop volumes where is_user_visible=false AND
re-apply should_hide_by_mount_path retroactively so stale DB rows
(detected before the Linux visibility filters existed) don't
inflate reported capacity.
- Extract should_hide_by_mount_path into volume/utils as a shared
helper used by both the list query and the stats calculation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* show capacity and visibility in sd volume list
Makes it possible to verify library-level capacity aggregation from
the CLI — previously the list only showed mount, fingerprint, and
tracked/mounted state, which meant debugging the ZFS pool capacity
issue required querying the library DB directly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* document filesystem support matrix and detection
New docs/core/filesystems.mdx covering per-filesystem capabilities
(CoW, pool-awareness, visibility filtering, capacity correction),
platform detection strategies, the FilesystemHandler trait, Linux/
macOS/ZFS visibility rules, the ZFS pool-root capacity problem and
fix, copy strategy selection, and known limitations.
Registered under File Management in both mint.json and docs.json.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* WIP: redundancy filter wiring across search, CLI, and UI
- core/src/ops/search: wire redundancy filters (at_risk, on_volumes,
not_on_volumes, min/max volume_count) through the search query;
fix UUID-to-SQLite BLOB literal so volume UUID comparisons actually
match (volumes.uuid is stored as a 16-byte BLOB, quoted-string
comparison silently returned zero rows).
- apps/cli: new redundancy subcommand + populate the new
SearchFilters fields from search args.
- packages/interface: redundancy at-risk and compare pages reworked
to consume the new filter surface; explorer context/hook updates
to support redundancy-scoped views.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* add web context menu renderer and UI polish
- New WebContextMenuProvider + Radix DropdownMenu-based renderer anchored
at cursor via a 1x1 virtual trigger. Handles separators, submenus,
disabled, and the danger variant via text-status-error.
- useContextMenu now routes web clicks through the provider instead of
parking data in unused local state, and trims leading/trailing/adjacent
separators so condition-filtered menus don't render orphaned lines.
- Drop app-frame corner rounding on the web build.
- Add shrink-0 to the sidebar space switcher so the scrollable sibling
can't compress it vertically.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* sd-server dev workflow: auto web build, shutdown watchdog, stable data dir
- build.rs runs `bun run build` in apps/web so `just dev-server` always
embeds the latest UI. rerun-if-changed covers apps/web/src,
packages/interface/src, and packages/ts-client/src so Rust-only edits
skip the rebuild. Skips gracefully when bun isn't on PATH or
SD_SKIP_WEB_BUILD is set; Dockerfile sets the latter since dist is
pre-built and bun isn't in the Rust stage.
- Graceful shutdown was hanging because the browser holds the /events
SSE stream open forever and axum waits for all connections to drain.
After the first signal, arm a background force-exit on second Ctrl+C
or 5s timeout so the process can't stick.
- Debug builds were starting from a fresh tempfile::tempdir() on every
run (the TempDir handle dropped at end of the closure, deleting the
dir we just took a path to). Default to ~/.spacedrive in debug so data
persists and `just dev-server` shares a data dir with the Tauri app.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* add Sources space item alongside Redundancy in default library layout
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* add TrueNAS native build script
Uses zig cc as C/C++ compiler on TrueNAS Scale where /usr is
read-only and no system gcc exists. Dev tools live at
/mnt/pool/dev-tools/ (zig, cmake, make, extracted deb headers).
Builds sd-server + sd-cli in ~4 min on a 12-core NAS. AI feature
disabled (whisper.cpp C11 atomics incompatible with zig clang-18).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* never block RPC on synchronous statistics calculation
On first load (fresh library, all stats zero), libraries.info used
to calculate statistics synchronously before responding. On large
libraries during active indexing this hangs indefinitely — the
closure-table walk in calculate_file_statistics loads every
descendant ID into a Vec then issues a WHERE IN(...) with millions
of entries, which SQLite can't finish while the indexer is writing.
Now always return cached (possibly zero) stats and let the
background recalculate_statistics task fill them in. The UI
refreshes via the ResourceChanged event when the calculation
completes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* self-heal protocol handler registration on re-init
Core::new() registers default protocol handlers after starting networking,
but swallows any failure (error is only logged). If the initial registration
fails — e.g. on a host where start_networking hasn't fully set up the event
loop command sender by the time register_default_protocol_handlers runs —
the registry is left empty. A subsequent call to Core::init_networking()
would see `services.networking().is_some()` and skip re-registration,
permanently leaving protocols unregistered for the life of the process.
sd-server calls init_networking() right after Core::new(), so it's the
client most exposed to this. Symptom: pairing over the web UI returns
"Pairing protocol not registered" while the same library works fine
from Tauri and mobile.
Fix: init_networking now queries the registry directly for the pairing
handler and re-registers the default set if it's missing, independent of
whether networking is already initialized.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fall back to pkarr+DNS discovery when mDNS port is unavailable
Iroh's endpoint.bind() fails wholesale if any configured discovery service
fails to initialize. MdnsDiscovery requires binding UDP :5353, which on
most Linux systems (including TrueNAS) is already owned by avahi-daemon.
Result: endpoint creation errors out with "Service 'mdns' error", the
event loop never starts, command_sender stays None, and protocol
registration fails — so sd-server has no working networking at all.
Make mDNS best-effort: on any error whose message mentions "mdns",
retry endpoint creation with only pkarr + DNS discovery. Local-network
auto-discovery is lost but remote pairing via node ID (which uses n0's
DNS infrastructure, not mDNS) continues to work normally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* succeed pairing if either mDNS or relay discovery wins
The dual-path discovery in start_pairing_as_joiner_with_code used
tokio::select! to race mDNS and relay. select! resolves on the first
branch to complete — including errors — so a host that can't bind
mDNS (e.g. a Linux box where avahi already owns UDP :5353) would fail
pairing wholesale: mDNS discovery errors out in <1ms with
"Failed to create mDNS discovery: Service 'mdns' error", that Err
wins the race, and relay discovery gets cancelled before it can even
begin.
Switch to futures::select_ok so we only return the error if EVERY
discovery path has failed. mDNS failing immediately now leaves relay
running to completion, which is the common case for remote pairing
into a NAS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- cargo fmt across all modified files
- Add Vite client types and Window.__SPACEDRIVE__ declaration
- Fix @sd/interface/platform import to @sd/interface
- Align @types/react versions between tauri and interface packages
- Remove unused imports/vars in useDropZone, DragOverlay, ContextMenuWindow
- Fix WebviewWindow.location references to use globalThis
- Exclude updater.example.ts from typecheck
- Simplified the timeout handling in `is_daemon_running` for better readability.
- Updated type definitions in the macOS Tauri library for clarity.
- Reformatted JSON configuration for better structure and readability.
- Changed function signatures in `files.rs` and `server.rs` to use `Path` instead of `PathBuf` for consistency.
- Enhanced error handling and argument passing in various functions for improved clarity.
- Added `#[allow(dead_code)]` annotations to unused functions in several modules to suppress warnings.
- Improved the display string methods in `volume.rs` and `pairing/types.rs` for better performance and clarity.
- Introduce an Axum-based HTTP server with an embedded daemon and a
JSON-RPC proxy to the daemon via a Unix socket - Bundle web UI assets
into the server with an assets feature and a build.rs that builds the
frontend using pnpm - Add multi-stage Dockerfile, docker-compose.yml,
and a Distroless runtime image - Provide TrueNAS deployment support with
a build script and setup guide - Add a new web UI (apps/web) with a
Vite-based dev/build flow and a web platform shim for the frontend -
Implement server logic (apps/server/src/main.rs): health, auth, /rpc
proxy and data-dir/socket-path wiring - Include server-specific
Cargo.toml and a comprehensive server README - Add architecture and
memory-focused docs to guide usage and design - Minor core tweak:
simplify location/resource event emission in
core/src/location/manager.rs to align with new flow - Tauri app: adjust
menus to add an Edit submenu and remove unused items
* Update rspc, prisma-client-rust, axum and tanstack-query
- Deleted some unused examples and fully commented out frontend code
- Implement many changes required due to the updates
- Update most rust dependencies
* Re-enable p2p
* Fix server
* Auto format
* Fix injected script format
- Update some github actions
- Update pnpm lock file
* Fix devtools showing up when app opens
- Fix million complaining about Sparkles component
* Fix sd-server
* Fix and improve thumbnails rendering
- Fix core always saying a new thumbnail was generated even for files that it skiped thumbnail generation
- Rewrite FileThumb and improve related components
* Ignore tmp files when running prettier
* Improve FileThumb component performance
- Rework useExplorerDraggable and useExplorerItemData hooks due to reduce unecessary re-renders
* More fixes for thumb component
- A couple of minor performance improvements to frontend code
* auto format
* Fix Thumbnail and QuickPreview
* Fix logic for when to show 'fail to load original' error message in QuickPreview
- Updated prisma-client-rust, libp2p, tauri, tauri-specta, rspc and hyper
* Fix type checking
- Format scripts
* Add script prettier config
* Fix serde missing feature
- Use rust-libp2p spacedrive fork again
- Update rspc
* Autoformat + fix pnpm lock
* Fix thumbnail first load again
* Autoformat
* autoformat
* Fix rust-libp2p fork url again?
* Remove usePathsInfiniteQuery hook
* Update tauri 2.0.6
* Basic cypress test
* Add e2e test command
* Add full e2e test for creating and deleting a library
* Add cypress to CI
* Fix cypress CI
- Use arm macos for running cypress
- Setup rust on cypress job
- Increase cypress CI timeout
* Remove unused APPLE_SIGNING_IDENTITY envvar
* Update deps again + Try to fix Cypress CI setup
* Update deps again
* Only test default location if it exists
* Use latest v18 NodeJS in CI
* Increase minimum node version due to updated dependency
- @typescript-eslint/eslint-plugin now requires node >=18.18
* Fix testing failing for optional default locations
* Enable video recording
- Fix screenshot and video artifact uploading
* Fix location test
- Use correct location name, instead of trying to derive it from the internal id
* fix: wait until libraries have loaded before checking the count
* fix: include new core version in lockfile
* fix: moved value
* fix: check the `libraries/` data dir manually
* Clear localstorage via localStoarge.clear() (#2040)
only clear localstorage in desktop using js
---------
Co-authored-by: Brendan Allan <brendonovich@outlook.com>
* feat: clear localstorage on start if no libraries are found
* chore: add a check to see if the node is for desktop or server use
this will prevent desktop/app localstorage from being cleared if it's a server being hosted
* fix: add secondary localstorage directory for macos
for some reason the app/onboarding progress is kept in `Library/WebKit/Spacedrive` (at least in dev?) so it also needs clearing
* feat: delete cache directories also
* chore: iterate over paths
* feat: add support for windows `localStorage` by using `data_local_dir`
* docs/style: better comments and logs
* feat: remove both `AppData` local and roaming on Windows
* fix: mobile builds
* chore: tweak error message for windows
* Drop Tauri custom URI handler
Me no likely but it has to be done.
* fix app startup with location
* fix "Add Location" button on web
* Serve correct content range
* Backport changes from a670d5a0
* none of my homies like panics
* minor fixes
* fmt with new Rust version
* fix `spacedrive://` custom protocol on Windows
(hopefully)
* custom protocol using `http::Response` + fix broken web
* import patches before App on web
* use `http::Request` for input to `handle_custom_uri`
* break into dedicated file + error handling
* serving files via custom protocol
* cargo fmt because vscode did cringe
* lru cache to reduce video chunk request time
* add helper to JS
* clippy be like
* remove duplicate Open buttons in context menu
* fix Linux 🙏
* no shot
* fix Windows custom URI passing (hopefully)
* better fix for custom uri on Linux
* upgrade Tauri for feature
* switch url replacement order
* prevent React dev tools script being added in prod to desktop
* remove React devtools from html
* upgrade Tauri; required upgrading rspc, Axum, PCR
* pass typecheck + less cringe bigint
* clippy is love, clippy is life
* Typecheck plz
* fix bigint to number conversion
* use httpz + localhost server for Linux
* clippy be right
* Remove console.log
* [wip] proper auth
* fix Linux sidebar padding
* Secure Axum server with random
* Extracting app setup specific to linux to a different file
* remove outdated comment
* Some tweaks on cursom_uri.rs
* file_path_with_location doesn't need to be a named include
* fix typo
* factually wrong comment
* Change `unwrap` to `expect`
* bruh
---------
Co-authored-by: Ericson Soares <ericson.ds999@gmail.com>
* Introducing location online/offline checks and location relink
* Some initial drafts for location watchers
* Location metadata relink and add library
* Many improvements at job system
Now using prisma batching at identifier job
Removing blocking I/O from extension subcrate
Implementing lazy generation of thumbnails
New current directory identifier job to be used on light rescans
* Some optimizations on identifier and object validator jobs
* merge jamie's identifier PR
* fully repaired identifier job
* properly hooked up object kind
* inspector fix
* fix video badge
* small improvements to libraries settings
* identifier and inspector improvements
* fix feature flags and hook up context menu location utilities
* BETTER CONTEXT MENU x100
* test-files
* style tweaks
* new icon designs
* manifest
* fix thumbnails on web
* media data
* New Location Watcher and some minor fixes
* disable broken media_data extractor, wip
* wip
* function name fix
* Fixing pnpm prep and some warnings
* Solving a race condition beetween indexer job and FS event handlerSome other minor warnings
* Generating thumbnails on watcher
* Remove event handler on watcher
* Some initial works on modify events and other small fixes
* File update event
* Trying to be more generic with used events and some tests to validate our assumptions
* Turning on location metadata file
* Introducing core unit tests on CI pipeline
* Submiting new unit test assumptions to validate on windows CI
* Fixing unit tests
* Fixing unit tests again
* Fixing unit tests
* Fixing unit tests for macos
* Fixing unit tests for macos again
* New structure for platform dependent event handling
Implementing event handlers for Linux and MacOS
* minor fixes + rustfmt + clippy
* Windows event handling
* Introducing a feature gate to only use location watching on desktop app for now
* Putting more stuff behind feature gates to avoid warnings
* Adding feature to cargo test on CI
* Changing some debug logs to trace logs and removing Jamie specific stuff
* Make location removal from manager less async
* fix build when "location-watcher" feature disabled
* fix types + clippy
* make location manager non-static
* remove uses of `to_string_lossy`
* more invalidate_query calls
* Expose `library_ctx` directly to avoid needless clones
* New materialized_path handling for directories
* Removing cascade delete between file_path and object
- Some other minor stuff
* remove unused `CurrentDirFileIdentifierJob`
Co-authored-by: Jamie Pine <ijamespine@me.com>
Co-authored-by: Oscar Beaumont <oscar@otbeaumont.me>
* Preparing some scaffolding for video thumbnails
* Implemented thumbnail generation for videos
* Propagating errors of `Node` creation
* Using ffmpeg feature gate
* Introducing ffmpegthumbnailer-rs as a subcrate on core
* - rename to thumbnailer
- fix explorer thumbnail bug
- add more supported video types
- re-fix explorer performance
* remove nested licence
Co-authored-by: Jamie Pine <ijamespine@me.com>
* move Rust backend to rspc
* move server to Axum + remove parts of old bridge
* move frontend over to @rspc/client
* move core to rspc + update deps
* fix Typescript errors + upgrade deps
* document invalidate_query! macro
* general cleanup + upgrade to PCR 0.6.0
* prisma error handling
* upgrade to rspc 0.0.4
* update vite-plugin-ssr
* fix typescript
* fix builds
* put landing page app name back
* hardcode ffmpeg version on Windows
* rename 'command' to 'mutation' to line up with react-query terminology
* upgrade rspc to v0.0.5 + fix types
* use shared ffmpeg binaries
* general Typescript cleanup
* fix clippy workflow failing due to tauri proc-macro
Co-authored-by: Brendan Allan <brendonovich@outlook.com>
* Introducing Lefthook for git hooks automation
* TypeScript typechecking and linting
* Rust formatting and linting
* Spellchecking (also corrected spell errors in some files)
* Check links in md files
* Introducing resumable jobs
* Abstractions to pause and resume jobs automatically when application exits and is started
* Changing database to use Bytes for UUID fields
* Changing uuid fields on core to use uuid::Uuid instead of String
* Updating some dependencies and introducing msg_pack serialization to save job state on database
* Fixing some clippy warnings
* Fixing a regression introduced on identifier job, doing too much db accesses concurrently