Skip to content

Conversation

@dluc
Copy link
Collaborator

@dluc dluc commented Nov 28, 2025

This PR introduces a complete command-line interface for Kernel Memory, enabling users to manage content via terminal commands.

Overview

Complete CLI implementation with 6 core commands, multiple output formats, comprehensive test coverage, and a friendly first-run experience.

Stats:

  • 106 files changed (+6,473/-202 lines)
  • 183 CLI tests + 77 Core tests (260 total)
  • Zero warnings, zero errors
  • Clean dependency injection architecture

Features

Commands

  • km upsert - Create or update content with optional metadata
  • km get <id> - Retrieve content by ID
  • km delete <id> - Delete content by ID
  • km list - List all content with pagination
  • km nodes - List configured nodes
  • km config - Query configuration settings

Output Formats

  • Human - Friendly, colored terminal output (default)
  • JSON - Machine-readable JSON
  • YAML - Machine-readable YAML

Global Options

  • --config <path> - Custom config file path
  • --node <name> - Target specific node
  • --format <human|json|yaml> - Output format
  • --verbosity <normal|quiet|silent> - Control output detail

Examples

# First-run experience
$ km list
Welcome to Kernel Memory! 🚀

No content found yet. This is your first run.

To get started:
  km upsert "Your content here"

# Add content
$ km upsert "Hello, world!" --id greeting
{
  "id": "greeting",
  "status": "success"
}

# Retrieve content
$ km get greeting --format yaml
id: greeting
content: Hello, world!
createdAt: 2025-11-28T10:00:00Z

# List with pagination
$ km list --skip 10 --take 20 --format json
{
  "items": [...],
  "pagination": {
    "totalCount": 45,
    "skip": 10,
    "take": 20,
    "returned": 20
  }
}

# Delete content
$ km delete greeting
{
  "id": "greeting",
  "status": "deleted"
}

Architecture

Config Injection

Configuration is loaded once at startup and injected via dependency injection:

  • No hardcoded file paths in commands
  • Tests inject mock configs (never touch ~/.km/)
  • Clean separation: config loading in Main, business logic in commands

Command Structure

Main → CliApplicationBuilder.Build(args) → Load Config → DI Container →
Commands receive AppConfig via constructor → Business logic executes

Exit Codes

  • 0 - Success (includes "no data yet" state)
  • 1 - User error (invalid arguments, ID not found)
  • 2 - System error (DB corruption, permission denied)

First-Run UX

When the database doesn't exist yet (expected on first run):

  • Shows welcoming message with examples (human format)
  • Returns valid empty JSON/YAML (machine-readable formats)
  • Exit code 0 (not an error)
  • Clear distinction between "no data yet" vs actual errors

Components Added

CLI Layer (src/Main/CLI/)

  • Commands/ - 6 command implementations (Upsert, Get, Delete, List, Nodes, Config)
  • OutputFormatters/ - Human, JSON, YAML formatters
  • Infrastructure/ - DI integration (TypeRegistrar, TypeResolver)
  • Exceptions/ - DatabaseNotFoundException for first-run state
  • Models/ - DTOs for structured output

Services Layer (src/Main/Services/)

  • ContentService - Business logic wrapping ContentStorage

Test Suite (tests/Main.Tests/)

  • Integration/ - 4 test suites (CLI integration, command execution, readonly commands, user data protection)
  • Unit/ - 12 test suites covering commands, formatters, settings, services
  • Helpers/ - TestCliApplicationBuilder for test config injection

Infrastructure

  • build.sh - Zero-warning build validation
  • coverage.sh - Test coverage reporting
  • km.sh - CLI wrapper script
  • TypeScript-style .editorconfig - Code style enforcement

Quality Metrics

Test Coverage

  • ✅ 183 Main.Tests passing
  • ✅ 77 Core.Tests passing
  • ✅ 260 total tests, zero skipped
  • ✅ Coverage meets 80% minimum requirement

Build Quality

  • ✅ Zero warnings
  • ✅ Zero errors
  • ✅ All analyzers enabled (Roslynator, .NET analyzers)
  • ✅ Formatted with dotnet format

Design Principles

  • ✅ SOLID principles
  • ✅ Single Responsibility Principle
  • ✅ Dependency injection
  • ✅ Clean separation of concerns
  • ✅ Comprehensive error handling

Testing Strategy

Integration Tests

  • End-to-end command execution
  • Multi-command workflows
  • Config injection verification
  • First-run experience validation

Unit Tests

  • Command initialization and validation
  • Output formatter behavior
  • Settings validation
  • Service layer logic
  • Error handling

Critical Tests

  • UserDataProtectionTests - Ensures tests never touch ~/.km/
  • ReadonlyCommandTests - Verifies readonly commands don't create files
  • CliIntegrationTests - Validates complete workflows

Breaking Changes

None - this is a new CLI, doesn't affect existing APIs or libraries.

Migration Guide

Not applicable - this is a new feature addition.

dluc and others added 15 commits November 27, 2025 12:38
- Added missing copyright headers to 60 files
- Fixed IDE0073 violations
- Removed Main.Tests reference from solution (was deleted)
- Created Main.Tests.csproj with xUnit and Moq
- Added Moq to Directory.Packages.props
- Added placeholder test (1 passing)
- Ready to add coverage-driven tests
- Integration tests: 18 end-to-end CLI workflows
- Service tests: 10 ContentService tests
- Formatter tests: 25 JSON/YAML/Factory tests
- Settings tests: 48 validation tests
- HumanOutputFormatter tests: 29 tests
- DTO tests: 12 model tests
- BaseCommand tests: 5 error handling tests

Current coverage: 42.5% (need to reach 80%)
- Extract CliApplicationBuilder (configures CLI commands)
- Extract ModeRouter (handles mode detection and routing)
- Keep Program.cs thin (just entry point delegation)
- Makes previously untestable code now testable

This will increase coverage significantly.
- 11 tests for ModeRouter (mode detection and routing)
- 2 tests for CliApplicationBuilder
- Coverage improved from 42.5% to 69.30% (+26.8 points)
- Still need 10.7 points to reach 80% target

Total: 166 tests passing
- Tests error paths in all commands
- Tests edge cases (non-existent IDs, empty DB)
- Tests all ConfigCommand flags
- Additional coverage for command execution paths

Total: 176 tests (was 166)
- Fix GlobalOptions import
- Fix NodesCommandSettings type mismatch

Ready to measure coverage
- Added EmptyRemainingArguments helper for CommandContext
- Fixed all CommandContext constructor calls
- All 175 tests now passing

Ready to measure coverage
Code quality fixes:
- CA1861: Convert inline arrays to static readonly fields (15 fixes)
- RCS1118: Mark local variables as const (51 fixes)
- IDE0073: Add copyright headers to test files (8 fixes)
- RCS1141: Add param XML documentation (4 fixes)
- IDE0130: Fix namespace mismatches (4 fixes)
- CA1869: Cache JsonSerializerOptions (2 fixes)
- CA1031: Specific exception handling (1 fix)
- CA2000: Dispose IDisposable objects (1 fix)
- CA2201: Don't throw generic exceptions (2 fixes)
- CS8625: Null literal fixes (3 fixes)
- RCS1037: Remove trailing whitespace (8 fixes)
- IDE0005: Remove unnecessary usings (4 fixes)

Build result: 0 warnings, 0 errors
Coverage: Main 92.79% (exceeds 80% target)
Tests: 175 passing, 0 failed, 0 skipped
Implemented config injection architecture to prevent tests from accidentally
writing to personal ~/.km directory. Config is now loaded once in Main before
any command logic runs, then injected via dependency injection.

Changes:
- Add DI infrastructure (TypeRegistrar/TypeResolver) for Spectre.Console.Cli
- Refactor CliApplicationBuilder to load config early and setup DI container
- Update all 6 commands to receive AppConfig via constructor injection
- Change BaseCommand.InitializeAsync() to synchronous Initialize() (no file I/O)
- Create TestCliApplicationBuilder for easy test config injection
- Add UserDataProtectionTests to verify tests never touch ~/.km
- Update all test files to inject configs explicitly

Architecture:
Main → CliApplicationBuilder.Build(args) → Load config → Register in DI →
Commands receive via constructor → Tests inject mock configs (no disk I/O)

Results:
✅ Build: 0 warnings, 0 errors
✅ Tests: 260 tests passed (100% success rate)
✅ Protection: Tests can NO LONGER touch ~/.km accidentally

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <[email protected]>
- Add coverage.sh script for generating test coverage reports
- Update km.sh wrapper script
- Improve HumanOutputFormatter for better list display
- Add comprehensive ContentStorageService tests
- Enhance ContentService test coverage

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <[email protected]>
When users first install KM and run 'km list' or 'km get', they now see
welcoming, helpful messages instead of technical errors.

Changes:
- Add DatabaseNotFoundException for expected first-run state
- Update BaseCommand to throw specific exception for missing DB
- Handle DatabaseNotFoundException gracefully in ListCommand and GetCommand
- Show friendly welcome message in human format with next-step guidance
- Return valid empty JSON/YAML for machine-readable formats
- Exit code 0 (success) for missing DB - it's not an error on first run
- Update tests to expect new friendly behavior

UX improvements:
- Human format: "Welcome to Kernel Memory! 🚀" with examples
- JSON format: Valid empty array/null (parseable output)
- Clear distinction: missing DB (first run) vs ID not found (user error)

Exit codes:
- 0 = Success (includes first-run "no data yet" state)
- 1 = User error (invalid arguments, ID not found in existing DB)
- 2 = System error (DB corruption, permission denied)
@dluc dluc changed the title Improve first-run UX: friendly messages when no database exists Add complete CLI application with 6 commands and friendly first-run experience Nov 28, 2025
@dluc dluc changed the title Add complete CLI application with 6 commands and friendly first-run experience Add CLI application: 6 commands, 3 output formats, 260 tests Nov 28, 2025
@dluc dluc merged commit 9002c28 into microsoft:main Nov 28, 2025
3 checks passed
@dluc dluc deleted the cli branch November 28, 2025 09:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant