Edit project settings
project.godot is an INI-style file with a few shapes that resist line editing: input actions are brace blocks containing serialized Object(...) values, autoloads carry a leading asterisk for singletons, and section order matters. godot-cli parses the file and writes it back rather than matching patterns over lines.
Look at what is there
godot-cli project show --project-root . --json
{
"project_name": "Demo",
"main_scene": "res://main.tscn",
"input_action_count": 4,
"autoload_count": 1,
"enabled_plugin_count": 0
}
Scalar settings
godot-cli project settings set --project-root . \
--section application --key run/main_scene --value res://main.tscn
godot-cli project settings list --project-root . --json
godot-cli project settings get --project-root . --section application --key config/name --json
Strings are quoted for you. Pass --raw when the value is already Godot-formatted, such as a Vector2(...) or a boolean.
project settings validate --project-root . checks that res:// paths in settings point at files that exist, which catches a main scene that was renamed.
Input map
Input actions are the fiddliest part of the file, so they are described as an intent and applied as a unit:
{
"actions": [
{
"name": "move_left",
"events": [
{ "type": "key", "keycode": "A", "physical": true },
{ "type": "joypad_motion", "axis": "left_x", "axis_value": -1.0 }
]
}
]
}
godot-cli project input apply --project-root . --intent input.json --json
applied 4 input action(s) (4 added, 0 replaced)
What lands in the file is the full serialized event Godot expects:
[input]
move_left={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,...,"physical_keycode":65,...)]
}
Applying the same intent twice replaces each action by name instead of appending a second copy, so re-running after an edit is safe. A ready-made WASD intent ships at $GODOT_CLI_HOME/examples/intents/wasd_movement.json.
Every event type Godot has
| Type | Names it takes |
|---|---|
key |
A letter or digit, space, escape, tab, enter, backspace, delete, home, end, the arrows, the page and lock keys, shift/ctrl/meta/alt, f1–f12 |
mouse_button |
left, right, middle, wheel_up, wheel_down, wheel_left, wheel_right, xbutton1, xbutton2 |
joypad_button |
a/south, b/east, x/west, y/north, back, guide, start, left_stick/l3, right_stick/r3, left_shoulder/lb, right_shoulder/rb, the d-pad, misc1, paddle1–4, touchpad |
joypad_motion |
left_x, left_y, right_x, right_y, trigger_left/LT, trigger_right/RT, with axis_value |
Names are matched without case, and each type also takes the raw Godot number
("keycode": 4194309, "button": 15) for anything not named here.
A key or mouse_button event takes modifier flags, so a chord is one event:
{ "type": "key", "keycode": "S", "physical": false, "ctrl": true }
An event can also name a device, which is what separates two players sharing a
binding. -1 is Godot's All Devices and the default:
{ "name": "player2_jump", "events": [
{ "type": "joypad_button", "button": "a", "device": 1 },
{ "type": "key", "keycode": "space" }
] }
project input apply --help lists every accepted name, and an unknown one
comes back with the whole set in details.hint rather than a bare failure.
Autoloads
{ "autoloads": [ { "name": "GameState", "path": "res://scripts/game_state.gd", "singleton": true } ] }
godot-cli project autoload apply --project-root . --intent autoload.json --json
godot-cli project autoload validate --project-root . --json
[autoload]
GameState="*res://scripts/game_state.gd"
The asterisk is how Godot marks a singleton. Autoloads merge by name; pass replace_all in the intent when the list should be exactly what you supplied.
Editor plugins
godot-cli project plugins list --project-root . --json
godot-cli project plugins enable --project-root . --plugin my_addon
godot-cli project plugins disable --project-root . --plugin old_plugin
godot-cli project plugins validate --project-root . --json
This toggles plugins that already exist at addons/<name>/plugin.cfg. godot-cli does not install from the Asset Library.
Rendering and physics
Both take short aliases in place of the raw setting keys:
godot-cli project rendering list --project-root . --json
godot-cli project rendering apply --project-root . --intent rendering_forward_plus.json --json
godot-cli project physics apply --project-root . --intent physics_jolt.json --json
project rendering validate and project physics validate check the values against the ones Godot accepts, so a typo in a driver name fails before you next open the project.
One intent for everything
project apply takes a single document containing any combination of the sections above and writes them in one pass:
{
"settings": { "application": { "run/main_scene": "res://main.tscn" } },
"input": { "actions": [ ... ] },
"autoload": { "autoloads": [ ... ] },
"rendering": { "method": "forward_plus" }
}
godot-cli project apply --project-root . --intent bootstrap.json --json
$GODOT_CLI_HOME/examples/intents/project_bootstrap.json is a working example. Every command here takes --dry-run to apply in memory and report what would change.