Gum Tool File Watch System Reference
SkillFiles & storageGum FileWatch system. Triggers: external file change detection, IgnoreNextChangeUntil, FileWatchManager, FileWatchLogic, FileChangeReactionLogic, reloading assets/elements when files change on disk.
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 Gum Tool File Watch System Reference skill
What this skill tells your AI
The instructions your AI receives, as published by vchelaru/gum in .claude/skills/gum-tool-file-watch/SKILL.md and read by ahel’s review.
Architecture
Three cooperating classes handle the full pipeline — all three now live in the headless Gum.Presentation assembly (ADR-0005):
FileWatchManager(Tools/Gum.Presentation/FileWatchPlugin/FileWatchManager.cs): OwnsFileSystemWatcherinstances, queues changed files, manages the ignore list, and exposesFlush().FileWatchLogic(Tools/Gum.Presentation/FileWatchPlugin/FileWatchLogic.cs): Determines which directories to watch by scanning all project elements for referenced files. CallsEnableWithDirectories()on project load/unload/variable change.FileChangeReactionLogic(Tools/Gum.Presentation/Managers/FileChangeReactionLogic.cs): Dispatches a queued file to the correct reload handler based on file extension.
MainFileWatchPlugin (Gum/Plugins/InternalPlugins/FileWatchPlugin/MainFileWatchPlugin.cs) is the WPF-hosted plugin entry point — it only owns the platform glue (control/tab/menu-item creation, timer subscription). Its event-reaction logic (project load/unload, variable-set, debug-panel display refresh) is extracted into FileWatchPluginController (Tools/Gum.Presentation/FileWatchPlugin/FileWatchPluginController.cs), also headless.
Change Pipeline
FileSystemWatcher event (background thread)
↓
FileWatchManager.HandleFileSystemChange()
- Checks ignore list (count-based and time-based)
- Verifies file's directory is being watched
- Adds to ChangedFilesWaitingForFlush, records LastFileChange
↓
PeriodicUiTimer (2s interval, Program.cs)
- Calls FileWatchManager.Flush() every 2 seconds
↓
Flush() early-outs if TimeToNextFlush > 0 (waits 2s after last change)
↓
FileChangeReactionLogic.ReactToFileChanged(file) per queued file
↓
Extension-specific reload (texture, element, project, font, CSV, behavior...)
A second PeriodicUiTimer at 200ms drives the File Watch debug panel UI only — it does not trigger flushes.
Watched Directories
FileWatchLogic.GetFileWatchRootDirectories() builds the watch set by:
- Collecting all files referenced by every screen, component, and standard element via
ObjectFinder.Self.GetFilesReferencedBy() - Adding the gum project's own directory
- Adding localization and font-character-file directories if configured
Deduplication: If directory A is already a root of directory B, B is not added separately. Subdirectories of a watched root are covered automatically (IncludeSubdirectories = true).
RefreshRootDirectory() is called on project load and whenever a variable that IsFile == true changes value.
Saving Edits Back to Disk
Edits are written out through IFileCommands.TryAutoSaveElement(ElementSave) /
TryAutoSaveCurrentElement() / TryAutoSaveObject(object) in
Tools/Gum.Presentation/Commands/FileCommands.cs, each of which no-ops unless
IProjectManager.AutoSave is true (ProjectManager.cs, backed by GeneralSettingsFile,
user-toggleable in Project Properties).
Landmine: "the element is edited" does not imply "the file on disk changed" — with AutoSave off,
in-memory changes sit unsaved until an explicit save. Code that mutates an element other than the
currently-selected one (e.g. a cascading delete affecting other elements' instances) should call
TryAutoSaveElement for that element, not assume it needs saving unconditionally.
Ignore Mechanism
IgnoreNextChangeUntil(FilePath, DateTime?) suppresses the next detected change for a file until the given time. Default is 5 seconds from now.
When to call it: Any time Gum itself writes a file to disk, to prevent the watcher from triggering a reload of the file it just saved.
Callers:
FileCommands.cs— element/project savesProjectManager.cs— full project save (ignores .gumx and all element files)FontManager.cs— font generation (ignores .bmfc, .fnt, and .png pages)AnimationCollectionViewModelManager.cs— animation saveTextureCoordinateSelectionPlugin— sprite sheet edits
A separate changesToIgnore dictionary supports count-based ignoring (decrement on each event), but it is rarely used; the time-based timedChangesToIgnore is the primary mechanism.
ReactToFileChanged Extension Dispatch
| Extension | Action |
|---|---|
png, gif, tga, bmp | Refresh wireframe if referenced by selected element |
achx | Reload animation chain if referenced by selected element |
fnt | Reload font (also looks up page PNGs) |
gusx, gutx, gucx | Reload element from disk, refresh tree + wireframe |
gumx | Reload entire project |
ganx | Print warning — Gum does not support runtime reload of animation collections |
behx | Reload behavior definition |
csv, resx | Reload localization file (RESX also matches satellites via IsLocalizationFileThatShouldTriggerReload) |
Debug UI Panel
The File Watch tab (hidden by default, toggled via View > Show File Watch) shows live state from FileWatchManager. A 200ms PeriodicUiTimer drives MainFileWatchPlugin, which delegates each tick to FileWatchPluginController.RefreshDisplay(), and displays:
- Which directories are being watched
- Files queued in
ChangedFilesWaitingForFlush(up to 15) - Countdown to next flush
- Currently active ignores with their remaining ignore time
FileWatchViewModel (Tools/Gum.Presentation/FileWatchPlugin/FileWatchViewModel.cs) is the data-bound VM; FileWatchControl.xaml (Gum/Plugins/InternalPlugins/FileWatchPlugin/) is the WPF view.
Non-Obvious Behaviors
Double-event prevention for Gum XML files: When FileSystemWatcher fires a Created event for .gumx/.gusx/.gutx/.gucx/.ganx/.behx files, it is ignored. These formats trigger both Changed and Created on save; only Changed is processed to avoid duplicates. Non-Gum files (e.g., PNG) do process Created.
Rename for PNG, CSV, and RESX: HandleRename routes renames for .png, .csv, and .resx. Many editors (Vim, JetBrains, some VS Code modes) use an atomic-save pattern — write to a temp file, then rename it over the target — so rename events must be handled for these types to avoid silently missing external edits.
Delete does nothing: HandleFileSystemDelete has no implementation — file deletions are not reacted to.
Flush debounce is cumulative: TimeToNextFlush = (LastFileChange + 2s) - Now. Every new file change resets LastFileChange, pushing the flush window out by another 2 seconds. Rapid successive changes delay flushing until things settle.
IsFlushing prevents re-entry but not concurrent queuing: The background FileSystemWatcher thread can still add to ChangedFilesWaitingForFlush while a flush is in progress (the lock protects the queue). Files added during a flush are picked up on the next flush cycle.
FileWatchManager is a singleton: Registered in Gum/Services/Builder.cs as both FileWatchManager and IFileWatchManager.
Key Files
| File | Purpose |
|---|---|
Tools/Gum.Presentation/FileWatchPlugin/FileWatchManager.cs | Core watcher, queue, ignore list, flush |
Tools/Gum.Presentation/FileWatchPlugin/FileWatchLogic.cs | Computes watched directories, enables/disables watcher |
Tools/Gum.Presentation/FileWatchPlugin/FileWatchPluginController.cs | WPF-free reactions (project/variable events, debug-panel display refresh) extracted from the plugin |
Tools/Gum.Presentation/Managers/FileChangeReactionLogic.cs | Dispatches flushed files to reload handlers |
Gum/Plugins/InternalPlugins/FileWatchPlugin/MainFileWatchPlugin.cs | Plugin entry point; owns WPF control/tab/menu-item wiring only |
Gum/Services/PeriodicUiTimer.cs | UI-thread-safe periodic timer used for both flush and display |
Gum/Program.cs (lines ~144–157) | Creates the 2s flush timer and calls fileWatchManager.Flush() |
Tools/Gum.Presentation/Commands/FileCommands.cs | Calls IgnoreNextChangeUntil before saving elements |
Tools/Gum.Presentation/Managers/ProjectManager.cs | Calls IgnoreNextChangeUntil before saving project |
Gum/Services/Fonts/FontManager.cs | Calls IgnoreNextChangeUntil before generating fonts |
Signals
- GitHub stars
- 620
- Forks
- 80
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
gum-tool-file-watch- Source
- github.com/vchelaru/gum