mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2025-12-11 20:15:30 +01:00
363 lines
9.1 KiB
Plaintext
363 lines
9.1 KiB
Plaintext
---
|
|
title: "CLI Architecture"
|
|
description: "Command-line interface for Spacedrive v2"
|
|
---
|
|
|
|
## Overview
|
|
|
|
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.
|
|
|
|
## Architecture
|
|
|
|
The CLI follows a client-daemon architecture:
|
|
|
|
- **CLI Binary** (`sd-cli` / `sd`) - The client that sends commands
|
|
- **Daemon Binary** (`sd-daemon`) - The background service that does the actual work
|
|
- **Unix Socket** - Communication channel between CLI and daemon
|
|
|
|
```
|
|
┌─────────┐ Unix Socket ┌──────────┐
|
|
│ sd │ ◄──────────────────► │ sd-daemon│
|
|
│ (client)│ │ (server) │
|
|
└─────────┘ └──────────┘
|
|
│
|
|
▼
|
|
┌──────────┐
|
|
│ Libraries│
|
|
└──────────┘
|
|
```
|
|
|
|
## Daemon Management
|
|
|
|
### Starting the Daemon
|
|
|
|
```bash
|
|
# Start in background
|
|
sd start
|
|
|
|
# Start in foreground (see logs)
|
|
sd start --foreground
|
|
```
|
|
|
|
The daemon:
|
|
- Runs as a background process
|
|
- Listens on a Unix socket at `~/Library/Application Support/spacedrive/daemon/daemon.sock`
|
|
- Manages all libraries and background tasks
|
|
- Can run multiple instances with `--instance` flag
|
|
|
|
### Auto-Start on Login
|
|
|
|
Install the daemon to start automatically on system boot:
|
|
|
|
```bash
|
|
# 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:
|
|
- Starts daemon on user login
|
|
- Restarts if it crashes
|
|
- Logs to `~/Library/Application Support/spacedrive/logs/`
|
|
|
|
### Multi-Instance Support
|
|
|
|
Run multiple daemon instances for different data directories:
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
## Configuration
|
|
|
|
The CLI stores configuration in `~/Library/Application Support/spacedrive/cli.json`:
|
|
|
|
```json
|
|
{
|
|
"current_library_id": "uuid-here",
|
|
"update": {
|
|
"repo": "spacedriveapp/spacedrive-cli-releases",
|
|
"channel": "stable"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Config Commands
|
|
|
|
```bash
|
|
# 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"
|
|
```
|
|
|
|
## Auto-Update System
|
|
|
|
The CLI includes a built-in update mechanism that fetches releases from a public GitHub repository.
|
|
|
|
### Update Architecture
|
|
|
|
```
|
|
┌─────────┐ ┌────────────┐
|
|
│sd update│ ──── GitHub API ────────►│ Releases │
|
|
└─────────┘ │ Repository │
|
|
│ └────────────┘
|
|
│ Download binaries │
|
|
▼ │
|
|
┌─────────────────┐ │
|
|
│ sd-macos-arm64 │◄──────────────────────┘
|
|
│ sd-daemon-... │
|
|
└─────────────────┘
|
|
│
|
|
│ Atomic replacement
|
|
▼
|
|
┌─────────────────┐
|
|
│ Installed bins │
|
|
└─────────────────┘
|
|
```
|
|
|
|
### Update Process
|
|
|
|
1. **Check for updates**: Queries GitHub API for latest release
|
|
2. **Download binaries**: Fetches platform-specific binaries
|
|
3. **Verify integrity**: Checks file sizes match expected values
|
|
4. **Atomic replacement**: Replaces binaries with rollback on failure
|
|
5. **Restart daemon**: If daemon was running, restarts it
|
|
|
|
```bash
|
|
# Check and install updates
|
|
sd update
|
|
|
|
# Force reinstall current version
|
|
sd update --force
|
|
```
|
|
|
|
### Release Repository Setup
|
|
|
|
The update system uses a public GitHub repository containing only releases (no source code):
|
|
|
|
1. Create public repo: `your-org/spacedrive-cli-releases`
|
|
2. For each release:
|
|
- Create empty commit: `git commit --allow-empty -m "Release v0.1.0"`
|
|
- Tag it: `git tag v0.1.0`
|
|
- Create GitHub release with binaries as assets
|
|
3. Configure CLI: `sd config set update.repo "your-org/spacedrive-cli-releases"`
|
|
|
|
The CI workflow automatically builds binaries for:
|
|
- macOS (arm64, x86_64)
|
|
- Linux (x86_64) - coming soon
|
|
- Windows (x86_64) - coming soon
|
|
|
|
## Command Structure
|
|
|
|
All CLI commands follow this pattern:
|
|
|
|
```bash
|
|
sd [--data-dir PATH] [--instance NAME] [--format FORMAT] <command> [args]
|
|
```
|
|
|
|
### Global Flags
|
|
|
|
- `--data-dir` - Override default data directory
|
|
- `--instance` - Connect to specific daemon instance
|
|
- `--format` - Output format: `human` (default) or `json`
|
|
|
|
### Core Commands
|
|
|
|
| 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 |
|
|
|
|
### Domain Commands
|
|
|
|
| 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 |
|
|
|
|
## Binary Distribution
|
|
|
|
For development and testing, binaries can be distributed without building from source:
|
|
|
|
1. **Build release binaries**:
|
|
```bash
|
|
cargo build --release --bin sd-cli --bin sd-daemon
|
|
```
|
|
|
|
2. **Copy both binaries** to target machine:
|
|
- `sd-cli` → rename to `sd`
|
|
- `sd-daemon` → keep as `sd-daemon`
|
|
|
|
3. **Place in PATH**:
|
|
```bash
|
|
mv sd ~/.local/bin/
|
|
mv sd-daemon ~/.local/bin/
|
|
chmod +x ~/.local/bin/sd ~/.local/bin/sd-daemon
|
|
```
|
|
|
|
4. **Remove quarantine** (macOS):
|
|
```bash
|
|
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.
|
|
|
|
## Development
|
|
|
|
### Building
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
### Code Structure
|
|
|
|
```
|
|
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
|
|
```
|
|
|
|
### Adding New Commands
|
|
|
|
1. Create a new module in `domains/`
|
|
2. Define command enum with clap derives
|
|
3. Implement `run()` function
|
|
4. Register in `domains/mod.rs` and `main.rs`
|
|
|
|
Example:
|
|
|
|
```rust
|
|
// 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(())
|
|
}
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
### Instance Name Validation
|
|
|
|
Instance names are validated to prevent path traversal:
|
|
- Only alphanumeric, dash, and underscore allowed
|
|
- Max 64 characters
|
|
- Cannot be empty
|
|
|
|
### Binary Verification
|
|
|
|
The update system verifies downloaded binaries:
|
|
- File size must match release asset size
|
|
- Future: SHA256 checksum verification
|
|
|
|
### Daemon Socket Permissions
|
|
|
|
The Unix socket is created with restrictive permissions (user-only access).
|
|
|
|
## Troubleshooting
|
|
|
|
### Daemon Won't Start
|
|
|
|
```bash
|
|
# Check if already running
|
|
sd status
|
|
|
|
# View logs
|
|
sd logs follow
|
|
|
|
# Reset data and restart
|
|
sd restart --reset
|
|
```
|
|
|
|
### Update Fails
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
### Socket Connection Errors
|
|
|
|
The daemon socket is located at:
|
|
```
|
|
~/Library/Application Support/spacedrive/daemon/daemon.sock
|
|
```
|
|
|
|
If connection fails:
|
|
1. Verify daemon is running: `ps aux | grep sd-daemon`
|
|
2. Check socket exists: `ls -la <socket-path>`
|
|
3. Restart daemon: `sd restart`
|