docs/core/cli.mdx
The Spacedrive CLI (sd) is a command-line interface for interacting with the Spacedrive daemon. It provides a comprehensive set of commands for managing libraries, files, devices, and daemon lifecycle.
The CLI follows a client-daemon architecture:
sd-cli / sd) - The client that sends commandssd-daemon) - The background service that does the actual work┌─────────┐ Unix Socket ┌──────────┐
│ sd │ ◄──────────────────► │ sd-daemon│
│ (client)│ │ (server) │
└─────────┘ └──────────┘
│
▼
┌──────────┐
│ Libraries│
└──────────┘
# Start in background
sd start
# Start in foreground (see logs)
sd start --foreground
The daemon:
~/Library/Application Support/spacedrive/daemon/daemon.sock--instance flagInstall the daemon to start automatically on system boot:
# Install LaunchAgent (macOS)
sd daemon install
# Check status
sd daemon status
# Uninstall
sd daemon uninstall
This creates a LaunchAgent at ~/Library/LaunchAgents/com.spacedrive.daemon.plist that:
~/Library/Application Support/spacedrive/logs/Run multiple daemon instances for different data directories:
# Start with custom instance name
sd --instance work start
sd --instance personal start
# Each instance gets its own socket
# daemon-work.sock
# daemon-personal.sock
The CLI stores configuration in ~/Library/Application Support/spacedrive/cli.json:
{
"current_library_id": "uuid-here",
"update": {
"repo": "spacedriveapp/spacedrive-cli-releases",
"channel": "stable"
}
}
# View all configuration
sd config show
# Get specific value
sd config get update.repo
# Set value
sd config set update.repo "your-org/releases-repo"
The CLI includes a built-in update mechanism that fetches releases from a public GitHub repository.
┌─────────┐ ┌────────────┐
│sd update│ ──── GitHub API ────────►│ Releases │
└─────────┘ │ Repository │
│ └────────────┘
│ Download binaries │
▼ │
┌─────────────────┐ │
│ sd-macos-arm64 │◄──────────────────────┘
│ sd-daemon-... │
└─────────────────┘
│
│ Atomic replacement
▼
┌─────────────────┐
│ Installed bins │
└─────────────────┘
# Check and install updates
sd update
# Force reinstall current version
sd update --force
The update system uses a public GitHub repository containing only releases (no source code):
your-org/spacedrive-cli-releasesgit commit --allow-empty -m "Release v0.1.0"git tag v0.1.0sd config set update.repo "your-org/spacedrive-cli-releases"The CI workflow automatically builds binaries for:
All CLI commands follow this pattern:
sd [--data-dir PATH] [--instance NAME] [--format FORMAT] <command> [args]
--data-dir - Override default data directory--instance - Connect to specific daemon instance--format - Output format: human (default) or json| Command | Description |
|---|---|
sd start | Start the daemon |
sd stop | Stop the daemon |
sd restart | Restart the daemon |
sd status | Show system status |
sd update | Update CLI and daemon |
| Command | Description |
|---|---|
sd library | Manage libraries |
sd location | Manage indexed locations |
sd file | File operations |
sd index | Indexing operations |
sd search | Search files |
sd tag | Tag management |
sd volume | Volume operations |
sd device | Device management |
sd job | Job control |
sd network | Networking and pairing |
sd logs | View daemon logs |
sd config | Configuration management |
sd daemon | Daemon lifecycle |
For development and testing, binaries can be distributed without building from source:
Build release binaries:
cargo build --release --bin sd-cli --bin sd-daemon
Copy both binaries to target machine:
sd-cli → rename to sdsd-daemon → keep as sd-daemonPlace in PATH:
mv sd ~/.local/bin/
mv sd-daemon ~/.local/bin/
chmod +x ~/.local/bin/sd ~/.local/bin/sd-daemon
Remove quarantine (macOS):
xattr -d com.apple.quarantine ~/.local/bin/sd
xattr -d com.apple.quarantine ~/.local/bin/sd-daemon
Both binaries must be in the same directory as the CLI expects to find the daemon binary in its parent directory.
# Build CLI only
cargo build --package sd-cli
# Build both CLI and daemon
cargo build --bin sd-cli --bin sd-daemon
# Release build
cargo build --release --bin sd-cli --bin sd-daemon
apps/cli/
├── src/
│ ├── main.rs # Entry point, daemon lifecycle
│ ├── config.rs # CLI configuration
│ ├── context.rs # Execution context
│ ├── domains/ # Command domains
│ │ ├── config/ # Config commands
│ │ ├── daemon/ # Daemon management
│ │ ├── update/ # Auto-update system
│ │ ├── library/ # Library operations
│ │ ├── location/ # Location operations
│ │ └── ...
│ └── util/ # Shared utilities
└── Cargo.toml
core/
└── src/
└── bin/
└── daemon.rs # Daemon binary
domains/run() functiondomains/mod.rs and main.rsExample:
// domains/myfeature/mod.rs
use anyhow::Result;
use clap::Subcommand;
#[derive(Subcommand, Debug)]
pub enum MyFeatureCmd {
/// Do something
Action { arg: String },
}
pub async fn run(ctx: &Context, cmd: MyFeatureCmd) -> Result<()> {
match cmd {
MyFeatureCmd::Action { arg } => {
// Implementation
}
}
Ok(())
}
Instance names are validated to prevent path traversal:
The update system verifies downloaded binaries:
The Unix socket is created with restrictive permissions (user-only access).
# Check if already running
sd status
# View logs
sd logs follow
# Reset data and restart
sd restart --reset
# Check configuration
sd config show
# Verify repo is accessible
curl https://api.github.com/repos/YOUR_ORG/YOUR_REPO/releases/latest
# Force clean reinstall
sd update --force
The daemon socket is located at:
~/Library/Application Support/spacedrive/daemon/daemon.sock
If connection fails:
ps aux | grep sd-daemonls -la <socket-path>sd restart