> ## Documentation Index
> Fetch the complete documentation index at: https://v2.spacedrive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Architecture

> 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 theme={null}
# 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 theme={null}
# 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 theme={null}
# 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 theme={null}
{
  "current_library_id": "uuid-here",
  "update": {
    "repo": "spacedriveapp/spacedrive-cli-releases",
    "channel": "stable"
  }
}
```

### Config Commands

```bash theme={null}
# 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 theme={null}
# 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 theme={null}
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 theme={null}
   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 theme={null}
   mv sd ~/.local/bin/
   mv sd-daemon ~/.local/bin/
   chmod +x ~/.local/bin/sd ~/.local/bin/sd-daemon
   ```

4. **Remove quarantine** (macOS):
   ```bash theme={null}
   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 theme={null}
# 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 theme={null}
// 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 theme={null}
# Check if already running
sd status

# View logs
sd logs follow

# Reset data and restart
sd restart --reset
```

### Update Fails

```bash theme={null}
# 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`
