Installs into .claude/skills of the current project.
Are you the author of Gohud?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/thruthesky-gohud)
---
name: gohud
description: >-
Build Godot 4.7+ game UI with gohud (res://addons/gohud; tested on Godot 4.7, officially supports 4.7 and newer): main menus, pause menus, settings screens,
inventories, HUDs with HP/MP bars, quick slots and a virtual joystick, dialogs, bottom sheets, forms,
snackbars, prompt cards, coach-mark tours, and looks from presets (default, sci-fi, medieval), JSON
themes, skins and icon sets — touch-safe, safe-area aware, RTL and translation ready. Use whenever
someone writes GDScript UI, HUD, menu or GUI code in a Godot project, mentions gohud or any Go* class
(GoUi, GoStyle, GoSurface, GoSheet, GoDialogs, GoForm, GoHudAnchor, GoBar, GoSlot, GoJoystick, GoNotice,
GoPromptCard, GoCoachMark, GoTheme, GoSkin, GoIconSet, GoConfig), wants to install gohud, or runs
/gohud preview, /gohud features (plugin form: /gohud:preview, /gohud:features, /gohud:gohud).
license: MIT
metadata:
author: JaeHo Song
homepage: https://thruthesky.github.io/gohud/
repository: https://github.com/thruthesky/gohud
---
# gohud — game UI for Godot 4.7+
gohud is a pure-GDScript HUD & UI kit, tested on Godot 4.7 and officially supported on Godot 4.7
and newer. Every class is global once the folder sits at `res://addons/gohud/`;
widgets are made with `.new()` + `add_child()` and styled by one theme, one skin and one icon set.
This skill carries the whole API (`references/`), runnable screen templates (`assets/templates/`) and a
preview launcher (`scripts/gohud_preview.py`).
Arguments given: `$ARGUMENTS`
## 1. Route the request
| First word of the arguments | Do |
|---|---|
| `preview` | §6 — launch the preview with the remaining arguments |
| `features` | Read `references/features.md` and present it grouped (one line of code per feature). If an area follows (`features theming`), also read that area's reference and go deeper |
| `update` | Read `references/setup.md` §7 and follow `commands/update.md` — update the add-on in the project **and** this skill, then verify the two agree |
| anything else / empty | §2 — build or change UI with gohud |
Reply in the language the user writes in; keep code identifiers as they are.
## 2. Workflow for building UI
1. **Check the project.** `test -f project.godot`, `test -f addons/gohud/plugin.cfg`, `godot --version` (needs 4.7+).
Note the gohud version (`version=` in `plugin.cfg`) — rules 4, 5 and 7 differ for 1.0.3 and older.
Missing add-on → install it (`references/setup.md` §1), then `godot --headless --path . --import`.
2. **Pick the look first.** `GoUi.use_preset(GoThemePresets.SCIFI_DARK)` (or the project setting) before any widget
is built. Nodes keep the theme they were built with; switching later means rebuilding the screen.
3. **Choose the widget for the job** — table in `references/surfaces.md` §7: blocking question → `GoDialogs`,
list over the game → `GoSheet`, side panel on a wide screen → `GoDrawer`, window → `GoSurface`,
full-screen menu/login/settings → root Control + `GoForm`, **message with an Undo button → `GoSnackbar`**,
fixed notice panel the HUD owns → `GoNotice`, optional question → `GoPromptCard`,
**info card next to a slot → `GoPopover`**, HUD pieces → `GoHudAnchor`.
Lists and forms: sortable/selectable rows → `GoTable`, pages → `GoPagination`, searchable picker →
`GoCombobox`, a field that can show an error → `GoField`, input welded to a button → `GoInputGroup`.
Waiting → `GoSpinner` (`GoSpinner.busy(button, true)` also blocks the double press).
A list the player scans (quests, mail, a shop) → rule 15 in §3 and the recipe in `references/recipes.md` §16.
4. **Start from a template** when one fits (§5): copy it into the project (e.g. `res://ui/`), rename, adjust, wire
its signals. Otherwise compose with `GoStyle` factories (`references/style.md`).
5. **Follow the rules in §3.** Look up exact signatures in the references before using a member you are not sure
of — do not guess APIs.
6. **Verify without a window:** `python3 ${CLAUDE_SKILL_DIR}/scripts/gohud_preview.py res://ui/my_screen.tscn --check`
(or `godot --headless --path . --quit-after 120 res://ui/my_screen.tscn` and scan for `SCRIPT ERROR`,
`Parse Error`, `ERROR: Failed`). Open a visible window only when the user asks to see it (§6).
## 3. Rules that prevent the real bugs
1. **Sizes and colours come from tokens**, never literals: `GoUi.metric(GoTheme.GAP)`, `GoUi.color(GoTheme.MUTED)`,
`GoStyle.*` factories. Literals break when the preset, breakpoint or touch size changes.
2. **Text vs keys.** `GoStyle.label()/button()` show text as written; `label_key()/button_key()` hold translation
keys. `list_button()`, `foldable()`, `section()`, `toggle()`, `checkbox()` translate by default — pass
`translate = false` for literal strings.
3. **Surfaces go in a `CanvasLayer`, and the owner closes them.** `GoSurface` only emits `close_requested`.
Layers: HUD 5 · `GoSheet` 10 · your popups 50 · `GoDialogs` 100.
4. **Per-page sheet buttons go through `sheet.add_footer(button)`** — the next `open()` removes them. `open()` only
hides `footer()`, so children added with `footer().add_child()` stay (right for a sheet-wide snackbar, wrong for a
Close button re-added on every open). gohud 1.0.3 and older have no `add_footer()`: remove your footer children first.
5. **Assemble `GoForm → GoScroll → column` before the form enters the tree.** `_ready` runs inside `add_child`; a
scroll added later is never found (no keyboard follow), and `%BackButton` (Android Back routing) is looked up once
there. In code: name the button `BackButton`, add it, set `back.owner = form` and `back.unique_name_in_owner = true`,
then `add_child(form)`. gohud 1.0.3 and older clear that owner when the scroll moves — there, own the whole branch
from a holder (`owner = holder` on every descendant; the templates do this, and it works on every version).
6. **HUD root: `mouse_filter = MOUSE_FILTER_IGNORE`.** Transient anchors (toasts, prompts, joystick) use
`reserve_space = false`; toasts at `TOP_CENTER` use `avoid_peers = true`. Put a `GoStyle.floating()` panel
behind HUD text that floats over content.
7. **`await` dialogs.** `{placeholders}` in the title and body are filled only from `args` (gohud 1.0.3 and older
format only the body — build the title string yourself there). Irreversible confirms use `destructive = true`
(last argument).
8. **Bars use fill tokens** (`GoTheme.DANGER_FILL`, `INFO_FILL`, `WARNING_FILL`, `SUCCESS_FILL`); text colours
look dull as fills on light themes.
9. **Touch:** icon-only buttons get a tooltip (`GoStyle.icon_button(icon, action, -1, &"Menu")`) — it is also the
accessible name. Side-by-side `GoIconButton`s / `GoSlot`s need `touch_peers`.
10. **Config:** after changing a plain `GoConfig` field in code call `GoUi.refresh()`; `theme`/`icons` refresh
themselves. `use_preset()` clears explicit `theme`/`skin`/`icons` — set overrides after it.
11. **Gameplay input pauses while a window is open:** `if GoSurface.is_any_open(): return`.
12. **Widgets that draw text inside a non-container parent must not wrap.** A `Label` with autowrap laid
out at zero width freezes its minimum height at 1 dp and the text disappears while the panel still
paints — this is why table cells, key caps and code cells set `AUTOWRAP_OFF`. When you place a child by
anchors, set `offset_*`, not `position`: `Control.position` is parent-space and ignores the anchors.
13. **Containers are 80% opaque; things you press are not.** Panels (`GoSurface`/`GoSheet`/`GoDialogs`/cards/
HUD panels/alerts/snackbars) fade their **face only** — never use `modulate.a` for this, it fades the text too.
Five layers decide the value, most specific first: the `alpha` argument or field at that call →
`GoConfig.container_alpha_overrides[GoTheme.BOX_*]` → `metric_overrides[<kind>_alpha]` →
`GoConfig.container_alpha` → theme `GoHud/constants/<kind>_alpha`. 🔑 **Every one of them is a ratio
`0.0–1.0`** (negative = not set), including `@export` fields such as `dialogs.alpha` and `drawer.alpha` —
same units everywhere, so there is nothing to memorise per widget. 🛑 The **two exceptions are the theme's
constants and `metric_overrides`**, which are percent integers (`80`) because a `Theme` constant cannot hold
a float. Call `GoUi.refresh()` after changing it from code. Read the resolved value with
`GoUi.surface_alpha(variant)`; apply it to a panel gohud did not build with `GoStyle.fade_panel(node)` (after
`add_child`). A `GoSkin` subclass overriding `surface_box`/`floating_box`/`alert_box` **must carry the `alpha`
parameter** or the script will not parse. 🔑 **Drag it before you argue about the number**: the opacity lab
(`examples/gallery/opacity_lab.gd`) is hosted by the gallery, the guided tour (chapter 16), the home screen
and the medieval example — it shows the four ways to set the value on one screen, over a pattern, because a
value check cannot tell you whether the text is still readable. Details: `references/theming.md` §4.
14. **Never hand-edit gohud's generated themes**; recolour through `color_overrides`, a Theme copy in your project,
a project-local `GoThemePreset`, or the JSON theme tools (`references/theming.md`).
15. **Lists must scan** — a list the player reads (quests, mail, a shop, a roster) is judged by numbers, not taste.
① **Space outside a row > space inside it ≥ space between its lines:** rows at least `GAP_SMALL` (8) apart
(`GAP` 12 when there is room), a two-line row padded 8 above and below and 12 at the sides, its two lines
`GAP_TINY` (4) apart — `list_button()` already pads its row this way. A cramped panel that used 4 for all three
ran its rows together. ② **The heading must be a size above the row titles.** Rows are `ROLE_BODY` (16) with a
`ROLE_CAPTION` (13) second line in `MUTED`; the heading the player reads first is `ROLE_SUBTITLE` (22). A
`GoSurface` or `GoSheet` short of height (or `compact`) drops **its own** title to `body`, so a list under it
becomes one size — put that heading in the body instead. ③ Say a thing once: no header line repeating the first
row. ④ Warning colours and warning icons only on rows where something is wrong; a level gate is a `LOCK` and
`MUTED` text (never `modulate.a` — rule 13). A badge that repeats on every row carries nothing — drop it; an icon
that states each row's own state (a lock, a check) may repeat. ⑤ A value at a row's end (`0 / 1`, a price)
is a label with `SIZE_SHRINK_END` — `GoStyle.label()` expands by default and would split the width with the
title. `list_button()` has no text slot at the end: build that row yourself and keep its padding and
`GoStyle.fit_content_height()`. ⑥ Your spacing does not survive everywhere: `GoStyle.form()` (every `GoForm`)
sets each box's `separation` to `GAP` unless it carries `set_meta(&"go_own_spacing", true)`, and a
`wrap_row()` forces everything inside it — all the way down — to natural width with wrapping off, so never put a
card or a row with an expanding title in one. **See it before you build it:** the gallery's List rows section
opens a lab (`examples/gallery/list_lab.gd`) with a cramped quest panel next to the same panel built by this
rule, each measured from its own nodes. Recipe: `references/recipes.md` §16.
More traps with their causes: `references/pitfalls.md`.
## 4. Minimal screen
```gdscript
extends Control
var dialogs: GoDialogs
func _ready() -> void:
GoUi.use_preset(GoThemePresets.DEFAULT_DARK)
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
theme = GoUi.theme()
RenderingServer.set_default_clear_color(GoUi.color(GoTheme.BACKGROUND))
var form := GoForm.new()
var scroll := GoScroll.new()
var column := GoStyle.column()
form.add_child(scroll)
scroll.add_child(column)
column.add_child(GoStyle.label("Hello gohud", GoTheme.ROLE_TITLE))
column.add_child(GoStyle.button("Open dialog", _on_open, GoStyle.Tone.PRIMARY))
add_child(form)
dialogs = GoDialogs.new()
add_child(dialogs)
func _on_open() -> void:
if await dialogs.confirm("Delete save", "This cannot be undone.", "Delete", "", "", {}, true):
print("deleted")
```
## 5. Templates — `assets/templates/`
Each is a complete, headless-tested script with no scene file. Copy, then connect signals.
| File | Extends | Builds | Public API |
|---|---|---|---|
| `main_menu.gd` | Control | Title, Continue / New game / Settings / Quit rows, confirm dialogs, a Continue button that becomes a spinner | signals `continue_requested` `new_game_requested` `settings_requested` `quit_confirmed` · `build()` · `set_loading(waiting)` |
| `game_hud.gd` | CanvasLayer (5) | HP/MP/XP panel, menu button with an unread badge, 4 quick slots, FOLLOW joystick, toast, prompt card, snackbar | signals `menu_requested` `slot_used(index)` `move_input(vector)` · `set_health/set_mana/set_experience(v, max)` · `toast(msg, tone)` · `await say(msg, actions, tone)` · `set_unread(count)` · `ask(title, subtitle, accept_text, accept, decline_text, decline)` |
| `pause_menu.gd` | CanvasLayer (50) | Centred GoSurface, pauses the tree, Escape opens/closes, a key cap that reads the real binding, quit confirm | signals `resumed` `settings_requested` `quit_to_title_requested` · `open()` `resume()` `toggle()` `is_open()` |
| `inventory_sheet.gd` | Node | GoSheet with search + category filter, long-press menu on each row, detail page with Back, Use / Drop with Undo | signals `item_used(item)` `item_dropped(item)` · `items` · `open()` `show_list()` `show_item(item)` |
| `settings_menu.gd` | Control | GoForm, foldable Display/Audio/Controls/Language sections built from `GoField` (so a row can show its own error), draft + Save/Reset, discard check | signals `closed(saved)` `settings_changed(values)` · `settings` · `save()` `request_back()` `reset_to_defaults()` |
Wiring them together and more screens (login, shop, quest log, character sheet, dropdown menus, tutorial tour):
`references/recipes.md`.
## 6. Preview — `/gohud preview` (plugin: `/gohud:preview`)
Run from the user's project folder so their `addons/gohud` is used (otherwise the bundled copy or a clone):
```bash
python3 ${CLAUDE_SKILL_DIR}/scripts/gohud_preview.py <arguments> # Windows: python
```
If `${CLAUDE_SKILL_DIR}` is not expanded, use the first existing path of
`${CLAUDE_PLUGIN_ROOT}/skills/gohud/scripts/gohud_preview.py`, `~/.claude/skills/gohud/scripts/gohud_preview.py`,
`.claude/skills/gohud/scripts/gohud_preview.py`.
| Arguments | Opens |
|---|---|
| *(none)* / `gallery` · `--preset scifi_dark` · `--phone` · `--size 1920x1080` | Every widget, preset picker, icon set; **List rows → Readable lists** opens the before/after list lab |
| `medieval` | Character sheet, satchel, quest journal |
| `icons` | Buttons from the 1,000-icon library: toolbar, text + icon, toggles, menu rows, segmented, a group, live search |
| `demo` · `demo --explore hud` | 23-chapter guided tour / one chapter (`list` shows keys) |
| `res://ui/main_menu.tscn` | A scene of the user's project, inside that project |
| `list` · `--check` · `--dry-run` · `--godot PATH` | Keys · headless smoke test · print command · Godot binary |
gohud's examples run in a sandbox project under the user cache, so the user's project is not modified. The script
detaches and prints the process id and log path. Exit 2 = Godot 4.7+ not found or bad arguments; exit 1 = import
or launch error (it prints the error lines). A visible window is what `/gohud preview` is for; for your own checks
use `--check`.
## 7. References — read the one you need
| File | Read when |
|---|---|
| `references/features.md` | `/gohud features`, or "what can gohud do" — catalogue of every feature with one-line code |
| `references/setup.md` | Installing, **updating (§7 — add-on and skill, `/gohud update`)**, enabling the plugin, every `GoConfig` field and default, boot order, layers, project settings, headless verification, gohud's tool commands |
| `references/surfaces.md` | `GoSurface` (placements, anchored menus, sub-pages), `GoSheet`, `GoDialogs` (layouts, destructive, args), `GoForm`, `GoScroll`, subclass hooks, which widget to use |
| `references/hud.md` | `GoHudAnchor` spots and avoidance, `GoBar`, `GoSlot`, `GoJoystick`, `GoIconButton`, `GoNotice`, `GoPromptCard`, `GoCoachMark`, composing a HUD |
| `references/style.md` | Every `GoStyle` factory signature: structure, text, buttons and tones, inputs, select/dropdown/segmented/tabs, cards, chips, tables, styleboxes, helpers |
| `references/theming.md` | Presets and resolution order, all tokens, **container opacity (§4)**, overrides, JSON themes (`new_theme.py`/`make_theme.py`), skins and dials, custom StyleBoxes, project-local presets, contrast |
| `references/platform.md` | Icons — the 84 default names, the game set (187) and the icon library (1,000) with `GoUi.add_icons()`, search and groups, custom icon sets/fonts/folders, localization and RTL, sound and haptics, accessibility, safe area, breakpoints, dp scale, Android Back |
| `references/recipes.md` | Full screens and wiring: game scene with HUD + pause + inventory, login, shop, quest log, a quest list that scans (§16), character sheet, context menu, tutorial, theme switcher |
| `references/pitfalls.md` | Symptoms → cause → fix for layout, text, input, theme and lifecycle traps |
Web (same content, with screenshots): overview https://thruthesky.github.io/gohud/ ·
install https://thruthesky.github.io/gohud/install.html · AI skill https://thruthesky.github.io/gohud/ai.html ·
widgets https://thruthesky.github.io/gohud/widgets.html · theming https://thruthesky.github.io/gohud/theming.html