Skip to main content

Keybinding Maps

Fresh provides several built-in keybinding maps to match different editing styles:
Standard keybindings inspired by modern editors like VS Code:
  • Ctrl+P - Quick open (files, commands, buffers)
  • Ctrl+S - Save file
  • Ctrl+Z / Ctrl+Y - Undo / Redo
  • Ctrl+F - Find in file
  • Arrow keys for navigation
  • Shift+Arrow for selection

Switching Keymaps

Change the active keymap in your config.json:
config.json
{
  "active_keybinding_map": "emacs"
}
Available maps:
  • "default" - Standard editor keybindings
  • "emacs" - Emacs-style keybindings
  • "vscode" - VS Code keybindings
  • "macos" - macOS terminal-friendly keybindings
  • "macos-gui" - macOS GUI keybindings
On macOS, Fresh defaults to the "macos" keymap which handles terminal-specific keyboard limitations.
You can also switch keymaps at runtime:
  • Via menu: View → Keybinding Style → [Select keymap]
  • Via command palette: Ctrl+P then type >switch keybinding map

Custom Keybindings

Add custom keybindings to override the active keymap:
config.json
{
  "keybindings": [
    {
      "key": "s",
      "modifiers": ["ctrl"],
      "action": "save",
      "args": {},
      "when": "normal"
    },
    {
      "key": "d",
      "modifiers": ["ctrl", "shift"],
      "action": "delete_line",
      "args": {},
      "when": "normal"
    }
  ]
}

Keybinding Structure

FieldTypeRequiredDescription
keystringYesKey name (e.g., "a", "Enter", "F1")
modifiersstring[]NoModifier keys: "ctrl", "shift", "alt"
actionstringYesAction to perform (e.g., "save", "move_left")
argsobjectNoArguments for the action
whenstringNoContext condition (e.g., "normal", "insert")

Key Names

Letter keys: "a", "b", "c", … "z", "A", "B", … Special keys:
  • "Enter", "Tab", "Backspace", "Delete", "Escape"
  • "Space", "Home", "End", "PageUp", "PageDown"
  • "Left", "Right", "Up", "Down"
  • "F1""F12"
Modifier keys: "ctrl", "shift", "alt"

Context Conditions

ContextDescription
"global"Active everywhere
"normal"Active in normal editing mode
"insert"Active in insert mode
"file_explorer_focused"Active when file explorer has focus
"has_selection"Active when text is selected
"lsp_available"Active when LSP is running for current buffer

Example: Custom Keybindings

{
  "keybindings": [
    {
      "comment": "Save with Ctrl+S",
      "key": "s",
      "modifiers": ["ctrl"],
      "action": "save",
      "when": "normal"
    },
    {
      "comment": "Duplicate line",
      "key": "d",
      "modifiers": ["ctrl", "shift"],
      "action": "duplicate_line",
      "when": "normal"
    },
    {
      "comment": "Open file explorer",
      "key": "e",
      "modifiers": ["ctrl"],
      "action": "toggle_file_explorer",
      "when": "global"
    }
  ]
}

Chord Keybindings

Define multi-key sequences (like Emacs C-x C-s):
{
  "keybindings": [
    {
      "keys": [
        {"key": "x", "modifiers": ["ctrl"]},
        {"key": "s", "modifiers": ["ctrl"]}
      ],
      "action": "save",
      "when": "normal"
    }
  ]
}

Custom Keymaps

Create your own named keymaps:
config.json
{
  "keybinding_maps": {
    "my-custom-map": {
      "inherits": "default",
      "bindings": [
        {
          "key": "s",
          "modifiers": ["ctrl"],
          "action": "save"
        }
      ]
    }
  },
  "active_keybinding_map": "my-custom-map"
}
Custom keymaps can inherit from built-in maps and add or override specific bindings.

Common Actions

Here are some frequently used actions for custom keybindings:

File Operations

{"action": "save"}           // Save current file
{"action": "save_as"}        // Save as...
{"action": "open"}           // Open file
{"action": "new"}            // New file
{"action": "close"}          // Close buffer
{"action": "quit"}           // Quit editor
{"action": "move_left"}      // Move cursor left
{"action": "move_right"}     // Move cursor right
{"action": "move_up"}        // Move cursor up
{"action": "move_down"}      // Move cursor down
{"action": "move_word_left"} // Move word left
{"action": "move_word_right"} // Move word right
{"action": "move_line_start"} // Move to line start
{"action": "move_line_end"}   // Move to line end
{"action": "goto_line"}      // Go to line number

Editing

{"action": "undo"}           // Undo
{"action": "redo"}           // Redo
{"action": "cut"}            // Cut selection
{"action": "copy"}           // Copy selection
{"action": "paste"}          // Paste
{"action": "delete_line"}    // Delete current line
{"action": "duplicate_line"} // Duplicate line
{"action": "search"}         // Find in file
{"action": "find_next"}      // Find next match
{"action": "find_previous"}  // Find previous match
{"action": "query_replace"}  // Find and replace

LSP

{"action": "lsp_hover"}           // Show hover info
{"action": "lsp_goto_definition"} // Go to definition
{"action": "lsp_references"}      // Find references
{"action": "lsp_rename"}          // Rename symbol
{"action": "lsp_code_actions"}    // Show code actions
{"action": "lsp_completion"}      // Show completions

UI

{"action": "command_palette"}     // Open command palette
{"action": "quick_open"}          // Quick open files
{"action": "toggle_file_explorer"} // Toggle file explorer
{"action": "split_horizontal"}    // Split horizontally
{"action": "split_vertical"}      // Split vertically

Viewing Current Keybindings

To see all active keybindings:
  1. Command palette: Ctrl+P>Show Keybindings
  2. Menu: Help → Keyboard Shortcuts
  3. Direct file: View the keymap file at keymaps/[name].json

macOS Terminal Configuration

macOS terminals have specific keyboard limitations. See the complete guide below:

macOS Keymap

Fresh includes a dedicated macOS keymap that addresses terminal-specific challenges. To use it:
{
  "active_keybinding_map": "macos"
}
The macOS keymap works around these limitations:Ctrl+Shift combinations don’t work. Some macOS terminals cannot reliably send Ctrl+Shift sequences. The macOS keymap uses Ctrl+Alt as an alternative modifier.Some Ctrl keys are ASCII control characters. Terminal protocols treat Ctrl+J as Line Feed, Ctrl+M as Carriage Return, and Ctrl+I as Tab. The macOS keymap avoids these collisions.International keyboards use Alt for essential characters. On German, French, and other ISO layouts, Alt (Option) combined with letters produces characters like @, [, ], {, }. The macOS keymap avoids blocking character input.
TerminalSupportConfiguration
KittyFullAdd macos_option_as_alt left to config
GhosttyFullAdd macos-option-as-alt = left to config
iTerm2CSI uEnable “Report keys using CSI u” in Settings
Terminal.appManualImport Fresh.terminal profile or configure manually

iTerm2 Setup

  1. Go to SettingsProfilesKeys
  2. Check Report keys using CSI u
  3. Set Left Option key to Esc+
  4. Set Right Option key to Normal (for special characters)

Terminal.app Setup

Import Profile (easiest):
  1. Locate scripts/macOS/Fresh.terminal in the repository
  2. In Terminal.app, go to SettingsProfiles
  3. Click the gear icon and select Import…
  4. Select the Fresh.terminal file
Manual Configuration:
  1. Settings → Profiles → Keyboard → Check Use Option as Meta key
  2. Add key mappings for Shift+Arrow keys:
    • Shift+Up: \033[1;2A
    • Shift+Down: \033[1;2B
    • Shift+Left: \033[1;2D
    • Shift+Right: \033[1;2C

Mission Control Conflicts

macOS uses Ctrl+Arrow for desktop switching. To use Ctrl+Arrow in Fresh:
  1. Open System SettingsKeyboardKeyboard ShortcutsMission Control
  2. Disable or rebind:
    • “Move left a space” (Ctrl+Left)
    • “Move right a space” (Ctrl+Right)
    • “Mission Control” (Ctrl+Up)
    • “Application windows” (Ctrl+Down)

Keyboard Enhancement Flags

Configure advanced keyboard protocol features:
config.json
{
  "editor": {
    "keyboard_disambiguate_escape_codes": true,
    "keyboard_report_event_types": false,
    "keyboard_report_alternate_keys": true,
    "keyboard_report_all_keys_as_escape_codes": false
  }
}
OptionDefaultDescription
keyboard_disambiguate_escape_codestrueUse CSI-u for unambiguous escape/modifier keys
keyboard_report_event_typesfalseReport key repeat and release events
keyboard_report_alternate_keystrueSend alternate keycodes
keyboard_report_all_keys_as_escape_codesfalseReport all keys as escape sequences
If you experience keyboard issues, try disabling all flags by setting them to false.

Linux: XFCE Window Manager

XFCE captures Ctrl+Alt+Up/Down for workspace switching. To disable:
  1. Open SettingsWindow ManagerKeyboard
  2. Find Upper workspace and Bottom workspace
  3. Click Clear for both shortcuts

Debugging Keyboard Issues

If keybindings aren’t working:
  1. Debug keyboard events: Help → Debug Keyboard Events
  2. See what your terminal sends for each keypress
  3. Adjust keybindings or terminal configuration accordingly
See Troubleshooting: Debug Keyboard Events for details.

Next Steps

Settings Reference

Complete editor configuration options

Theme Configuration

Customize colors and themes

Build docs developers (and LLMs) love