# 🔧 Configuration
Gitwig stores its config in `~/.gitwig/config.toml`. The directory is created automatically on first launch.
### First-run migration
If `~/.gitwig/config.toml` doesn't exist yet, Gitwig looks for an existing config to migrate from:
1. A path passed as the first CLI argument (`gitwig path/to/config.toml`).
2. `./config/config.toml` relative to the current working directory.
3. `./config/config.toml` relative to the executable.
4. `~/.config/gitwig/config.toml` (new XDG location), `~/.config/twig/config.toml` (legacy Twig XDG location), or `~/.twig/config.toml` (legacy Twig home location).
5. Nothing found — a default config is written to `~/.gitwig/config.toml`.
After the first run the migrated (or generated) file becomes the sole source of truth; the original is left untouched.
### Example: `config.toml`
```toml
items = ["Repo A", "Repo B", "Side Project", "Test Repo"]
# Event-loop poll interval in milliseconds (default: 100).
# Lower → more responsive input, higher → less CPU usage. Sane range: 16–500.
poll_interval_ms = 100
# Seconds a background `git fetch` may run before it is cancelled (default: 30).
# Prevents an unreachable remote from pinning a repository card forever.
# Set to 0 to disable the limit.
fetch_timeout_secs = 30
# Sorting preferences for the main page list
sort_by = "custom"
sort_reverse = false
# Enable compatibility mode to use simple ASCII symbols
compatibility_mode = false
# Directories to watch recursively for automatic workspace syncing
watch_dirs = ["~/development"]
# Number of months inactive to be considered stale
stale_threshold_months = 1
# Hide/show stale projects on the main page list
show_stale_projects = true
# Managed by the app: the sticky label filter ("project view") and the
# quick-label slots behind the 1-9 keys, in slot order (FIFO on first view).
# active_label_filter = "work"
# label_slots = ["work", "oss", "archive"]
```
### Config keys
| `items` | `[String]` | `[]` | Paths shown in the main list. Managed by the in-app `a` (directory scan) / `e` / `d` shortcuts. |
| `enable_watch_dirs` | `Boolean` | `true` | Enable or disable the Watch Directories automatic workspace sync functionality. |
| `watch_dirs` | `[String]` | `[]` | Directories watched recursively for automatic workspace synchronization. When a new Git repository is cloned or created in these directories, it is automatically added to `items` and persisted. Paths matching `scan.excludes` are ignored. |
| `poll_interval_ms` | `Integer` | `100` | How long (ms) the event loop waits between input checks. Lower feels snappier; higher saves CPU. |
| `fetch_timeout_secs` | `Integer` | `30` | Seconds a background fetch may run before Gitwig cancels it. Guards against remotes that accept a connection but never reply. `0` disables the limit; otherwise the minimum is `5`. |
| `max_commits` | `Integer` | `0` | Maximum commits to load in workspace view. Set to `0` for unlimited. |
| `page_size` | `Integer` | `10` | Number of lines/items scrolled by Page Up / Page Down. |
| `sort_by` | `String` | `"custom"` | Main list sorting preference (`"custom"`, `"alphabetical"`, `"recent_visit"`, `"latest_changes"`). Managed by `o`. |
| `sort_reverse` | `Boolean` | `false` | Inverts the main list sorting direction (ascending vs. descending). Managed by `O`. |
| `theme` | `String` | `"default"` | Active theme configuration name. Managed in Settings `s`. |
| `compatibility_mode` | `Boolean` | `false` | Enable to use simple ASCII symbols instead of rich Unicode icons/emojis (prevents layout alignment issues in restricted terminals like RustRover's built-in terminal). |
| `scan.max_depth` | `Integer` | `6` | Maximum directory depth to search for git repositories during discovery. |
| `scan.start_dir` | `String` | `"$HOME"` | Starting directory for interactive repository discovery scanning. |
| `scan.excludes` | `[String]` | `["node_modules", "target", "venv", ".venv", "checkout"]` | Directory names excluded from discovery scanning and filesystem watching. If left empty, automatically resets to defaults. |
| `scan.git_only` | `Boolean` | `true` | Only scan folders that contain a .git directory. |
| `auto_fetch_interval_mins` | `Integer` | `10` | Time interval in minutes to automatically run background fetches for all repositories. Set to `0` to disable. Individual repositories can override this cadence (or opt out with `0`) via the Repository Settings popup (`s` on the Overview screen), stored under `repo_configs`; a whole label group can override it too via Label Settings, stored under `label_configs` (see [Per-label settings](#per-label-settings)). |
| `show_system_stats` | `Boolean` | `false` | Display CPU and Memory utilization of the Gitwig process in the bottom status bar. |
| `enable_commit_signatures` | `Boolean` | `false` | Verify GPG/SSH signatures on commits list (requires spawning git subprocesses). |
| `graph_max_commits` | `Integer` | `1000` | Maximum commits visualized in the Graph tab history. Set to `0` for unlimited. |
| `detail_cache_ttl_secs` | `Integer` | `30` | How long in seconds repository details are cached in memory before reloading. |
| `tab_ttl_secs` | `Integer` | `60` | How long in seconds lazy-loaded tab data remains cached in memory before automatic refresh. |
| `stale_threshold_months` | `Integer` | `1` | Number of months inactive (no commits) for a repository to be considered stale. |
| `show_stale_projects` | `Boolean` | `true` | Show or hide stale repositories in the list on the main page. |
| `editor` | `String` | `""` | Custom terminal editor executable to open files with from the Files tab (`e`/`o`). |
| `ssh_strict_host_checking` | `Boolean` | `false` | Enforce strict SSH host key checking (`StrictHostKeyChecking=yes`). All Gitwig SSH operations additionally run with `BatchMode=yes`: ssh can never prompt for passphrases or confirmations over the TUI — an operation needing interactive auth fails fast and the error is shown in the error popup (per-repo fetch failures show a compact `✗` marker; press `E` for details). Load your key into `ssh-agent` for passphrase-protected keys. |
| `git_app` | `String` | `""` | Preferred external Git GUI application (e.g. `gitui` or `lazygit`), launched with `g`. |
| `show_grouping` | `Boolean` | `true` | Enable or disable repository label grouping sidebar on the home page. |
| `labels` | `Map<String, [String]>` | `{}` | Repository path → list of labels. Managed by the in-app `l` shortcut. |
| `active_label_filter` | `String` | *(unset)* | Sticky home-list label filter ("project view"). Managed by the `L` label picker; persists across restarts until deselected, and auto-clears if the label no longer exists on any tracked repository. |
| `label_slots` | `Array<String>` | `[]` | Quick-label slots backing the numbered chips and the `1`-`9` keys on the home screen, in slot order. Managed automatically, FIFO: a label takes the next free slot the first time it is viewed through the label filter and keeps it; once all nine are taken the oldest entry is evicted; labels no repository carries are pruned on save. |
| `label_configs` | `Map<String, Table>` | `{}` | Per-label settings shared by every repository carrying that label (see [Per-label settings](#per-label-settings)). Managed by the Label Settings popup (`→` on a label in the `L` picker). Auto-pruned when no repository carries the label. |
| `view_mode` | `String` | `"cards"` | Home page repository list layout mode (`"cards"`, `"compact"`, `"tile"`). Managed by `v`. |
| `tile_columns` | `Integer` | `0` | Number of columns in tile layout mode (`0` = auto-calculate based on terminal width). |
| `resync_on_tab_change` | `Boolean` | `false` | Automatically reload repository details from disk when switching tabs. |
| `prompt_cwd_repo` | `Boolean` | `true` | On startup, offer to track the repository you launched Gitwig from when it is not on the list yet. Set to `false` to never prompt. |
### Keybindings
Keyboard shortcuts live in a separate `keybindings.toml` beside `config.toml`. Entries there override the built-in defaults and are preserved across upgrades — see [Customizing Keybindings](keybindings.md#customizing-keybindings) for the format and override semantics.
### Per-label settings
Settings can be attached to a **label** and are then shared by every repository carrying that label. They are the settings subset of the per-repository overrides — `theme`, `page_size`, `max_commits`, `resync_on_tab_change`, `auto_fetch_interval_mins`, and `editor` — and are edited in the **Label Settings** popup, opened with `→` on a highlighted label in the `L` label picker.
Each setting resolves through three tiers, most specific first:
1. **Per-repository override** (`repo_configs`, set in the Repository Settings popup).
2. **Label** (`label_configs`) — the first of the repository's labels, in the order they are stored, that defines the setting.
3. **Global default** (the top-level config key).
A row left empty at one tier inherits the next tier down. `auto_fetch_interval_mins = 0` at the label tier opts the whole group out of background fetching (handy for an `archive` label). When a label sets a `theme`, the home repository-list view is tinted with that theme while that label's filter ("project view") is active. Entries are stored as `[label_configs.<label>]` tables and are pruned automatically once no repository carries the label.
```toml
[label_configs.work]
theme = "nord"
auto_fetch_interval_mins = 2
[label_configs.archive]
auto_fetch_interval_mins = 0
```
### Keys Gitwig manages for you
These appear in `config.toml` but are written by the app, not meant to be edited by hand:
| `visits` | A repository is opened — feeds the `recent_visit` sort and the Recent group. |
| `pinned` / `starred` | You pin (`p`) or star (`*`) a repository. |
| `labels` / `label_slots` / `active_label_filter` | You edit labels, view a label filter, or pick a quick-label slot. |
| `repo_configs` / `label_configs` | You change a setting in Repository Settings or Label Settings. |
`compact_view` is **deprecated**. It is read once on load, converted to `view_mode = "compact"`, and then cleared — set `view_mode` instead.
### Themes
The active theme is selected via the `theme` key and lives in `~/.gitwig/themes/<name>.theme`. A set of popular themes is written there on first launch (`catppuccin`, `cyberpunk`, `dracula`, `forest`, `gitwig`, `gruvbox`, `monokai`, `nord`, `oceanic`, `onedark`, `rosepine`, `solarized_dark`, `tokyonight`), alongside `default`. Themes are managed in-app via Settings `s`.
A `.theme` file sets five keys:
```toml
# Gitwig — Verdigris brand theme (gitwig.theme)
accent = "#4db08a" # selections, focus borders, active tabs
warning = "#bd6b3d" # edit state, modified badges
danger = "#b2402e" # delete prompts, conflicts, removed lines
success = "#3c8a6b" # committed badges, added lines
border_type = "rounded" # "plain", "rounded", "double", "thick"
```
Colors accept either one of the 16 named terminal colors (`"black"`, `"red"`, `"green"`, `"yellow"`, `"blue"`, `"magenta"`, `"cyan"`, `"gray"`, `"darkgray"`, `"lightred"`, `"lightgreen"`, `"lightyellow"`, `"lightblue"`, `"lightmagenta"`, `"lightcyan"`, `"white"`) or a true-color hex value like `"#4db08a"` (requires a terminal with true-color support).
Gitwig writes back to whichever file it loaded from, so edits made in the UI persist across runs.