diff --git a/.agents/skills/add-cli-command/SKILL.md b/.agents/skills/add-cli-command/SKILL.md index b88add44..e8b2893f 100644 --- a/.agents/skills/add-cli-command/SKILL.md +++ b/.agents/skills/add-cli-command/SKILL.md @@ -10,7 +10,7 @@ Paths are relative to `crates/clickhousectl/`. 1. Follow the procedure for the kind of command: - Local (`local ...`, runs on this machine): [references/local.md](references/local.md) - Cloud (`cloud ...`, calls the Cloud API): [references/cloud.md](references/cloud.md) -2. Write help text to "Writing help text" in the root `AGENTS.md`. +2. Write help text with the `cli-help-text` skill (`.agents/skills/cli-help-text/SKILL.md`). 3. Finish with the steps below. ## Finish @@ -26,7 +26,7 @@ Copy this checklist and tick it off as you go: ``` - [ ] Procedure steps (local.md or cloud.md) -- [ ] Help text follows the root AGENTS.md rules +- [ ] Help text follows the cli-help-text skill - [ ] try_parse_from tests for new flags - [ ] Both classifiers map new files - [ ] README example diff --git a/.agents/skills/cli-help-text/SKILL.md b/.agents/skills/cli-help-text/SKILL.md new file mode 100644 index 00000000..6e0c5f5a --- /dev/null +++ b/.agents/skills/cli-help-text/SKILL.md @@ -0,0 +1,110 @@ +--- +name: cli-help-text +description: Writes and reviews `clickhousectl` `--help` text — command `about` lines, flag help, option order, and the `CONTEXT FOR AGENTS:` block — so people and coding agents can learn the CLI from help alone. Use when adding or changing a command or flag, editing clap `about`/`after_help`/arg doc comments, reviewing help in a PR, or fixing a help-structure test failure. +--- + +# CLI help text + +Help is how people and coding agents learn the CLI. An agent reads `--help` the way it reads a tool description, +so every line should help it pick the right command, pass the right inputs, and avoid a surprise. Anything else +is noise that costs the reader time and tokens. + +## Where help lives + +- `#[command(about = ..., after_help = ...)]` and arg doc comments in `src/cli.rs`, `src/local/cli.rs`, + `src/cloud/cli.rs` and `src/cloud/.rs` (all under `crates/clickhousectl/`). +- `const INSTALL_AFTER_HELP` in `src/local/cli.rs`. +- `src/cloud/permissions.rs` appends API-key permission lines to every executable Cloud command, built from each + domain's declarations. Don't write those lines by hand. + +## Screen shape + +A help screen has only these parts, in this order: + +1. A one-line `about`. +2. clap's `Usage:`, `Arguments:`/`Options:` and `Commands:` sections, with the standard headings. +3. Optionally, a trailing `CONTEXT FOR AGENTS:` block set with `after_help`. + +No `long_about`, `before_help`, `after_long_help`, or any other `after_help` header. + +## `about` + +- An imperative verb phrase, up to about 60 characters, no trailing period. +- Say what the command does, not how it does it. +- Keep siblings parallel: "List X", "Get X details", "Create X", "Delete X". +- Mark beta commands with `(Beta)`. + +## Flags and arguments + +- One line, up to about 70 characters. Include units or format: "Interval in seconds", "RFC 3339 timestamp". +- Don't restate what clap renders: `[default: …]` and `[possible values: …]`. +- Put a cross-flag constraint on the flag it limits: "Only with `--replication-mode cdc_only`". +- Add a second doc-comment paragraph (up to about 3 lines) only for a constraint the flag's name and type + can't convey. +- Use enums (`value_enum`) rather than describing valid strings in prose, so clap lists and checks them. +- Shared flags (`--org-id`, `--org-name`, `--api-key`, `--api-secret`, `--url`, `--json`, `--debug`) read the same + everywhere. Copy the wording from an existing declaration. +- Resource names stay positional, under `Arguments`. Compatibility flags stay hidden. + +## Option order + +- Command-specific flags first, with display ranks below 900. +- Then the shared block, in this order: `--org-id`, `--org-name` (where it exists), `--api-key`, `--api-secret`, + `--url`, `--json`, `--debug`. Use the `help_order` ranks in `src/cli.rs` (900–906). clap adds `--help` at 999. +- Set the rank at every declaration, including local `--json` and auth flags, so inherited flags keep the block + together. +- Both local clients order common arguments as name, host, port, version, query, queries-file. +- Keep release-only URL hiding as it is. + +## `CONTEXT FOR AGENTS:` + +At most 8 content lines, ideally 3 to 6. Write densely: the block is for agents, not people, so pack related +facts onto one line. Permission lines added by `permissions.rs` don't count toward the 8. + +Include only what changes what the agent does next: + +- An auth requirement or precondition ("must be stopped first"). If meeting it takes a command or flag, name + it: "stop first (`cloud service stop`)". The agent shouldn't have to guess or read more help to find it. +- Runtime behaviour the flags don't show, when it affects how the command is used: timeouts, stdin handling, + irreversibility, long waits, retry safety. +- An output note, only if it changes what the agent does with the output. +- A `Typical flow:` line describing likely follow-on commands. +- Rarely, a docs URL: only when help can't cover something the agent needs. Never more than one. + +NEVER include implementation details, crate or file names, HTTP and API mechanics, storage paths, history or +compatibility notes, reassurance, or anything already in the `about` line, the flag list or `[default:]`. + +Put shared context (auth model, typical flow) on the parent command, such as `cloud service` or +`local server`. A leaf gets a block only for its own gotcha. A plain `get` or `list` usually needs none. + +Write it plainly. State the fact and, where it isn't obvious, the reason. Don't use capitals or "MUST" for +emphasis: current models follow plain instructions closely, and emphasis makes them over-apply a rule. + +Before (states mechanics, not consequences): + +``` +CONTEXT FOR AGENTS: +Calls DELETE /v1/organizations/{id}/services/{id} via clickhouse-cloud-api. +IMPORTANT: you MUST stop the service first!! +``` + +After: + +``` +CONTEXT FOR AGENTS: +Irreversible. Running service must be stopped first (--force or `cloud service stop`). +``` + +## Tests + +NEVER add tests that pin help or README wording, such as `help.contains("some sentence")` or whole-screen +equality. + +## Checklist + +1. Edit the clap definitions. +2. Build, then read each changed screen as an agent would see it: + `cargo run -q -p clickhousectl -- --help`. Check the parent's screen too. +3. Check each line against the rules above. For each `CONTEXT FOR AGENTS:` line, ask whether an agent would act + differently without it. If not, delete it. +4. Run `cargo test -p clickhousectl` to catch structure failures, then the gates in the root `AGENTS.md`. diff --git a/.agents/skills/openapi-drift-remediation/SKILL.md b/.agents/skills/openapi-drift-remediation/SKILL.md index 655b9e87..200b7727 100644 --- a/.agents/skills/openapi-drift-remediation/SKILL.md +++ b/.agents/skills/openapi-drift-remediation/SKILL.md @@ -16,7 +16,7 @@ An API PR may touch CLI code only to keep it compiling after a breaking library surface and an unchanged wire request (pin it with a test). A CLI PR never changes the library. Read `crates/clickhouse-cloud-api/AGENTS.md` (model policy, analyzer configuration) and the root `AGENTS.md` -(help text, tests, gates) before editing. This skill is the workflow; those files are the rules. +(tests, gates) before editing. This skill is the workflow; those files are the rules. ## 1. Reproduce and inventory diff --git a/.claude/skills/cli-help-text b/.claude/skills/cli-help-text new file mode 120000 index 00000000..d55d2b8f --- /dev/null +++ b/.claude/skills/cli-help-text @@ -0,0 +1 @@ +../../.agents/skills/cli-help-text \ No newline at end of file diff --git a/.gitignore b/.gitignore index dc36ec94..9f55b6e2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,11 +14,13 @@ /.agents/skills/* !/.agents/skills/openapi-drift-remediation/ !/.agents/skills/add-cli-command/ +!/.agents/skills/cli-help-text/ /.claude/* !/.claude/skills/ /.claude/skills/* !/.claude/skills/openapi-drift-remediation !/.claude/skills/add-cli-command +!/.claude/skills/cli-help-text /.codex/ /.cursor/ /.opencode/ diff --git a/AGENTS.md b/AGENTS.md index f72a1fb9..c50207ed 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -75,41 +75,8 @@ domain keeps its definitions, handlers and tests together in `src/cloud/ ## Writing help text -- Help lives in `#[command(about/after_help)]` and arg doc comments in `src/cli.rs`, `src/local/cli.rs`, - `src/cloud/cli.rs`, and `src/cloud/.rs`; one block is `const INSTALL_AFTER_HELP` in `src/local/cli.rs`. - `src/cloud/permissions.rs` adds permission context from domain declarations and API-library metadata. -- A help screen has only: one-line `about`, clap's `Usage:`, `Arguments:`/`Options:`, `Commands:`, and an optional - trailing `CONTEXT FOR AGENTS:` block via `after_help`. No `long_about`; no other `after_help` header. -- `about`: imperative verb phrase, ≤ ~60 chars, no trailing period, no implementation detail; keep siblings parallel - ("List X", "Get X details", "Create X", "Delete X"). Flag help: one line, ≤ ~70 chars, include units/format - ("Interval in seconds"), and never repeat clap's `[default: …]` or `[possible values: …]` in prose. -- Use `(Beta)` for beta markers; keep `(limited preview)` distinct. -- State cross-flag constraints on the flag itself ("only with `--replication-mode cdc_only`"). Add a second - doc-comment paragraph (≤ ~3 lines) only for a constraint the flag's name and type cannot convey. -- Shared flags (`--api-key`, `--api-secret`, `--url`, `--org-id`, `--org-name`, `--json`, `--debug`) read identically everywhere. -- Help options: command-specific flags first (display ranks below 900), then the contiguous shared block - `--org-id`, `--org-name` (when available), `--api-key`, `--api-secret`, `--url`, `--json`, `--debug`, `--help`. - Use `src/cli.rs`'s `help_order` ranks 900–906; `--org-name` uses 901, and clap supplies help at 999. - Apply ranks at every declaration, including local JSON and auth flags; inheritance must preserve the block. - Both local clients order common arguments as name, host, port, version, query, queries-file. Names stay in - Arguments; compatibility flags stay hidden. Keep standard headings and release-only URL hiding. -- `CONTEXT FOR AGENTS:` — hard cap 8 content lines, target 3-6, one fact per line. May hold: an auth requirement or - precondition; credential precedence without storage paths; where to get required inputs - ("Service ID: `cloud service list`"); non-obvious runtime behaviour - (timeouts, stdin handling, irreversibility, "must be stopped first"); an output note only when it changes what the - agent does; a `Typical flow:` line; at most one docs URL. - It must NOT hold implementation details, crates/files, HTTP or API mechanics, storage paths, history or - compatibility notes, reassurance, or anything already in the flag list, `[default:]`, or the `about` line. -- Put shared context (auth model, how to find IDs, typical flow) on the parent (`cloud service`, `local server`). - The permission helper adds API-key requirements to every executable Cloud command; pure grouping commands - stay unchanged. Keep other leaf context specific to a gotcha. Permission lines count toward the 8-line cap; - move longer operational guidance to the README when necessary. -- Do not write tests that pin help or README wording (`help.contains("some sentence")`, `include_str!` on - `README.md`, whole-screen equality). They protect phrasing, not facts, and turn every rewording into a test edit. - Test structure instead: `try_parse_from` outcomes, `ErrorKind`, defaults and value names clap renders, hidden - flags staying hidden, every subcommand having an `about`, block size, and a flag reading identically everywhere. - A fact that must not disappear from help is guarded by review against this section, not by a substring. -- Content users still need but help must not carry goes to `README.md` as a short example or ≤ 3-line note. +Use the `cli-help-text` skill (`.agents/skills/cli-help-text/SKILL.md`) whenever you add or change a command, a +flag, or any help text. It holds the help standard and its test rule. ## Tests @@ -128,7 +95,7 @@ Test coverage is non-negotiable. `telemetry_test.rs`. Add a new file rather than growing `cli_request_shape_test.rs`, which is Cloud-only. - **Pure logic** — inline `mod tests` blocks across `src/` for version resolution, auth precedence, output formatting, platform detection, and other module-local helpers. -- **Help and README text** — structural assertions only (see Writing help text). No wording pins. +- **Help and README text** — structural assertions only (see the `cli-help-text` skill). No wording pins. ## CI gates