Agent skill

Gum Codegen

by vchelaru in vchelaru/FlatRedBall

A skill your agent uses when working on Glue's Gum code generation — adding/removing/version-gating generated properties on Gum standard runtime types (NineSlice, Text, Container, Sprite, etc.), or…

MITAuto-check passedDevelopment

Install Gum Codegen

skills CLI
$ npx skills add vchelaru/FlatRedBall --skill gum-codegen -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install vchelaru/FlatRedBall gum-codegen --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/vchelaru/FlatRedBall.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/gum-codegen .claude/skills/gum-codegen && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
gum-codegen
GitHub stars
578
Token cost
~3.3k tokens
SKILL.md length
1,465 words
Files
1
Skills in repo
32
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when working on Glue's Gum code generation — adding/removing/version-gating generated properties on Gum standard runtime types (NineSlice, Text, Container, Sprite, etc.), or…

  • Works in 3 steps: Property generation — emits the public T… → State generation — emits the case… → Inheritance — emits the :…
  • Working on Glues Gum code generation — adding/removing/version-gating generated properties on Gum standard runtime types (NineSlice
  • SKILL.md covers There are THREE independent…, Glue never back-fills a loaded…, The compiler can never catch a… and Where it lives, plus 5 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Gum Codegen is an agent skill from vchelaru/FlatRedBall. Use when working on Glue's Gum code generation — adding/removing/version-gating generated properties on Gum standard runtime types (NineSlice, Text, Container, Sprite, etc.), or debugging "why is/isn't this Gum variable being generated."

Its SKILL.md is about 3.3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering Project scaffolding. The repository describes itself as: Cross-platform 2D game engine focused on ultimate productivity built in .NET. The licence is MIT.

When your agent uses it

  • Working on Glues Gum code generation — adding/removing/version-gating generated properties on Gum standard runtime types (NineSlice
  • Debugging why is/isnt this Gum variable being generated

Example prompts

  • “why is/isn”
  • “/gum-codegen”

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Property generation — emits the public T Foo { get; set; } (or backing-field) property on the runtime class. Driven by…
  2. State generation — emits the case VariableState.Default: Foo = …; assignments inside the state-switch. Driven by StateCodeGenerator.
  3. Inheritance — emits the : global::Gum.Wireframe.IFooRuntime on the class declaration, via each per-type generator's…

What it can do on your machine

Read from SKILL.md and the folder at commit f30172a. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are csharp).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Gum Codegen loads about 3.3k tokens when it runs. Until then it costs about 62 tokens; SKILL.md has 1,465 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~62
When it runs · the whole SKILL.md, loaded when a task matches
~3.3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from vchelaru/FlatRedBall at commit f30172a, republished under its MIT licence (© vchelaru). 1,465 words, ~3,267 tokens.

Download SKILL.mdSave it as .claude/skills/gum-codegen/SKILL.md (or your agent's skills folder).
name
gum-codegen
description
Use when working on Glue's Gum code generation — adding/removing/version-gating generated properties on Gum standard runtime types (NineSlice, Text, Container, Sprite, etc.), or debugging "why is/isn't this Gum variable being generated."
version
1.0.0

Gum Code Generation in Glue

Glue does not rely on Gum's own runtime code generation for the standard element runtimes. Instead, the Gum plugin regenerates these classes itself from the Gum project data. The upside is tight control over what gets emitted; the downside is that whenever Gum adds, removes, or renames a variable on a standard type, Glue's generator has to be updated to match — otherwise the new variable is silently emitted (causing build/runtime errors on older projects) or silently omitted (causing missing properties on newer projects).

This skill is about the omission side: how Glue decides which Gum variables to skip when generating a standard runtime, and how to gate that decision on a GluxVersions value. For the version-numbering rules themselves, see the gluj-versions skill.

There are THREE independent decisions, not one

Generating a standard runtime like NineSliceRuntime.Generated.cs involves three independent code paths. All three must agree on whether a member exists in a given version, and each disagreement has its own compiler error:

  1. Property generation — emits the public T Foo { get; set; } (or backing-field) property on the runtime class. Driven by StandardsCodeGenerator and per-type generators (NineSliceCodeGenerator, etc.).
  2. State generation — emits the case VariableState.Default: Foo = …; assignments inside the state-switch. Driven by StateCodeGenerator.
  3. Inheritance — emits the : global::Gum.Wireframe.IFooRuntime on the class declaration, via each per-type generator's AddAdditionalInheritance (wired up in StandardsCodeGenerator.GenerateStandardElementSaveCodeFor).

Property vs. state disagreement is CS0103: The name 'IsTilingMiddleSections' does not exist in the current context — a state-init assignment for a property nobody generated. Inheritance vs. property disagreement is CS0535: does not implement interface member (issue #1979).

Pipelines 1 and 2 are driven by the project's variables; pipeline 3 is driven by GluxVersions alone, so it is the one that most easily drifts. The Gum.Wireframe.I*Runtime interfaces it names are hand-written in the sibling Gum repo under #if FRB (Gum/Wireframe/CustomSetPropertyOnRenderable.cs) and mirror what Glue generates; they grow as Gum routes more of its property dispatch through the runtime instead of the renderable. Glue holds no reference to GumCore, so nothing in Glue can read one — NineSliceCodeGenerator.InterfaceMemberNames restates the contract by hand, and GumGeneratedCodeCompilesTests is what detects drift. ContainerCodeGenerator/PolygonCodeGenerator avoid the problem differently, by emitting their interface members from GenerateAdditionalMethods rather than relying on the project's variables at all.

When you add a version gate, update every pipeline that touches the member. Searching for an existing skipped variable name (e.g. "IgnoredByParentSize", "StackSpacing") is the fastest way to spot every place that needs a parallel change — they typically appear in both StandardsCodeGenerator.RefreshVariableNamesToSkipForProperties and StateCodeGenerator.RefreshVariableNamesToSkipBasedOnGlueVersion.

Glue never back-fills a loaded project's standard elements (landmine)

Codegen emits from the variables in the project's own .gutx, and Glue never reconciles that against Gum's canonical schema. Gum's tool does (GumProjectSaveExtensionMethods.Initialize back-fills each standard element from StandardElementsManager, gated by VariableSave.MinimumGumxVersion); Glue calls GumProjectSave.Load and never that. What it does call — FileReferenceTracker.InitializeElements — passes each element its own default state, which resolves variable types but back-fills nothing.

Consequences worth knowing before debugging "why isn't this variable generated":

  • A .gutx written before Gum added a variable never gains it, at any Glue version. Every checked-in sample is in this state.
  • Bumping GluxVersions alone will not make a variable appear — if the project's .gutx lacks it, no gate change helps.
  • A fixture built from StandardElementsManager.Self.GetDefaultStateFor(name) is a current editor's output, so it cannot reproduce this. Load a real sample's .gumx and call Initialize(element.DefaultState) per element to match production — see GumGeneratedCodeCompilesTests.LegacyGutxStandardElementRuntimes_ShouldCompileAgainstTheRealEngine.
  • ProjectLoader.LoadProject bumps the .gluj's FileVersion to LatestVersion on load. So the live combination is always current GluxVersions + whatever the .gutx happens to contain, which is exactly what produced #1979.

The compiler can never catch a runtime mismatch (landmine)

Glue has no compile-time knowledge of the runtime types it generates against. mStandardElementToQualifiedTypes holds fully-qualified type names as plain strings; RenderingLibrary.Graphics.Text is not a referenced assembly in any Glue project, and it is not among GumPlugin's embedded LibraryFiles resources either (LineRectangle.cs is embedded, Text.cs is not). So emitting ContainedText.DropshadowBlur for a member that doesn't exist compiles Glue perfectly and only fails in the user's game project, as CS1061.

This is why the bug class recurs: Rectangle/Circle's fill/stroke family (#1907), the Arc/ColoredCircle gradient CS0266, and Text's dropshadow-channel + LocalizeText family were each found by a user's build breaking, not by CI.

GlueUnitTests/GumPlugin/GumRuntimeMemberContractTests.cs is the guard: it builds the engine's Forms solution, reflects over the real GumCore/SkiaInGum assemblies, and asserts every ContainedXxx.Member the generator emits exists on the mapped runtime type. It's driven off StandardsCodeGenerator.StandardElementToQualifiedTypes, so a standard element added to that map is covered automatically. When Gum extends a standard element's schema, that test — not the compiler — is what tells you whether FRB's runtime can back it.

Note the fix is per-member, not per-type: Text legitimately backs HasDropshadow/DropshadowOffsetX/DropshadowOffsetY (it has a single DropshadowColor) while having no per-channel color, no blur, and no LocalizeText. Skip only what's actually unbacked.

Where it lives

Property pipeline:

  • Central orchestrator: FRBDK/Glue/GumPlugin/GumPlugin/CodeGeneration/StandardsCodeGenerator.cs
  • Per-type contributors: NineSliceCodeGenerator.cs, TextCodeGenerator.cs, ContainerCodeGenerator.cs, etc. (same folder)
  • Wired up in MainGumPlugin.cs (each per-type generator is instantiated and passed into StandardsCodeGenerator).

State pipeline:

  • FRBDK/Glue/GumPlugin/GumPlugin/CodeGeneration/StateCodeGenerator.cs
  • Two relevant entry points: RefreshVariablesToSkipForStates() (unconditional skips and per-type contributions) and RefreshVariableNamesToSkipBasedOnGlueVersion() (version-gated skips, the right place for a GluxVersions-keyed gate).
Show full SKILL.md (616 more words)Show less

The two skip lists

StandardsCodeGenerator keeps two collections that drive omission, both cleared and rebuilt every time RefreshVariableNamesToSkipForProperties() runs:

  1. mVariableNamesToSkipForProperties — List<string>. Applies to every standard element. Use for variables that should never be generated regardless of type (X, Y, Width, Visible, etc., already handled by GraphicalUiElement).
  2. _typedVariableNamesToSkipForProperties — Dictionary<string, List<string>> keyed by standard element name (e.g. "NineSlice"). Use for variables that only exist on a specific type and should be skipped only there.

Both lists are consumed by GetIfShouldGenerateProperty(variable, standardElementSave), which is called for every variable on the default state during generation. Anything in either list short-circuits to false.

Version-gating an omission

There are two patterns depending on whether the variable is type-specific.

Global (any standard element): use the local ExcludeIfVersionLessThan helper inside RefreshVariableNamesToSkipForProperties:

csharp
ExcludeIfVersionLessThan("CustomFrameTextureCoordinateWidth", GluxVersions.GumUsesSystemTypes);

This adds the name to mVariableNamesToSkipForProperties only when the loaded project is below the gating version.

Type-specific: put the gate on the per-type generator as a bool property, then conditionally add to its contribution. NineSliceCodeGenerator is the canonical small example:

csharp
bool HasNineSliceAnimate =>
    _glueState.CurrentGlueProject?.FileVersion >= (int)GluxVersions.GumNineSliceHasAnimate ||
    _glueState.CurrentMainProject?.IsFrbSourceLinked() == true;

internal void AddTypeSpecificVariableNamesToSkipForProperties(
    Dictionary<string, List<string>> typedVariableNamesToSkipForProperties)
{
    var variablesToIgnore = new List<string>();
    typedVariableNamesToSkipForProperties.Add("NineSlice", variablesToIgnore);

    if (!HasNineSliceAnimate)
    {
        variablesToIgnore.Add("Animate");
    }
}

Two things to note in that pattern:

  • IsFrbSourceLinked() plays the same role as REFERENCES_FRB_SOURCE in embedded code files: if the user references FRB as source, treat the feature as available regardless of FileVersion. Always include this arm for type-specific gates.
  • The list is registered in the dictionary unconditionally (with the type name as key). Only the contents are conditional. This is so GetIfShouldGenerateProperty can do a single dictionary lookup per type.

Live GumxVersions gating — a different axis than the GluxVersions skip-lists above

Everything above gates on GluxVersions (Glue's own file format) at skip-list-refresh time. A standard element's variable family — and even which qualified runtime type it maps to — can instead need gating on Gum's own project version (GumxVersions, e.g. ShapeVariableExpansion), read live off Gum.Managers.ObjectFinder.Self.GumProjectSave.Version at generation time rather than cached in a skip-list refresh. This matters when one generator instance/process must serve whatever gumx version happens to be loaded (old and new projects both use the same Glue build), so the decision can't be baked in once. See StandardsCodeGenerator.IsRectangleFillStrokeSupported/GetQualifiedTypeFor for the pattern: a live bool checked both when choosing the contained type (mStandardElementToQualifiedTypes lookup vs. an override) and when deciding per-property generation, instead of a static skip list.

State-pipeline gate

StateCodeGenerator.RefreshVariableNamesToSkipBasedOnGlueVersion uses a paired Include / Skip helper pattern. To gate a new variable, add a block alongside the existing ones:

csharp
if (version >= (int)GluxVersions.NineSliceHasTilingMiddleSections)
{
    Include("IsTilingMiddleSections");
}
else
{
    Skip("IsTilingMiddleSections");
}

For a variable that only exists on a single standard type (like IsTilingMiddleSections on NineSlice), a global skip is fine — older projects don't have that type with that variable, so a global gate is harmless and matches existing precedent (StackSpacing, IgnoredByParentSize, IsBold, etc., are all gated globally here).

There's also a per-type variant analogous to the property pipeline (AddTypeSpecificVariableNamesToSkipForStates on per-type generators, dictionary-keyed by element name). Use it only when a variable name might collide across types and the gate must apply to one type.

When you're adding a new gate

  1. Decide if the variable is global or type-specific.
  2. Add a GluxVersions entry per the gluj-versions skill (including LatestVersion, SyntaxVersionAttribute, docs).
  3. Update every pipeline that touches it:
    • Property pipeline: ExcludeIfVersionLessThan(...) in StandardsCodeGenerator.RefreshVariableNamesToSkipForProperties (global) or the NineSliceCodeGenerator-style HasFeature bool + conditional Add (type-specific).
    • State pipeline: an if/else Include / Skip block in StateCodeGenerator.RefreshVariableNamesToSkipBasedOnGlueVersion.
    • Inheritance: only if the member belongs to a Gum.Wireframe.I*Runtime interface — gate the members on the same bool as AddAdditionalInheritance, never a separate one.
  4. The gate's polarity is "skip when below version", i.e. older projects don't see the new variable. The new variable becomes visible at and above the gating version.

A pre-flight check that's saved time more than once: pick one already-gated variable (IgnoredByParentSize is a good one) and grep for it. Every place it appears is a place your new variable probably also needs to appear.

© vchelaru, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/gum-codegen of vchelaru/FlatRedBall.

Open the folder on GitHubat commit f30172a

Compare with similar skills

Gum Codegen next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Gum Codegen compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Gum Codegen this skillvchelaru/FlatRedBall578—~3.3kAutomated safety check: PassMIT
Nx Generatenomcopter/react-mosaic4.8k7 repos~1.9kAutomated safety check: PassCustom licence
PonytailDavidObando/gsharp5658 repos~1.7kAutomated safety check: PassMIT
Run Nx Generatornrwl/nx29k2 repos~592Automated safety check: NotesMIT
Conductor Setupgemini-cli-extensions/conductor3.8k—~4.2kAutomated safety check: PassApache-2.0
Mirage VFS Adapter Authoringstrukto-ai/mirage3.7k—~2.5kAutomated safety check: PassApache-2.0

Similar skills

  • Nx Generate

    nomcopter/react-mosaic

    Generate code using nx generators. An agent skill from nomcopter/react-mosaic.

    4.8k GitHub starsUsed in 7 repos~1.9k tokens
    DevelopmentAuto-check passed
  • Ponytail

    DavidObando/gsharp

    Forces the laziest solution that actually works, simplest, shortest, most minimal.

    565 GitHub starsUsed in 8 repos~1.7k tokens
    DevelopmentAuto-check passed
  • Run Nx generators with prioritization for workspace-plugin generators.

    29k GitHub starsUsed in 2 repos~592 tokens
    DevelopmentAuto-check: notes
  • Conductor Setup

    gemini-cli-extensions/conductor

    Scaffolds the project and sets up the Conductor environment.

    3.8k GitHub stars~4.2k tokensUpdated 1 mo ago
    DevelopmentAuto-check passed
  • Builds or extends a custom Mirage virtual filesystem adapter for an API, database, object store or app data, with a working mount configuration and filesystem tests.

    3.7k GitHub stars~2.5k tokensUpdated today
    DevelopmentAuto-check passed
  • Enforces this repository's TypeScript backend module architecture under server/: feature folders, barrel exports, and where shared types and utilities belong.

    14k GitHub stars~1.2k tokensUpdated today
    DevelopmentAuto-check passed

More from vchelaru/FlatRedBall

All 32 skills in this repo
  • Glue Live Game Testing

    vchelaru/FlatRedBall

    Testing GlueControl's embedded runtime (CommandReceiver, GlueControlManager) against a real running game process.

    578 GitHub stars~1.5k tokensUpdated 5 days ago
    Auto-check passed
  • Glue Unit Test Bootstrap

    vchelaru/FlatRedBall

    Bootstrapping GlueUnitTests that touch GlueState.Self/GlueCommands.Self/ProjectManager.

    578 GitHub stars~4.3k tokensUpdated 5 days ago
    Auto-check passed
  • Gluj Versions

    vchelaru/FlatRedBall

    A skill your agent uses when adding, modifying, or reasoning about Gluj/Glux file format versions, the GluxVersions enum, FileVersion checks, or anything that gates behavior on the version of a…

    578 GitHub stars~1.4k tokensUpdated 5 days ago
    Auto-check passed
  • Release

    vchelaru/FlatRedBall

    FRB1 (engine + Glue) release runbook — gh CLI sequence for Engine.yml/glue.yml, version scheme, release notes.

    578 GitHub stars~3.5k tokensUpdated 5 days ago
    Auto-check passed
  • Release Notes

    vchelaru/FlatRedBall

    Drafts FRB1 release notes from commits/PRs since the last release.

    578 GitHub stars~1.9k tokensUpdated 5 days ago
    Auto-check passed
  • Skills Writer

    vchelaru/FlatRedBall

    Creates and updates skill files (.claude/skills//SKILL.md). An agent skill from vchelaru/FlatRedBall.

    578 GitHub stars~2.7k tokensUpdated 5 days ago
    Auto-check passed

Categories

Questions about Gum Codegen

What does Gum Codegen do?

A skill your agent uses when working on Glue's Gum code generation — adding/removing/version-gating generated properties on Gum standard runtime types (NineSlice, Text, Container, Sprite, etc.), or…. Gum Codegen is an agent skill from vchelaru/FlatRedBall.

When should I use Gum Codegen?

Gum Codegen fits situations like: working on Glues Gum code generation — adding/removing/version-gating generated properties on Gum standard runtime types (NineSlice; debugging why is/isnt this Gum variable being generated.

How do I install Gum Codegen in Claude Code?

Run `npx skills add vchelaru/FlatRedBall --skill gum-codegen -a claude-code`. Or copy the skill folder (.claude/skills/gum-codegen in vchelaru/FlatRedBall) into .claude/skills/gum-codegen in your project. Claude Code loads it when a task matches its description.

How do I install Gum Codegen in Codex?

Run `npx skills add vchelaru/FlatRedBall --skill gum-codegen -a codex`. Or copy the skill folder (.claude/skills/gum-codegen in vchelaru/FlatRedBall) into .agents/skills/gum-codegen in your project. Codex loads it when a task matches its description.

Can I use Gum Codegen in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add vchelaru/FlatRedBall --skill gum-codegen -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/gum-codegen, .gemini/skills/gum-codegen, .github/skills/gum-codegen and .opencode/skills/gum-codegen in your project.

What does Gum Codegen need to run?

SKILL.md names no scripts, command-line tools or credentials: Gum Codegen is instructions for the agent only.

Does Gum Codegen access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Gum Codegen safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Gum Codegen use?

Gum Codegen is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Gum Codegen use?

About 3.3k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Gum Codegen?

Skills that share tags, products or a category with Gum Codegen: Nx Generate (nomcopter/react-mosaic, 4.8k stars), Ponytail (DavidObando/gsharp, 565 stars), Run Nx Generator (nrwl/nx, 29k stars) and Conductor Setup (gemini-cli-extensions/conductor, 3.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Gum Codegen?

vchelaru (a GitHub user) maintains it in vchelaru/FlatRedBall, which has 578 GitHub stars. The repository holds 32 skills in this directory. The repository was last updated on October 2, 2026.

Source: vchelaru/FlatRedBall on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.