Anvil is a Godot 4 (C#) editor plugin that generates compile-time safe StringName constants for the names and paths your project already has — tracked folders, global groups, input actions, and audio buses — so you stop typing raw strings by hand and stop finding out about typos at runtime.
Referencing resources, groups, actions, and buses by raw string is fragile:
// note: you can use UID instead, this is just an option when working with raw file paths
GD.Load<AudioStream>("res://sfx/planted.wav"); // typo-prone, breaks silently if the file moves
AddToGroup("enimies"); // no compiler error, just a bug
Input.IsActionPressed("interact"); // same risk if the action gets renamedAnvil scans folders you choose, plus your project's global groups, input actions, and audio buses, and generates a single Storage class with strongly-typed StringName constants for everything it finds:
using Anvil;
GD.Load<AudioStream>(Storage.Sfx.Planted);
AddToGroup(Storage.GlobalGroups.Enemies);
Input.IsActionPressed(Storage.InputActions.Interact);Rename a file, delete a folder, or mistype an ID, and you get a compile error instead of a silent runtime bug.
- Folder tracking — right-click any folder in the FileSystem dock and choose Track with Anvil... to generate an ID for every file inside it.
- Two generation modes per tracked folder:
Id— constants are just the file's base name (Storage.Sfx.Planted), plus aHintStringfor use with[Export(PropertyHint.Enum, ...)].FullPath— constants are the fullres://path to the file, useful when you need toLoad()it directly.
- Recursive scanning — optionally include subfolders.
- Global groups — every group declared in Project Settings → Globals → Groups is generated automatically as
Storage.GlobalGroups.*, no tracking required. - Input actions — every custom action in Project Settings → Input Map is generated as
Storage.InputActions.*(Godot's built-inui_*actions are excluded), no tracking required. - Audio buses — every bus in the current audio bus layout is generated as
Storage.AudioBuses.*, no tracking required.
- Copy the
addons/anvilfolder into your project'saddons/directory. - Enable the plugin under Project → Project Settings → Plugins.
- Anvil will generate
Storage.csandanvil_rules.tresautomatically on load, and again whenever you run Generate Anvil IDs from the Project → Tools menu.
Right-click any folder in the FileSystem dock and select Track with Anvil....
You'll be asked for:
| Field | Description |
|---|---|
| Output Name | The name of the generated nested class, e.g. Sfx → Storage.Sfx |
| Recursive | Whether to include files in subfolders |
| Mode | Id or FullPath, as described above |
Already-tracked folders show Edit Anvil Tracking... and Untrack from Anvil instead, so you can reconfigure or stop tracking a folder at any time.
Anvil generates automatically on project load. To regenerate manually (e.g. after adding new files to a tracked folder), use Project → Tools → Generate Anvil IDs.
using Anvil;
GD.Load<AudioStream>(Storage.Sfx.Planted);
AddToGroup(Storage.GlobalGroups.Enemies);
Input.IsActionPressed(Storage.InputActions.Interact);
AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex(Storage.AudioBuses.Music), -6f);
[Export(PropertyHint.Enum, Storage.Sfx.HintString)]
public string SoundId;If you're referencing IDs from one folder repeatedly in a file, using static drops the Storage. prefix:
using static Anvil.Storage;
GD.Load<AudioStream>(Sfx.Planted);
AddToGroup(GlobalGroups.Enemies);Anvil stores your tracked-folder configuration in res://addons/anvil/anvil_rules.tres — a plain Godot Resource (AnvilRuleSet, containing a list of AnvilRule), editable either through the context menu dialog or directly in the inspector.
On generation, Anvil:
- Loads
anvil_rules.tres. - Validates every rule — skipping (with a warning) any rule with an empty output name, a duplicate output name, or a folder that no longer exists.
- Scans each valid tracked folder (respecting the
Recursiveflag and excluding.import/.uidfiles). - Scans declared global groups and input actions.
- Reads the current audio bus layout from
AudioServer. - Writes everything into
res://addons/anvil/generated/Storage.cs.
addons/anvil/
├── plugin.cfg
├── AnvilPlugin.cs
├── anvil_rules.tres # generated on first run
├── generated/ # generated on first run
│ └── Storage.cs
├── icons/
│ └── anvil_icon.svg
└── src/
├── AnvilContextMenu.cs
├── AnvilFileIO.cs
├── AnvilGenerator.cs
├── AnvilRule.cs
├── AnvilRuleManager.cs
├── AnvilRuleSet.cs
├── AnvilTrackFolderDialog.cs
├── AnvilValidator.cs
└── ForgeMode.cs
Storage.cs is generated at runtime into res://addons/anvil/generated/ — not part of the repo itself.
- Renaming or moving a tracked folder in the FileSystem dock is not detected automatically — Anvil matches rules by exact string path, so a rename leaves the old rule pointing at a path that no longer exists (reported as a warning on generation) and the new location untracked. Re-track the new location and remove the stale rule manually.
Storage.csis regenerated in full every time — don't hand-edit it, your changes will be overwritten.
MIT


