Configuration & aliases
ggc reads configuration from one of:
$XDG_CONFIG_HOME/ggc/config.yaml~/.config/ggc/config.yaml(default on Linux/macOS)~/.ggcconfig.yaml(legacy path; still respected for older installs)
The first file that exists wins. If none exists, built-in defaults are used. On Windows the path resolves via %APPDATA%\ggc\config.yaml.
Editor autocomplete (JSON Schema)
A JSON Schema for the config file is published alongside these docs: https://bmf-san.github.io/ggc/ggc-config.schema.json. Add this header to your YAML to get autocomplete, hover docs, and validation in VS Code (with the YAML extension) and anything else that speaks SchemaStore conventions:
# yaml-language-server: $schema=https://bmf-san.github.io/ggc/ggc-config.schema.json
meta:
version: v8.3.0
# ...
The schema mirrors the Go struct (internal/config.Config); a unit test guards against drift between the two, so what's published is what ggc actually reads.
Anatomy
meta:
version: v8.3.0 # auto-maintained by ggc
commit: abcdef1 # auto-maintained by ggc
created-at: 2025-01-15_12:34:56
ui:
color: true
git:
default-remote: origin
default-branch: main
aliases:
ship: status && commit amend --no-edit && push force
cleanup: branch delete merged
interactive:
profile: default # one of: default | emacs | vi | readline
meta.* is rewritten by ggc on startup; don't edit it by hand.
Aliases
An alias is a named sequence of ggc commands separated by &&. Anything you can type in the prompt you can put behind an alias.
ggc ship
runs the three commands above in order, stopping at the first failure.
Placeholders
Numeric placeholders let an alias accept arguments:
aliases:
commit-msg: "commit -m '{0}'"
feature: ["branch checkout {0}", "push {0}"]
Then:
ggc commit-msg "Fix bug"
ggc feature main
See the alias validation grammar for the exact rules (nesting, escaping, reserved names).
Keybindings
Profiles
Pick a profile in one line:
interactive:
profile: emacs
| Profile | Feel |
|---|---|
default |
Curated ggc defaults (recommended) |
emacs |
GNU readline-style |
vi |
Modal, hjkl navigation |
readline |
Strict GNU readline compatibility |
Overriding individual keys
Under interactive.keybindings you can override any binding by its logical name:
interactive:
keybindings:
move_up: "ctrl+p"
move_down: "ctrl+n"
accept: "enter"
cancel: "esc"
toggle_workflow: "ctrl+w"
Supported key notations
Three equivalent forms are accepted; pick whichever reads best:
| Notation | Example |
|---|---|
ctrl+ |
ctrl+p |
C- |
C-p |
| raw caret | ^P |
alt+ / M- and shift+ work the same way. Function keys (f1..f12), arrow keys (up, down, left, right), and named keys (enter, esc, tab, space, backspace) are all recognized.
Layered overrides
The config is evaluated in this order, later layers winning:
interactive.profilebaselineinteractive.keybindings(global)interactive.<os>—darwin/linux/windowsinteractive.contexts.<ctx>— e.g.contexts.picker,contexts.searchinteractive.terminals.<term>— e.g.terminals.alacritty,terminals.iterm2
Example: use emacs everywhere, but tweak move_up on macOS only:
interactive:
profile: emacs
darwin:
keybindings:
move_up: "ctrl+p"
Inspecting the resolved keymap
ggc config list
ggc config get interactive.keybindings
ggc config get interactive.darwin.keybindings
If you're unsure what key your terminal is sending, run:
ggc debug-keys
and press keys — it prints the raw escape sequences.
Editing
ggc config edit # opens the config file in $EDITOR
ggc config path # prints the resolved path
ggc config list # print the fully-merged config
History
ggc persists each executed command to a per-user JSONL store so the
interactive prompt's recall (Ctrl+P / Ctrl+N),
incremental search (Ctrl+R) and the ggc history
subcommands have something to read.
history:
enabled: true # default; set to false to disable writes entirely
max-entries: 1000 # default; cap before truncate-rewrite kicks in
Behaviour:
- Reads are always available, even when
enabled: false— useful for inspecting prior commands while temporarily off the record. GGC_NO_HISTORY=1in the environment forces disabled state and overrides the config value. Handy in one-off shells / CI.- The store lives under
$TMPDIR/ggc-<uid>/history.jsonlon Unix-like systems andUserCacheDir()on Windows. Useggc history clearto wipe it. - The
historysubcommand itself (includinghistory clear,history search ...,history last ...) is never recorded so navigating history doesn't pollute it. - Inside the interactive prompt, the
historypicker and Ctrl+R reverse-i-search share the same store and use the same deduplication policy (newest occurrence wins per display string). The picker shows up to 30 recent unique entries; Ctrl+R searches up to 200. - Inside the Ctrl+R overlay Ctrl+C cancels the overlay rather than quitting ggc; the global "quit" meaning is restored as soon as you exit the overlay.
tmux
Under tmux, most terminals mangle the modifier prefix unless xterm-keys is on. Add to ~/.tmux.conf:
set -g xterm-keys on
Then reload tmux. Without this, ctrl+arrow / alt+... will arrive as bare arrow keys.