Skip to content

fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1)#22

Merged
tig merged 3 commits into
developfrom
fix/markdown-renderer-lifecycle
Jun 11, 2026
Merged

fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1)#22
tig merged 3 commits into
developfrom
fix/markdown-renderer-lifecycle

Conversation

@tig

@tig tig commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

Fixes the constitution C1 violation flagged by Codex review on the back-merge PRs (#20/#21): MarkdownRenderer.RenderToAnsi called Application.Create() / app.Init() / app.Dispose() directly, even though only CliHost may call Terminal.Gui lifecycle entrypoints. This path is reachable from help --cat, root --help, and viewer --cat rendering, so lifecycle ownership was no longer centralized.

Changes

  • Add internal CliHost.RunHeadlessRender(width, height, render) that owns the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO environment scope).
  • MarkdownRenderer.RenderToAnsi keeps its public signature and now only performs view layout/drawing inside the callback. Encoding handling and width/height probing are unchanged.
  • Separate style commit: pre-existing new () / unchecked ( spacing deviations surfaced by the pinned dotnet jb cleanupcode pass, committed so the CI cleanup + clean-diff gate stays green.

No public API change (so no specs/ update required under C2); rendering behavior is unchanged.

Residual C1 note (intentionally out of scope)

InputCommandRunner still carries a defensive if (!app.Initialized) app.Init() — it exists only because CliHost.RunWithTerminalGuiAsync currently skips Init() for inline input commands. PR #9 fixes that root cause (always Init() in CliHost); once #9 merges, the defensive call becomes dead and can be removed. Removing it here would break inline input commands on develop and conflict with #9.

Verification

  • dotnet build — 0 warnings, 0 errors
  • Unit tests: 20/20 pass; integration tests: 32/32 pass
  • dotnet jb cleanupcode + dotnet format → clean git diff

🤖 Generated with Claude Code

tig and others added 3 commits June 11, 2026 10:01
…g in CliHost

MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering.

Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again.

No public API change; rendering behavior is unchanged.

Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tig tig merged commit f4398a8 into develop Jun 11, 2026
6 checks passed
tig added a commit that referenced this pull request Jun 11, 2026
The defensive init existed only because CliHost previously skipped Init() for inline input commands. This branch makes CliHost always call app.Init() before command.RunAsync, so the call is dead code — and it was itself a C1 violation (only CliHost may call Terminal.Gui lifecycle APIs). Completes the lifecycle centralization started in #22.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tig added a commit that referenced this pull request Jun 11, 2026
* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22)

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost

MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering.

Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again.

No public API change; rendering behavior is unchanged.

Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style: apply ReSharper cleanup normalizations

Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Revert "style: apply ReSharper cleanup normalizations"

This reverts commit 25921ba.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Library improvements extracted from survey example work (#23)

* feat: library improvements extracted from survey example work (#9)

Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here):

CliHost:
- Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently
- Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly
- Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create()
- Run DefaultCommand when args are empty instead of falling through to root help

JSON envelope (constitution C4):
- Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine

InputCommandRunner:
- Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation

Docs/specs (constitution C2):
- Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md
- Fix stale example project paths in README.md and examples/greet/README.md

Tests/infra:
- Add envelope resolver round-trip test
- Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions)
- Bump Terminal.Gui to 2.4.3 release

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: preserve caller-supplied writers after TUI shutdown (Codex P2)

The post-TUI console refresh used `stdout is not StringWriter` to decide
whether to re-acquire Console.Out/Error, so any caller-supplied writer
that was not a StringWriter (e.g. a StreamWriter over a stream or file)
was silently replaced and the result went to the process console.

Capture whether each writer is the real console (by reference) before
Terminal.Gui runs - the comparison is only valid then, since changing
Console.OutputEncoding replaces Console.Out/Error - and refresh each
writer independently, leaving caller-supplied writers untouched.

Adds an integration regression test that routes the TUI path through a
StreamWriter-over-MemoryStream stdout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump version to 0.2.0-develop for upcoming release

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tig added a commit that referenced this pull request Jun 11, 2026
* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Release v0.1.0-beta.1 (#17)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove duplicate TestSetup class introduced by merge

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* Release v0.1.0 (#19)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Release v0.2.0 (#24)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22)

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost

MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering.

Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again.

No public API change; rendering behavior is unchanged.

Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style: apply ReSharper cleanup normalizations

Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Revert "style: apply ReSharper cleanup normalizations"

This reverts commit 25921ba.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Library improvements extracted from survey example work (#23)

* feat: library improvements extracted from survey example work (#9)

Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here):

CliHost:
- Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently
- Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly
- Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create()
- Run DefaultCommand when args are empty instead of falling through to root help

JSON envelope (constitution C4):
- Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine

InputCommandRunner:
- Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation

Docs/specs (constitution C2):
- Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md
- Fix stale example project paths in README.md and examples/greet/README.md

Tests/infra:
- Add envelope resolver round-trip test
- Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions)
- Bump Terminal.Gui to 2.4.3 release

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: preserve caller-supplied writers after TUI shutdown (Codex P2)

The post-TUI console refresh used `stdout is not StringWriter` to decide
whether to re-acquire Console.Out/Error, so any caller-supplied writer
that was not a StringWriter (e.g. a StreamWriter over a stream or file)
was silently replaced and the result went to the process console.

Capture whether each writer is the real console (by reference) before
Terminal.Gui runs - the comparison is only valid then, since changing
Console.OutputEncoding replaces Console.Out/Error - and refresh each
writer independently, leaving caller-supplied writers untouched.

Adds an integration regression test that routes the TUI path through a
StreamWriter-over-MemoryStream stdout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump version to 0.2.0-develop for upcoming release

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tig added a commit that referenced this pull request Jun 11, 2026
* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22)

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost

MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering.

Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again.

No public API change; rendering behavior is unchanged.

Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style: apply ReSharper cleanup normalizations

Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Revert "style: apply ReSharper cleanup normalizations"

This reverts commit 25921ba.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Library improvements extracted from survey example work (#23)

* feat: library improvements extracted from survey example work (#9)

Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here):

CliHost:
- Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently
- Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly
- Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create()
- Run DefaultCommand when args are empty instead of falling through to root help

JSON envelope (constitution C4):
- Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine

InputCommandRunner:
- Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation

Docs/specs (constitution C2):
- Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md
- Fix stale example project paths in README.md and examples/greet/README.md

Tests/infra:
- Add envelope resolver round-trip test
- Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions)
- Bump Terminal.Gui to 2.4.3 release

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: preserve caller-supplied writers after TUI shutdown (Codex P2)

The post-TUI console refresh used `stdout is not StringWriter` to decide
whether to re-acquire Console.Out/Error, so any caller-supplied writer
that was not a StringWriter (e.g. a StreamWriter over a stream or file)
was silently replaced and the result went to the process console.

Capture whether each writer is the real console (by reference) before
Terminal.Gui runs - the comparison is only valid then, since changing
Console.OutputEncoding replaces Console.Out/Error - and refresh each
writer independently, leaving caller-supplied writers untouched.

Adds an integration regression test that routes the TUI path through a
StreamWriter-over-MemoryStream stdout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump version to 0.2.0-develop for upcoming release

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Back-merge v0.2.0 from main into develop (#25)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Release v0.1.0-beta.1 (#17)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove duplicate TestSetup class introduced by merge

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* Release v0.1.0 (#19)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Release v0.2.0 (#24)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22)

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost

MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering.

Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again.

No public API change; rendering behavior is unchanged.

Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style: apply ReSharper cleanup normalizations

Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Revert "style: apply ReSharper cleanup normalizations"

This reverts commit 25921ba.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Library improvements extracted from survey example work (#23)

* feat: library improvements extracted from survey example work (#9)

Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here):

CliHost:
- Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently
- Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly
- Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create()
- Run DefaultCommand when args are empty instead of falling through to root help

JSON envelope (constitution C4):
- Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine

InputCommandRunner:
- Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation

Docs/specs (constitution C2):
- Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md
- Fix stale example project paths in README.md and examples/greet/README.md

Tests/infra:
- Add envelope resolver round-trip test
- Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions)
- Bump Terminal.Gui to 2.4.3 release

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: preserve caller-supplied writers after TUI shutdown (Codex P2)

The post-TUI console refresh used `stdout is not StringWriter` to decide
whether to re-acquire Console.Out/Error, so any caller-supplied writer
that was not a StringWriter (e.g. a StreamWriter over a stream or file)
was silently replaced and the result went to the process console.

Capture whether each writer is the real console (by reference) before
Terminal.Gui runs - the comparison is only valid then, since changing
Console.OutputEncoding replaces Console.Out/Error - and refresh each
writer independently, leaving caller-supplied writers untouched.

Adds an integration regression test that routes the TUI path through a
StreamWriter-over-MemoryStream stdout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump version to 0.2.0-develop for upcoming release

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: restore Application.AppModel after dispatch and lock in init contract (#27)

Application.AppModel is process-wide static state. RunWithTerminalGuiAsync
left it set to the dispatched command's app model (e.g. Inline), so later
Terminal.Gui sessions in the same process - embedding scenarios, headless
MarkdownRenderer rendering - inherited the wrong model. Save the previous
value and restore it in a finally block (issue #26).

Adds regression tests written first:
- InputCommand_Inline_RestoresAppModelAfterDispatch and
  InputCommand_ThrowsCancellation_RestoresAppModel failed before the fix.
- InputCommand_Inline_ReceivesInitializedApplication locks in the
  ICliCommand.RunAsync init contract for the inline path (issue #18,
  already fixed by the always-Init change in #23).

Fixes #18
Fixes #26

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* chore: bump version to 0.2.1-develop for upcoming release

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
tig added a commit that referenced this pull request Jun 11, 2026
* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Release v0.1.0-beta.1 (#17)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove duplicate TestSetup class introduced by merge

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* Release v0.1.0 (#19)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Release v0.2.0 (#24)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22)

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost

MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering.

Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again.

No public API change; rendering behavior is unchanged.

Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style: apply ReSharper cleanup normalizations

Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Revert "style: apply ReSharper cleanup normalizations"

This reverts commit 25921ba2e94cb5bd699c766a8b81f84bc9e2df8d.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Library improvements extracted from survey example work (#23)

* feat: library improvements extracted from survey example work (#9)

Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here):

CliHost:
- Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently
- Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly
- Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create()
- Run DefaultCommand when args are empty instead of falling through to root help

JSON envelope (constitution C4):
- Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine

InputCommandRunner:
- Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation

Docs/specs (constitution C2):
- Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md
- Fix stale example project paths in README.md and examples/greet/README.md

Tests/infra:
- Add envelope resolver round-trip test
- Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions)
- Bump Terminal.Gui to 2.4.3 release

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: preserve caller-supplied writers after TUI shutdown (Codex P2)

The post-TUI console refresh used `stdout is not StringWriter` to decide
whether to re-acquire Console.Out/Error, so any caller-supplied writer
that was not a StringWriter (e.g. a StreamWriter over a stream or file)
was silently replaced and the result went to the process console.

Capture whether each writer is the real console (by reference) before
Terminal.Gui runs - the comparison is only valid then, since changing
Console.OutputEncoding replaces Console.Out/Error - and refresh each
writer independently, leaving caller-supplied writers untouched.

Adds an integration regression test that routes the TUI path through a
StreamWriter-over-MemoryStream stdout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump version to 0.2.0-develop for upcoming release

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Release v0.2.1 (#28)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost (C1) (#22)

* fix: centralize Terminal.Gui lifecycle for headless markdown rendering in CliHost

MarkdownRenderer.RenderToAnsi previously called Application.Create()/Init()/Dispose() directly, violating constitution C1 (only CliHost may call Terminal.Gui lifecycle APIs). This path is reachable from help --cat, root --help, and viewer --cat rendering.

Move the headless ANSI-driver create/init/dispose block (including the DisableRealDriverIO scope) into an internal CliHost.RunHeadlessRender(width, height, render) helper. MarkdownRenderer keeps its public signature and now only performs view layout and drawing inside the callback, so lifecycle ownership is centralized again.

No public API change; rendering behavior is unchanged.

Note: InputCommandRunner still carries a defensive app.Init() that exists only because CliHost skips Init() for inline input commands; PR #9 fixes that root cause, after which the defensive call can be removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style: apply ReSharper cleanup normalizations

Pre-existing deviations surfaced by the pinned 'dotnet jb cleanupcode' pass: space before parens in generic 'new ()' constraints and after 'unchecked'. Committed so the CI cleanup + clean-diff gate passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Revert "style: apply ReSharper cleanup normalizations"

This reverts commit 25921ba2e94cb5bd699c766a8b81f84bc9e2df8d.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Library improvements extracted from survey example work (#23)

* feat: library improvements extracted from survey example work (#9)

Non-survey changes split out of #9 (the survey example itself is destined for spectre-console/Examples and will not merge here):

CliHost:
- Route non-success viewer --cat results through ResultWriter so diagnostics reach stderr (or the --json error envelope) instead of exiting silently
- Force UTF-8 and re-acquire Console.Out/Error after a Terminal.Gui session so post-TUI Unicode output renders correctly
- Always call app.Init() before command.RunAsync (restores the ICliCommand.RunAsync contract for inline input commands); set Application.AppModel before Create()
- Run DefaultCommand when args are empty instead of falling through to root help

JSON envelope (constitution C4):
- Add CliHostOptions.ResultJsonResolver so consumer result types serialize through source-generated contexts; threaded through JsonEnvelope.ToJson and ResultWriter.Write via JsonTypeInfoResolver.Combine

InputCommandRunner:
- Remove defensive app.Init() — dead now that CliHost always initializes, and itself a C1 violation

Docs/specs (constitution C2):
- Document ResultJsonResolver and DefaultCommand dispatch in specs/library-spec.md
- Fix stale example project paths in README.md and examples/greet/README.md

Tests/infra:
- Add envelope resolver round-trip test
- Make HelpCommand integration tests CI-stable (drop nondeterministic driver-buffer assertions)
- Bump Terminal.Gui to 2.4.3 release

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: preserve caller-supplied writers after TUI shutdown (Codex P2)

The post-TUI console refresh used `stdout is not StringWriter` to decide
whether to re-acquire Console.Out/Error, so any caller-supplied writer
that was not a StringWriter (e.g. a StreamWriter over a stream or file)
was silently replaced and the result went to the process console.

Capture whether each writer is the real console (by reference) before
Terminal.Gui runs - the comparison is only valid then, since changing
Console.OutputEncoding replaces Console.Out/Error - and refresh each
writer independently, leaving caller-supplied writers untouched.

Adds an integration regression test that routes the TUI path through a
StreamWriter-over-MemoryStream stdout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump version to 0.2.0-develop for upcoming release

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Back-merge v0.2.0 from main into develop (#25)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Release v0.1.0-beta.1 (#17)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks (#14)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help TUI: set Markdown.Text in Initialized handler, add integration tests

The help command's TUI viewer rendered empty content because
Markdown.Text was set before the view was initialized/laid out.
Following the pattern from gui-cs/clet's MarkdownClet, set the text
inside the Initialized event handler on the containing Runnable.

Also switches from RunnableWrapper to a plain Runnable with an embedded
Markdown view — the help viewer is read-only and needs no result
extraction.

Adds integration tests using Application.Create()/Init(ansi) with
StopAfterFirstIteration to verify:
- The TUI renders without hanging
- Driver contents contain expected command text
- Subcommand help renders correctly
- RenderCatAsync produces ANSI output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add hero GIF recording and polish README

- Re-record docs/images/hero.gif using tuirec v0.4.0 with the example app
- Rewrite README for clarity: add badges, a Why section, feature table,
  real JSON output example, contributing pointer, and cleaner structure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MarkdownRenderer global state leaks

- Save and restore DisableRealDriverIO env var in finally block
- Move app.Init inside try/finally so cleanup runs if Init throws
- Add MarkdownRendererTests verifying env var restoration
- Disable test parallelization (Terminal.Gui uses global state)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: set IApplication.AppModel and defer Init() for inline input commands (#16)

RunWithTerminalGuiAsync previously always called Init() regardless of whether
the command actually uses the TUI. For inline input commands, Init() modifies
terminal state (cursor save/scroll), and if the command returns without
running the TUI event loop (e.g. greet hello), Dispose() restores the cursor
to the wrong position, causing output to appear at incorrect rows.

Fix:
- Set app.AppModel on the IApplication instance (not the process-wide static)
- Only call Init() upfront for fullscreen commands (viewers, --fullscreen)
- For inline input commands, defer Init() to InputCommandRunner where the
  TUI is actually started via app.RunAsync()
- Commands that compute and return without TUI (like greet) never trigger
  Init(), so terminal state is never modified

Fixes #15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove duplicate TestSetup class introduced by merge

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* Release v0.1.0 (#19)

* feat: help TUI viewer, markdown rendering, rename ExampleApp to greet

- HelpCommand.RunAsync launches a TUI Markdown viewer (Runnable +
  Markdown + StatusBar) matching clet's pattern, instead of returning
  raw text in CommandResult
- MetadataHelpProvider.GetRootHelp emits markdown (tables, headers)
  instead of plain text
- CliHost.WriteRootFlag passes --help output through
  MarkdownRenderer.RenderToAnsi for ANSI-styled stdout
- Rename examples/Terminal.Gui.Cli.ExampleApp to examples/greet
  with AssemblyName=greet
- Add README.md for the greet example app
- Add visual UI tests (CommandUiHarness + golden-file assertions)
  ported from clet's CletUiHarness pattern
- Add MetadataHelpProviderTests and CliHost help rendering tests

Closes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix terminal encoding for ANSI rendering and add multiple help topics

- Port clet's MarkdownHelpRenderer approach: set Console.OutputEncoding to
  UTF-8 before rendering, use a full TG ANSI driver with proper layout/draw
  cycle, and restore encoding afterward. Fixes garbled box-drawing chars.
- Add FarewellCommand with --until option for navigation testing
- Add embedded markdown help files (help.md, greet.md, farewell.md, info.md)
- Configure EmbeddedMarkdownHelpProvider in greet example
- Fix InfoCommand to properly launch TUI viewer (was returning text without
  calling app.RunAsync, causing terminal to hang until Enter pressed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add default command support, help link navigation, and fix positional args

- Add DefaultCommand option to CliHostOptions so bare args/options are
  retried as the default command (e.g. 'greet World' == 'greet greet World')
- Refactor CliHost.RunAsync into DispatchCommandAsync/ExecuteCommandAsync
- Add help:topic link navigation in HelpCommand via Markdown.LinkClicked
- Add 'Back to main help' links in all sub-topic help files
- Add help:command anchors in root help.md for topic navigation
- Make GreetCommand and FarewellCommand accept positional args for name
- Set greet example DefaultCommand = 'greet'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Port clet's BrowseBar with back/forward nav and syntax highlighting

- Add BrowseBar (ported from clet) with back/forward history stacks,
  Ctrl+Left/Right shortcuts, and proper statusbar styling
- Rewrite HelpCommand.RunAsync to match clet's HelpClet pattern:
  BrowseBar, LinkClicked handler, NavigateTo, viewport reset
- Add TextMateSyntaxHighlighter for code block coloring
- Add horizontal scrollbar to markdown view
- Update golden file for new status bar layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add visual help browser tests and greet example execution tests

- HelpBrowserUiTests: proves BrowseBar back/forward arrows render,
  embedded help content displays, subcommand view shows options,
  and golden file assertion for the browser layout
- GreetExampleTests: proves every documented example in the help files
  actually works (greet World, --formal Alice, farewell Bob,
  farewell --until tomorrow Bob, default command dispatch, etc.)
- Add embedded help.md resource to integration test assembly
- Total: 24 integration tests, 17 unit tests (41 total, all passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Escape markdown table cells in MetadataHelpProvider

Pipe characters and newlines in command/option descriptions would break
the generated markdown table structure. Add EscapeCell helper that
replaces | with \| and collapses newlines to spaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use explicit type in collection expression for ReSharper compliance

ReSharper cannot infer target type for 'new' inside collection expressions,
so use explicit 'new CommandOptionDescriptor(...)' instead of 'new (...)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add SourceLink and symbol package support (#11)

Enable source debugging and .snupkg generation for NuGet consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Back-merge main into develop (#13)

* Plan: help command and --help flag should render markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix help command and --help flag to render markdown

- Convert MetadataHelpProvider.GetRootHelp to generate markdown with
  ## headings, bullet lists, and backtick formatting
- Fix CliHost.WriteRootFlag to render via MarkdownRenderer.RenderToAnsi
  instead of plain stdout.WriteLine
- Fix HelpCommand.RunAsync to display markdown in a fullscreen
  Terminal.Gui Markdown viewer using RunnableWrapper
- Add tests for --help ANSI output, help --cat, and MetadataHelpProvider
  markdown generation

Fixes #5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant