Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c3774ce
Replace `range` clet with `linear-range` (D-025)
tig May 6, 2026
9f74619
Update LinearRangeClet.cs
tig May 6, 2026
68e9e5a
Merge develop, fix linear-range tests/docs/csproj to match implementa…
tig May 6, 2026
c393428
Add range and attribute as short aliases
tig May 6, 2026
22c281c
Add examples to clet help via embedded Help/*.md files
tig May 6, 2026
739e25e
Fix range help: use --options for multi, add numeric range example
tig May 6, 2026
d3e9908
Support --cat for help and clet <alias> help syntax
tig May 6, 2026
4c1103d
Add navigable links between help pages
tig May 6, 2026
69ffc46
Fix help table links: remove backticks that broke markdown parsing
tig May 6, 2026
3465ba9
Work around TG table link bug: add clickable list after clet table
tig May 6, 2026
decd7b5
Add help examples for all clets
tig May 6, 2026
c6ad95c
Add help examples for the help command itself
tig May 6, 2026
d53bad6
Move help-on-help to a navigable link instead of always at bottom
tig May 6, 2026
2fbc0d0
Refactor: make help a registered viewer clet
tig May 6, 2026
acf06d6
Fix Help on help link navigating to overview instead of help page
tig May 6, 2026
075e70b
Fix help: stack overflow, unknown alias error, --cat link noise
tig May 6, 2026
80e65d3
Fix --cat output: preserve OSC 8 hyperlink sequences in sanitizer
tig May 6, 2026
3413c35
Add Reporting Problems section to help with link to GitHub Issues
tig May 6, 2026
1ef1961
Open links in help content in the default browser
tig May 6, 2026
77449d4
Open http/https links in default browser from md viewer
tig May 6, 2026
5eec24f
Merge develop (#96 file-access), combine link handling in md clet
tig May 6, 2026
8b6cb8a
Fix CI: update tests for HelpClet and --cat fallthrough behavior
tig May 6, 2026
1056ae3
Fix test assertions: lowercase for dispatcher, handle stdin in md --cat
tig May 6, 2026
69c57a2
Fix smoke test: HelpClet outputs "Unknown alias" (uppercase)
tig May 6, 2026
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ Works for humans and AI agents alike.
| `duration` | Prompts for a duration and returns an ISO-8601 duration string (e.g. PT1H30M). | |
| `color` | Prompts for a color and returns a hex string (#rrggbb). | |
| `multi-select` | Presents a list of options with checkboxes and returns the selected texts. | `--options`, `args...` |
| `attribute-picker` | Prompts for text attributes (foreground, background, style) and returns a JSON object. | |
| `attribute-picker`, `attribute` | Prompts for text attributes (foreground, background, style) and returns a JSON object. | |
| `pick-file`, `file` | Opens a file picker dialog and returns the selected file path(s). | `--multi`, `--root`, `--filter` |
| `pick-directory`, `dir` | Opens a directory picker dialog and returns the selected directory path. | `--root` |
| `range` | Prompts for a numeric range (low..high) and returns a JSON object. | `--step` |
| `linear-range`, `range` | Presents a linear range selector (single, multi, or bounded range) over labelled options. | `--mode`, `--options`, `--range-kind`, `args...` |
| `md`, `markdown` | Renders Markdown files in a themed, scrollable viewer. | `--theme`, `--cat`, `args...` |

## Install
Expand Down Expand Up @@ -158,7 +158,7 @@ Esc and Ctrl-C cancel input clets; `q`, Esc, and Ctrl-C dismiss viewer clets. `-

### Q: Which clets ship in v1.0?

**Input (14):** `text`, `int`, `decimal`, `select`, `multi-select`, `confirm`, `pick-file`, `pick-directory`, `date`, `time`, `duration`, `color`, `attribute-picker`, `range`
**Input (14):** `text`, `int`, `decimal`, `select`, `multi-select`, `confirm`, `pick-file`, `pick-directory`, `date`, `time`, `duration`, `color`, `attribute-picker`, `linear-range`

**Viewer (1):** `md` (Markdown via Terminal.Gui's built-in `Markdown` View)

Expand Down
2 changes: 1 addition & 1 deletion specs/clet-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ For schema-lock at v0.5, the shape of `value` is fixed per alias.
| `duration` | string, ISO-8601 duration (`PT1H30M`) |
| `color` | string, `#RRGGBB` (lowercase hex) |
| `attribute-picker` | object, `{"fg": "#RRGGBB", "bg": "#RRGGBB", "style": "..."}` |
| `range` | object, `{"low": <T>, "high": <T>}` (`int` only at v0.3 — see [D-011](decisions.md)) |
| `linear-range` | object, shape depends on `--mode`. Single: `{"mode":"single","value":"<label>","index":N}`. Multi: `{"mode":"multi","values":[...],"indices":[...]}`. Range: `{"mode":"range","kind":"closed\|left\|right\|none",...}` with start/end fields conditional on kind. See [D-032](decisions.md). |

### 4.4 Registration

Expand Down
30 changes: 23 additions & 7 deletions specs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,15 @@ Format: `## D-NNN: <short title> (status)`. Status is one of `Active`, `Supersed

---

## D-011: `range` is integer-only at v0.3 (Active)
## D-011: `range` is integer-only at v0.3 (Superseded by D-032)

**Context.** Spec §4.3.2 defines the `range` value shape as `{"low": <T>, "high": <T>}` where `<T>` is the scalar of the underlying numeric/date/time type.

**Decision.** At v0.3, `T = int` only. The `RangeClet` uses two `NumericUpDown<int>` controls. Decimal range and date/time range are deferred until demand exists — adding them later is a new clet alias or a generic type parameter, not a breaking change to the existing wire format.

**Status.** Active. Revisit if users request decimal or date ranges before v0.5 schema-lock.
**Status.** Superseded by D-032. The `range` clet itself is gone; `linear-range` replaces it with an option-label string type, so the integer-only constraint no longer applies.

**Pointers.** `src/Clet/Clets/Input/RangeClet.cs`, `src/Clet/Clets/Input/RangeView.cs`.
**Pointers.** *(Files referenced here have been removed; see D-029.)*

---

Expand Down Expand Up @@ -353,8 +353,6 @@ Both channels tag every build (needed for auto-increment). Both publish to NuGet

---

---

## D-025: Clets declare `AcceptsPositionalArgs`; non-positional clets reject them early (Active)

**Context.** The CLI parser in `CommandLineRoot.DispatchAlias` collected all non-flag tokens into `CletRunOptions.Arguments` and forwarded them unconditionally. Clets that don't consume positional args (everything except `select`, `multi-select`, and `md`) silently ignored them, giving the user no feedback. `clet color - blue` would open the color picker as if the args weren't there. A bare `-` (common stdin convention) also fell through to positional args rather than being flagged.
Expand Down Expand Up @@ -456,7 +454,25 @@ This is clet's own defense. TG's cell model is treated as defense-in-depth, not

---

## D-032: `clet md` file-access confinement policy (Active)
## D-032: Replace `range` clet with `linear-range` backed by Terminal.Gui's `LinearRange<T>` (Active, supersedes D-011)

**Context.** The original `range` clet wrapped a hand-rolled `RangeView` (`NumericUpDown<int>` × 2 + a `..` label) and emitted `{"low": <int>, "high": <int>}` per spec §4.3.2. It worked, but the UX was poor — two independent spinners with no visual sense of the range relationship — and it duplicated functionality TG shipped via [Terminal.Gui PR #5204](https://github.com/gui-cs/Terminal.Gui/pull/5204) (the `LinearRange<T>` `IValue` refactor).

**Decision.** Delete `RangeClet`, `RangeView`, and their tests. Add `LinearRangeClet` (alias `linear-range`) backed by the `LinearRange<T>` view family, with three modes controlled by `--mode single|multi|range` (default `single`). Wire format changes from `{low, high}` to a mode-dependent JSON object:

- `--mode single` → `{"mode":"single", "value":"<label>", "index":<N>}`
- `--mode multi` → `{"mode":"multi", "values":[...], "indices":[...]}`
- `--mode range` → `{"mode":"range", "kind":"closed|left|right|none", "start":"<label>", "end":"<label>", "startIndex":<N>, "endIndex":<M>}` (fields conditional on kind)

Additional options: `--orientation horizontal|vertical`, `--range-kind closed|left|right` (default `closed`, only for `--mode range`), `--allow-empty`, `--hide-legends`.

**Status.** Active. Supersedes [D-011](#d-011-range-is-integer-only-at-v03-active).

**Pointers.** `src/Clet/Clets/Input/LinearRangeClet.cs`, spec §4.3.2, README, [Terminal.Gui PR #5204](https://github.com/gui-cs/Terminal.Gui/pull/5204).

---

## D-033: `clet md` file-access confinement policy (Active)

**Context.** `clet md FILE` is an arbitrary file-read primitive. In agent contexts, positional arguments may be attacker-influenced via indirect prompt injection. An attacker could instruct an agent to run `clet md /home/$USER/.aws/credentials`, exfiltrating file content through the rendered ANSI output or `--cat` stdout. Glob patterns (`clet md '/etc/*.conf'`) amplify this to directory enumeration. Issue #38 documents the full threat surface.

Expand All @@ -467,7 +483,7 @@ This is clet's own defense. TG's cell model is treated as defense-in-depth, not
4. **Aggregate size cap:** 32 MiB across all glob matches.
5. **Glob count cap:** 128 files maximum.
6. **Binary rejection:** NUL byte in first 8 KiB refuses the file.
7. **`--allow-file <path>`** (repeatable): Bypasses extension + cwd checks for the named path. Size and binary checks still apply.
7. **`--allow-file <path>`** (repeatable): Bypasses extension + cwd checks for the named path or directory. Size and binary checks still apply.
8. **`--allow-binary`:** Disables NUL-byte detection.

For `pick-file`/`pick-directory`, `--root` remains a starting directory, not a sandbox. The interactive file picker is user-driven and OS-permission-gated; confinement is the OS sandbox's responsibility, not clet's. Help text updated to make this explicit.
Expand Down
2 changes: 1 addition & 1 deletion src/Clet/Clets/Input/AttributePickerClet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Clet;
internal sealed class AttributePickerClet : IClet<JsonObject?>
{
public string PrimaryAlias => "attribute-picker";
public IReadOnlyList<string> Aliases => ["attribute-picker"];
public IReadOnlyList<string> Aliases => ["attribute-picker", "attribute"];
public string Description => "Prompts for text attributes (foreground, background, style) and returns a JSON object.";
public CletKind Kind => CletKind.Input;
public Type ResultType => typeof (JsonObject);
Expand Down
Loading
Loading