gum-cli

$npx mdskill add vchelaru/Gum/gum-cli

Execute headless Gum project creation, validation, and code generation.

  • Builds projects, validates elements, and generates C# code without a GUI.
  • Depends on Gum.ProjectServices and integrates with GumCommon.
  • Uses command parameters to determine specific actions like templates or output paths.
  • Outputs human-readable reports or structured JSON data for CI pipelines.
SKILL.md
.github/skills/gum-cliView on GitHub ↗
---
name: gum-cli
description: Reference guide for GumCli — the headless command-line tool for Gum projects. Load this when working on gumcli commands (new, check, codegen, codegen-init), Gum.ProjectServices, HeadlessErrorChecker, ProjectLoader, HeadlessCodeGenerationService, CodeGenerationAutoSetupService, or the FormsTemplateCreator.
---

# GumCli Reference

## What It Is

**GumCli** (`gumcli`) is a cross-platform .NET 8.0 console app that lets developers create, validate, and generate code for Gum projects without the WPF editor. Primary use cases: CI pipelines, scripting, editor integrations.

**Location:** `Tools/Gum.Cli/`
**Depends on:** `Gum.ProjectServices` → `GumCommon`

## Commands

| Command | Purpose |
|---------|---------|
| `gumcli new <path> [--template]` | Create a new project. Templates: `forms` (default, includes all Forms UI controls) or `empty` (minimal). |
| `gumcli check <project.gumx> [--json]` | Validate all elements (.gusx, .gutx, .gucx) that belong to the project. Human-readable or JSON output. Use this for post-write validation of any element file, not just the .gumx. |
| `gumcli codegen <project.gumx> [--element <name>...]` | Generate C# code. Requires `ProjectCodeSettings.codsj`. Per-element error check gates generation. |
| `gumcli codegen-init <project.gumx> [--force] [--csproj <path>]` | Auto-detect `.csproj`, derive namespace and output library, write `ProjectCodeSettings.codsj`. Use `--csproj` when the Gum project is not inside the MonoGame project directory. |
| `gumcli fonts <project.gumx>` | Generate missing bitmap font files (.fnt + .png). Windows-only (bmfont.exe). |

**Exit codes:** 0 = success, 1 = errors found / generation blocked, 2 = load failure, bad args, or non-Windows (fonts).

## Architecture

```
Program.cs
  ├── NewCommand      → ProjectCreator / FormsTemplateCreator
  ├── CheckCommand    → ProjectLoader → HeadlessErrorChecker
  ├── CodegenCommand  → ProjectLoader → HeadlessErrorChecker (gates) → HeadlessCodeGenerationService
  ├── CodegenInitCommand → CodeGenerationAutoSetupService
  └── FontsCommand    → ProjectLoader → HeadlessFontGenerationService (Windows-gated)
```

Each command class has a static `Create()` returning a `System.CommandLine` `Command` with handler, then a static `Execute()` doing the work.

**CLI-specific adapters:**
- `ConsoleCodeGenLogger` — implements `ICodeGenLogger`, writes to stdout/stderr
- `HeadlessNameVerifier` — implements `INameVerifier` for C# name validation

## Gum.ProjectServices

The headless service library GumCli depends on. All logic lives here; the CLI just wires it together.

**Key types:**

| Type | Role |
|------|------|
| `ProjectLoader` / `IProjectLoader` | Loads `.gumx`; detects malformed XML; returns `ProjectLoadResult` with fatal errors and non-fatal `LoadErrors` |
| `HeadlessErrorChecker` / `IHeadlessErrorChecker` | Validates base types, behaviors, parent refs, variable types. Delegates from tool's `ErrorChecker`. |
| `ProjectCreator` / `IProjectCreator` | Creates blank projects with subfolder structure |
| `FormsTemplateCreator` / `IFormsTemplateCreator` | Extracts embedded Forms template resources |
| `HeadlessCodeGenerationService` | Orchestrates per-element code file generation |
| `CodeGenerationAutoSetupService` | Walks up to find `.csproj`, derives `CodeProjectRoot`, namespace, output library |
| `CodeOutputProjectSettingsManager` | Loads/saves `ProjectCodeSettings.codsj` |
| `ErrorResult` | POCO: `ElementName`, `Message`, `Severity` (`Warning`/`Error`) |

**Non-obvious:** `HeadlessErrorChecker` is not a duplicate of the tool's `ErrorChecker` — the tool's `ErrorChecker` **delegates to** `HeadlessErrorChecker`. Zero duplication by design.

`HeadlessErrorChecker` accepts a second constructor overload taking `IEnumerable<IAdditionalErrorSource>` for extensibility; the CLI uses the single-argument overload.

`HeadlessNameVerifier` only implements real logic in `IsValidCSharpName`; all other `INameVerifier` methods return `true` unconditionally. This is intentional — the CLI only needs C# name validation for codegen.

`ProjectLoader` runs `DetectSilentlyDroppedContent` after deserialization to catch incorrect XML element names (e.g., `<States>` instead of `<State>`, `<InstanceSave>` instead of `<Instance>`) that `XmlSerializer` silently ignores. Without this, AI-generated files with wrong structure load as empty elements with no error.

`CodeGenerationAutoSetupService` detects MonoGame vs non-MonoGame projects by scanning for `<PackageReference Include="MonoGame.Framework.` or `nkast.Xna.Framework` in the `.csproj`, then sets `OutputLibrary` accordingly. Namespace falls back to the `.csproj` filename (dots/dashes/spaces replaced with underscores) when `<RootNamespace>` is absent.

`CodeGenerationAutoSetupService` has two `Run` overloads: `Run(gumxFilePath)` for auto-detection, and `Run(gumxFilePath, explicitCsprojPath)` for when the caller already knows the `.csproj` path. The explicit overload validates the file exists and skips directory walking entirely; all namespace/OutputLibrary derivation logic is shared via the private `BuildResultFromCsprojDirectory` helper.

Font files are named like `Font18Arial.fnt` and `Font18Arial_0.png` (size+name convention, zero-indexed). Always use `gumcli fonts <project.gumx>` to generate missing bitmap fonts — never create `.fnt` files manually.

## Codegen Flow (non-obvious details)

- `codegen` iterates elements individually (not via `GenerateCodeForAllElements`) so it can run per-element error checks first; `GenerateCodeForAllElements` exists on `HeadlessCodeGenerationService` but the CLI does not call it
- Only Screens and Components are generated; StandardElements are intentionally excluded
- Errors (`ErrorSeverity.Error`) block generation for that element; warnings print to stderr but do not block
- `ObjectFinder.Self` cache is managed at the CLI level (enabled before the loop, disabled in `finally`)
- If `ProjectCodeSettings.codsj` is missing, `codegen` attempts `CodeGenerationAutoSetupService` auto-detection first and writes the settings file before continuing; exit code 2 only if auto-detection also fails
- When `--element` is specified, `checkForMissing: true` is passed so `GenerateCodeForElement` auto-generates any referenced elements whose code files do not yet exist; full-run mode skips that check
- `codegen-init` exits with code 2 (not 1) if settings already exist and `--force` is absent

## Key Files

| File | Purpose |
|------|---------|
| `Tools/Gum.Cli/Program.cs` | Entry point, assembles RootCommand |
| `Tools/Gum.Cli/Commands/` | One file per command |
| `Gum.ProjectServices/ProjectLoader.cs` | Headless project loading |
| `Gum.ProjectServices/HeadlessErrorChecker.cs` | All headless error checks |
| `Gum.ProjectServices/CodeGeneration/HeadlessCodeGenerationService.cs` | Headless codegen orchestration |
| `Gum.ProjectServices/CodeGeneration/CodeGenerator.cs` | Main codegen engine (~5400 lines) |
| `Tests/Gum.Cli.Tests/` | CLI command tests |
| `Tests/Gum.ProjectServices.Tests/` | Service layer tests (36 tests) |

## Testing Notes

- `ObjectFinder` is a singleton — tests disable parallel execution (`TestAssemblyInitialize`)
- `BaseTestClass` pre-populates `GumProjectSave` with standard elements and handles `ObjectFinder.Self` cleanup
More from vchelaru/Gum