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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/content/docs/getting-started/cli-mode.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Commands:
client {id} remove
```

Help also lists a `Global Options:` section covering the built-in flags and any [custom global options](/reference/dependency-injection/#global-options) you registered, with their descriptions.

## Shell completion

Register Repl's completion scripts to get tab completion in your shell:
Expand All @@ -74,6 +76,27 @@ myapp completion install --shell nu # Nushell

This writes a managed block to the shell's profile file. Tab completion then works for all routes, context segments, and option names.

**What completion returns:**

- Command literals and context segments from your graph.
- The route's own options, plus static global options (`--help`, `--interactive`, `--no-interactive`, `--no-logo`, output aliases, `--output:<format>`, `--answer:<name>`, and the result-flow flags `--result:page-size`, `--result:cursor`, `--result:pager`, `--result:all`).
- Enum member names for a pending enum-typed option.
- `.WithCompletion(...)` provider values — **opt-in per provider**.

Every shell Tab spawns a new process and blocks the shell until the app answers, so a slow completion provider (network, database) must never run there implicitly. A provider only serves shell completion when its registration opts in:

```csharp
app.Map("contact inspect {clientId}", (string clientId) => Inspect(clientId))
.WithCompletion(
"clientId",
(ctx, input, ct) => LookupClientIdsAsync(input, ct),
CompletionProviderScope.InteractiveAndShell);
```

The default scope (`CompletionProviderScope.Interactive`) keeps the provider on in-process surfaces only: the interactive Tab menu and the `complete` ambient command. Each provider invocation is also bounded by `ShellCompletionOptions.ProviderTimeout` (default: 1 second) — a stalled provider degrades completion to the static candidates instead of blocking the shell.

Shell completion and the [interactive REPL autocomplete](/getting-started/repl-mode/#history-and-completion) draw candidates from the same source and parse prior tokens the same way. Two deliberate differences remain: on an empty token after a complete command, shell completion lists option names while the interactive menu shows parameter placeholders (options appear from the first typed `-`); and the interactive menu runs every registered provider while the shell bridge only runs opted-in ones.

**Other commands:**

```bash
Expand Down
10 changes: 9 additions & 1 deletion src/content/docs/getting-started/repl-mode.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,17 @@ These are always available in REPL mode regardless of your command graph:
## History and completion

- **Up/Down arrows** navigate command history.
- **Tab** triggers autocomplete for routes and parameters (requires `UseDefaultInteractive()`).
- **Tab** triggers autocomplete (requires `UseDefaultInteractive()`).
- History is in-memory by default and does not persist across sessions. Inject a custom <ApiRef uid="Repl.IHistoryProvider" /> to add persistence (file, database, or any backing store).

The Tab menu completes:

- **Routes and context segments** from your command graph, with parameter placeholders shown for the positions a command still expects.
- **Option names**, from the first typed `-`: the route's own options, global options (`--help`, `--output:<format>`, `--answer:<name>`, …), and the result-flow flags (`--result:page-size`, `--result:cursor`, `--result:pager`, `--result:all`).
- **Option and parameter values**: a `.WithCompletion(...)` provider runs first, and enum-typed parameters fall back to their member names (respecting the parameter's effective case sensitivity).

Unlike [shell completion](/getting-started/cli-mode/#shell-completion), which is opt-in per provider, the interactive menu runs every registered completion provider — it executes in-process, so there is no shell to block.

## Customizing the prompt

```csharp
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/reference/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ app.Context("admin", admin =>
| `.AsResource()` | Registers as an MCP resource (URI derived from route) |
| `.AsPrompt()` | Registers as an MCP prompt template |
| `.AsMcpAppResource()` | Registers as an MCP Apps UI resource |
| `.WithCompletion(provider)` | Registers Tab completion for this route |
| `.WithCompletion(targetName, provider[, scope])` | Registers Tab completion for the named parameter or option. The optional `CompletionProviderScope` (default `Interactive`) opts the provider into shell completion (`InteractiveAndShell`) |

## Parameters

Expand Down
21 changes: 13 additions & 8 deletions src/content/docs/reference/customization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ See [Result-Flow Paging](/reference/result-flow-paging/) for the full source pag

## ANSI capability levels

Repl detects the terminal's color capability at startup and chooses rendering accordingly.

Repl detects the terminal's color capability at startup and chooses rendering accordingly. Detected capability tiers (informational):

| Detected tier | Rendering |
Expand All @@ -70,11 +68,12 @@ Repl detects the terminal's color capability at startup and chooses rendering ac

**Detection chain** (first match wins):

1. `NO_COLOR` env var → disable ANSI
2. `CLICOLOR_FORCE` env var → force ANSI
3. `TERM` / `COLORTERM` heuristics
4. Platform-specific checks (Windows Console, VS Code terminal, etc.)
5. Redirection check (piped stdout → no ANSI)
1. Session override — a hosted session can force ANSI on or off (`TerminalSessionOverrides.AnsiSupported`)
2. Explicit `OutputOptions.AnsiMode` (`Always` / `Never`)
3. `NO_COLOR` env var → disable ANSI
4. `CLICOLOR_FORCE=1` env var → force ANSI (even when stdout is redirected)
5. `TERM=dumb` → disable ANSI
6. Redirection check (piped stdout → no ANSI)

Override programmatically using <ApiRef uid="Repl.Rendering.AnsiMode" />:

Expand Down Expand Up @@ -225,7 +224,13 @@ return new Panel(new Markup(content))

### Detecting Spectre capability

Spectre.Console detects terminal capabilities automatically. On terminals without ANSI support, all output degrades gracefully to plain text — no code changes needed.
Spectre rendering follows the same [ANSI detection chain](#ansi-capability-levels) as the rest of the framework — no configuration required:

- **Colors** are emitted only when the host detection allows ANSI; otherwise the color system degrades to `NoColors` and output stays plain text.
- **Unicode box-drawing** degrades per output sink: full Unicode borders when the sink's encoding carries them, Spectre's square ASCII-safe fallback on a legacy OEM codepage, and ASCII transliteration (`+`, `-`, `|`) when no box glyph survives (redirected consoles, CI logs, pipes). The active verdict is exposed as `SpectreTerminalDetection.CurrentBoxDrawingSupport` for diagnostics.
- **CI logs are plain by default** — Spectre's built-in CI enrichers are disabled so they cannot override the host detection. Set `CLICOLOR_FORCE=1` in the workflow to restore colored logs.

Outside a Repl container (bare `AddSpectreConsole()` without `UseSpectreConsole()`), the profile falls back to Spectre's own detection.

---

Expand Down
8 changes: 7 additions & 1 deletion src/content/docs/reference/dependency-injection.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,17 @@ Global options are flags available on every command invocation, parsed before th
```csharp
app.Options(o =>
{
o.Parsing.AddGlobalOption<string>("tenant");
o.Parsing.AddGlobalOption<bool>("verbose");

// With aliases, default value, and a help description
o.Parsing.AddGlobalOption<string>(
"tenant", aliases: ["t"], defaultValue: null,
description: "Tenant to operate on.");
});
```

Custom global options appear in `--help` under the `Global Options:` section, with their description (or `Custom global option.` when none was given). Default values are intentionally not displayed in help.

Access them in DI factory registrations:

```csharp
Expand Down
2 changes: 2 additions & 0 deletions src/content/docs/reference/mcp-concepts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ app.Map("prompts summarize {id:int}", (int id, IContactStore store) =>
.WithDescription("Generate a summary prompt for a contact.");
```

Non-optional route arguments are advertised as `required` in `prompts/list`, matching the validation `prompts/get` applies. Handlers that return a plain `string` surface it as the prompt's text — not as a quoted JSON string literal.

---

## MCP Apps
Expand Down
96 changes: 81 additions & 15 deletions src/content/docs/reference/terminal-integration.mdx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
title: Terminal Integration
description: Terminal features used by Repl — size detection, keyboard input, progress reporting, terminal capabilities, and the path toward a future TUI mode.
description: Terminal features used by Repl — size detection, keyboard input, progress reporting, shell-integration marks, terminal capabilities, and the path toward a future TUI mode.
---

import { Aside } from '@astrojs/starlight/components';
import ApiRef from '../../../components/ApiRef.astro';

Repl integrates with the host terminal at several levels: it detects window size, decodes VT keyboard sequences, emits progress notifications to capable terminals, and classifies terminal identity to adapt rendering. This page documents those interactions.
Repl integrates with the host terminal at several levels: it detects window size, decodes VT keyboard sequences, emits progress notifications and shell-integration marks to capable terminals, and classifies terminal identity to adapt rendering. This page documents those interactions.

**VT sequence notation used throughout this page:**

Expand All @@ -33,7 +33,7 @@ ANSI escape sequences are enabled or disabled based on a precedence chain:
| Redirected output | `Console.IsOutputRedirected` disables ANSI |
| `TERM=dumb` | Disables ANSI |

When ANSI is enabled, the default renderer uses **256-color** SGR styling (`38;5;N`). Add `Repl.Spectre` for 24-bit color (`38;2;r;g;b`) and richer rendering — Spectre.Console always requests true-color when ANSI is on.
When ANSI is enabled, the default renderer uses **256-color** SGR styling (`38;5;N`). Add `Repl.Spectre` for 24-bit color (`38;2;r;g;b`) and richer rendering — Spectre honors the same detection chain, requesting true-color when the host allows ANSI and degrading to plain text when it doesn't.

---

Expand Down Expand Up @@ -140,6 +140,68 @@ OSC 9;4 is never emitted when ANSI output is disabled or when the session is in

---

## Shell integration marks (OSC 133 / OSC 633)

Modern terminals understand semantic marks that delimit the prompt, the user input, and the command output. When the marks are present, the terminal can offer command navigation (jump between commands), command-aware selection and copy, success/failure decorations in the gutter, and sticky command headers. Repl owns the prompt and the command lifecycle in interactive mode, so it emits those marks itself — no shell script hooks required.

The feature is opt-in:

```csharp
var app = ReplApp.Create()
.UseTerminalIntegration(); // ShellIntegration = Auto by default

// or explicitly:
app.UseTerminalIntegration(options =>
{
options.ShellIntegration = ShellIntegrationMode.Always;
});
```

Each interactive prompt cycle is delimited with the FinalTerm semantic sequence (OSC 133), or the VS Code shell-integration dialect (OSC 633) when the VS Code integrated terminal is detected:

| Moment | Mark |
|---|---|
| Before the prompt text | `A` (prompt start) |
| After the prompt text, before input | `B` (input start) |
| After a committed line (VS Code only) | `E;<command line>` (command-line report) |
| Right before command execution | `C` (output start) |
| After the command completes | `D;<exit code>` (command end) |

Exit codes follow shell conventions: `0` for success, `1` for errors (failed results, unknown commands, validation failures), and `130` (128+SIGINT) when a command is cancelled with Ctrl+C. An abandoned cycle — Escape at the prompt, an empty line, or end of input — reports `D` without an exit code, the FinalTerm "command aborted" form.

### Modes

`ShellIntegrationMode` mirrors the `AdvancedProgressMode` semantics:

- **`Auto`** (default) — emit when the terminal is known to render marks. For a hosted session, only what the remote client advertised counts: `TerminalCapabilities.ShellIntegrationMarks`, usually inferred from its reported terminal identity. For the local console, the environment identifies Windows Terminal (`WT_SESSION`), VS Code (`TERM_PROGRAM=vscode`), or WezTerm (`TERM_PROGRAM=WezTerm`); multiplexers (tmux, GNU screen) stay off because mark positioning is unreliable through panes.
Comment thread
carldebilly marked this conversation as resolved.
- **`Always`** — emit whenever the structural gates allow it. Useful for terminals that render marks but are not auto-detected, such as iTerm2 reached over SSH.
- **`Never`** — never emit.

Regardless of mode, marks are never written when output is redirected (and no hosted session is active), when ANSI output is disabled (`NO_COLOR`, `TERM=dumb`, `AnsiMode.Never`), or around a protocol-passthrough command (MCP stdio, completion payloads) — no mark may sit inside a raw protocol stream.

CLI one-shot mode emits no marks: Repl does not own the surrounding shell prompt there, and fake prompt markers would corrupt the host shell's own command navigation.

<Aside type="caution">
The VS Code `E` mark reports the committed command line verbatim to the terminal, which may persist it for command detection and history — including secrets passed as command arguments. This mirrors what VS Code's own shell integration does for regular shells; if commands take secrets, prefer prompting for them interactively instead of passing them as arguments.
</Aside>

<Aside type="note">
Unlike VS Code, Windows Terminal (≥ 1.21) surfaces mark features only through explicit settings: `"showMarksOnScrollbar": true` on the profile for scrollbar pips, and `scrollToMark` actions bound to keys (e.g. Ctrl+Up/Down) for command navigation. Neither is on by default.
</Aside>

### Troubleshooting

Ask the running app first: <ApiRef uid="Repl.IReplSessionInfo" /> exposes `ShellIntegrationStatus`, which reports the detection outcome for the current prompt cycle — the active dialect (`"OSC 133"`, `"OSC 633 (VS Code)"`) or `"off (<gate>)"` naming the gate that disabled emission:

```csharp
app.Map("terminal", (IReplSessionInfo session) =>
session.ShellIntegrationStatus ?? "no prompt cycle yet");
```

If a terminal is misdetected and shows raw `]133;…` text, set `ShellIntegrationMode.Never` app-side, or use `NO_COLOR=1` as a local end-user escape hatch (it disables all ANSI styling, marks included). For hosted sessions, fix the identity or capabilities the client advertises — environment variables on the server affect every connected session.

---

## Terminal capabilities

When a session connects, Repl classifies its terminal identity to determine which capabilities to enable. The identity string comes from:
Expand All @@ -150,20 +212,23 @@ When a session connects, Repl classifies its terminal identity to determine whic

The classifier maps substrings of the identity string to capability flags:

| Terminal identity contains | `Ansi` | `ProgressReporting` | `VtInput` | `ResizeReporting` |
|---|---|---|---|---|
| `windows terminal` | ✓ | ✓ | ✓ | ✓ |
| `wezterm` | ✓ | ✓ | ✓ | ✓ |
| `iterm` | ✓ | ✓ | ✓ | ✓ |
| `ghostty` | ✓ | ✓ | ✓ | ✓ |
| `conemu` | ✓ | ✓ | ✓ | ✓ |
| `xterm`, `vt`, `ansi` | ✓ | | ✓ | ✓ |
| `alacritty`, `rxvt`, `konsole`, `gnome`, `linux` | ✓ | | ✓ | ✓ |
| `screen`, `tmux` | ✓ | | ✓ | ✓ |
| `dumb` | | | | |
| Terminal identity contains | `Ansi` | `ProgressReporting` | `ShellIntegrationMarks` | `VtInput` | `ResizeReporting` |
|---|---|---|---|---|---|
| `windows terminal` | ✓ | ✓ | ✓ | ✓ | ✓ |
| `wezterm` | ✓ | ✓ | ✓ | ✓ | ✓ |
| `iterm` | ✓ | ✓ | ✓ | ✓ | ✓ |
| `ghostty` | ✓ | ✓ | ✓ | ✓ | ✓ |
| `conemu` | ✓ | ✓ | | ✓ | ✓ |
| `vscode` | ✓ | | ✓ | ✓ | ✓ |
| `xterm`, `vt`, `ansi` | ✓ | | | ✓ | ✓ |
| `alacritty`, `rxvt`, `konsole`, `gnome`, `linux` | ✓ | | | ✓ | ✓ |
| `screen`, `tmux` | ✓ | | | ✓ | ✓ |
| `dumb` | | | | | |

Matching is case-insensitive and substring-based — `xterm-256color` matches `xterm`.

`ShellIntegrationMarks` is what [Auto mode](#modes) checks for hosted sessions. A `vscode` identity additionally selects the OSC 633 dialect. ConEmu deliberately lacks the flag: it renders OSC 9;4 progress but not FinalTerm/VS Code prompt marks.

`VtInput` enables VT keyboard sequence decoding. `ResizeReporting` enables live terminal resize events. Omitting either flag in a <ApiRef uid="Repl.TerminalSessionOverrides" /> override will silently suppress that behavior.

For local sessions (no identity string), terminal detection falls back to environment variables: `WT_SESSION`, `ConEmuANSI` (any case — `on`, `On`, `ON` all match), and `TERM_PROGRAM` are checked for OSC 9;4 gating.
Expand Down Expand Up @@ -214,6 +279,7 @@ In CLI mode, Repl suppresses banners and interactive prompts automatically. For
**Currently in place:**

- OSC 9;4 progress in supported terminals
- Shell-integration marks (OSC 133 / OSC 633) for command navigation and gutter decorations
- ANSI 256-color rendering (default) and 24-bit color via `Repl.Spectre`
- Screen clear and cursor positioning for interactive menus
- VT key decoding (arrows, Home/End, PgUp/PgDn, F1–F4)
Expand All @@ -227,7 +293,7 @@ In CLI mode, Repl suppresses banners and interactive prompts automatically. For
- Alternate screen buffer (`?1049`)
- Bracketed paste mode (`?2004`)
- Sixel and Kitty graphics
- OSC 7 (working directory), OSC 8 (hyperlinks), OSC 52 (clipboard), OSC 133 (shell integration marks)
- OSC 7 (working directory), OSC 8 (hyperlinks), OSC 52 (clipboard)
- True-color palette in the default renderer (256-color only; 24-bit available via `Repl.Spectre`)

These primitives form the foundation for a future TUI mode — full-screen, keystroke-driven surfaces (panels, menus, live updates) that will compose with the same command graph. The current `Repl.Spectre` integration covers static rich rendering; a dedicated `Repl.Tui` package is on the roadmap.
Loading