Manuals
Manuals




Automating the Defold editor

The Defold Editor opens up a special server for automated actions. HTTP API controls the opened project. Use it for editor commands, builds, project resources, previews, preferences, console output, documentation search, or editor-script integrations. To inspect or control the running game instead, use the engine service or a runtime automation API.

The editor HTTP API is experimental and may change between Defold versions. The /openapi.json document generated by the running editor is the source of truth for its available operations and schemes.

Starting the editor from an external tool

An external tool needs the editor executable and the absolute path to the project’s game.project file.

Installed Defold versions can be located through installations.json, as described in the Editor manual. Its launcherPath field contains the executable to start. Pass the game.project path as the first positional argument to open that project directly.

The optional --port or -p argument selects the editor server port. Omitting it lets Defold choose an available port and is usually preferable when several projects may be open.

# Linux
/path/to/Defold/Defold --port 8181 /absolute/path/to/project/game.project
# macOS
/path/to/Defold.app/Contents/MacOS/Defold --port 8181 /absolute/path/to/project/game.project
# Windows
C:\path\to\Defold\Defold.exe --port 8181 C:\absolute\path\to\project\game.project

The editor is a graphical desktop application. Start it in an interactive user session with access to the display. Use Bob when a graphical session is unavailable, such as in headless CI, or for creating standalone bundles. An open editor also supports compile-only automation through /command/compile.

After starting the editor, wait until the project has opened and .internal/editor.port exists. Then poll /openapi.json until it returns a valid document. Do not assume that creating the process means the project is ready.

Locating the editor server

The editor starts a local HTTP server while a project is open. Select Help ▸ Open Editor Server to open its home page in the default browser:

The local editor server home page

The selected port is written inside the project to:

.internal/editor.port

The examples and commands in this manual will from now on refer to these shell variables:

PORT="$(cat .internal/editor.port)"
BASE_URL="http://127.0.0.1:$PORT"

The port file belongs to the current editor session. Read it again after restarting the editor.

The editor server is a trusted local control interface. Do not expose it through a public address, port forward, or untrusted tunnel.

Discovering operations through OpenAPI

The only Defold-specific bootstrap information an external tool should need is the editor port and the OpenAPI document:

curl -sS "http://127.0.0.1:$(cat .internal/editor.port)/openapi.json"

The returned OpenAPI 3.0.3 document describes the operations supported by the running editor version, including paths, methods, parameters, command names, request formats, responses, status codes, and authentication requirements.

List the documented paths:

curl -sS "$BASE_URL/openapi.json" |
  jq -r '.paths | keys[]'

List the documented editor command paths:

curl -sS "$BASE_URL/openapi.json" |
  jq -r '.paths | keys[] | select(startswith("/command/"))'

In Defold 1.13.2 and later, each command has its own path in the OpenAPI document. Earlier versions describe commands through a /command/{command} path and a command-name enum.

A version-aware integration should verify each required operation and configure requests from the returned schema. We advise against maintaining a supposedly exhaustive copy of endpoint or command names, as this can get outdated.

Project-defined routes also appear in /openapi.json when their editor scripts provide an OpenAPI operation description.

Executing editor commands

Invoke editor commands by sending a POST request to the command’s documented path, for example:

POST /command/compile
POST /command/run

To compile the project without running it:

curl -sS \
  -X POST \
  "$BASE_URL/command/compile" |
  jq

To compile and run the project:

curl -sS \
  -X POST \
  "$BASE_URL/command/run" |
  jq

These pipelines display the response body. In automation scripts, also check the HTTP status and success, using the pattern in Building HTML5.

Since Defold 1.13.2, /command/build is a deprecated compatibility alias for /command/run and is not listed in OpenAPI. Use /command/run in new integrations.

A successful compile returns HTTP status 200 with a structured result:

{
  "success": true,
  "issues": []
}

A failed build returns HTTP status 422 with issues such as:

{
  "success": false,
  "issues": [
    {
      "message": "Example compiler message",
      "severity": "error",
      "resource": "/main/player.script",
      "range": {
        "start": {
          "line": 12,
          "character": 4
        },
        "end": {
          "line": 12,
          "character": 17
        }
      }
    }
  ]
}

The available fields depend on the error. Use the resource path and source range when present, but also handle issues that contain only a message.

Commonly useful commands, when listed by the running editor, include:

compile
Compile the project without running it.
run
Compile and run the project.
clean-build
Clear the build cache, then compile and run. Use this only when an ordinary build behaves inconsistently or appears to miss changes.
build-html5
Build the project for HTML5 and make the output available through the editor server.
fetch-libraries
Download and reload project dependencies.
hot-reload
Reload modified resources into a running game.
reload-extensions
Reload editor scripts.
debugger-start, debugger-stop, and the debugger step commands
Control a debug session and the running project.

Exact names and availability depend on the editor version and current editor state; discover them from /openapi.json.

Commands that operate on project resources synchronize external file changes before execution.

Command responses and asynchronous work

Responses depend on the command. In Defold 1.13.2 and later, compile, run, clean-build, build-html5, debugger-start, and hot-reload wait for command completion and return a structured result with success and issues, as shown above. A successful result returns HTTP 200; a build or validation failure returns 422.

Other commands can still return 202, for example debugger-break. Inspect the operation in the current OpenAPI schema and handle the actual HTTP response status:

Status Meaning
200 The command completed and returned a result
202 The command was accepted and continues asynchronously
403 The command is not active in the current editor state
404 The command is not available
422 Build or validation failed
500 An internal editor error occurred

An HTTP 202 response is not proof that the requested result exists. Wait for the relevant output, resource, console marker, or served URL and enforce a timeout.

Building HTML5

If the current OpenAPI document lists /command/build-html5, invoke it through that path. In a shell script, capture the HTTP status separately from the response body and stop on a failed request or build:

build_response_file="$(mktemp)" || exit 1
if ! build_http_status="$(curl -sS \
  -X POST \
  -o "$build_response_file" \
  -w '%{http_code}' \
  "$BASE_URL/command/build-html5")"; then
  cat "$build_response_file"
  rm -f "$build_response_file"
  exit 1
fi

cat "$build_response_file"
if [ "$build_http_status" != "200" ] ||
   ! jq -e '.success == true' "$build_response_file" > /dev/null; then
  rm -f "$build_response_file"
  exit 1
fi
rm -f "$build_response_file"

In Defold 1.13.2 and later, this request waits for the build to finish and returns a structured result. The example prints the response body, including any build issues, and proceeds only on HTTP 200 with success: true. After a successful build, the editor opens the game in a browser and serves it at:

http://127.0.0.1:<editor-port>/html5/

A completed build does not mean that the game has finished loading in the browser. Wait for the canvas and application readiness before sending input or checking gameplay. See Browser tests for HTML5 for more details.

Searching API documentation

When present in /openapi.json, the /ref operation searches API documentation included with the running editor version. It provides names and signatures that match that version.

For example, to search for a function, use:

curl -sS \
  --get \
  --data-urlencode "q=go.animate" \
  "$BASE_URL/ref" |
  jq

Filter by environment and language:

curl -sS \
  --get \
  --data-urlencode "environment=runtime" \
  --data-urlencode "language=Lua" \
  --data-urlencode "q=collision message|raycast" \
  "$BASE_URL/ref" |
  jq

The search parameters are:

environment
editor, runtime, or comma-separated values.
language
Lua, C, C++, or comma-separated values.
q
A case-insensitive expression. Whitespace represents AND, while | represents OR.

The are also condensed documentation resources: LLM documentation index links to official manuals, API namespaces, and examples and the full LLM documentation lists complete documentation to support offline search and local indexing.

AI agents should prefer though specified searches instead of retrieving an entire reference when only one API or message is needed, in order to save on tokens and have a better prepared and clean context for a given task.

Reading console output

Read the editor console as JSON:

curl -sS "$BASE_URL/console" | jq

The response contains console text in lines and semantic regions in regions, including errors, evaluation results, and resource references.

To follow console output continuously, use:

curl -N "$BASE_URL/console/stream"

The stream includes existing console lines and then remains open for new output. Close it after receiving a completion marker or error, detecting process termination, or reaching a timeout or line limit.

For test-result framing and failure classification, see Automated testing and verification.

Rendering scene previews

The Defold editor (since 1.13.1) can render a supported scene resource “screenshot” to PNG through command /preview/{path}:

mkdir -p build/automation

curl -sS \
  "$BASE_URL/preview/main/main.collection?width=1280&height=720" \
  --output build/automation/main-preview.png

This renders the main collection from the open Basic 3D template project in a default initial view:

An editor-rendered preview of the main collection

You can use render to get previews of resources that utilise the visual scene editor, for example one can render a model component in the same way, that allows to verify it’s look or e.g. shader correctness:

curl -sS \
  "$BASE_URL/preview/assets/models/cube.model?width=1280&height=720" \
  --output build/automation/cube-preview.png

An editor-rendered preview of the cube model

The path after /preview/ does not include a leading slash. The optional dimensions default to the project display size and must be between 1 and 4096.

Status Meaning
200 The preview was rendered
400 The dimensions are invalid
404 The resource was not found
422 The resource is not loaded or does not support scene previews

Previews might be very useful for visual analysis of the project - checking level layouts, GUI layouts, shader and lighting setup, visual regressions, or create documentation thumbnails.

An editor preview is not a screenshot of the running game. It does not verify dynamically created objects, runtime post-processing, or platform-specific rendering. Use a runtime screenshot when those elements are needed.

Executing editor Lua

The authenticated POST /eval operation executes Lua in the editor extension environment. The per-session bearer token is stored in:

.internal/editor.token

Read the token and execute code:

TOKEN="$(cat .internal/editor.token)"

curl -sS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: text/plain" \
  --data-binary 'print(editor.version) return editor.platform' \
  "$BASE_URL/eval"

Printed output and return values are returned as text. Typical responses are:

Status Meaning
200 The code was executed
401 The bearer token is missing or invalid
422 The Lua code could not be parsed or executed
503 The editor extension environment is not ready

A client may retry after 503, but it should use a bounded number of attempts. Correct the code before repeating a request that returned 422.

Evaluated code can use the Editor API and the editor scripting environment. It cannot use game runtime APIs such as go.* to manipulate a running game. Use a runtime test, debugger, browser test, or runtime automation API for gameplay.

Modifying resources and files

Many Defold source resources use text formats and can be edited via any text editing tool. For modifying Defold project structured resources prefer editor transactions.

Change Preferred method
Lua, shader, JSON, or another known text format Direct file modification
Unsaved text in an open editor tab editor.get() and editor.transact()
Collection, game object, GUI, atlas, or another structured resource Editor transaction
Repeatedly generated content Standalone generator
Repeatable project operation Editor command or custom HTTP endpoint
CI-only transformation Standalone script run before Bob

Inspect a resource before changing it:

curl -sS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: text/plain" \
  --data-binary '
    local path = "/game.project"
    pprint(editor.properties(path))
    return editor.get(path, "path")
  ' \
  "$BASE_URL/eval"

Check editor.can_get(), editor.can_set(), and the other editor.can_*() functions before performing a transaction.

Use editor.execute() in editor Lua to run a formatter, validator, or generator:

local output = editor.execute(
  "python3",
  "scripts/generate_levels.py",
  {
    out = "capture"
  }
)

print(output)

When the command does not modify project resources, set reload_resources = false to avoid an unnecessary reload.

Do not modify files in .internal/ or generated content in build/.

Preferences

Editor preferences can be read and written through the path documented in OpenAPI, currently /prefs/{path}.

You can for example read the configured code font size:

curl -sS "$BASE_URL/prefs/code/font/size" | jq

Or set it to e.g. 16:

curl -sS \
  -X POST \
  -H "Content-Type: application/json" \
  --data '16' \
  "$BASE_URL/prefs/code/font/size"

The editor validates the value against its preference schema. An invalid path or value returns HTTP 400.

Preferences are persistent user or project-user settings, not project configuration stored in game.project. If automation needs to change a preference temporarily, save the previous value and restore it afterward.

Project-defined routes

Editor scripts can define additional routes with get_http_server_routes(). An optional OpenAPI operation table exposes a route through the same /openapi.json document as built-in operations.

Project-defined routes can provide content generation, validation, reports, localization checks, resource analysis, project-specific tests, or a smaller interface for an IDE or external controller.

A good route should perform one clearly named operation, validate its input, return a structured result, be idempotent where possible, and limit expensive work.

Project-defined routes are not automatically protected by the /eval token. Add project-specific authentication and safety checks when a route performs sensitive operations.

Lifecycle hooks

Hooks are functions that can be run before and after builds, before and after bundle creation, and when a game process starts or terminates. A project can contain one hooks.editor_script file in its root. Only the root hook file receives these events, giving the project one place to define their order.

local M = {}

local function validate_project()
  print(editor.execute(
    "python3",
    "scripts/validate_project.py",
    {
      out = "capture",
      reload_resources = false
    }
  ))
end

function M.on_build_started(opts)
  validate_project()
end

function M.on_build_finished(opts)
  print("Build successful:", opts.success)
end

return M

An error raised from on_build_started() stops the editor build. Lifecycle hooks run only in the editor; put shared validation and generation logic in standalone scripts that can also be invoked from CI.

Security and compatibility

Treat the entire editor server as a trusted local interface:

  • Do not expose the port access publicly.
  • Protect .internal/editor.token; it authorizes /eval for the current session.
  • Do not give outside unrestricted /eval access.
  • Keep the token in the local integration layer rather than prompts, reports, or logs.
  • Remember that project-defined routes do not inherit /eval authentication.
  • Use up-to-date /openapi.json.
  • Use bounded waits for asynchronous automatic commands and for editor startup.

Engine Server

The editor server belongs to the editor process. A running game has a different port and different responsibilities, described in the engine service and runtime HTTP API manual.