# Shell Integration — Rust Port Overview

**Feature ID**: FE-06
**Status**: planned
**Language**: Rust 2021
**Source**: Python implementation in `apcore-cli-python/src/apcore_cli/shell.py`

---

## What This Feature Does

Shell Integration provides `completion` and `man` as first-class clap subcommands on the root `apcore-cli` CLI. It:

1. Generates shell completion scripts for bash, zsh, fish, elvish, and powershell using `clap_complete::generate`. Invalid shell names are rejected by clap at parse time (exit 2).
2. Generates roff-formatted man pages for any named CLI subcommand. Unknown command names produce stderr `"Error: Unknown command '{name}'."` and exit 2.
3. Both subcommands are pure output commands: they write to stdout and exit 0 on success.
4. `register_shell_commands` follows the clap v4 builder idiom: accepts and returns `Command`.

---

## Rust-Specific Design Decisions

### `clap_complete` Replaces Hand-Written Scripts

The Python implementation hand-writes bash, zsh, and fish completion scripts with dynamic module-ID hooks (embedding `apcore-cli list --format json | python3 -c ...` in the generated script). The Rust port replaces all hand-written scripts with `clap_complete::generate`. This:

- Eliminates ~100 lines of brittle string-formatting code.
- Adds elvish and powershell support at zero implementation cost.
- Removes the `python3` runtime dependency from the generated bash/zsh scripts.

The dynamic module-ID hook is deferred to a follow-up task once the registry is wired at the `core-dispatcher` level.

### `ShellError` Instead of `std::process::exit`

Command handlers return `Result<String, ShellError>` rather than calling `std::process::exit` directly. The binary entry point converts errors to exit codes:

| Error variant | Exit code |
|---------------|-----------|
| `ShellError::UnknownCommand` | 2 |

This keeps handlers testable without terminating the test process.

### `register_shell_commands` Returns `Command`

Following the clap v4 builder idiom used throughout this project:

```rust
pub fn register_shell_commands(cli: Command, prog_name: &str) -> Command
```

The existing stub uses `&mut Command`. The `cli-wiring` task updates the signature and adjusts `main.rs` and `lib.rs`.

### Man Pages via Hand-Written Roff

The Python implementation uses a combination of click parameter introspection and string formatting to produce roff. The Rust port mirrors this approach using clap `Arg` introspection:

- Synopsis built from `cmd.get_arguments()` — positionals vs named options, required vs optional.
- Description from `cmd.get_about()`.
- Options from `get_arguments()` filtering for args with `long` or `short`.
- EXIT CODES and ENVIRONMENT are static sections defined as constant arrays — identical content to the Python implementation.

`clap_mangen` is not used because it is not in `Cargo.toml` and the spec's required sections (especially EXIT CODES and ENVIRONMENT) are not generated by `clap_mangen` anyway.

### No `Cargo.toml` Changes Required

`clap_complete = "4"` is already present. `thiserror` and `anyhow` are already present. No new dependencies needed.

---

## Files Modified

| File | Role |
|------|------|
| `src/shell.rs` | Full rewrite: `ShellError`, `KNOWN_BUILTINS`, `register_shell_commands`, `completion_command`, `man_command`, `cmd_completion`, `cmd_man`, `generate_man_page`, `build_synopsis`, `format_roff_date` |
| `tests/test_shell.rs` | Replace all `assert!(false, "not implemented")` stubs with working assertions |
| `src/lib.rs` | Update re-export to include `ShellError`, `cmd_completion`, `cmd_man`, `completion_command`, `generate_man_page`, `build_synopsis`, `KNOWN_BUILTINS` |
| `src/main.rs` | Update `register_shell_commands` call site from `&mut Command` to builder pattern |

No new source files. No `Cargo.toml` changes required.

---

## Task Execution Order

```
shell-error-type
      │
  ┌───┴────────────────┐
  │                    │
completion-command   man-page-generator
  │                    │
  └────────┬───────────┘
           │
       cli-wiring
```

Full sequence: `shell-error-type` → `completion-command` + `man-page-generator` (parallel) → `cli-wiring`

---

## Acceptance Gate

All tasks complete when:

- `cargo test` reports zero failures in `src/shell.rs` (inline unit tests) and `tests/test_shell.rs` (integration tests).
- `cargo clippy -- -D warnings` produces no warnings in `src/shell.rs`.
- `cargo build --release` succeeds.
- No `todo!()` macros remain in `src/shell.rs`.
- No `assert!(false, "not implemented")` calls remain in `src/shell.rs` or `tests/test_shell.rs`.
- Manual check: `cargo run -- completion bash | bash -n /dev/stdin` exits 0 (unix).
- Manual check: `cargo run -- man exec` outputs roff containing `.TH` and `.SH EXIT CODES`.
- Manual check: `cargo run -- man nonexistent`; echo $? prints `2`.
