# 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:
| `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
| `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`.