Skip to content

Commit 0658fda

Browse files
authored
docs(rfd): Add RFD 062 for CLI usage tracking (#469)
Introduce RFD 062, which proposes local-only CLI usage tracking. The design records which commands and arguments are invoked per workspace into a `usage.json` file, enabling future adaptive features without sending any data externally. Also updates RFD 060 to reflect the revised `CliRecord` design: the `flag` and `raw_value` fields are replaced by a single `arg_id` field (the clap argument ID), with raw values and display names deferred to render time via `ArgMatches::get_raw()` and `Command::find_subcommand()`. This keeps the recorder lightweight and avoids cloning values at every `apply_*` call site. --------- Signed-off-by: Jean Mertz <git@jeanmertz.com>
1 parent 54cf780 commit 0658fda

3 files changed

Lines changed: 612 additions & 10 deletions

File tree

docs/.vitepress/rfd-summaries.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,15 @@
236236
"summary": "Add `jp completions` and `jp manpage` subcommands using clap_complete and clap_mangen for shell integration."
237237
},
238238
"060-config-explain.md": {
239-
"hash": "cfa8458677aef01bb18793dab19605f67968b23ad00905a9d02dbd1bc7647bc0",
239+
"hash": "9aab2d559dfa612cc7580293424e57a9cd7b0887b1b7766ac5e8dd2a39b123d3",
240240
"summary": "Global `--explain` flag traces config resolution through 9 layers, showing where each field value originates."
241241
},
242242
"061-interactive-config.md": {
243243
"hash": "0b3bcc7ed9bbafde9e3599e05238320856c4e5711af34cc35dbade7d4d0ecbc8",
244244
"summary": "Bare `--cfg` flag triggers interactive configuration browser for searching, inspecting, and editing config fields with type-appropriate prompts."
245+
},
246+
"062-cli-usage-tracking.md": {
247+
"hash": "2a7d38872df128034bd34fa8df7030af0d7f0e97a06cf5d9d522631818805e04",
248+
"summary": "Adds local-only CLI usage tracking to record command invocations and argument patterns per workspace for adaptive features."
245249
}
246250
}

docs/rfd/060-config-explain.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,17 +322,28 @@ trait IntoPartialAppConfig {
322322
struct CliRecord {
323323
/// The config field path. Compile-time constant.
324324
field: &'static str,
325-
/// The CLI flag that set it. Compile-time constant.
326-
flag: &'static str,
327-
/// The raw value as provided by the user.
328-
raw_value: String,
325+
/// The clap argument ID that set it (e.g. `model`, `no_reasoning`).
326+
/// Compile-time constant.
327+
arg_id: &'static str,
329328
/// Optional note (e.g., "resolved via alias").
330329
note: Option<String>,
331330
}
332331

333332
struct CliRecorder(Vec<CliRecord>);
334333
```
335334

335+
`CliRecord` stores only the config field path, the clap argument ID, and an
336+
optional transformation note. It does **not** store the raw value or the display
337+
flag name (`--model`, `-m`). Both can be looked up at render time:
338+
339+
- **Raw value**: from `ArgMatches::get_raw(arg_id)`, which is available in
340+
`run_inner()` via Clap's `Cli::command().get_matches()`.
341+
- **Display flag name**: from the `Command` definition via
342+
`Command::find_subcommand()` and `Arg::get_long()` / `Arg::get_short()`.
343+
344+
This avoids cloning raw values in every `apply_*` helper and keeps the recorder
345+
lightweight — just two `&'static str` pointers and an occasional note.
346+
336347
The helper functions that bridge CLI flags to config fields record their
337348
assignments:
338349

@@ -346,12 +357,12 @@ fn apply_model(
346357
partial.assistant.model.id = id.into();
347358

348359
if let Some(rec) = recorder {
349-
rec.record("assistant.model.id", "--model", id, None);
360+
rec.record("assistant.model.id", "model", None);
350361
}
351362
}
352363
```
353364

354-
The `&'static str` for `field` and `flag` means these are compile-time
365+
The `&'static str` for `field` and `arg_id` means these are compile-time
355366
constants, not runtime strings constructed elsewhere. The mapping lives next to
356367
the code that performs the mapping — the only place that can keep it accurate.
357368

@@ -473,9 +484,9 @@ Did you mean one of:
473484
- **CLI recorder is opt-in per call site**: Each `apply_*` helper that bridges a
474485
CLI flag to a config field needs a `recorder.record(...)` call. Forgetting to
475486
add one when a new flag is introduced means the diff still shows the field
476-
changed, but without the flag annotation. A test validates that recorded field
477-
paths are valid, but cannot detect missing recordings — that requires code
478-
review discipline.
487+
changed, but without the flag annotation. A test validates that recorded
488+
`arg_id` values match real clap argument IDs and that field paths are valid,
489+
but cannot detect missing recordings — that requires code review discipline.
479490

480491
- **Inheritable config complexity**: When `inherit = false` is set, the explain
481492
output needs to show which layers were skipped and why. This adds conditional

0 commit comments

Comments
 (0)