Skip to content

Joona-t/godot-dev-bridge

Repository files navigation

godot-dev-bridge

View and drive a running Godot game with no screenshare and no mouse.

A tiny dev-only autoload + a stdlib-only Python CLI that let an external process — your shell, a CI job, or an AI coding agent — control a live Godot game over a JSON file protocol: run commands, render frames to PNG, and evaluate GDScript, all while the game runs muted in a parked background window. Think Puppeteer, but for a running Godot game.

gdbridge start                 # launch the game with the bridge, parked + muted
gdbridge shot frame.png        # render the current frame to a PNG you can open
gdbridge eval 'return get_tree().current_scene.name'
gdbridge call <your_command> k=v ...   # any command your project registered
gdbridge stop

Built for the loop where an agent edits code, renders a frame, and looks at it — no desktop automation, no flaky screen-grabs, no stolen mouse.

Why

Verifying a Godot change usually means watching the window yourself, or driving the OS with screenshot/mouse automation that hijacks your screen and breaks on HiDPI. godot-dev-bridge replaces that with a clean, scriptable channel:

  • Headless-feeling, but actually rendered. Frames come from the game's own offscreen framebuffer (get_viewport().get_texture()), so captures work while the window sits in a corner, unfocused — but unlike --headless, real rendering runs.
  • Background-stable. It decouples the loop from display vsync (VSYNC_DISABLED + Engine.max_fps) and disables macOS App Nap, so it keeps responding while you work in other apps.
  • Zero cost when shipped. The autoload is inert unless the GODOT_DEV_BRIDGE env var is set (the CLI sets it). Your players never run it.
  • Game-agnostic core, project-specific commands. The published core knows nothing about your game. Projects add their own verbs at runtime via a one-line registry (DevBridge.register_command(...)).

Install

The addon (in your game):

  1. Copy addons/dev_bridge/ into your project, or install via the Godot Asset Library.
  2. Enable Dev Bridge in Project Settings → Plugins. (This registers the DevBridge autoload for you.)

The CLI (on your machine):

# it's a single stdlib-only script — put it on your PATH
curl -o /usr/local/bin/gdbridge https://raw.githubusercontent.com/Joona-t/godot-dev-bridge/main/cli/gdbridge
chmod +x /usr/local/bin/gdbridge

Requires Python 3.8+ and a Godot 4 binary (found via $GODOT, your PATH, or the usual install locations).

Commands

Run from anywhere inside your Godot project (it finds project.godot by walking up).

Command What it does
start [--scene S] [--res WxH] [--no-park] [--godot PATH] kill old Godot, launch windowed with the bridge, wait until it's online
stop quit the game, clean up
ping health: project + Godot version, current scene, fps
commands list built-in + project-registered commands
shot [path] [--settle N] render the current frame to PNG (prints the path)
eval "<gdscript>" [--shot P] run GDScript live (get_tree(), self, tree, scene available)
scene <res://…|short> / reload change / reload the scene
tree [--depth N] / node <path> dump the scene tree / a node's script vars
key <code> [--up] / action <name> [--up] / click <x> <y> inject input
call <name> [k=v …] [--shot P] call any command your project registered

Most action commands accept -s/--shot PATH to also capture a frame.

Add your own commands

The core ships with zero knowledge of your game. To expose game-specific verbs, register Callables on the autoload — see docs/EXTENDING.md:

# my_bridge_commands.gd  (autoload it AFTER DevBridge)
extends Node
func _ready() -> void:
    var b := get_node_or_null("/root/DevBridge")
    if b and b.is_enabled():
        b.register_command("spawn", _spawn, "spawn N enemies")
func _spawn(args: Dictionary) -> Dictionary:
    var n := int(args.get("n", 1))
    # ... do the thing ...
    return {"spawned": n}

Then gdbridge call spawn n=5, or give it friendly ergonomics with a .gdbridge.json alias → gdbridge spawn 5.

For AI agents

gdbridge is designed to be driven by coding agents. See AGENTS.md for the agent contract, and integrations/claude-code/ for a ready-made Claude Code skill.

Try the demo

cd demo && gdbridge start && gdbridge shot /tmp/cube.png && open /tmp/cube.png
gdbridge spin 90 -s /tmp/spun.png && gdbridge stop

How it works

See docs/PROTOCOL.md. In short: the CLI writes request.json (monotonic seq) into a per-project temp dir; the autoload polls it each frame, runs the command, optionally renders a PNG, and writes response.json. Single-writer-per-file

  • atomic temp-then-rename = no races. A 5s watchdog prevents a stuck capture from wedging the bridge.

Platform support

macOS is maintainer-tested. Linux and Windows code paths are present (stdlib process control, per-OS Godot detection) and community-tested — issues/PRs welcome. Note: some Linux/Windows compositors throttle fully-occluded windows; park-don't-minimize + vsync-decouple mitigate this (a SubViewport capture path is planned for v1.1).

License

MIT © Joona Tyrninoksa. Contributions welcome.

About

View and drive a running Godot game with no screenshare or mouse — file-protocol commands, frames to PNG, a GDScript REPL. Puppeteer for Godot. For dev iteration, CI, and AI agents.

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors