Gum gum-service
Reference guide for GumService — the runtime entry point for MonoGame/Raylib/KNI/FNA games. Load this when working on GumService initialization, Uninitialize, DeferredQueue, hot reload, or the Root/PopupRoot/ModalRoot containers.
install
source · Clone the upstream repo
git clone https://github.com/vchelaru/Gum
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/vchelaru/Gum "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/gum-service" ~/.claude/skills/vchelaru-gum-gum-service && rm -rf "$T"
manifest:
.claude/skills/gum-service/SKILL.mdsource content
GumService Reference
What It Is
GumService is the runtime-facing API that game developers use to initialize, update, and draw Gum UI. It lives in MonoGameGum/GumService.cs (compiled for XNALIKE, RAYLIB via #if).
Not the CLI.
Gum.Cli / Gum.ProjectServices are separate tools for headless project validation and codegen.
Lifecycle
GumService.Default.Initialize(game) // one-time setup ↓ per frame: GumService.Default.Update(gameTime) GumService.Default.Draw() ↓ on teardown (optional): GumService.Default.Uninitialize()
Initialize throws if called twice without an intervening Uninitialize.
Singleton Pattern
Default is lazily initialized via ??=. Uninitialize() sets _default = null, so after teardown GumService.Default creates a fresh instance — any stored reference to the old instance is now orphaned.
Uninitialize — Non-Obvious Details
Uninitialize() resets a large amount of shared static state across multiple singletons. Key things it does that are surprising:
- Nulls
,GraphicalUiElement.SetPropertyOnRenderable
, etc. — delegates wired byAddRenderableToManagersFormsUtilities.InitializeDefaults - Calls
— clearsElementSaveExtensions.ClearRegistrations()
/RegisterGueInstantiation
callbacksRegisterDefaultInstantiationType - Calls
— disposes GPU content and empties the cacheLoaderManager.Self.DisposeAndClear() - Nulls and removes
andFrameworkElement.PopupRoot
from managersFrameworkElement.ModalRoot - Resets
toFileManager.RelativeDirectory
(only meaningful if a project was loaded)"Content/" - Calls
(XNALIKE only)_systemManagers.Renderer.Uninitialize() - Sets
— next access to_default = null
creates a newDefaultGumService
FormsUtilities.Uninitialize() is internal; tests access it via InternalsVisibleTo.
Roots
| Property | Purpose |
|---|---|
| Main scene container; sized to canvas on each |
| Overlaid above Root; for non-modal popups |
| Topmost layer; blocks input to everything below |
PopupRoot and ModalRoot are FrameworkElement statics, not instance fields — they are shared across all GumService instances.
Key Files
| File | Purpose |
|---|---|
| Main class |
| Input/cursor/gamepad setup; lives here |
| called during Uninitialize |
| called during Uninitialize |
| Tests for GPU-accessible Uninitialize behavior |
| Tests for non-GPU Uninitialize behavior |
Testing Split
Uninitialize tests are split across two projects because
FormsUtilities, LoaderManager, and ElementSaveExtensions don't all require a GPU:
—Gum.ProjectServices.Tests
,LoaderManager
,ElementSaveExtensions
(no GPU needed)ObjectFinder
—MonoGameGum.Tests.V2
, root containers,FormsUtilities
statics (require test setup with a mockFrameworkElement
)SystemManagers
Hot Reload
GumService.EnableHotReload(absoluteGumxSourcePath) wires up a GumHotReloadManager that watches the source project directory and rebuilds Root.Children when .gumx/.gusx/.gucx/.gutx/.fnt files change. GumService.Update ticks it each frame; Uninitialize stops and nulls it. For details on the reload pipeline, debounce, font cache eviction, and gotchas, load the gum-runtime-hot-reload skill. Public docs: docs/code/hot-reload.md.