# Configuration file

> Where Capslock keeps its files, the YAML format of your mappings and settings, backups, and how unknown fields are preserved.

---

LLMS index: [llms.txt](/llms.txt)

---

You never have to edit these files: everything here can be changed in the app.
They are plain YAML so that you can read them, keep them in version control, or
move them to another Mac with **Export** and **Import**.

## Where files are kept {#location}

```filetree {title="~/Library/Application Support/com.vonng.capslock/"}
- action_mappings.yml     # mappings, actions, profile
- app_config.yml          # settings
- backups/                # automatic snapshots
- Logs/
  - Capslock.log          # diagnostic log
- ClipboardSlots/         # encrypted clipboard slots
- usage_stats.json        # Statistics counts
- hidutil-transaction.json  # recovery record
```

Settings › Recovery › **Show Config Folder** opens it in Finder. Your language
choice is kept in the app's preferences, and the clipboard key in your
Keychain.

## action_mappings.yml {#mappings}

The file has three parts: a `capslock_profile` block that Capslock maintains,
your custom `actions`, and the `mappings`. Built-in actions are never written
to the file.

```yaml
capslock_profile:
  id: classic-v3
  version: 3.1.0
  runtime_policy:            # written only after you change profile behaviour
    unmapped_keys: passthrough
    modifier_sides: left
actions:
- id: 4C1F0A52-6E2B-4D0B-9C1E-2B7D3F8E9A10
  name: Open Calculator
  action:
    kind: open_app
    bundle_id: com.apple.calculator
    app_name: Calculator
mappings:
- trigger:
    kind: single_tap_hyper
  action_id: builtin.escape
- trigger:
    kind: hyper_plus_key
    key: 72                  # H
    plane: 0
  action_id: builtin.move_left
- trigger:
    kind: hyper_plus_key
    key: 67                  # C
    plane: 8                 # Shift
  action_id: 4C1F0A52-6E2B-4D0B-9C1E-2B7D3F8E9A10
```

### Mappings {#mapping-fields}

| Field | Meaning |
| --- | --- |
| `trigger.kind` | `hyper_plus_key`, `single_tap_hyper`, `double_tap_hyper`, or `double_tap_modifier` |
| `trigger.key` | For `hyper_plus_key`: the key, as a JavaScript key code (72 is H) |
| `trigger.plane` | For `hyper_plus_key`: 0 to 15, the sum of Command 1, Option 2, Control 4, Shift 8 |
| `trigger.modifier` | For `double_tap_modifier`: which modifier |
| `action_id` | A built-in ID such as `builtin.move_left`, or the `id` of a custom action |
| `action` | An inline action, used instead of `action_id` |
| `bindings` | Optional [app rules](/docs/guide/apps/#yaml) |
{.fields}

### Actions {#action-kinds}

| `kind` | Fields |
| --- | --- |
| `key_combo` | `target_key`, and `with_ctrl`, `with_alt`, `with_cmd`, `with_target_shift` |
| `jump` | `direction`, `count` |
| `open_app` | `bundle_id`, `app_name` |
| `command` | `command`, `trusted` |
| `input_source` | `input_source_id` |
| `hold_modifier` | `modifier` |
| `directional`, `independent` | `action` (used by built-ins) |
| `native` | `native_action` (mouse, scroll, media, clipboard and sleep actions from the Classic layout) |
{.fields}

A `command` action loaded from a file you edited or imported is not trusted
until you approve it in the app, even if the file says `trusted: true`.

## app_config.yml {#app-config}

```yaml
schema_version: 1
hyper_output_mode: classic_compatibility   # or native_clean
hold_to_reveal_enabled: true
hold_to_reveal_threshold_ms: 550
hold_reveal_dismiss_mode: action_start     # or caps_release
double_tap_window_ms: 200
show_hud: false
hud_duration_ms: 1350
theme_mode: system                         # light, dark
cjkv_fix_strategy: none                    # shortcut_simulation, switching_focus
show_window_on_launch: true
hide_dock_icon: false
stats_show_inline: true
key_remaps: []                             # e.g. {source: right_option, destination: f19}
```

## Backups {#backups}

Before a change that replaces a lot at once, such as an import, reinstalling
the Classic layout, removing an app's rules, or changing profile behaviour,
Capslock saves a copy of `action_mappings.yml` in `backups/`. The newest 20
are kept.

## Safety rules for the files {#safety}

- **Unknown fields are kept.** Keys, fields and whole entries that this
  version does not understand are written back unchanged, so a configuration
  from a newer version survives being opened by an older one.
- **A broken file is never overwritten.** If `action_mappings.yml` cannot be
  read, Capslock backs it up, shows the configuration as read-only, and does
  not start until you repair it or import a good one. Diagnostics reports
  "Configuration needs repair".
- **Outside edits are detected.** Changes made in another editor are reloaded
  when you switch back to Capslock, and a save never overwrites them.
- **Older formats load.** A bare list of mappings from earlier versions is
  read as mappings with inline actions; editing a mapping converts it to the
  current form.

---

Backlinks:

- [Customize](/docs/guide/)
- [App rules](/docs/guide/apps/)
- [Settings, menu bar and statistics](/docs/guide/settings/)
