# Rho Single CLI TODO

Status: implemented on `madhava/cli-all`. Keep this file until the branch is
merged and the release artifacts are confirmed.

## Objective

Finish the migration from a dispatcher plus many `rho-*` binaries to one real
installed binary:

```text
rho <subcommand> ...
```

The crate name stays `rho-cli`; the installed executable should be `rho`.

## Current Evidence

- [x] `Cargo.toml` now defines one binary target:
  - `rho`
- [x] `src/bin/rho.rs` dispatches to internal command modules directly.
- [x] Command implementations moved to `src/commands/*.rs`.
- [x] `.github/workflows/release.yml` now sets `RHO_BINS: rho`.
- [x] Release packaging builds with `cargo build --release --locked --target ... --bin rho`.
- [x] `install.sh` verifies only `rho`.
- [x] E2E tests invoke `cargo run --quiet --bin rho -- <subcommand> ...`.

## Target Shape

- One binary target remains in `Cargo.toml`:
  - `rho`
- All user-facing commands are subcommands of `rho`.
- Command logic lives in normal Rust modules, not in sibling executables.
- Release archives contain only `rho`.
- `cargo install rho-cli --bin rho` installs the full CLI.
- `rho --version` and `rho version` continue to report the crate version.

## Command Map

| Old entrypoint | New entrypoint |
| --- | --- |
| `rho-dataset ...` | `rho dataset ...` |
| `rho-publish ...` | `rho publish ...` |
| `rho-message ...` | `rho message ...` |
| `rho-request ...` | `rho request ...` |
| `rho-tools ...` | `rho tools ...` |
| `rho-run ...` | `rho run ...` |
| `rho-result ...` | `rho result ...` |
| `rho-id ...` | `rho id ...` |
| `rho-crypto ...` | `rho crypto ...` |
| `rho-repo ...` | `rho repo ...` |
| dispatcher alias `rho approve ...` | keep as `rho approve ...`, backed by request logic |
| dispatcher alias `rho status ...` | keep as `rho status ...`, backed by repo logic |
| dispatcher alias `rho add user ...` | keep as `rho add user ...`, backed by repo logic |
| current `rho gh ...` | keep in `rho` |
| current `rho commit ...` | keep in `rho` |
| current `rho env ...` | keep in `rho` |
| current `rho install-shell ...` | keep in `rho` |

## Non-Goals

- Do not redesign command behavior during this migration.
- Do not introduce long-term compatibility binaries.
- Do not add a CLI framework unless the migration proves the existing parsing is
  too brittle to maintain.
- Do not block on live Pi/provider tests; keep those manual.

## Migration Plan

### 1. Create command modules

- [x] Add `src/commands/mod.rs`.
- [x] Move each implementation file into a module:
  - [x] `src/bin/rho_dataset.rs` -> `src/commands/dataset.rs`
  - [x] `src/bin/rho_publish.rs` -> `src/commands/publish.rs`
  - [x] `src/bin/rho_message.rs` -> `src/commands/message.rs`
  - [x] `src/bin/rho_request.rs` -> `src/commands/request.rs`
  - [x] `src/bin/rho_tools.rs` -> `src/commands/tools.rs`
  - [x] `src/bin/rho_run.rs` -> `src/commands/run.rs`
  - [x] `src/bin/rho_result.rs` -> `src/commands/result.rs`
  - [x] `src/bin/rho_id.rs` -> `src/commands/id.rs`
  - [x] `src/bin/rho_crypto.rs` -> `src/commands/crypto.rs`
  - [x] `src/bin/rho_repo.rs` -> `src/commands/repo.rs`
- [x] Export command modules through `src/commands/mod.rs` for `src/bin/rho.rs`.

### 2. Convert `main()` functions

- [x] Replace each moved `fn main()` with a callable entrypoint.
- [x] Use one consistent shape:

```rust
pub fn run(args: &[String]) -> i32
```

- [x] Preserve current usage functions and exit-code behavior.
- [x] Avoid panics for ordinary CLI errors.
- [x] Keep stdout/stderr contracts stable for tests and scripts.

If converting direct `std::process::exit(...)` calls is too large for one PR,
allow an intermediate helper that exits from inside the module, but only as a
temporary migration step.

### 3. Replace dispatcher process spawning

- [x] Update `src/bin/rho.rs` so subcommands call modules directly instead of
  launching `rho-*` binaries.
- [x] Keep existing built-in commands in `rho.rs`:
  - [x] `gh`
  - [x] `commit`
  - [x] `env`
  - [x] `install-shell`
  - [x] `version`
- [x] Preserve aliases:
  - [x] `rho approve ...`
  - [x] `rho status ...`
  - [x] `rho add user ...`

### 4. Update tests and scripts

- [x] Replace `cargo run --quiet --bin rho-dataset -- ...` with
  `cargo run --quiet --bin rho -- dataset ...`.
- [x] Replace `cargo run --quiet --bin rho-publish -- ...` with
  `cargo run --quiet --bin rho -- publish ...`.
- [x] Replace `cargo run --quiet --bin rho-tools -- ...` with
  `cargo run --quiet --bin rho -- tools ...`.
- [x] Replace `cargo run --quiet --bin rho-request -- ...` with
  `cargo run --quiet --bin rho -- request ...`.
- [x] Replace `cargo run --quiet --bin rho-run -- ...` with
  `cargo run --quiet --bin rho -- run ...`.
- [x] Search for any remaining `--bin rho-` and remove it.
- [x] Keep `./rho <subcommand>` tests as-is where they already exercise the
  dispatcher path.

### 5. Remove extra binary targets

- [x] Delete all non-`rho` `[[bin]]` entries from `Cargo.toml`.
- [x] Delete or repurpose the old `src/bin/rho_*.rs` files after their logic is
  moved.
- [x] Confirm `cargo metadata --no-deps --format-version 1` lists one binary
  target named `rho`.
- [x] Confirm `cargo build --bins` still works and only builds `rho`.

### 6. Update release and install packaging

- [x] Change release `RHO_BINS` to `rho`.
- [x] Change release build from `--bins` to `--bin rho`.
- [x] Package only `rho` in Linux/macOS tarballs and Windows zip files.
- [x] Update release notes from "binaries" to "the rho binary".
- [x] Update `install.sh` to install and verify only `rho`.
- [x] Confirm `cargo publish --dry-run --locked` packages only the intended
  installed executable.

### 7. Update docs

- [x] Update docs that describe `rho-*` as installed commands in touched e2e docs.
- [x] Keep architecture doc filenames like `rho-id.md` if they describe the
  subsystem rather than a binary.
- [x] Add or update README install examples:
  - `cargo install rho-cli --bin rho`
  - `rho id ...`
  - `rho crypto ...`
  - `rho repo ...`
  - `rho run ...`

## Compatibility Decision

Preferred: make the next minor release the clean single-binary release and
document the new subcommand invocations.

Fallback: if compatibility shims are needed for one release, keep tiny wrapper
binaries only. They must call the same internal modules as `rho` and must not
contain duplicate command logic. Remove them in the following release.

## Acceptance Gates

- [x] `cargo fmt --all -- --check`
- [x] `cargo clippy --all-targets --all-features --locked -- -D warnings`
- [x] `cargo test --all-targets --all-features --locked`
- [x] `./test.sh`
- [x] `cargo publish --dry-run --locked --allow-dirty`
- [x] `rg -- '--bin rho-' tests scripts docs .github install.sh Cargo.toml` returns no migration blockers.
- [x] `cargo metadata --no-deps --format-version 1` proves there is exactly one
  binary target: `rho`.
- [x] Release workflow packages only `rho`.
- [x] `install.sh` verifies only `rho`.
- [x] Local smoke checks pass:
  - [x] `cargo run --quiet --bin rho -- version`
  - [x] `cargo run --quiet --bin rho -- id list`
  - [x] `cargo run --quiet --bin rho -- tools list --shared-root sandbox/nonexistent-shared-root`
  - [x] `printf '' | cargo run --quiet --bin rho -- crypto smudge`

## First PR Scope

Make the first implementation PR mechanical:

- Move command code into modules.
- Replace dispatcher process spawning with module calls.
- Update tests from `--bin rho-*` to `--bin rho -- <subcommand>`.
- Remove extra bin targets only after tests pass.
- Do not mix in README, Homebrew, completions, or command redesign.
