NAME
gsctl — GNOME settings,
searchable and undoable.
A command-line interface to GSettings/dconf, built for AI agents and usable by people.
Find the key that controls something, see its type and allowed values, change it with
validation and --dry-run, and undo anything from a journal.
JSON for agents, text for people.
# paste this into Claude Code, Codex, Cursor or any coding agent
Read https://junoddev.github.io/gsctl/agents.md and set up gsctl on this machine.# it installs gsctl, checks the session, adds the skill and offers a permission gate. read the file
# prebuilt x86_64 / aarch64 Linux binary into ~/.local/bin (glibc 2.35+)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/junoddev/gsctl/releases/latest/download/gsctl-installer.sh | sh# or grab an archive with the man page and completions from releases
# Rust 1.92+ and GLib headers (libglib2.0-dev / glib2-devel / glib2)
cargo install gsctl --lockedgit clone https://github.com/junoddev/gsctl
cd gsctl && cargo install --path . --lockedv0.1.2 · MIT OR Apache-2.0 · Linux + GNOME
SYNOPSIS
gsctl search words… # ranked search over keys, summaries, descriptions gsctl schema schema [key] # type, default, value, allowed values gsctl get|set|reset schema key [value] [--dry-run] [--yes] gsctl changed # only what differs from defaults gsctl history | revert id|last # every write is journaled gsctl keys find|list|conflicts|add|remove gsctl ext list|info|enable|disable gsctl export | apply [--prune] # per-area JSON for your dotfiles gsctl watch | doctor | man | completions shell
DESCRIPTION
On a desktop like Omarchy, every piece reads
a plain-text file in ~/.config, so an agent can read the setup, edit a line and reload.
GNOME can't work that way: Shell, Mutter and the apps keep their settings in one binary dconf
database, described by thousands of typed keys, with no file to read or edit.
gsettings has the metadata but no search, no JSON, no error an agent can act on and no
record of what changed. dconf dump is thousands of lines of preferences mixed with machine
state. gsctl gives GNOME what Omarchy gets from plain files: a settings surface an agent can read,
search and change safely. It's a proxy over dconf, not a copy, so Settings, gsettings and
gsctl always agree.
- search — ranked over schema ids, key names, summaries, descriptions and installed extensions
- validate — type and range checks before anything is written; writes are read back
- dry-run — every write command shows exactly what it would change
- undo — a journal of old values;
revert lastwalks back like an undo stack - shortcuts — all five keybinding schemas, custom bindings and extension shortcuts in one place
- extensions — their settings included, enabled state by GNOME Shell's own rules
EXAMPLES
$ gsctl search "screen timeout" --limit 1 --format text org.gnome.desktop.session idle-delay 0 # Time before session is considered idle (seconds of inactivity before the screen blanks; 0 = never) 149 matches (showing 1 of 149; use --limit for more) $ gsctl set org.gnome.desktop.interface color-scheme sideways --dry-run error: "sideways" is not one of the allowed values: default, prefer-dark, prefer-light hint: see `gsctl schema org.gnome.desktop.interface color-scheme` $ gsctl set org.gnome.desktop.interface color-scheme prefer-dark --format text set org.gnome.desktop.interface color-scheme: 'default' -> 'prefer-dark' $ gsctl revert last --format text reverted org.gnome.desktop.interface color-scheme: 'prefer-dark' -> 'default' $ gsctl keys add Terminal '<Super>Return' ptyxis --dry-run --format text would add 'Terminal' at /org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/: <Super>Return runs 'ptyxis' (guarded: needs --yes)
AGENTS
JSON on stdout by default. When stderr isn't a terminal, errors are JSON too, with a stable
code, an exit_code, a hint, and for bad values the allowed
range: enough to fix the call without another lookup.
$ gsctl set org.gnome.desktop.interface color-scheme sideways --dry-run {"error":{"code":"invalid_value","exit_code":4, "message":"\"sideways\" is not one of the allowed values: default, prefer-dark, prefer-light", "schema":"org.gnome.desktop.interface","key":"color-scheme","type":"s", "range":{"kind":"enum","choices":["default","prefer-dark","prefer-light"]}, "hint":"see `gsctl schema org.gnome.desktop.interface color-scheme`; ..."}}
| 0 | ok | 4 | invalid value |
| 1 | internal error | 5 | not writable or no session |
| 2 | usage | 6 | guarded key, needs --yes |
| 3 | not found | 7 | conflict |
Machine-readable docs, served as plain files:
- agents.md — setup instructions: install, verify, add the skill, add a permission gate
- skill/SKILL.md — the operating manual: search → schema → dry-run → set → verify
- llms.txt — index for crawlers and agents
SAFETY
gsctl trusts you. It makes changes visible (--dry-run, the journal) and undoable
(revert), and asks for --yes only on keys that can lock you out, cut off remote
access or make GNOME run a command. Secrets are redacted in output. It isn't a sandbox:
anything running as you can call dconf write, so for an agent the real gate is the
agent's own permissions. In Claude Code:
{
"permissions": {
"ask": ["Bash(gsctl * --yes)", "Bash(gsctl * --yes *)"],
"deny": [
"Bash(dconf write *)", "Bash(dconf load *)", "Bash(dconf reset *)",
"Bash(gsettings set *)", "Bash(gsettings reset *)", "Bash(gsettings reset-recursively *)"
]
}
}Every --yes asks you first, and writes go through gsctl, where they're validated and
journaled. See SECURITY.md.
TESTED ON
Ubuntu 26.04 and Fedora 44 (GNOME 50). Every push builds and runs the test suite on Ubuntu 22.04 and 24.04, Fedora and Arch; each release also passes a 96-case regression suite in a live GNOME session. x86_64 and aarch64 binaries need glibc 2.35 or newer.
SEE ALSO
github.com/junoddev/gsctl, releases, crates.io, CHANGELOG, gsettings(1), dconf(1)