GumService Reference
SkillDev toolsGumService, runtime entry point for MonoGame/Raylib/KNI/FNA. Triggers: GumService init, Uninitialize, DeferredQueue, hot reload, Root/PopupRoot/ModalRoot containers.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the GumService Reference skill
What this skill tells your AI
The instructions your AI receives, as published by vchelaru/gum in .claude/skills/gum-service/SKILL.md and read by ahel’s review.
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) under the Gum namespace (since issue #3119 / syntax version 3). Legacy MonoGameGum.GumService / RaylibGum.GumService names are permanent [Obsolete] subclass shims in MonoGameGum/GumServiceCompat.cs (linked into RaylibGum.csproj). WindowZoomMode, GumHotReloadManager, and related hot-reload types also live in namespace Gum.
The soft migration is intentional and finished — do not flag it as incomplete. What matters is what the user types: new code uses using Gum; and types the service as GumService (= Gum.GumService) with no using MonoGameGum; / using RaylibGum; — that is 100% future-proof. Gum.GumService.Default is deliberately typed as the derived [Obsolete] shim so legacy using MonoGameGum; / using RaylibGum; declarations keep compiling; the user never names the obsolete type, so the modern path is warning-free. Do not propose "completing" this by retyping Default to Gum.GumService or removing the shims — that would break back-compat and is not planned (stable for the foreseeable future). The fact that Default's declared type is an obsolete shim is not a problem and must not be raised as a follow-up.
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.
Draw() draws everything through SystemManagers.Default in one call — for manual control over what's drawn when/to-which-target (e.g. compositing onto multiple RenderTarget2Ds in one frame), use GumBatch's immediate-mode Begin/Draw/End instead (docs/code/rendering/gumbatch.md; internals in the gum-monogame-rendering skill).
Only the gumProjectFile overload loads a project. Initialize(game, gumProjectFile) loads the .gumx and runs the project-load path — which applies project-level settings (standard-element defaults, localization, and the project's TextureFilter → Renderer.TextureFilter, issue #3199). The Initialize(game, DefaultVisualsVersion) / parameterless overloads are code-only and never touch that path. So when manually verifying anything that depends on a loaded project, you must pass the .gumx path or the behavior under test never runs. The cheapest from-file smoke test is Initialize(game, "GumProject/GumProject.gumx") plus a SpriteRuntime (SourceFileName set, scaled up) added to Root.
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,AddRenderableToManagers, etc. — delegates wired byFormsUtilities.InitializeDefaults - Calls
ElementSaveExtensions.ClearRegistrations()— clearsRegisterGueInstantiation/RegisterDefaultInstantiationTypecallbacks - Calls
LoaderManager.Self.DisposeAndClear()— disposes GPU content and empties the cache - Nulls and removes
FrameworkElement.PopupRootandFrameworkElement.ModalRootfrom managers - Resets
FileManager.RelativeDirectoryto"Content/"(only meaningful if a project was loaded) - Calls
_systemManagers.Renderer.Uninitialize()(XNALIKE only) - Sets
_default = null— next access toDefaultcreates a newGumService
FormsUtilities.Uninitialize() is internal; tests access it via InternalsVisibleTo.
Roots
| Property | Purpose |
|---|---|
Root | Main scene container; sized to canvas on each Update |
PopupRoot | Overlaid above Root; for non-modal popups |
ModalRoot | Topmost layer; blocks input to everything below |
PopupRoot and ModalRoot are FrameworkElement statics, not instance fields — they are shared across all GumService instances.
Multiple GumService Instances
The constructor is public (new GumService()), but two instances don't give two independent UI spaces — GraphicalUiElement.CanvasWidth/CanvasHeight, FormsUtilities's Cursor/Keyboard, and SystemManagers.Default/ISystemManagers.Default are static, so the second instance's Initialize() overwrites state the first depends on (e.g. Cursor's zoom-aware hit-testing reads SystemManagers.Default directly, not its owning instance). Tracked as issue #4096.
Key Files
| File | Purpose |
|---|---|
MonoGameGum/GumService.cs | Main class (namespace Gum) |
MonoGameGum/GumServiceCompat.cs | [Obsolete] subclass shims for MonoGameGum.GumService / RaylibGum.GumService; also holds the AddChild codegen crutch and ToGraphicalUiElement forwarder |
MonoGameGum/Forms/FormsUtilities.cs | Input/cursor/gamepad setup; Uninitialize() lives here |
GumRuntime/ElementSaveExtensions.GumRuntime.cs | ClearRegistrations() called during Uninitialize |
RenderingLibrary/Content/LoaderManager.cs | DisposeAndClear() called during Uninitialize |
Tests/MonoGameGum.Tests.V3/GumServiceUninitializeTests.cs | Tests for GPU-accessible Uninitialize behavior |
Tests/Gum.ProjectServices.Tests/UninitializeTests.cs | 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,ObjectFinder(no GPU needed)MonoGameGum.Tests.V3—FormsUtilities, root containers,FrameworkElementstatics (require test setup with a mockSystemManagers)
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.
Signals
- GitHub stars
- 620
- Forks
- 80
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
gum-service- Source
- github.com/vchelaru/gum