This guide covers the repository workflow, build pipeline, validation, preview, and maintenance conventions. Read DESIGN.md before changing theme geometry or visual layering.
Development is tested on Ubuntu and Debian-family systems with GRUB 2. The scripts use Bash strict mode and standard GNU utilities.
Install the expected tools on Ubuntu with:
sudo apt install \
grub-common grub-pc-bin \
imagemagick fonts-dejavu-core \
qemu-system-x86 xorriso mtoolsImportant commands include:
convertandidentifyfor deterministic PNG generation and validationgrub-script-checkfor generated GRUB syntaxgrub-mkrescueandxorrisofor the isolated preview ISOqemu-system-x86_64for preview executionmformatfrom mtools for GRUB rescue-image generation
There are three distinct layers:
theme/sinless/ Canonical source and configuration
dist/ Clean generated deployment/preview output
.cache/codex/ Generated task and validation state
Never treat dist/ as source. scripts/build.sh removes and recreates it on
every build.
theme/sinless/
├── assets/
│ ├── backgrounds/
│ ├── characters/
│ ├── generated/version/
│ ├── icons/
│ ├── menu/
│ │ ├── branding/
│ │ └── selected/
│ ├── overlays/
│ └── progress/
├── config/
│ ├── grub/42_sinless_tools
│ ├── preview.conf
│ └── version.txt
├── fonts/
└── theme.txt
No PNG may be placed directly under theme/sinless/.
After changing source code, configuration, or assets, run:
./scripts/build.sh
./scripts/verify.sh
./scripts/preview.sh --build-only
./scripts/preview.sh --windowDo not run install.sh as part of normal development. Installation is a
separate, explicit system operation.
scripts/build.sh performs a clean deterministic build.
The script derives the repository root from its own location. It does not depend on the caller's working directory.
Required configuration, fonts, character, branding, icons, menu slices, progress slices, and overlays must exist. The canonical GRUB helper must be executable.
theme/sinless/config/version.txt must contain exactly one assignment in this
form:
THEME_VERSION="1.0"The parser does not execute or source the file. Values are limited to a short, safe version character set.
ImageMagick creates the static final version label and embeds the configured version in PNG metadata. The output is forced to true RGBA for GRUB compatibility.
Full-screen overlays are merged into the deployment background. Menu and character glows are composited beneath their subjects into true RGBA outputs. This keeps the number of live GRUB transparency layers low and avoids indexed alpha rendering defects.
The build creates:
dist/
├── grub/42_sinless_tools
├── preview/
└── sinless/
Directories receive mode 0755, normal files 0644, and the GRUB helper
0755.
GRUB requires icons/ beside theme.txt. The build creates:
dist/sinless/icons -> assets/icons
Do not replace this with duplicated canonical icon files.
Run:
./scripts/verify.shThe verifier checks:
- Canonical and generated directory structure
- Required nested source and dist files
- Safe non-empty version configuration
- Valid source and generated PNGs when ImageMagick is available
- No root-level theme PNGs
- Exact overlay inventory and build consumption
- Theme references against existing nested files
- Progress frame/fill declarations and layering
- Character/menu geometry and declaration order
- Generated version metadata
- GRUB helper output with
shandgrub-script-check - Both required custom menu entries
- Configuration wrapper behavior and script syntax
- Dist synchronization and generated glow composition
- Absence of the obsolete foreground-character asset
Verification exits nonzero on any failure. Do not install a failing build.
The preview script always uses dist/sinless/; it never reads deployable assets
directly from source.
./scripts/preview.sh --build-onlyThis writes an isolated ISO to:
dist/preview/sinless-grub-preview.iso
./scripts/preview.sh --window
./scripts/preview.sh --fullscreenSDL software output is the default because GTK zoom/scaling can produce a black window on some systems. To test GTK explicitly:
SINLESS_PREVIEW_BACKEND=gtk ./scripts/preview.sh --window./scripts/preview.sh --width 1600 --height 900 --timeout 20Equivalent environment variables are supported for width, height, and timeout:
SINLESS_PREVIEW_WIDTH=1600 \
SINLESS_PREVIEW_HEIGHT=900 \
SINLESS_PREVIEW_TIMEOUT=20 \
./scripts/preview.sh --windowThe preview menu contains Ubuntu, Windows 11 Pro, Advanced Options, BIOS/UEFI Settings, GRUB Command Line, and SinLess Theme Configuration. Preview entries do not boot real operating systems; dummy entries reload the isolated preview menu.
Run:
./sinless-theme-configThe utility manages version, timeout, resolution, preview mode, build,
verification, and preview actions. It validates input and writes configuration
through temporary files without eval.
Show current values without entering the menu:
./sinless-theme-config --showThe utility never invokes install.sh.
The main layout is theme/sinless/theme.txt.
When changing geometry:
- Preserve the 51% menu-text right boundary.
- Keep the character at or beyond 52%.
- Keep timeout text above the progress frame.
- Keep branding centered on the menu frame's 30% horizontal center.
- Check image declaration ordering in the real preview.
- Test at 1920×1080 and at least one smaller resolution.
Use only properties documented by the installed GRUB manual. Unsupported CSS, JavaScript, background loops, or animation syntax do not belong in a GRUB theme.
Canonical full-screen sources should be 1920×1080. Keep detailed effects away
from the left-side menu text region. Every overlay must be referenced by
theme.txt or consumed by build.sh.
The sole canonical character is:
assets/characters/hooded-character.png
It must remain a transparent true-RGBA PNG. Do not recreate
hooded-character-foreground.png.
The matching glow is assets/overlays/character-glow.png. Its canvas dimensions
must match the character because the build composites them directly.
GRUB uses nine-slice filenames ending in _c, _n, _s, _e, _w, _ne,
_nw, _se, and _sw. Do not rename or omit these files.
Progress fill pixels must remain inside the visible frame at both partial and
full states. Keep highlight_overlay = "false" unless a real GRUB preview proves
a replacement behaves correctly.
Add canonical class icons under assets/icons/. Use a square RGBA PNG and match
the existing 64×64 icon convention. Add the path to build and verification lists
when the icon becomes required.
GRUB uses PFF2 fonts, not TTF/OTF files directly. If replacing the font, generate
the PFF2 asset with grub-mkfont, update the internal font name in theme.txt,
and verify it in QEMU.
The canonical source is:
theme/sinless/config/grub/42_sinless_tools
Test its emitted configuration with:
temporary_file="$(mktemp)"
sh theme/sinless/config/grub/42_sinless_tools >"${temporary_file}"
grub-script-check "${temporary_file}"
rm -f "${temporary_file}"Do not hardcode a kernel path, initrd path, root UUID, boot disk, encryption mapping, ZFS pool, resume device, or distro-specific boot chain. If a safe Ubuntu boot-to-configuration chain cannot be derived, retain the informational fallback.
- Use
#!/usr/bin/env bashfor Bash scripts. - Enable
set -Eeuo pipefailfor mutating workflows. - Derive the project root from
BASH_SOURCE. - Use arrays for required file sets.
- Quote paths and variables.
- Avoid
evaland sourcing user-editable configuration. - Fail before making partial output when prerequisites are missing.
- Keep build, verify, and preview isolated from live GRUB paths.
- Keep installation and uninstallation explicitly root-gated.
Run syntax checks after script changes:
bash -n scripts/*.sh sinless-theme-configIf ShellCheck is installed:
shellcheck scripts/*.sh sinless-theme-configLong-running refactor and validation state is recorded under:
.cache/codex/theme-refactor-progress.md
The directory is generated and ignored by Git. It is not part of the deployable theme.
Use the default SDL backend:
./scripts/preview.sh --windowIf SINLESS_PREVIEW_BACKEND=gtk is set in the environment, unset it before
launching.
Rebuild before previewing:
./scripts/build.sh
./scripts/verify.sh
./scripts/preview.sh --windowThe preview reads dist/, not canonical source files directly.
Convert the GRUB-facing output to true RGBA (PNG32) and prefer build-time
compositing. Indexed PNG transparency is unreliable on some GRUB video backends.
Run ./scripts/build.sh and repeat verification. Do not manually patch dist/.
That is expected. GRUB 2.12 has no supported timer or mutable theme-label mechanism for blinking and typewriter effects.
- Canonical paths contain no root-level PNGs.
- No obsolete or unconsumed overlays remain.
-
./scripts/build.shpasses. -
./scripts/verify.shpasses with zero failures. -
./scripts/preview.sh --build-onlypasses. - The 1920×1080 preview is visually inspected.
- Progress fill remains within its frame.
- Character does not cover menu text.
- Version label is visible.
- No live GRUB files were modified during development.