.claude/skills/cli-expert/SKILL.md
CLI development expert for building production-grade command-line tools. Covers System.CommandLine, POSIX conventions, help text design, output formatting, and MCP-to-CLI feature parity for the CodeCompress CLI.
npx skillsauth add MCrank/code-compress cli-expertInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are a CLI development expert for the CodeCompress project. Guide the implementation of production-grade CLI commands with proper help text, output formatting, error handling, and feature parity with the MCP server.
For .NET project conventions, see dotnet-reference.md.
Never rely on training data for CLI framework APIs. Always fetch current documentation.
Use the Context7 MCP (resolve-library-id → query-docs):
resolve-library-id("System.CommandLine") → query-docs(id, "RootCommand Option Handler")Use the Ref MCP as a secondary source.
The CLI tool lives at src/CodeCompress.Cli/ and shares CodeCompress.Core with the MCP server. Both use identical business logic — the CLI is a process-per-invocation wrapper while the MCP server is long-running.
Key class: CliProjectScope — creates a scoped SQLite connection, SqliteSymbolStore, and IndexEngine per CLI invocation. Disposed on exit.
Every CLI command mirrors an MCP tool with identical parameters and output structure:
| CLI Command | MCP Tool | Category |
|---|---|---|
| index | index_project | Indexing |
| snapshot | snapshot_create | Indexing |
| invalidate-cache | invalidate_cache | Indexing |
| outline | project_outline | Query |
| get-symbol | get_symbol | Query |
| expand-symbol | expand_symbol | Query |
| get-symbols | get_symbols | Query (batch) |
| get-module-api | get_module_api | Query |
| search | search_symbols | Query |
| search-text | search_text | Query |
| topic-outline | topic_outline | Query |
| find-references | find_references | Query |
| changes | changes_since | Delta |
| file-tree | file_tree | Delta |
| deps | dependency_graph | Dependency |
| project-deps | project_dependencies | Dependency |
When implementing a CLI command, read the MCP tool source first to ensure identical Core API calls and parameter handling.
var rootCommand = new RootCommand(
"CodeCompress CLI — Compressed, symbol-level code access. " +
"Saves 80-90% tokens vs reading raw files.");
var jsonOption = new Option<bool>("--json", "Output as JSON (default: human-readable)");
rootCommand.AddGlobalOption(jsonOption);
rootCommand.AddCommand(CreateIndexCommand(jsonOption));
rootCommand.AddCommand(CreateOutlineCommand(jsonOption));
// ... register all commands
return await rootCommand.InvokeAsync(args);
static Command CreateIndexCommand(Option<bool> jsonOption)
{
var pathOption = new Option<string>("--path", "Absolute path to the project root")
{
IsRequired = true
};
var languageOption = new Option<string?>("--language", "Filter to a specific language");
var command = new Command("index", "Index a project to build a searchable symbol database. " +
"Must be called before any query commands. Re-running performs incremental update.")
{
pathOption,
languageOption
};
command.SetHandler(async (context) =>
{
var path = context.ParseResult.GetValueForOption(pathOption)!;
var language = context.ParseResult.GetValueForOption(languageOption);
var json = context.ParseResult.GetValueForOption(jsonOption);
var ct = context.GetCancellationToken();
// ... implementation
context.ExitCode = 0;
});
return command;
}
--json — output structured JSON to stdout (default: human-readable)--version — show version (built into System.CommandLine via rootCommand.AddOption)| Convention | Example | Rule |
|---|---|---|
| Long options | --path, --query | Double dash, kebab-case |
| Short aliases | -p for --path | Single dash, single char (common options only) |
| Boolean flags | --json, --include-private | No value needed |
| Required options | --path | IsRequired = true |
| Optional with default | --limit 20 | Default shown in help |
| Value separator | --path /foo or --path=/foo | Space or = (System.CommandLine handles both) |
| Code | Meaning | When | |------|---------|------| | 0 | Success | Command completed successfully | | 1 | General error | Runtime failure (symbol not found, DB error, path validation) | | 2 | Usage error | Bad arguments, missing required options (System.CommandLine auto-handles) |
Set in handler: context.ExitCode = 1;
System.CommandLine returns exit code 2 automatically for parsing errors.
Human-readable (default):
JSON (--json):
JsonNamingPolicy.SnakeCaseLower — matches MCP server outputPattern:
if (json)
{
var jsonText = JsonSerializer.Serialize(result, serializerOptions);
await Console.Out.WriteLineAsync(jsonText).ConfigureAwait(false);
}
else
{
await WriteHumanOutput(result).ConfigureAwait(false);
}
Serializer options:
var serializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
WriteIndented = true,
};
Errors always go to stderr. Format:
Error: Symbol not found: FooBar.
Hint: Use 'codecompress search --path <path> --query Foo*' to discover symbol names.
Error: Project not indexed.
Hint: Run 'codecompress index --path <path>' first.
Never show: Stack traces, internal paths, SQL queries, or raw exception messages.
Should include:
Recommended Workflow:
1. index Build/update the symbol database
2. outline Get a compressed codebase overview
3. search Find symbols or patterns (FTS5)
4. get-symbol Retrieve exact source code by name
--json, --version)Each command's --help should show:
System.CommandLine auto-generates most of this from Command and Option descriptions.
All path validation follows the same OWASP A01 rules as the MCP server:
PathValidator.ValidatePath() on every --path inputIPathValidator injected via DIvar scope = await CreateProjectScopeAsync(path, provider).ConfigureAwait(false);
await using (scope.ConfigureAwait(false))
{
// Use scope.Store, scope.Engine, scope.RepoId, scope.ProjectRoot
}
Use context.GetCancellationToken() from System.CommandLine for Ctrl+C handling:
command.SetHandler(async (context) =>
{
var ct = context.GetCancellationToken();
await scope.Engine.IndexProjectAsync(path, language, cancellationToken: ct)
.ConfigureAwait(false);
});
When this skill is invoked as a sub-agent, the caller must provide:
development
TDD expert with deep TUnit, NSubstitute, and Verify knowledge. Use for writing tests, test infrastructure, and enforcing test-first methodology in the CodeCompress project.
tools
--- name: security-expert description: Security expert covering OWASP Top 10 and MCP-specific threats (prompt injection, data exfiltration, tool poisoning). Use for security reviews, implementation guidance, and audit of CodeCompress code. argument-hint: [review|enforce] [file-or-directory] disable-model-invocation: true --- # Security Expert — CodeCompress You are a security expert for the CodeCompress MCP server. This server indexes codebases and provides AI agents with compressed code acces
development
Language parser development expert for CodeCompress. Covers the ILanguageParser strategy pattern, regex-based symbol extraction, and language-specific grammar for all current parsers (Luau, C#, Terraform, Blazor, .NET Project, JSON) and planned parsers (Python, Go, Rust).
tools
Implement a feature from a mini-plan document, user story, or GitHub issue using TDD, enforcing security and .NET/MCP best practices. Pass the path to a mini-plan .md file, user story, or GitHub issue URL/file. Also use when the user says "implement issue