diff --git a/README.md b/README.md index bbd6ee9..c54e767 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,108 @@ -# cli -A `Terminal.Gui` library that lets applications expose Views as scriptable CLI commands with typed JSON output, POSIX exit codes, and AI-agent discoverability. +# Terminal.Gui.Cli + +![Terminal.Gui.Cli Example App](docs/images/hero.gif) + +A .NET library that lets [Terminal.Gui](https://github.com/gui-cs/Terminal.Gui) applications expose Views as scriptable CLI commands with typed JSON output, POSIX exit codes, and AI-agent discoverability. + +Ships as a single NuGet package: **[`Terminal.Gui.Cli`](https://www.nuget.org/packages/Terminal.Gui.Cli)**. + +## What it does + +`Terminal.Gui.Cli` provides a hosting layer (`CliHost`) that wires up: + +- **CLI parsing** — positional command dispatch, typed options, `--initial` pre-fill for input commands. +- **Structured output** — `--json` emits a versioned `JsonEnvelope`; `--cat` renders viewer content headlessly. +- **AI-agent discoverability** — `--opencli` emits machine-readable metadata; `--agent-guide` serves embedded Markdown guidance. +- **Built-in help** — `--help` renders command/option metadata via pluggable `IHelpProvider`. +- **Exit codes** — deterministic POSIX exit codes from `CommandResult` status. + +## Command model + +| Kind | Interface | Description | +|------|-----------|-------------| +| **Input** | `ICliCommand` | Launches a Terminal.Gui UI, returns a typed result. | +| **Viewer** | `IViewerCommand` | Displays content; supports `--cat` for headless rendering. | + +Commands register explicitly (no reflection scanning) and resolve by case-insensitive alias. + +## Quickstart + +```csharp +using Terminal.Gui.Cli; + +CliHost host = new (options => +{ + options.ApplicationName = "my-app"; + options.Version = "1.0.0"; +}); + +host.Registry.Register (new MyCommand ()); + +return await host.RunAsync (args); +``` + +```sh +# Interactive (launches Terminal.Gui) +my-app greet --initial "World" + +# JSON envelope +my-app greet --initial "World" --json + +# Agent discovery +my-app --opencli +my-app agent-guide + +# Headless viewer +my-app info --cat +``` + +## Framework options + +All commands inherit these options from the host: + +| Option | Description | +|--------|-------------| +| `--help` / `-h` | Show help | +| `--version` | Show version | +| `--opencli` | Emit OpenCLI metadata JSON | +| `--json` | Wrap output in JSON envelope | +| `--initial ` | Pre-fill input value | +| `--timeout ` | Cancel after duration (e.g., `30s`, `5m`) | +| `--output ` / `-o` | Write output to file | +| `--cat` | Headless render (viewer commands only) | + +## Repository layout + +``` +specs/ Constitution and library spec +src/ Terminal.Gui.Cli library +tests/ Unit, integration, and smoke tests +examples/ Example console app +scripts/ Tooling and recording scripts +docs/ Images and documentation assets +``` + +## Build + +Requires .NET 10 SDK. Solution file: `Terminal.Gui.Cli.slnx`. + +```sh +dotnet restore Terminal.Gui.Cli.slnx +dotnet build Terminal.Gui.Cli.slnx + +# Tests +dotnet run --project tests/Terminal.Gui.Cli.Tests +dotnet run --project tests/Terminal.Gui.Cli.IntegrationTests +dotnet run --project tests/Terminal.Gui.Cli.SmokeTests + +# Example app +dotnet run --project examples/Terminal.Gui.Cli.ExampleApp -- greet --initial "World" --json +``` + +## Status + +**Alpha** — `0.1.0-develop` pre-release stream on the `develop` branch. + +## License + +MIT; see [`LICENSE`](LICENSE). diff --git a/docs/images/hero.gif b/docs/images/hero.gif new file mode 100644 index 0000000..da61867 Binary files /dev/null and b/docs/images/hero.gif differ diff --git a/scripts/HERO-GIF.md b/scripts/HERO-GIF.md new file mode 100644 index 0000000..7f377b1 --- /dev/null +++ b/scripts/HERO-GIF.md @@ -0,0 +1,86 @@ +# Hero GIF Recording Guide + +Produces `docs/images/hero.gif` — an animated GIF demonstrating the example app's CLI features. + +## Prerequisites + +- [tuirec](https://github.com/gui-cs/tuirec) v0.3.4+ on PATH (`go install github.com/gui-cs/tuirec/cmd/tuirec@latest`) +- .NET 10 SDK (for building the example app) +- PowerShell 7+ (`pwsh`) on PATH +- `agg` is auto-downloaded by tuirec on first use + +## Build the example app + +```powershell +dotnet build examples/Terminal.Gui.Cli.ExampleApp -c Debug --nologo +``` + +## Record + +The recording uses a PowerShell script to run multiple CLI invocations in sequence, +captured by tuirec in `--inline` mode (no alternate screen, normal scrolling buffer). + +```powershell +$binary = (Resolve-Path "examples/Terminal.Gui.Cli.ExampleApp/bin/Debug/net10.0/Terminal.Gui.Cli.ExampleApp.exe").Path + +# Create the demo script that runs each CLI feature +$script = @" +Write-Host '`$ example-app --help' -ForegroundColor Green +& '$binary' --help +Write-Host '' +Write-Host '`$ example-app greet --initial "World" --json' -ForegroundColor Green +& '$binary' greet --initial 'World' --json +Write-Host '' +Write-Host '`$ example-app info --cat' -ForegroundColor Green +& '$binary' info --cat +Write-Host '' +Write-Host '`$ example-app --opencli' -ForegroundColor Green +& '$binary' --opencli +"@ +$script | Set-Content -Path artifacts/demo.ps1 -Encoding utf8 + +tuirec record ` + --binary "pwsh" ` + --args "-NoProfile","-File","artifacts/demo.ps1" ` + --name "hero" ` + --inline ` + --show-command '$ ./demo.ps1' ` + --keystrokes 'wait:5000' ` + --startup-delay 3000 ` + --drain 2000 ` + --cols 100 ` + --rows 35 ` + --keystroke-delay 60 ` + --max-duration 20 ` + --verbosity high + +# Copy to final location +Copy-Item ./artifacts/hero.gif ./docs/images/hero.gif -Force +``` + +## Demo sequence + +The script runs four CLI invocations back-to-back. All output appears in a single scrolling terminal frame: + +| Feature | Command | +|------------------------|-------------------------------------------------| +| Help | `example-app --help` — lists commands + options | +| JSON envelope | `example-app greet --initial "World" --json` | +| Headless viewer | `example-app info --cat` | +| Agent discovery | `example-app --opencli` — machine-readable JSON | + +## Tuning tips + +- **Terminal size**: 100x35 gives enough vertical space to show all outputs without scrolling previous content off-screen. +- **`--inline` mode**: Required because the demo runs non-interactive commands that print to stdout and exit. Without `--inline`, tuirec captures an empty alternate screen. +- **`--startup-delay 3000`**: Allows `pwsh` to start. Reduce on fast machines. +- **`--drain 2000`**: Holds the final frame so viewers can read the opencli output. +- **GIF too large**: Reduce `--rows` or remove one of the demo commands. Current result is ~75KB. +- **Wrong binary path**: After building, verify the exe exists. On Linux/macOS omit `.exe`. + +## Troubleshooting + +1. **Empty GIF (just the show-command prompt)**: You probably forgot `--inline`. Without it, the normal-screen output from pwsh is invisible. +2. **Output garbled or overlapping**: Increase `--startup-delay` so pwsh finishes initialization before tuirec starts capturing. +3. **GIF not generated**: Ensure `agg` was downloaded. Check `./artifacts/` for the `.cast` file; if present, re-run `agg` manually. +4. **PowerShell colors wrong**: The demo uses `Write-Host -ForegroundColor Green` for prompts. This renders as ANSI color 10 which most themes show as green.