Skip to content

Build mode (headless exports)

Godot ships with a headless export mode out of the box. Forge doesn’t need to install anything in your project to use it. You define export tasks in .forge/tasks.toml, point them at your project’s export presets, and run them from the command palette.

Before tasks can run:

  1. Open the Godot Editor and define at least one export preset under Project → Export. Save the preset with a name ("Web", "Linux", "Windows Desktop").
  2. Tell Forge where the Godot binary is. Settings → Workspace → Godot binary is the persistent setting; the GODOT environment variable overrides it for one-off use.

Forge sets $env:GODOT automatically when it has a Godot path resolved, so you can use the variable in your tasks:

[[tasks]]
name = "godot-export-web"
label = "Export HTML5 build"
shell = "powershell"
command = '& "$env:GODOT" --headless --export-release "Web" .build/web/index.html'
[[tasks]]
name = "godot-export-windows"
label = "Export Windows build"
shell = "powershell"
command = '& "$env:GODOT" --headless --export-release "Windows Desktop" .build/win/game.exe'
[[tasks]]
name = "godot-headless-test"
label = "Headless smoke test"
shell = "powershell"
command = '& "$env:GODOT" --headless --path . --quit-after 60'

The preset name in quotes ("Web", "Windows Desktop") must match the name you saved in Godot’s export dialog exactly.

Open the command palette (Ctrl+Shift+P) and pick Task: Export HTML5 build. Forge spawns a fresh terminal session with the command pre-loaded. Output streams in real time. The task is done when Godot exits and the prompt returns.

The --quit-after N flag makes Godot exit after N seconds. Useful for CI and for verifying that your scene loads without errors. Combine with --headless and you can run a quick “does this even load” check from Forge or a remote build server.

There isn’t one. Unity needs a custom C# entry point because Unity’s CLI build flow is awkward without one. Godot’s --export-release is already a clean entry point, so wrapping it in a .gd script wouldn’t add anything.

If you want a single tag-and-go script that builds every target at once, write a small .gd that calls EditorInterface.export_preset for each preset, then add a single task that runs it. The pattern is yours to define.