opencode-cloud 3.0.2

CLI for managing opencode as a persistent cloud service
Documentation
# opencode-cloud Rust CLI

**This is the source of truth for all CLI commands.**

The Rust CLI (`occ`) contains the complete implementation of all opencode-cloud commands. The Node CLI (`packages/cli-node`) is a transparent passthrough wrapper that spawns this binary.

## Architecture

opencode-cloud uses a dual-CLI strategy:

1. **Rust CLI** (this package) - Complete implementation, all logic lives here
2. **Node CLI** (`packages/cli-node`) - Wrapper that spawns Rust binary with `stdio: 'inherit'`

This architecture provides:
- **Single source of truth** - All command logic in one place (Rust)
- **No duplication** - Node wrapper has zero command logic
- **Automatic sync** - New Rust commands instantly work via Node
- **Full TTY support** - Colors, interactive prompts, progress bars all work
- **Cross-platform** - Users choose their preferred installation method

## Building

### Development Build

```bash
# Build Rust CLI only
cargo build -p opencode-cloud

# Run directly
./target/debug/occ --help

# Or via cargo
cargo run -p opencode-cloud -- start
```

### Release Build

```bash
cargo build -p opencode-cloud --release
./target/release/occ --help
```

### Full Project Build

```bash
# Build all packages (core + CLIs)
just build
```

## Project Structure

```
packages/cli-rust/
├── src/
│   ├── bin/
│   │   ├── occ.rs              # Binary entry point (occ)
│   │   └── opencode-cloud.rs   # Binary entry point (opencode-cloud)
│   ├── commands/
│   │   ├── mod.rs              # Command registry
│   │   ├── start.rs            # occ start
│   │   ├── stop.rs             # occ stop
│   │   ├── status.rs           # occ status
│   │   ├── config/             # occ config subcommands
│   │   ├── user/               # occ user subcommands
│   │   ├── mount/              # occ mount subcommands
│   │   └── ...                 # Other commands
│   ├── output/
│   │   ├── spinner.rs          # Progress spinners
│   │   ├── colors.rs           # Terminal color utilities
│   │   ├── errors.rs           # Error formatting
│   │   └── urls.rs             # URL formatting helpers
│   ├── wizard/
│   │   ├── mod.rs              # Interactive setup wizard
│   │   ├── auth.rs             # Auth prompts
│   │   └── network.rs          # Network prompts
│   └── lib.rs                  # Shared CLI implementation
├── Cargo.toml
└── README.md                   # This file
```

## Adding Commands

To add a new command (e.g., `occ shell`):

### 1. Create the command module

```bash
touch src/commands/shell.rs
```

### 2. Implement the command

```rust
use anyhow::Result;
use clap::Args;
use opencode_cloud_core::DockerClient;

#[derive(Args)]
pub struct ShellArgs {
    /// Shell to use (default: bash)
    #[arg(short, long, default_value = "bash")]
    shell: String,
}

pub async fn cmd_shell(args: &ShellArgs, quiet: bool) -> Result<()> {
    let client = DockerClient::new()?;

    if !client.is_container_running().await? {
        anyhow::bail!("Container is not running. Start it with: occ start");
    }

    client.exec_interactive(&args.shell, None).await?;
    Ok(())
}
```

### 3. Register in `commands/mod.rs`

```rust
mod shell;
pub use shell::{ShellArgs, cmd_shell};
```

### 4. Add to CLI enum in `src/lib.rs`

```rust
#[derive(Subcommand)]
enum Commands {
    // ... existing commands
    /// Open a shell in the container
    Shell(commands::ShellArgs),
}
```

### 5. Add command handler in `src/lib.rs`

In the `match cli.command` block:

```rust
Some(Commands::Shell(args)) => {
    let rt = tokio::runtime::Runtime::new()?;
    rt.block_on(commands::cmd_shell(&args, cli.quiet))
}
```

### 6. Test

```bash
# Build
cargo build -p opencode-cloud

# Test Rust CLI
./target/debug/occ shell --help
./target/debug/occ shell

# Node CLI automatically works too
node packages/cli-node/dist/index.js shell
```

**That's all!** No changes needed in `packages/cli-node` - it automatically delegates to the new Rust command.

## Testing

```bash
# Run all tests
cargo test -p opencode-cloud

# Run specific test
cargo test -p opencode-cloud cmd_shell

# With verbose output
cargo test -p opencode-cloud -- --nocapture
```

## Installation

### From Source (Development)

```bash
cargo install --path packages/cli-rust
```

### From crates.io (Users)

```bash
cargo install opencode-cloud
```

### Via npm (Users)

```bash
npm install -g opencode-cloud
# or
npx opencode-cloud
```

The npm package includes this Rust CLI and compiles it during installation.

## Code Style

See [CLAUDE.md](../../CLAUDE.md) for detailed code style guidelines.

Quick reference:
- Prefer `?` for error propagation over `unwrap()`
- Use `let...else` for early returns
- Prefix `Option` types with `maybe_`
- Document public APIs with `///` comments
- Run `cargo fmt` and `cargo clippy` before committing

## Contributing

See [CONTRIBUTING.md](../../CONTRIBUTING.md) for full contribution guidelines.