diff --git a/CLAUDE.md b/CLAUDE.md
index 63c2c87..0df42db 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -21,7 +21,7 @@ If guidance conflicts, follow `specs/constitution.md`.
- `tests/Terminal.Gui.Cli.Tests` — unit tests
- `tests/Terminal.Gui.Cli.IntegrationTests` — integration tests
- `tests/Terminal.Gui.Cli.SmokeTests` — smoke tests
-- `examples/Terminal.Gui.Cli.ExampleApp` — sample console app
+- `examples/greet` — sample console app
## Build and test
diff --git a/Terminal.Gui.Cli.slnx b/Terminal.Gui.Cli.slnx
index 2a828b3..f78cb7c 100644
--- a/Terminal.Gui.Cli.slnx
+++ b/Terminal.Gui.Cli.slnx
@@ -16,7 +16,7 @@
-
+
diff --git a/examples/Terminal.Gui.Cli.ExampleApp/InfoCommand.cs b/examples/Terminal.Gui.Cli.ExampleApp/InfoCommand.cs
deleted file mode 100644
index b9331d2..0000000
--- a/examples/Terminal.Gui.Cli.ExampleApp/InfoCommand.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using Terminal.Gui.App;
-
-namespace Terminal.Gui.Cli.ExampleApp;
-
-/// A viewer command that displays application information.
-public sealed class InfoCommand : IViewerCommand
-{
- private const string InfoText = """
- Example App v1.0.0
- A demonstration of the Terminal.Gui.Cli library.
-
- This app shows how to:
- - Register input and viewer commands
- - Use --help, --json, --opencli, and agent-guide
- - Embed an agent-guide.md resource
- - Support --cat for headless content rendering
- """;
-
- ///
- public string PrimaryAlias => "info";
-
- ///
- public IReadOnlyList Aliases { get; } = ["info"];
-
- ///
- public string Description => "Display application information.";
-
- ///
- public CommandKind Kind => CommandKind.Viewer;
-
- ///
- public Type ResultType => typeof (string);
-
- ///
- public IReadOnlyList Options { get; } = [];
-
- ///
- public Task RunAsync (
- IApplication app,
- string? initial,
- CommandRunOptions options,
- CancellationToken cancellationToken)
- {
- return Task.FromResult (new CommandResult (CommandStatus.Ok, InfoText, null, null));
- }
-
- ///
- public Task RenderCatAsync (
- CommandRunOptions options,
- TextWriter stdout,
- CancellationToken cancellationToken)
- {
- ArgumentNullException.ThrowIfNull (stdout);
- stdout.Write (InfoText);
- return Task.FromResult (new CommandResult (CommandStatus.Ok, null, null, null));
- }
-}
diff --git a/examples/Terminal.Gui.Cli.ExampleApp/Program.cs b/examples/Terminal.Gui.Cli.ExampleApp/Program.cs
deleted file mode 100644
index e241dff..0000000
--- a/examples/Terminal.Gui.Cli.ExampleApp/Program.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Reflection;
-using Terminal.Gui.Cli;
-using Terminal.Gui.Cli.ExampleApp;
-
-CliHost host = new (options =>
-{
- options.ApplicationName = "example-app";
- options.Version = "1.0.0";
- options.AgentGuide = "Terminal.Gui.Cli.ExampleApp.agent-guide.md";
- options.AgentGuideIsResource = true;
- options.ResourceAssembly = Assembly.GetExecutingAssembly ();
-});
-
-host.Registry.Register (new GreetCommand ());
-host.Registry.Register (new InfoCommand ());
-
-return await host.RunAsync (args);
diff --git a/examples/Terminal.Gui.Cli.ExampleApp/Terminal.Gui.Cli.ExampleApp.csproj b/examples/Terminal.Gui.Cli.ExampleApp/Terminal.Gui.Cli.ExampleApp.csproj
deleted file mode 100644
index 3737551..0000000
--- a/examples/Terminal.Gui.Cli.ExampleApp/Terminal.Gui.Cli.ExampleApp.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- Exe
- Terminal.Gui.Cli.ExampleApp
- Terminal.Gui.Cli.ExampleApp
- false
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/greet/FarewellCommand.cs b/examples/greet/FarewellCommand.cs
new file mode 100644
index 0000000..5e269fc
--- /dev/null
+++ b/examples/greet/FarewellCommand.cs
@@ -0,0 +1,52 @@
+using Terminal.Gui.App;
+
+namespace Terminal.Gui.Cli.Greet;
+
+/// An input command that says goodbye to someone.
+public sealed class FarewellCommand : ICliCommand
+{
+ ///
+ public string PrimaryAlias => "farewell";
+
+ ///
+ public IReadOnlyList Aliases { get; } = ["farewell", "bye"];
+
+ ///
+ public string Description => "Say goodbye to someone.";
+
+ ///
+ public CommandKind Kind => CommandKind.Input;
+
+ ///
+ public Type ResultType => typeof (string);
+
+ ///
+ public IReadOnlyList Options { get; } =
+ [
+ new ("until", "u", typeof (string), "When you expect to meet again.", false, null)
+ ];
+
+ ///
+ public bool AcceptsPositionalArgs => true;
+
+ ///
+ public Task> RunAsync (
+ IApplication app,
+ string? initial,
+ CommandRunOptions options,
+ CancellationToken cancellationToken)
+ {
+ var name = options.Arguments.Count > 0
+ ? string.Join (" ", options.Arguments)
+ : initial ?? "World";
+ var until = options.CommandOptions.TryGetValue ("until", out var untilValue)
+ ? untilValue
+ : null;
+
+ var farewell = until is not null
+ ? $"Goodbye, {name}! See you {until}."
+ : $"Goodbye, {name}!";
+
+ return Task.FromResult (new CommandResult (CommandStatus.Ok, farewell, null, null));
+ }
+}
diff --git a/examples/Terminal.Gui.Cli.ExampleApp/GreetCommand.cs b/examples/greet/GreetCommand.cs
similarity index 85%
rename from examples/Terminal.Gui.Cli.ExampleApp/GreetCommand.cs
rename to examples/greet/GreetCommand.cs
index f0308ca..766d164 100644
--- a/examples/Terminal.Gui.Cli.ExampleApp/GreetCommand.cs
+++ b/examples/greet/GreetCommand.cs
@@ -1,6 +1,6 @@
using Terminal.Gui.App;
-namespace Terminal.Gui.Cli.ExampleApp;
+namespace Terminal.Gui.Cli.Greet;
/// An input command that prompts for a name and returns a greeting.
public sealed class GreetCommand : ICliCommand
@@ -26,6 +26,9 @@ public sealed class GreetCommand : ICliCommand
new ("formal", "f", typeof (bool), "Use a formal greeting style.", false, null)
];
+ ///
+ public bool AcceptsPositionalArgs => true;
+
///
public Task> RunAsync (
IApplication app,
@@ -33,7 +36,10 @@ public Task> RunAsync (
CommandRunOptions options,
CancellationToken cancellationToken)
{
- var name = initial ?? "World";
+ var name = options.Arguments.Count > 0
+ ? string.Join (" ", options.Arguments)
+ : initial ?? "World";
+
var formal = options.CommandOptions.TryGetValue ("formal", out var formalValue)
&& formalValue.Equals ("true", StringComparison.OrdinalIgnoreCase);
diff --git a/examples/greet/InfoCommand.cs b/examples/greet/InfoCommand.cs
new file mode 100644
index 0000000..82ce38c
--- /dev/null
+++ b/examples/greet/InfoCommand.cs
@@ -0,0 +1,102 @@
+using Terminal.Gui.App;
+using Terminal.Gui.Input;
+using Terminal.Gui.ViewBase;
+using Terminal.Gui.Views;
+
+namespace Terminal.Gui.Cli.Greet;
+
+/// A viewer command that displays application information in a TUI markdown view.
+public sealed class InfoCommand : IViewerCommand
+{
+ private const string InfoMarkdown = """
+ # greet — Info
+
+ **Version:** 1.0.0
+
+ A demonstration of the `Terminal.Gui.Cli` library.
+
+ ## Features
+
+ This app shows how to:
+
+ - Register input and viewer commands
+ - Use `--help`, `--json`, `--opencli`, and `agent-guide`
+ - Embed an `agent-guide.md` resource
+ - Support `--cat` for headless content rendering
+ - Launch a TUI markdown viewer for `help` and `info`
+
+ ## Usage
+
+ ```
+ greet [name] Greet someone (default: World)
+ greet --formal [name] Use a formal greeting style
+ greet help Browse help topics
+ greet help greet Help for the greet command
+ greet info Show this info page
+ greet --help Render help as ANSI to stdout
+ ```
+ """;
+
+ ///
+ public string PrimaryAlias => "info";
+
+ ///
+ public IReadOnlyList Aliases { get; } = ["info"];
+
+ ///
+ public string Description => "Display application information.";
+
+ ///
+ public CommandKind Kind => CommandKind.Viewer;
+
+ ///
+ public Type ResultType => typeof (void);
+
+ ///
+ public IReadOnlyList Options { get; } = [];
+
+ ///
+ public async Task RunAsync (
+ IApplication app,
+ string? initial,
+ CommandRunOptions options,
+ CancellationToken cancellationToken)
+ {
+ Runnable window = new ()
+ {
+ Title = "Info",
+ Width = Dim.Fill (),
+ Height = Dim.Fill ()
+ };
+
+ Markdown markdownView = new ()
+ {
+ Width = Dim.Fill (),
+ Height = Dim.Fill (1)
+ };
+
+ StatusBar statusBar = new (
+ [
+ new Shortcut (Application.GetDefaultKey (Command.Quit), "Quit", window.RequestStop)
+ ]);
+
+ window.Add (markdownView, statusBar);
+
+ window.Initialized += (_, _) => { markdownView.Text = InfoMarkdown; };
+
+ await app.RunAsync (window, cancellationToken);
+
+ return new CommandResult (CommandStatus.Ok, null, null, null);
+ }
+
+ ///
+ public Task RenderCatAsync (
+ CommandRunOptions options,
+ TextWriter stdout,
+ CancellationToken cancellationToken)
+ {
+ ArgumentNullException.ThrowIfNull (stdout);
+ MarkdownRenderer.RenderToAnsi (InfoMarkdown, stdout);
+ return Task.FromResult (new CommandResult (CommandStatus.Ok, null, null, null));
+ }
+}
diff --git a/examples/greet/Program.cs b/examples/greet/Program.cs
new file mode 100644
index 0000000..2c8480d
--- /dev/null
+++ b/examples/greet/Program.cs
@@ -0,0 +1,22 @@
+using System.Reflection;
+using Terminal.Gui.Cli;
+using Terminal.Gui.Cli.Greet;
+
+Assembly assembly = Assembly.GetExecutingAssembly ();
+
+CliHost host = new (options =>
+{
+ options.ApplicationName = "greet";
+ options.Version = "1.0.0";
+ options.DefaultCommand = "greet";
+ options.AgentGuide = "Terminal.Gui.Cli.Greet.agent-guide.md";
+ options.AgentGuideIsResource = true;
+ options.ResourceAssembly = assembly;
+ options.HelpProvider = new EmbeddedMarkdownHelpProvider (assembly);
+});
+
+host.Registry.Register (new GreetCommand ());
+host.Registry.Register (new FarewellCommand ());
+host.Registry.Register (new InfoCommand ());
+
+return await host.RunAsync (args);
diff --git a/examples/greet/README.md b/examples/greet/README.md
new file mode 100644
index 0000000..11ee92f
--- /dev/null
+++ b/examples/greet/README.md
@@ -0,0 +1,51 @@
+# greet
+
+A sample CLI app built with `Terminal.Gui.Cli` that generates greetings.
+
+## Usage
+
+```bash
+# Launch the TUI greeting prompt
+greet greet
+
+# Provide a name directly (headless)
+greet greet --initial "Alice"
+
+# Formal greeting style
+greet greet --initial "Bob" --formal
+
+# JSON envelope output
+greet greet --initial "World" --json
+
+# Show help in the TUI markdown viewer
+greet help
+
+# Render help as ANSI markdown to stdout
+greet help --cat
+
+# Show root help (ANSI markdown to stdout)
+greet --help
+
+# Show version
+greet --version
+```
+
+## Commands
+
+| Command | Description |
+|---------|-------------|
+| `greet` | Prompt for a name and return a greeting. |
+| `info` | Display application information. |
+| `help` | Show command help in a TUI markdown viewer. |
+
+## Building
+
+```bash
+dotnet build examples/Terminal.Gui.Cli.Greet/Terminal.Gui.Cli.Greet.csproj
+```
+
+## Running
+
+```bash
+dotnet run --project examples/Terminal.Gui.Cli.Greet -- greet --initial "World"
+```
diff --git a/examples/greet/Resources/Help/farewell.md b/examples/greet/Resources/Help/farewell.md
new file mode 100644
index 0000000..20e2ae7
--- /dev/null
+++ b/examples/greet/Resources/Help/farewell.md
@@ -0,0 +1,36 @@
+# farewell
+
+Say goodbye to someone.
+
+[Back to main help](help:help)
+
+## Usage
+
+```
+farewell [name]
+farewell --until