---
title: Configuration
url: 'https://xcommander.dev/docs/configuration'
markdown: 'https://xcommander.dev/docs/configuration.md'
date: '2026-11-09'
description: 'XCommander works without any configuration. When you want to change a key, add your own, or pick another leader, you write a small text file in TOML format. Changes apply as soon as you save: no restart. Where the files go File Applies to ~/.config/xcommander/config.toml Every project .xco…'
---

configuration.md 

# Configuration

XCommander works without any configuration. When you want to change a key, add your own, or pick another leader, you write a small text file in [TOML](https://toml.io) format. Changes apply **as soon as you save**: no restart.

## Where the files go

| File | Applies to |
|---|---|
| `~/.config/xcommander/config.toml` | Every project |
| `.xcommander.toml` in a project's folder | That project only, on top of the global file |

Neither file exists until you create it. The folder `~/.config` is hidden in Finder; from Terminal:

```sh
mkdir -p ~/.config/xcommander
touch ~/.config/xcommander/config.toml
xed ~/.config/xcommander/config.toml
```

`xed` opens it in Xcode. Any code editor works; avoid TextEdit, whose smart quotes turn `"m z"` into `“m z”`, which isn't valid TOML.

The **project folder** is the nearest folder, going up from the file you're editing, that holds an `.xcodeproj`, an `.xcworkspace`, a `Package.swift` or a `.git` folder.

The project file is applied after the global one, so it only needs the lines that differ. You can commit it to the project's repository and share it with your team.

## An example

```toml
version = 1

[general]
leader = "⌃SPC"         # see "Choosing a leader" below
panel-delay = 200       # milliseconds before the which-key panel appears (default 350)
sequence-timeout = 15   # seconds before an unfinished sequence gives up (default 10)

[groups]
m = "build"             # what the which-key panel calls the m group

[keys]
"m z" = "make.clean"    # bind a key sequence to a command id
"f s" = "file.saveAll"

[unbind]
keys = ["q X"]          # remove keys XCommander ships with
```

Every file must start with `version = 1`. If the format ever changes in a way that would make an old file mean something different, the version goes up, and XCommander refuses a file it doesn't understand rather than guessing.

When a setting is in both the file and the **Settings** window, **the file wins**.

## Sections

| Section | What it does |
|---|---|
| `[general]` | The leader key, `panel-delay` and `sequence-timeout` |
| `[groups]` | The name the which-key panel shows for each group |
| `[keys]` | Bind a key sequence to a command id. Replaces whatever that sequence did before: binding a single `m` replaces the whole m group |
| `[unbind]` | `keys = [...]`: remove key sequences XCommander ships with |

Two more sections exist in the format but aren't built yet: `[commands]` (macros, a named list of commands) and `[layouts]` (saved pane arrangements). XCommander tells you it ignored them, and loads the rest of the file.

## Writing keys

A sequence is keys separated by spaces, written the way the which-key panel shows them: `m m`, `c d`, `f F`. Don't include the leader.

- **Uppercase** means with Shift: `"g F"` is g then Shift-f.
- **Modifiers** are written as symbols before the key: `⌃` Control, `⌥` Option, `⇧` Shift, `⌘` Command.
- Keys without a character have names: `ESC`, `SPC`, `TAB`, `RET`, `DEL`, the arrows `← → ↑ ↓`, and `F1` to `F12`.
- A key is the **character you type**, whatever your keyboard layout. On a French keyboard, `/` is the key that types `/`.

`ESC` can't be bound, anywhere in a sequence: it's how you cancel one, including one your own configuration broke.

## Finding command ids

Every command has an id, like `make.build` or `pane.swap`. The [command reference](https://xcommander.dev/docs/commands) lists them all, with their default keys. You can also print the list from the app itself, which is always exactly what your version supports:

```sh
/Applications/XCommander.app/Contents/MacOS/XCommander --print-reference
```

## Choosing a leader

The leader is the key that starts every sequence. Pick one in **Settings → General**, or with `leader` in `[general]`:

| Leader | Notes |
|---|---|
| `⌥RET` | The default. Xcode doesn't use it. |
| `⌘ESC` | Xcode doesn't use it. |
| `⌃RET` | Xcode doesn't use it. |
| `⌃SPC` | Hides Xcode's *Show Completions*, and macOS often uses it to switch input sources. |
| `⌥SPC` | Alfred and Raycast use it by default. |

The leader is swallowed while Xcode is in front, so it must be a chord you would never type as text. That's why there's no free choice of key.

## When a file has a mistake

XCommander never applies half a file. It reads and checks the whole file first, and only switches to it if it's valid. If you save a file with a typo, you keep working with the last good keymap, and the problem is reported:

- in **Settings → Diagnostics → Check config**;
- from Terminal, with `--check`, which runs the exact code the app uses and suggests the closest match for a mistyped command id:

```sh
/Applications/XCommander.app/Contents/MacOS/XCommander --check ~/.config/xcommander/config.toml
```

It prints what it found and exits with an error code if the file can't be used, so you can also use it in a script or a Git hook for a shared project file.

---

## Navigation

- Parent: [Documentation](https://xcommander.dev/docs.md)
- Previous: [Command reference](https://xcommander.dev/docs/commands.md)
- Next: [Troubleshooting](https://xcommander.dev/docs/troubleshooting.md)
