Skip to content
gwmgwmgwmv1.10.0

User-level global config

The same .gwm.toml schema may also live at a user-level location, applied to every repo on the machine. Set a preference once (a theme, a worktree base, a keymap) and every repo inherits it unless its own .gwm.toml overrides it (issue #190).

~/.config/gwm/config.toml

$XDG_CONFIG_HOME, when set, is honoured outright ($XDG_CONFIG_HOME/gwm/config.toml): an explicit config home wins whether or not the file exists there. Otherwise gwm considers the cross-platform ~/.config/gwm/config.toml and the platform config dir (dirs::config_dir(), so Application Support on macOS and %APPDATA% on Windows), and the first that exists wins; with neither present, ~/.config/gwm/config.toml is the canonical location on every platform (issue #372; before it, macOS silently looked only under Application Support). It accepts the identical schema to .gwm.toml. See .gwm.toml schema.

~/.config/gwm/config.toml
[theme]
preset = "catppuccin"
[tui]
sidebar_position = "left"

The global file is merged underneath each repo’s .gwm.toml as a deep TOML overlay, then a single validation pass runs on the merged result. The repo always wins on conflict:

  • Scalars: the repo value overrides the global value.
  • Tables ([theme], [worktree], [tui], …): merged key-by-key recursively, so disjoint sections from both files coexist and a nested override keeps the untouched sibling keys.
  • Arrays ([[labels]], [[bootstrap.copy]], [[milestones]], …): replaced wholesale by the repo when present. They are never element-wise unioned: a repo’s [[labels]] fully supersedes the global set rather than producing a confusing concatenation.

In this example, global sets a theme and a couple of labels; the repo overrides one theme role and declares its own label set:

~/.config/gwm/config.toml
[theme]
preset = "catppuccin"
focus = "#89b4fa"
[[labels]]
name = "global-label"
# <repo>/.gwm.toml
[theme]
focus = "cyan" # scalar — repo wins
[[labels]] # array — repo replaces the global set wholesale
name = "bug"

Resolved result: theme.preset = "catppuccin" (from global, untouched), theme.focus = "cyan" (repo wins on the conflicting scalar, the other catppuccin roles survive), and exactly one label bug (the global global-label is gone, because the array was replaced, not merged).

With no global file present, loading is identical to before #190: repo-only, then the built-in default. The absent-global case is preserved byte-for-byte.

Set GWM_NO_GLOBAL_CONFIG=1 to force strictly repo-only loading, ignoring any global file that happens to exist. CI uses this for deterministic runs so a runner’s stray ~/.config/gwm/config.toml can’t perturb a build.

Terminal window
GWM_NO_GLOBAL_CONFIG=1 gwm list

Validation (theme, keymap, aliases, labels, bootstrap guards, …) runs on the merged result, not on each layer in isolation, so a global preset combined with a repo override is checked as the user will actually see it. The same load-time errors apply (.gwm.toml schema → validation rules).