This file provides guidance for AI agents (Claude Code, GitHub Copilot, etc.) working on this codebase.
AppVeyor CLI is a .NET 10 command-line tool for the AppVeyor CI/CD REST API. It uses Spectre.Console.Cli for command parsing and rich terminal output, with JSON output support for AI/machine consumption.
src/AppVeyorCli/
Program.cs - Entry point, DI setup, command tree registration
Infrastructure/ - Spectre.Console DI bridge, global settings, read-only guard
Configuration/ - Config file and env var management (~/.appveyor/config.json)
Api/ - IAppVeyorClient interface + HttpClient implementation
Models/ - C# record types for API entities (Project, Build, User, Role, etc.)
Output/ - IOutputRenderer abstraction (ConsoleRenderer vs JsonRenderer)
Commands/ - One folder per domain (Config, Projects, Builds, Environments, Deployments, Users, Collaborators, Roles)
tests/AppVeyorCli.Tests/
Infrastructure/ - MockAppVeyorServer (fake HTTP server for integration tests)
Api/ - Serialization and config unit tests
Commands/ - Integration tests using CommandApp + MockAppVeyorServer
- Each command is an
AsyncCommand<TSettings>with settings inheriting fromGlobalSettings - Commands receive
IAppVeyorClientandIConsoleProvidervia constructor injection - Output goes through
OutputRendererFactory.Create(settings.Json, consoleProvider.Console)which returns either aConsoleRenderer(rich Spectre tables) orJsonRenderer(clean JSON) - Write commands must call
ReadOnlyGuard.ThrowIfReadOnly(settings)as first line in ExecuteAsync
AppVeyorClientusesHttpClientwith base URLhttps://ci.appveyor.com/api/- All paths are relative (e.g.
projects, not/api/projects) - System.Text.Json source generators via
AppVeyorJsonContextfor AOT compatibility - All methods accept
CancellationToken
- Spectre.Console.Cli overrides user-registered
IAnsiConsolein DI, so we useIConsoleProvideras an indirection layer - Tests inject
TestConsoleviaIConsoleProviderto capture command output
MockAppVeyorServerusesHttpListeneron a random port with retry logic- Routes are registered as full paths including
/api/prefix (e.g./api/projects) - Use
RegisterJsonResponsewith source-genJsonTypeInfofor type-safe mock responses - Use
RegisterRawResponsefor error scenarios (401, 404, etc.)
dotnet tool restore # Restore Cake tool
dotnet run build.cs # Clean + Build + Test (Cake SDK)
dotnet test # Tests only- Create settings class inheriting from
GlobalSettingsin the appropriateCommands/subfolder - Create command class as
AsyncCommand<TSettings>withIAppVeyorClientandIConsoleProviderin constructor - Use
OutputRendererFactory.Create(settings.Json, consoleProvider.Console)for output - For write commands, add
ReadOnlyGuard.ThrowIfReadOnly(settings)as first line - Register the command in
Program.csunder the appropriateAddBranch - Add API method to
IAppVeyorClientandAppVeyorClientif needed - Register any new model types in
AppVeyorJsonContext - Add tests in
tests/AppVeyorCli.Tests/Commands/
- Create a C# record in
Models/with[JsonPropertyName]attributes - Register the type (and array type if needed) in
AppVeyorJsonContext - Add serialization round-trip tests in
Api/SerializationTests.cs
- Target framework:
net10.0, C# 14 - Models: immutable record types
- Serialization: System.Text.Json source generators only (no reflection)
- Async: all API calls use async/await with CancellationToken
- Error handling:
AppVeyorApiExceptionwith typed status codes - Project slug format:
account/slug(parsed bysettings.Parse())