Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 50 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
# Terminal.Gui.Cli

![Terminal.Gui.Cli Example App](docs/images/hero.gif)
[![NuGet](https://img.shields.io/nuget/vpre/Terminal.Gui.Cli)](https://www.nuget.org/packages/Terminal.Gui.Cli)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

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.
> A .NET library that turns [Terminal.Gui](https://github.com/gui-cs/Terminal.Gui) apps into scriptable CLI tools — with typed JSON output, POSIX exit codes, and built-in AI-agent discoverability.

Ships as a single NuGet package: **[`Terminal.Gui.Cli`](https://www.nuget.org/packages/Terminal.Gui.Cli)**.
![Terminal.Gui.Cli in action](docs/images/hero.gif)

## What it does
## Why

`Terminal.Gui.Cli` provides a hosting layer (`CliHost`) that wires up:
Terminal.Gui gives you rich TUI applications. **Terminal.Gui.Cli** lets those same apps participate in scripts, pipelines, and agentic workflows — no separate CLI layer needed.

- **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.
One NuGet package. One `CliHost`. All your views become commands.

## Command model
## Features

| Kind | Interface | Description |
|------|-----------|-------------|
| **Input** | `ICliCommand<T>` | 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.
| Capability | How |
|---|---|
| **CLI parsing** | Positional command dispatch, typed options, `--initial` pre-fill |
| **Structured output** | `--json` emits a versioned `JsonEnvelope` |
| **Headless rendering** | `--cat` renders viewer content without a TUI |
| **AI discoverability** | `--opencli` metadata + `agent-guide` embedded Markdown |
| **Built-in help** | `--help` via pluggable `IHelpProvider` |
| **Exit codes** | Deterministic POSIX codes from `CommandResult` |

## Quickstart

```sh
dotnet add package Terminal.Gui.Cli
```

```csharp
using Terminal.Gui.Cli;

Expand All @@ -36,73 +39,81 @@ CliHost host = new (options =>
options.Version = "1.0.0";
});

host.Registry.Register (new MyCommand ());
host.Registry.Register (new GreetCommand ());

return await host.RunAsync (args);
```

Then run it:

```sh
# Interactive (launches Terminal.Gui)
my-app greet --initial "World"
my-app greet --initial "World" # interactive TUI
my-app greet --initial "World" --json # → {"schemaVersion":1,"status":"ok","value":"Hello, World!"}
my-app info --cat # headless viewer output
my-app --opencli # machine-readable command metadata
my-app agent-guide # embedded agent guidance (Markdown)
```

# JSON envelope
my-app greet --initial "World" --json
## Command model

# Agent discovery
my-app --opencli
my-app agent-guide
| Kind | Interface | Description |
|------|-----------|-------------|
| **Input** | `ICliCommand<T>` | Launches a Terminal.Gui UI, returns a typed result |
| **Viewer** | `IViewerCommand` | Displays content; supports `--cat` for headless rendering |

# Headless viewer
my-app info --cat
```
Commands register explicitly (no reflection scanning) and resolve by case-insensitive alias.

## Framework options
## Global options

All commands inherit these options from the host:
Every command inherits these from the host:

| Option | Description |
|--------|-------------|
| `--help` / `-h` | Show help |
| `--version` | Show version |
| `--opencli` | Emit OpenCLI metadata JSON |
| `--json` | Wrap output in JSON envelope |
| `--initial <value>` | Pre-fill input value |
| `--initial <value>` | Pre-fill input value (non-interactive mode) |
| `--timeout <duration>` | Cancel after duration (e.g., `30s`, `5m`) |
| `--output <path>` / `-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
examples/ Example console app (see hero GIF above)
specs/ Constitution and library specification
scripts/ Tooling and recording scripts
docs/ Images and documentation assets
```

## Build
## Building from source

Requires .NET 10 SDK. Solution file: `Terminal.Gui.Cli.slnx`.
Requires **.NET 10 SDK**. Solution: `Terminal.Gui.Cli.slnx`.

```sh
dotnet restore Terminal.Gui.Cli.slnx
dotnet build Terminal.Gui.Cli.slnx

# Tests
# Run all test tiers
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
# Try the 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.
**Alpha** — `0.1.0-develop` pre-release. API surface is stabilizing; breaking changes possible.

## Contributing

See [`specs/constitution.md`](specs/constitution.md) for architectural rules and PR requirements.

## License

MIT; see [`LICENSE`](LICENSE).
MIT see [`LICENSE`](LICENSE).
Binary file modified docs/images/hero.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading