CLI audit scoring the current command surface across human ergonomics, robot/agent ergonomics, documentation quality, and flag design. Paired with a detailed implementation plan for restructuring commands into a more consistent, discoverable hierarchy.
32 KiB
Command Restructure: Implementation Plan
Reference: command-restructure/CLI_AUDIT.md
Scope: 10 proposals, 3 implementation phases, estimated ~15 files touched
Phase 1: Zero-Risk Quick Wins (1 commit)
These four changes are purely additive -- no behavior changes, no renames, no removed commands.
P1: Help Grouping
Goal: Group the 29 visible commands into 5 semantic clusters in --help output.
File: src/cli/mod.rs (lines 117-399, the Commands enum)
Changes: Add #[command(help_heading = "...")] to each variant:
#[derive(Subcommand)]
#[allow(clippy::large_enum_variant)]
pub enum Commands {
// ── Query ──────────────────────────────────────────────
/// List or show issues
#[command(visible_alias = "issue", help_heading = "Query")]
Issues(IssuesArgs),
/// List or show merge requests
#[command(visible_alias = "mr", alias = "merge-requests", alias = "merge-request", help_heading = "Query")]
Mrs(MrsArgs),
/// List notes from discussions
#[command(visible_alias = "note", help_heading = "Query")]
Notes(NotesArgs),
/// Search indexed documents
#[command(visible_alias = "find", alias = "query", help_heading = "Query")]
Search(SearchArgs),
/// Count entities in local database
#[command(help_heading = "Query")]
Count(CountArgs),
// ── Intelligence ───────────────────────────────────────
/// Show a chronological timeline of events matching a query
#[command(help_heading = "Intelligence")]
Timeline(TimelineArgs),
/// People intelligence: experts, workload, active discussions, overlap
#[command(help_heading = "Intelligence")]
Who(WhoArgs),
/// Personal work dashboard: open issues, authored/reviewing MRs, activity
#[command(help_heading = "Intelligence")]
Me(MeArgs),
// ── File Analysis ──────────────────────────────────────
/// Trace why code was introduced: file -> MR -> issue -> discussion
#[command(help_heading = "File Analysis")]
Trace(TraceArgs),
/// Show MRs that touched a file, with linked discussions
#[command(name = "file-history", help_heading = "File Analysis")]
FileHistory(FileHistoryArgs),
/// Find semantically related entities via vector search
#[command(help_heading = "File Analysis", ...)]
Related { ... },
/// Detect discussion divergence from original intent
#[command(help_heading = "File Analysis", ...)]
Drift { ... },
// ── Data Pipeline ──────────────────────────────────────
/// Run full sync pipeline: ingest -> generate-docs -> embed
#[command(help_heading = "Data Pipeline")]
Sync(SyncArgs),
/// Ingest data from GitLab
#[command(help_heading = "Data Pipeline")]
Ingest(IngestArgs),
/// Generate searchable documents from ingested data
#[command(name = "generate-docs", help_heading = "Data Pipeline")]
GenerateDocs(GenerateDocsArgs),
/// Generate vector embeddings for documents via Ollama
#[command(help_heading = "Data Pipeline")]
Embed(EmbedArgs),
// ── System ─────────────────────────────────────────────
// (init, status, health, doctor, stats, auth, token, migrate, cron,
// completions, robot-docs, version -- all get help_heading = "System")
}
Verification:
lore --helpshows grouped output- All existing commands still work identically
lore robot-docsoutput unchanged (robot-docs is hand-crafted, not derived from clap)
Files touched: src/cli/mod.rs only
P3: Singular/Plural Entity Type Fix
Goal: Accept both issue/issues, mr/mrs everywhere entity types are value-parsed.
File: src/cli/args.rs
Change 1 -- CountArgs.entity (line 819):
// BEFORE:
#[arg(value_parser = ["issues", "mrs", "discussions", "notes", "events"])]
pub entity: String,
// AFTER:
#[arg(value_parser = ["issue", "issues", "mr", "mrs", "discussion", "discussions", "note", "notes", "event", "events"])]
pub entity: String,
File: src/cli/args.rs
Change 2 -- SearchArgs.source_type (line 369):
// BEFORE:
#[arg(long = "type", value_parser = ["issue", "mr", "discussion", "note"], ...)]
pub source_type: Option<String>,
// AFTER:
#[arg(long = "type", value_parser = ["issue", "issues", "mr", "mrs", "discussion", "discussions", "note", "notes"], ...)]
pub source_type: Option<String>,
File: src/cli/mod.rs
Change 3 -- Drift.entity_type (line 287):
// BEFORE:
#[arg(value_parser = ["issues"])]
pub entity_type: String,
// AFTER:
#[arg(value_parser = ["issue", "issues"])]
pub entity_type: String,
Normalization layer: In the handlers that consume these values, normalize to the canonical form (plural for entity names, singular for source_type) so downstream code doesn't need changes:
File: src/app/handlers.rs
In handle_count (~line 409): Normalize entity string before passing to run_count:
let entity = match args.entity.as_str() {
"issue" => "issues",
"mr" => "mrs",
"discussion" => "discussions",
"note" => "notes",
"event" => "events",
other => other,
};
In handle_search (search handler): Normalize source_type:
let source_type = args.source_type.as_deref().map(|t| match t {
"issues" => "issue",
"mrs" => "mr",
"discussions" => "discussion",
"notes" => "note",
other => other,
});
In handle_drift (~line 225): Normalize entity_type:
let entity_type = if entity_type == "issue" { "issues" } else { &entity_type };
Verification:
lore count issueworks (same aslore count issues)lore search --type issues 'foo'works (same as--type issue)lore drift issue 42works (same asdrift issues 42)- All existing invocations unchanged
Files touched: src/cli/args.rs, src/cli/mod.rs, src/app/handlers.rs
P5: Fix -f Short Flag Collision
Goal: Remove -f shorthand from count --for so -f consistently means --force across the CLI.
File: src/cli/args.rs (line 823)
// BEFORE:
#[arg(short = 'f', long = "for", value_parser = ["issue", "mr"])]
pub for_entity: Option<String>,
// AFTER:
#[arg(long = "for", value_parser = ["issue", "mr"])]
pub for_entity: Option<String>,
Also update the value_parser to accept both forms (while we're here):
#[arg(long = "for", value_parser = ["issue", "issues", "mr", "mrs"])]
pub for_entity: Option<String>,
And normalize in handle_count:
let for_entity = args.for_entity.as_deref().map(|f| match f {
"issues" => "issue",
"mrs" => "mr",
other => other,
});
File: src/app/robot_docs.rs (line 173) -- update the robot-docs entry:
// BEFORE:
"flags": ["<entity: issues|mrs|discussions|notes|events>", "-f/--for <issue|mr>"],
// AFTER:
"flags": ["<entity: issues|mrs|discussions|notes|events>", "--for <issue|mr>"],
Verification:
lore count notes --for mrstill workslore count notes -f mrnow fails with a clear error (unknown flag-f)lore ingest -fstill works (means--force)
Files touched: src/cli/args.rs, src/app/robot_docs.rs
P9: Consistent --open Short Flag on notes
Goal: Add -o shorthand to notes --open, matching issues and mrs.
File: src/cli/args.rs (line 292)
// BEFORE:
#[arg(long, help_heading = "Actions")]
pub open: bool,
// AFTER:
#[arg(short = 'o', long, help_heading = "Actions", overrides_with = "no_open")]
pub open: bool,
#[arg(long = "no-open", hide = true, overrides_with = "open")]
pub no_open: bool,
Verification:
lore notes -oopens first result in browser- Matches behavior of
lore issues -oandlore mrs -o
Files touched: src/cli/args.rs
Phase 1 Commit Summary
Files modified:
src/cli/mod.rs-- help_heading on all Commands variants + drift value_parsersrc/cli/args.rs-- singular/plural value_parsers, remove-ffrom count, add-oto notessrc/app/handlers.rs-- normalization of entity/source_type stringssrc/app/robot_docs.rs-- update count flags documentation
Test plan:
cargo check --all-targets
cargo clippy --all-targets -- -D warnings
cargo fmt --check
cargo test
lore --help # Verify grouped output
lore count issue # Verify singular accepted
lore search --type issues 'x' # Verify plural accepted
lore drift issue 42 # Verify singular accepted
lore notes -o # Verify short flag works
Phase 2: Renames and Merges (2-3 commits)
These changes rename commands and merge overlapping ones. Hidden aliases preserve backward compatibility.
P2: Rename stats -> index
Goal: Eliminate status/stats/stat confusion. stats becomes index.
File: src/cli/mod.rs
// BEFORE:
/// Show document and index statistics
#[command(visible_alias = "stat", help_heading = "System")]
Stats(StatsArgs),
// AFTER:
/// Show document and index statistics
#[command(visible_alias = "idx", alias = "stats", alias = "stat", help_heading = "System")]
Index(StatsArgs),
Note: alias = "stats" and alias = "stat" are hidden aliases (not visible_alias) -- old invocations still work, but --help shows index.
File: src/main.rs (line 257)
// BEFORE:
Some(Commands::Stats(args)) => handle_stats(cli.config.as_deref(), args, robot_mode).await,
// AFTER:
Some(Commands::Index(args)) => handle_stats(cli.config.as_deref(), args, robot_mode).await,
File: src/app/robot_docs.rs (line 181)
// BEFORE:
"stats": {
"description": "Show document and index statistics",
...
// AFTER:
"index": {
"description": "Show document and index statistics (formerly 'stats')",
...
Also update references in:
robot_docs.rsquick_start.lore_exclusive array (line 415):"stats: Database statistics..."->"index: Database statistics..."robot_docs.rsaliases.deprecated_commands: add"stats": "index","stat": "index"
File: src/cli/autocorrect.rs
Update CANONICAL_SUBCOMMANDS (line 366-area):
// Replace "stats" with "index" in the canonical list
// Add ("stats", "index") and ("stat", "index") to SUBCOMMAND_ALIASES
Update COMMAND_FLAGS (line 166-area):
// BEFORE:
("stats", &["--check", ...]),
// AFTER:
("index", &["--check", ...]),
File: src/cli/robot.rs -- update expand_fields_preset if any preset key is "stats" (currently no stats preset, so no change needed).
Verification:
lore indexworks (shows document/index stats)lore statsstill works (hidden alias)lore statstill works (hidden alias)lore index --checkworkslore --helpshowsindexin System group, notstatslore robot-docsshowsindexkey in commands map
Files touched: src/cli/mod.rs, src/main.rs, src/app/robot_docs.rs, src/cli/autocorrect.rs
P4: Merge health into doctor
Goal: One diagnostic command (doctor) with a --quick flag for the pre-flight check that health currently provides.
File: src/cli/mod.rs
// BEFORE:
/// Quick health check: config, database, schema version
#[command(after_help = "...")]
Health,
/// Check environment health
#[command(after_help = "...")]
Doctor,
// AFTER:
// Remove Health variant entirely. Add hidden alias:
/// Check environment health (--quick for fast pre-flight)
#[command(
after_help = "...",
alias = "health", // hidden backward compat
help_heading = "System"
)]
Doctor {
/// Fast pre-flight check only (config, DB, schema). Exit 0 = healthy.
#[arg(long)]
quick: bool,
},
File: src/main.rs
// BEFORE:
Some(Commands::Doctor) => handle_doctor(cli.config.as_deref(), robot_mode).await,
...
Some(Commands::Health) => handle_health(cli.config.as_deref(), robot_mode).await,
// AFTER:
Some(Commands::Doctor { quick }) => {
if quick {
handle_health(cli.config.as_deref(), robot_mode).await
} else {
handle_doctor(cli.config.as_deref(), robot_mode).await
}
}
// Health variant removed from enum, so no separate match arm
File: src/app/robot_docs.rs
Merge the health and doctor entries:
"doctor": {
"description": "Environment health check. Use --quick for fast pre-flight (exit 0 = healthy, 19 = unhealthy).",
"flags": ["--quick"],
"example": "lore --robot doctor",
"notes": {
"quick_mode": "lore --robot doctor --quick — fast pre-flight check (formerly 'lore health'). Only checks config, DB, schema version. Returns exit 19 on failure.",
"full_mode": "lore --robot doctor — full diagnostic: config, auth, database, Ollama"
},
"response_schema": {
"full": { ... }, // current doctor schema
"quick": { ... } // current health schema
}
}
Remove the standalone health entry from the commands map.
File: src/cli/autocorrect.rs
- Remove
"health"fromCANONICAL_SUBCOMMANDS(clap'saliashandles it) - Or keep it -- since clap treats aliases as valid subcommands, the autocorrect system will still resolve typos like
"helth"to"health"which clap then maps todoctor. Either way works.
File: src/app/robot_docs.rs -- update workflows.pre_flight:
"pre_flight": [
"lore --robot doctor --quick"
],
Add to aliases.deprecated_commands:
"health": "doctor --quick"
Verification:
lore doctorruns full diagnostic (unchanged behavior)lore doctor --quickruns fast pre-flight (exit 0/19)lore healthstill works (hidden alias, runsdoctor --quick)lore --helpshows onlydoctorin System grouplore robot-docsshows merged entry
Files touched: src/cli/mod.rs, src/main.rs, src/app/robot_docs.rs, src/cli/autocorrect.rs
Important edge case: lore health via the hidden alias will invoke Doctor { quick: false } unless we handle it specially. Two options:
Option A (simpler): Instead of making health an alias of doctor, keep both variants but hide Health:
#[command(hide = true, help_heading = "System")]
Health,
Then in main.rs, Commands::Health maps to handle_health() as before. This is less clean but zero-risk.
Option B (cleaner): In the autocorrect layer, rewrite health -> doctor --quick before clap parsing:
// In SUBCOMMAND_ALIASES or a new pre-clap rewrite:
("health", "doctor"), // plus inject "--quick" flag
This requires a small enhancement to autocorrect to support flag injection during alias resolution.
Recommendation: Use Option A for initial implementation. It's one line (hide = true) and achieves the goal of removing health from --help while preserving full backward compatibility. The doctor --quick flag is additive.
P7: Hide Pipeline Sub-stages
Goal: Remove ingest, generate-docs, embed from --help while keeping them fully functional.
File: src/cli/mod.rs
// Add hide = true to each:
/// Ingest data from GitLab
#[command(hide = true)]
Ingest(IngestArgs),
/// Generate searchable documents from ingested data
#[command(name = "generate-docs", hide = true)]
GenerateDocs(GenerateDocsArgs),
/// Generate vector embeddings for documents via Ollama
#[command(hide = true)]
Embed(EmbedArgs),
File: src/cli/mod.rs -- Update Sync help text to mention the individual stage commands:
/// Run full sync pipeline: ingest -> generate-docs -> embed
#[command(after_help = "\x1b[1mExamples:\x1b[0m
lore sync # Full pipeline: ingest + docs + embed
lore sync --no-embed # Skip embedding step
...
\x1b[1mIndividual stages:\x1b[0m
lore ingest # Fetch from GitLab only
lore generate-docs # Rebuild documents only
lore embed # Re-embed only",
help_heading = "Data Pipeline"
)]
Sync(SyncArgs),
File: src/app/robot_docs.rs -- Add a "hidden": true field to the ingest/generate-docs/embed entries so agents know these are secondary:
"ingest": {
"hidden": true,
"description": "Sync data from GitLab (prefer 'sync' for full pipeline)",
...
Verification:
lore --helpno longer shows ingest, generate-docs, embedlore ingest,lore generate-docs,lore embedall still worklore sync --helpmentions individual stage commandslore robot-docsstill includes all three (withhidden: true)
Files touched: src/cli/mod.rs, src/app/robot_docs.rs
Phase 2 Commit Summary
Commit A: Rename stats -> index
src/cli/mod.rs,src/main.rs,src/app/robot_docs.rs,src/cli/autocorrect.rs
Commit B: Merge health into doctor, hide pipeline stages
src/cli/mod.rs,src/main.rs,src/app/robot_docs.rs,src/cli/autocorrect.rs
Test plan:
cargo check --all-targets
cargo clippy --all-targets -- -D warnings
cargo fmt --check
cargo test
# Rename verification
lore index # Works (new name)
lore stats # Works (hidden alias)
lore index --check # Works
# Doctor merge verification
lore doctor # Full diagnostic
lore doctor --quick # Fast pre-flight
lore health # Still works (hidden)
# Hidden stages verification
lore --help # ingest/generate-docs/embed gone
lore ingest # Still works
lore sync --help # Mentions individual stages
Phase 3: Structural Consolidation (requires careful design)
These changes merge or absorb commands. More effort, more testing, but the biggest UX wins.
P6: Consolidate file-history into trace
Goal: trace absorbs file-history. One command for file-centric intelligence.
Approach: Add --mrs-only flag to trace. When set, output matches file-history format (flat MR list, no issue/discussion linking). file-history becomes a hidden alias.
File: src/cli/args.rs -- Add flag to TraceArgs:
pub struct TraceArgs {
pub path: String,
#[arg(short = 'p', long, help_heading = "Filters")]
pub project: Option<String>,
#[arg(long, help_heading = "Output")]
pub discussions: bool,
#[arg(long = "no-follow-renames", help_heading = "Filters")]
pub no_follow_renames: bool,
#[arg(short = 'n', long = "limit", default_value = "20", help_heading = "Output")]
pub limit: usize,
// NEW: absorb file-history behavior
/// Show only MR list without issue/discussion linking (file-history mode)
#[arg(long = "mrs-only", help_heading = "Output")]
pub mrs_only: bool,
/// Only show merged MRs (file-history mode)
#[arg(long, help_heading = "Filters")]
pub merged: bool,
}
File: src/cli/mod.rs -- Hide FileHistory:
/// Show MRs that touched a file, with linked discussions
#[command(name = "file-history", hide = true, help_heading = "File Analysis")]
FileHistory(FileHistoryArgs),
File: src/app/handlers.rs -- Route trace --mrs-only to the file-history handler:
fn handle_trace(
config_override: Option<&str>,
args: TraceArgs,
robot_mode: bool,
) -> Result<(), Box<dyn std::error::Error>> {
if args.mrs_only {
// Delegate to file-history handler
let fh_args = FileHistoryArgs {
path: args.path,
project: args.project,
discussions: args.discussions,
no_follow_renames: args.no_follow_renames,
merged: args.merged,
limit: args.limit,
};
return handle_file_history(config_override, fh_args, robot_mode);
}
// ... existing trace logic ...
}
File: src/app/robot_docs.rs -- Update trace entry, mark file-history as deprecated:
"trace": {
"description": "Trace why code was introduced: file -> MR -> issue -> discussion. Use --mrs-only for flat MR listing.",
"flags": ["<path>", "-p/--project", "--discussions", "--no-follow-renames", "-n/--limit", "--mrs-only", "--merged"],
...
},
"file-history": {
"hidden": true,
"deprecated": "Use 'trace --mrs-only' instead",
...
}
Verification:
lore trace src/main.rsworks unchangedlore trace src/main.rs --mrs-onlyproduces file-history outputlore trace src/main.rs --mrs-only --mergedfilters to merged MRslore file-history src/main.rsstill works (hidden command)lore --helpshows onlytracein File Analysis group
Files touched: src/cli/args.rs, src/cli/mod.rs, src/app/handlers.rs, src/app/robot_docs.rs
P8: Make count a Flag on Entity Commands
Goal: lore issues --count replaces lore count issues. Standalone count becomes hidden.
File: src/cli/args.rs -- Add --count to IssuesArgs, MrsArgs, NotesArgs:
// In IssuesArgs:
/// Show count only (no listing)
#[arg(long, help_heading = "Output", conflicts_with_all = ["iid", "open"])]
pub count: bool,
// In MrsArgs:
/// Show count only (no listing)
#[arg(long, help_heading = "Output", conflicts_with_all = ["iid", "open"])]
pub count: bool,
// In NotesArgs:
/// Show count only (no listing)
#[arg(long, help_heading = "Output", conflicts_with = "open")]
pub count: bool,
File: src/app/handlers.rs -- In handle_issues, handle_mrs, handle_notes, check the count flag early:
// In handle_issues (pseudocode):
if args.count {
let count_args = CountArgs { entity: "issues".to_string(), for_entity: None };
return handle_count(config_override, count_args, robot_mode).await;
}
File: src/cli/mod.rs -- Hide Count:
/// Count entities in local database
#[command(hide = true, help_heading = "Query")]
Count(CountArgs),
File: src/app/robot_docs.rs -- Mark count as hidden, add --count documentation to issues/mrs/notes entries.
Verification:
lore issues --countreturns issue countlore mrs --countreturns MR countlore notes --countreturns note countlore count issuesstill works (hidden)lore count discussions --for mrstill works (no equivalent in the new pattern -- discussions/events/references still need the standalonecountcommand)
Important note: count supports entity types that don't have their own command (discussions, events, references). The standalone count must remain functional (just hidden). The --count flag on issues/mrs/notes handles the common cases only.
Files touched: src/cli/args.rs, src/cli/mod.rs, src/app/handlers.rs, src/app/robot_docs.rs
P10: Add --sort to search
Goal: Allow sorting search results by score, created date, or updated date.
File: src/cli/args.rs -- Add to SearchArgs:
/// Sort results by field (score is default for ranked search)
#[arg(long, value_parser = ["score", "created", "updated"], default_value = "score", help_heading = "Sorting")]
pub sort: String,
/// Sort ascending (default: descending)
#[arg(long, help_heading = "Sorting", overrides_with = "no_asc")]
pub asc: bool,
#[arg(long = "no-asc", hide = true, overrides_with = "asc")]
pub no_asc: bool,
File: src/cli/commands/search.rs -- Thread the sort parameter through to the search query.
The search function currently returns results sorted by score. When --sort created or --sort updated is specified, apply an ORDER BY clause to the final result set.
File: src/app/robot_docs.rs -- Add --sort and --asc to the search command's flags list.
Verification:
lore search 'auth' --sort score(default, unchanged)lore search 'auth' --sort created --asc(oldest first)lore search 'auth' --sort updated(most recently updated first)
Files touched: src/cli/args.rs, src/cli/commands/search.rs, src/app/robot_docs.rs
Phase 3 Commit Summary
Commit C: Consolidate file-history into trace
src/cli/args.rs,src/cli/mod.rs,src/app/handlers.rs,src/app/robot_docs.rs
Commit D: Add --count flag to entity commands
src/cli/args.rs,src/cli/mod.rs,src/app/handlers.rs,src/app/robot_docs.rs
Commit E: Add --sort to search
src/cli/args.rs,src/cli/commands/search.rs,src/app/robot_docs.rs
Test plan:
cargo check --all-targets
cargo clippy --all-targets -- -D warnings
cargo fmt --check
cargo test
# trace consolidation
lore trace src/main.rs --mrs-only
lore trace src/main.rs --mrs-only --merged --discussions
lore file-history src/main.rs # backward compat
# count flag
lore issues --count
lore mrs --count -s opened
lore notes --count --for-issue 42
lore count discussions --for mr # still works
# search sort
lore search 'auth' --sort created --asc
Documentation Updates
After all implementation is complete:
CLAUDE.md / AGENTS.md
Update the robot mode command reference to reflect:
stats->index(with note thatstatsis a hidden alias)health->doctor --quick(with note thathealthis a hidden alias)- Remove
ingest,generate-docs,embedfrom the primary command table (mention as "hidden, usesync") - Remove
file-historyfrom primary table (mention as "hidden, usetrace --mrs-only") - Add
--countflag to issues/mrs/notes documentation - Add
--sortflag to search documentation - Add
--mrs-onlyand--mergedflags to trace documentation
robot-docs Self-Discovery
The robot_docs.rs changes above handle this. Key points:
- New
"hidden": truefield on deprecated/hidden commands - Updated descriptions mentioning canonical alternatives
- Updated flags lists
- Updated workflows section
File Impact Summary
| File | Phase 1 | Phase 2 | Phase 3 | Total Changes |
|---|---|---|---|---|
src/cli/mod.rs |
help_heading, drift value_parser | stats->index rename, hide health, hide pipeline stages | hide file-history, hide count | 4 passes |
src/cli/args.rs |
singular/plural, remove -f, add -o |
— | --mrs-only/--merged on trace, --count on entities, --sort on search |
2 passes |
src/app/handlers.rs |
normalize entity strings | route doctor --quick | trace mrs-only delegation, count flag routing | 3 passes |
src/app/robot_docs.rs |
update count flags | rename stats->index, merge health+doctor, add hidden field | update trace, file-history, count, search entries | 3 passes |
src/cli/autocorrect.rs |
— | update CANONICAL_SUBCOMMANDS, SUBCOMMAND_ALIASES, COMMAND_FLAGS | — | 1 pass |
src/main.rs |
— | stats->index variant rename, doctor variant change | — | 1 pass |
src/cli/commands/search.rs |
— | — | sort parameter threading | 1 pass |
Before / After Summary
Command Count
| Metric | Before | After | Delta |
|---|---|---|---|
| Visible top-level commands | 29 | 21 | -8 (-28%) |
| Hidden commands (functional) | 4 | 12 | +8 (absorbed) |
| Stub/unimplemented commands | 2 | 2 | 0 |
| Total functional commands | 33 | 33 | 0 (nothing lost) |
lore --help Output
Before (29 commands, flat list, ~50 lines of commands):
Commands:
issues List or show issues [aliases: issue]
mrs List or show merge requests [aliases: mr]
notes List notes from discussions [aliases: note]
ingest Ingest data from GitLab
count Count entities in local database
status Show sync state [aliases: st]
auth Verify GitLab authentication
doctor Check environment health
version Show version information
init Initialize configuration and database
search Search indexed documents [aliases: find]
stats Show document and index statistics [aliases: stat]
generate-docs Generate searchable documents from ingested data
embed Generate vector embeddings for documents via Ollama
sync Run full sync pipeline: ingest -> generate-docs -> embed
migrate Run pending database migrations
health Quick health check: config, database, schema version
robot-docs Machine-readable command manifest for agent self-discovery
completions Generate shell completions
timeline Show a chronological timeline of events matching a query
who People intelligence: experts, workload, active discussions, overlap
me Personal work dashboard: open issues, authored/reviewing MRs, activity
file-history Show MRs that touched a file, with linked discussions
trace Trace why code was introduced: file -> MR -> issue -> discussion
drift Detect discussion divergence from original intent
related Find semantically related entities via vector search
cron Manage cron-based automatic syncing
token Manage stored GitLab token
help Print this message or the help of the given subcommand(s)
After (21 commands, grouped, ~35 lines of commands):
Query:
issues List or show issues [aliases: issue]
mrs List or show merge requests [aliases: mr]
notes List notes from discussions [aliases: note]
search Search indexed documents [aliases: find]
Intelligence:
timeline Chronological timeline of events
who People intelligence: experts, workload, overlap
me Personal work dashboard
File Analysis:
trace Trace code provenance / file history
related Find semantically related entities
drift Detect discussion divergence
Data Pipeline:
sync Run full sync pipeline
System:
init Initialize configuration and database
status Show sync state [aliases: st]
doctor Check environment health (--quick for pre-flight)
index Document and index statistics [aliases: idx]
auth Verify GitLab authentication
token Manage stored GitLab token
migrate Run pending database migrations
cron Manage automatic syncing
robot-docs Agent self-discovery manifest
completions Generate shell completions
version Show version information
Flag Consistency
| Issue | Before | After |
|---|---|---|
-f collision (force vs for) |
ingest -f=force, count -f=for |
-f removed from count; -f = force everywhere |
| Singular/plural entity types | count issues but search --type issue |
Both forms accepted everywhere |
notes --open missing -o |
notes --open (no shorthand) |
notes -o works (matches issues/mrs) |
search missing --sort |
No sort override | --sort score|created|updated + --asc |
Naming Confusion
| Before | After | Resolution |
|---|---|---|
status vs stats vs stat (3 names, 2 commands) |
status + index (2 names, 2 commands) |
Eliminated near-homonym collision |
health vs doctor (2 commands, overlapping scope) |
doctor + doctor --quick (1 command) |
Progressive disclosure |
trace vs file-history (2 commands, overlapping function) |
trace + trace --mrs-only (1 command) |
Superset absorbs subset |
Robot Ergonomics
| Metric | Before | After |
|---|---|---|
| Commands in robot-docs manifest | 29 | 21 visible + hidden section |
| Agent decision space for "system check" | 4 commands | 2 commands (status, doctor) |
| Agent decision space for "file query" | 3 commands + 2 who modes | 1 command (trace) + 2 who modes |
| Entity type parse errors from singular/plural | Common | Eliminated |
| Estimated token cost of robot-docs | Baseline | ~15% reduction (fewer entries, hidden flagged) |
What Stays Exactly The Same
- All 33 functional commands remain callable (nothing is removed)
- All existing flags and their behavior are preserved
- All response schemas are unchanged
- All exit codes are unchanged
- The autocorrect system continues to work
- All hidden/deprecated commands emit their existing warnings
What Breaks (Intentional)
lore count -f mr(the-fshorthand) -- must use--forinsteadlore --helplayout changes (commands are grouped, 8 commands hidden)lore robot-docsoutput changes (newhiddenfield, renamed keys)- Any scripts parsing
--helptext (butrobot-docsis the stable contract)