{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Config",
  "description": "Main configuration structure",
  "type": "object",
  "properties": {
    "version": {
      "description": "Configuration version (for migration support)\nConfigs without this field are treated as version 0",
      "type": "integer",
      "format": "uint32",
      "minimum": 0,
      "default": 0
    },
    "theme": {
      "description": "Color theme name",
      "$ref": "#/$defs/ThemeOptions",
      "default": "high-contrast"
    },
    "locale": {
      "description": "UI locale (language) for translations\nIf not set, auto-detected from environment (LC_ALL, LC_MESSAGES, LANG)",
      "$ref": "#/$defs/LocaleOptions",
      "default": null
    },
    "check_for_updates": {
      "description": "Check for new versions on startup (default: true).\nWhen enabled, also sends basic anonymous telemetry (version, OS, terminal type).",
      "type": "boolean",
      "default": true
    },
    "self_update": {
      "description": "Offer an interactive in-editor update when a new version is detected\n(default: true). When on, clicking the status-bar update indicator (or\nthe \"Update fresh\" command) prompts to update now; confirming runs the\nupdate locally in the background and logs to the data dir. When off, the\nindicator is passive (it only tells you a version is available). Has no\neffect if `check_for_updates` is false or the install method can't\nself-update.",
      "type": "boolean",
      "default": true
    },
    "editor": {
      "description": "Editor behavior settings (indentation, line numbers, wrapping, etc.)",
      "$ref": "#/$defs/EditorConfig",
      "default": {
        "animations": true,
        "cursor_jump_animation": true,
        "line_numbers": true,
        "relative_line_numbers": false,
        "highlight_current_line": true,
        "highlight_occurrences": true,
        "hide_current_line_on_selection": false,
        "highlight_current_column": false,
        "line_wrap": true,
        "wrap_indent": true,
        "wrap_column": null,
        "page_width": 80,
        "syntax_highlighting": true,
        "show_menu_bar": true,
        "screensaver_enabled": false,
        "screensaver_idle_minutes": 5,
        "menu_bar_mnemonics": true,
        "show_tab_bar": true,
        "show_status_bar": true,
        "status_bar": {
          "left": [
            "{trust}",
            "{remote}",
            "{terminal_restart}",
            "{cursor}",
            "{diagnostics}",
            "{cursor_count}",
            "{messages}"
          ],
          "right": [
            "{read_only}",
            "{line_ending}",
            "{encoding}",
            "{language}",
            "{lsp}",
            "{warnings}",
            "{update}",
            "{palette}"
          ],
          "separator": ""
        },
        "show_prompt_line": false,
        "show_vertical_scrollbar": true,
        "show_horizontal_scrollbar": false,
        "show_tilde": true,
        "nerd_font_icons": false,
        "use_terminal_bg": false,
        "set_window_title": true,
        "terminal_auto_title": true,
        "cursor_style": "default",
        "rulers": [],
        "indentation_guide": "none",
        "indentation_guide_glyph": "▏",
        "rainbow_indentation": false,
        "whitespace_show": true,
        "whitespace_spaces_leading": false,
        "whitespace_spaces_inner": false,
        "whitespace_spaces_trailing": false,
        "whitespace_tabs_leading": true,
        "whitespace_tabs_inner": true,
        "whitespace_tabs_trailing": true,
        "whitespace_newlines": false,
        "whitespace_carriage_returns": false,
        "use_tabs": false,
        "tab_size": 4,
        "auto_indent": true,
        "auto_close": true,
        "auto_surround": true,
        "virtual_space": "off",
        "scroll_offset": 3,
        "default_line_ending": "lf",
        "trim_trailing_whitespace_on_save": false,
        "ensure_final_newline_on_save": false,
        "auto_read_only": true,
        "highlight_matching_brackets": true,
        "rainbow_brackets": true,
        "completion_popup_auto_show": false,
        "quick_suggestions": true,
        "quick_suggestions_delay_ms": 150,
        "suggest_on_trigger_characters": true,
        "enable_inlay_hints": true,
        "enable_semantic_tokens_full": false,
        "diagnostics_inline_text": false,
        "mouse_hover_enabled": true,
        "mouse_hover_delay_ms": 500,
        "double_click_time_ms": 500,
        "auto_save_enabled": false,
        "auto_save_interval_secs": 30,
        "hot_exit": true,
        "confirm_quit": false,
        "restore_previous_session": true,
        "skip_session_restore_when_files_passed": true,
        "auto_create_empty_buffer_on_last_buffer_close": true,
        "recovery_enabled": true,
        "auto_recovery_save_interval_secs": 2,
        "auto_revert_poll_interval_ms": 2000,
        "keyboard_disambiguate_escape_codes": true,
        "keyboard_report_event_types": false,
        "keyboard_report_alternate_keys": true,
        "keyboard_report_all_keys_as_escape_codes": false,
        "snapshot_interval": 100,
        "highlight_context_bytes": 10000,
        "large_file_threshold_bytes": 10485760,
        "estimated_line_length": 80,
        "read_concurrency": 64,
        "file_tree_poll_interval_ms": 3000
      }
    },
    "file_explorer": {
      "description": "File explorer panel settings",
      "$ref": "#/$defs/FileExplorerConfig",
      "default": {
        "respect_gitignore": true,
        "show_hidden": false,
        "show_gitignored": false,
        "custom_ignore_patterns": [],
        "width": "30%",
        "preview_tabs": true,
        "side": "left",
        "auto_open_on_last_buffer_close": true,
        "follow_active_buffer": false,
        "compact_directories": true,
        "tree_indicator_collapsed": ">",
        "tree_indicator_expanded": "▼"
      }
    },
    "file_browser": {
      "description": "File browser settings (Open File dialog)",
      "$ref": "#/$defs/FileBrowserConfig",
      "default": {
        "show_hidden": false
      }
    },
    "clipboard": {
      "description": "Clipboard settings (which clipboard methods to use)",
      "$ref": "#/$defs/ClipboardConfig",
      "default": {
        "use_osc52": true,
        "use_system_clipboard": true
      }
    },
    "terminal": {
      "description": "Terminal settings",
      "$ref": "#/$defs/TerminalConfig",
      "default": {
        "jump_to_end_on_output": true,
        "shell": null,
        "skip_app_execution_alias": true,
        "resume_agents": true,
        "mouse_drag_selects": true,
        "mouse_forwarding": "requested"
      }
    },
    "keybindings": {
      "description": "Custom keybindings (overrides for the active map)",
      "type": "array",
      "items": {
        "$ref": "#/$defs/Keybinding"
      },
      "default": []
    },
    "keybinding_maps": {
      "description": "Named keybinding maps (user can define custom maps here)\nEach map can optionally inherit from another map",
      "type": "object",
      "additionalProperties": {
        "$ref": "#/$defs/KeymapConfig"
      },
      "default": {}
    },
    "active_keybinding_map": {
      "description": "Active keybinding map name",
      "$ref": "#/$defs/KeybindingMapOptions",
      "default": "default"
    },
    "languages": {
      "description": "Per-language configuration overrides (tab size, formatters, etc.)",
      "type": "object",
      "additionalProperties": {
        "$ref": "#/$defs/LanguageConfig"
      },
      "default": {}
    },
    "default_language": {
      "description": "Default language for files whose type cannot be detected.\nMust reference a key in the `languages` map (e.g., \"bash\").\nApplied when no extension, filename, glob, or built-in detection matches.\nThe referenced language's full configuration (grammar, comment_prefix,\ntab_size, etc.) is used for unrecognized files.",
      "type": [
        "string",
        "null"
      ],
      "default": null,
      "x-enum-from": "/languages"
    },
    "lsp_enabled": {
      "description": "Master switch for LSP support. When false, no language server is\nstarted automatically for any language (per-language and universal\nservers alike), without having to disable each server individually.\nServers can still be started manually, e.g. via the command palette's\n\"Start/Restart LSP Server\".",
      "type": "boolean",
      "default": true
    },
    "lsp": {
      "description": "LSP server configurations by language.\nEach language maps to one or more server configs (multi-LSP support).\nAccepts both single-object and array forms for backwards compatibility.",
      "type": "object",
      "additionalProperties": {
        "$ref": "#/$defs/LspLanguageConfig"
      },
      "default": {}
    },
    "universal_lsp": {
      "description": "Universal LSP servers that apply to all languages.\nThese servers run alongside language-specific LSP servers defined in `lsp`.\nKeyed by a unique server name (e.g. \"quicklsp\").",
      "type": "object",
      "additionalProperties": {
        "$ref": "#/$defs/LspLanguageConfig"
      },
      "default": {}
    },
    "warnings": {
      "description": "Warning notification settings",
      "$ref": "#/$defs/WarningsConfig",
      "default": {
        "show_status_indicator": true
      }
    },
    "plugins": {
      "description": "Plugin configurations by plugin name\nPlugins are auto-discovered from the plugins directory.\nUse this to enable/disable specific plugins.",
      "type": "object",
      "additionalProperties": {
        "$ref": "#/$defs/PluginConfig"
      },
      "default": {},
      "x-standalone-category": true,
      "x-no-add": true
    },
    "packages": {
      "description": "Package manager settings for plugin/theme installation",
      "$ref": "#/$defs/PackagesConfig",
      "default": {
        "sources": [
          "https://github.com/sinelaw/fresh-plugins-registry"
        ]
      }
    },
    "env": {
      "description": "Environment auto-activation detectors (venv / direnv / mise / …).",
      "$ref": "#/$defs/EnvConfig",
      "default": {
        "detectors": [
          {
            "name": ".venv",
            "markers": [
              ".venv"
            ],
            "kind": "path-only",
            "snippet": "source .venv/bin/activate",
            "require": [
              ".venv/bin/python",
              ".venv/bin/python3",
              ".venv/Scripts/python.exe"
            ]
          },
          {
            "name": "venv",
            "markers": [
              "venv"
            ],
            "kind": "path-only",
            "snippet": "source venv/bin/activate",
            "require": [
              "venv/bin/python",
              "venv/bin/python3",
              "venv/Scripts/python.exe"
            ]
          },
          {
            "name": "direnv",
            "markers": [
              ".envrc"
            ],
            "kind": "shell",
            "snippet": "eval \"$(direnv export bash)\"",
            "require": []
          },
          {
            "name": "mise",
            "markers": [
              "mise.toml",
              ".mise.toml",
              ".tool-versions"
            ],
            "kind": "shell",
            "snippet": "eval \"$(mise env -s bash)\"",
            "require": []
          },
          {
            "name": "pipenv",
            "markers": [
              "Pipfile"
            ],
            "kind": "shell",
            "snippet": "source \"$(pipenv --venv)/bin/activate\"",
            "require": []
          },
          {
            "name": "poetry",
            "markers": [
              "poetry.lock"
            ],
            "kind": "shell",
            "snippet": "source \"$(poetry env info --path)/bin/activate\"",
            "require": []
          }
        ]
      }
    }
  },
  "$defs": {
    "ThemeOptions": {
      "description": "Available color themes",
      "type": "string",
      "x-enum-from": "$themes"
    },
    "LocaleOptions": {
      "description": "UI locale (language). Use null for auto-detection from environment.",
      "enum": [
        null,
        "cs",
        "de",
        "en",
        "es",
        "fr",
        "it",
        "ja",
        "ko",
        "pt-BR",
        "ru",
        "th",
        "uk",
        "vi",
        "zh-CN"
      ]
    },
    "EditorConfig": {
      "description": "Editor behavior configuration",
      "type": "object",
      "properties": {
        "animations": {
          "description": "Enable frame-buffer animations (tab-switch slides, dashboard\nbringup, plugin-driven effects). When `false`, every animation\ncall is a no-op: the UI is fully static and each render lands\nthe final frame immediately. Useful on slow terminals, over\nSSH, or for users who prefer no motion.",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "cursor_jump_animation": {
          "description": "Enable the cursor-jump trail animation on long cursor moves\n(search jumps, go-to-definition, pane switches). Has no effect\nwhen `animations` is `false`.",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "line_numbers": {
          "description": "Show line numbers in the gutter (default for new buffers)",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "relative_line_numbers": {
          "description": "Show line numbers relative to cursor position",
          "type": "boolean",
          "default": false,
          "x-section": "Display"
        },
        "highlight_current_line": {
          "description": "Highlight the line containing the cursor",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "highlight_occurrences": {
          "description": "Highlight all occurrences of the word under the cursor",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "hide_current_line_on_selection": {
          "description": "Hide the current-line background highlight whenever a selection is\nvisible.  When `true` (default: `false`), the `current_line_bg` fill\nis suppressed for the active split as soon as any cursor has a\nnon-empty selection, reducing visual clutter while text is selected.",
          "type": "boolean",
          "default": false,
          "x-section": "Display"
        },
        "highlight_current_column": {
          "description": "Highlight the column containing the cursor",
          "type": "boolean",
          "default": false,
          "x-section": "Display"
        },
        "line_wrap": {
          "description": "Wrap long lines to fit the window width (default for new views)",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "wrap_indent": {
          "description": "Indent wrapped continuation lines to match the leading whitespace of the original line",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "wrap_column": {
          "description": "Column at which to wrap lines when line wrapping is enabled.\nIf not specified (`null`), lines wrap at the viewport edge (default behavior).\nA value of `0` is treated the same as `null` (no fixed wrap column).\nExample: `80` wraps at column 80. The actual wrap column is clamped to the\nviewport width (lines can't wrap beyond the visible area).",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0,
          "default": null,
          "x-section": "Display"
        },
        "page_width": {
          "description": "Width of the page in page view mode (in columns).\nControls the content width when page view is active, with centering margins.\nDefaults to 80. Set to `null` (or `0`) to use the full viewport width.",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0,
          "default": 80,
          "x-section": "Display"
        },
        "syntax_highlighting": {
          "description": "Enable syntax highlighting for code files",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "show_menu_bar": {
          "description": "Whether the menu bar is visible by default.\nThe menu bar provides access to menus (File, Edit, View, etc.) at the top of the screen.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "screensaver_enabled": {
          "description": "Enable the wave-animation screensaver. When the editor has been\nidle (no key or mouse input) for `screensaver_idle_minutes`, a\ndecorative wave washes over the screen until you press a key or\nmove the mouse.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Display"
        },
        "screensaver_idle_minutes": {
          "description": "Minutes of inactivity before the wave-animation screensaver starts\n(only when `screensaver_enabled`). A value of `0` disables it.\nDefault: 5",
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 5,
          "x-section": "Display"
        },
        "menu_bar_mnemonics": {
          "description": "Whether menu bar mnemonics (Alt+letter shortcuts) are enabled.\nWhen enabled, pressing Alt+F opens the File menu, Alt+E opens Edit, etc.\nDisabling this frees up Alt+letter keybindings for other actions.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "show_tab_bar": {
          "description": "Whether the tab bar is visible by default.\nThe tab bar shows open files in each split pane.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "show_status_bar": {
          "description": "Whether the status bar is visible by default.\nThe status bar shows file info, cursor position, and editor status at the bottom of the screen.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "status_bar": {
          "description": "Status bar layout and element configuration.\nControls which elements appear in the status bar and how they are arranged.",
          "$ref": "#/$defs/StatusBarConfig",
          "default": {
            "left": [
              "{trust}",
              "{remote}",
              "{terminal_restart}",
              "{cursor}",
              "{diagnostics}",
              "{cursor_count}",
              "{messages}"
            ],
            "right": [
              "{read_only}",
              "{line_ending}",
              "{encoding}",
              "{language}",
              "{lsp}",
              "{warnings}",
              "{update}",
              "{palette}"
            ],
            "separator": ""
          },
          "x-section": "Status Bar"
        },
        "show_prompt_line": {
          "description": "Whether the prompt line is always visible.\nThe prompt line is the bottom-most line used for search, file open, and other prompts.\nWhen `false` (the default), the prompt line auto-hides — it only appears\nwhile a prompt is active and disappears again once the prompt closes.\nWhen `true`, the prompt line is always reserved at the bottom of the screen.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Display"
        },
        "show_vertical_scrollbar": {
          "description": "Whether the vertical scrollbar is visible in each split pane.\nCan be toggled at runtime via command palette or keybinding.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "show_horizontal_scrollbar": {
          "description": "Whether the horizontal scrollbar is visible in each split pane.\nThe horizontal scrollbar appears when line wrap is disabled and content extends beyond the viewport.\nCan be toggled at runtime via command palette or keybinding.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Display"
        },
        "show_tilde": {
          "description": "Show tilde (~) markers on lines after the end of the file.\nThese vim-style markers indicate lines that are not part of the file content.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "nerd_font_icons": {
          "description": "Use Nerd Font icons for decorative UI glyphs (e.g. the settings\ncategory icons). Nerd Font glyphs live in the Unicode private-use\narea and only render correctly when the terminal uses a patched\n\"Nerd Font\"; on any other font they show up as `?` or empty boxes.\nWhen disabled, standard Unicode symbols (covered by normal\nterminal font fallback) are used instead.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Display"
        },
        "use_terminal_bg": {
          "description": "Use the terminal's default background color instead of the theme's editor background.\nWhen enabled, the editor background inherits from the terminal emulator,\nallowing transparency or custom terminal backgrounds to show through.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Display"
        },
        "set_window_title": {
          "description": "Update the terminal window title (via OSC 2) to reflect the active buffer.\nWhen enabled, Fresh sets the terminal/tab title to \"<file> — Fresh\" as\nyou switch buffers. Harmless on terminals that don't understand the\nescape sequence — they silently ignore it.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "terminal_auto_title": {
          "description": "Auto-name terminal tabs after the running program (tmux-style). When\nenabled, an integrated terminal's tab reflects its foreground process\n(e.g. `python3`, `vim`) combined with any title the program set via\nan OSC escape sequence, instead of the static `*Terminal N*` label.\nDisable to keep the fixed `*Terminal N*` names.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Display"
        },
        "cursor_style": {
          "description": "Cursor style for the terminal cursor.\nOptions: blinking_block, steady_block, blinking_bar, steady_bar, blinking_underline, steady_underline\nDefault: blinking_block",
          "$ref": "#/$defs/CursorStyle",
          "default": "default",
          "x-section": "Display"
        },
        "rulers": {
          "description": "Vertical ruler lines at specific column positions.\nDraws subtle vertical lines to help with line length conventions.\nExample: [80, 120] draws rulers at columns 80 and 120.\nDefault: [] (no rulers)",
          "type": "array",
          "items": {
            "type": "integer",
            "format": "uint",
            "minimum": 0
          },
          "default": [],
          "x-section": "Display"
        },
        "indentation_guide": {
          "description": "Vertical indentation guide rendering mode.\nGuides are drawn at indentation levels derived from the active buffer's\ntab size. They replace existing leading whitespace cells visually only;\nbuffer text, cursor positions, and mouse mappings are unchanged.\nModes:\n- `none`: disable indentation guides.\n- `all`: draw every indentation level in leading whitespace.\n- `active`: draw only the innermost guide for the cursor's current\n  indentation block.\n\nDefault: none",
          "$ref": "#/$defs/IndentationGuideMode",
          "default": "none",
          "x-section": "Display"
        },
        "indentation_guide_glyph": {
          "description": "Glyph used to draw indentation guides. The default is a left-aligned\nvertical guide character. Leading/trailing whitespace is ignored, and\nblank values reset to the default glyph. Use a single display-cell glyph\nfor stable layout.\nDefault: ▏",
          "type": "string",
          "default": "▏",
          "x-section": "Display"
        },
        "rainbow_indentation": {
          "description": "Color indentation guides by indent level, using the active theme's\n`indent_rainbow_1` through `indent_rainbow_6` colors.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Display"
        },
        "whitespace_show": {
          "description": "Master toggle for whitespace indicator visibility.\nWhen disabled, no whitespace indicators (·, →) are shown regardless\nof the per-position settings below.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Whitespace"
        },
        "whitespace_spaces_leading": {
          "description": "Show space indicators (·) for leading whitespace (indentation).\nLeading whitespace is everything before the first non-space character on a line.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Whitespace"
        },
        "whitespace_spaces_inner": {
          "description": "Show space indicators (·) for inner whitespace (between words/tokens).\nInner whitespace is spaces between the first and last non-space characters.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Whitespace"
        },
        "whitespace_spaces_trailing": {
          "description": "Show space indicators (·) for trailing whitespace.\nTrailing whitespace is everything after the last non-space character on a line.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Whitespace"
        },
        "whitespace_tabs_leading": {
          "description": "Show tab indicators (→) for leading tabs (indentation).\nCan be overridden per-language via `show_whitespace_tabs` in language config.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Whitespace"
        },
        "whitespace_tabs_inner": {
          "description": "Show tab indicators (→) for inner tabs (between words/tokens).\nCan be overridden per-language via `show_whitespace_tabs` in language config.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Whitespace"
        },
        "whitespace_tabs_trailing": {
          "description": "Show tab indicators (→) for trailing tabs.\nCan be overridden per-language via `show_whitespace_tabs` in language config.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Whitespace"
        },
        "whitespace_newlines": {
          "description": "Show newline indicators (↵) at the end of every line.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Whitespace"
        },
        "whitespace_carriage_returns": {
          "description": "Show carriage-return indicators (␍) for the CR half of CRLF line\nendings, next to the newline position. Stray CR bytes that are not\npart of the buffer's line ending always render as `<0D>` escapes.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Whitespace"
        },
        "use_tabs": {
          "description": "Whether pressing Tab inserts a tab character instead of spaces.\nThis is the global default; individual languages can override it\nvia their own `use_tabs` setting.\nDefault: false (insert spaces)",
          "type": "boolean",
          "default": false,
          "x-section": "Editing"
        },
        "tab_size": {
          "description": "Number of spaces per tab character\nA value of `0` is treated as unset and falls back to the default (4).",
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 4,
          "x-section": "Editing"
        },
        "auto_indent": {
          "description": "Automatically indent new lines based on the previous line",
          "type": "boolean",
          "default": true,
          "x-section": "Editing"
        },
        "auto_close": {
          "description": "Automatically close brackets, parentheses, and quotes when typing.\nWhen enabled, typing an opening delimiter like `(`, `[`, `{`, `\"`, `'`, or `` ` ``\nwill automatically insert the matching closing delimiter.\nAlso enables skip-over (moving past existing closing delimiters) and\npair deletion (deleting both delimiters when backspacing between them).\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Editing"
        },
        "auto_surround": {
          "description": "Automatically surround selected text with matching pairs when typing\nan opening delimiter. When enabled and text is selected, typing `(`, `[`,\n`{`, `\"`, `'`, or `` ` `` wraps the selection instead of replacing it.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Editing"
        },
        "virtual_space": {
          "description": "Allow the cursor to move beyond the end of a line (virtual space).\n\"off\": cursor is clamped to line content. \"block\": only block\n(rectangular) selections extend past line ends, producing true\nrectangles. \"on\": arrow keys, clicks, and block selections may all\nplace the cursor past the end of a line; typing there fills the gap\nwith spaces.\nDefault: \"off\"",
          "$ref": "#/$defs/VirtualSpaceMode",
          "default": "off",
          "x-section": "Editing"
        },
        "scroll_offset": {
          "description": "Minimum lines to keep visible above/below cursor when scrolling",
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 3,
          "x-section": "Editing"
        },
        "default_line_ending": {
          "description": "Default line ending format for new files.\nFiles loaded from disk will use their detected line ending format.\nOptions: \"lf\" (Unix/Linux/macOS), \"crlf\" (Windows), \"cr\" (Classic Mac)\nDefault: \"lf\"",
          "$ref": "#/$defs/LineEndingOption",
          "default": "lf",
          "x-section": "Editing"
        },
        "trim_trailing_whitespace_on_save": {
          "description": "Remove trailing whitespace from lines when saving.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Editing"
        },
        "ensure_final_newline_on_save": {
          "description": "Ensure files end with a newline when saving.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Editing"
        },
        "auto_read_only": {
          "description": "Automatically open files in read-only mode when they are not\nwritable on disk (filesystem permissions) or live in a\nlibrary/vendor directory (rustup toolchains, node_modules,\n/usr/include, /nix/store, ...). When disabled, such files open\neditable; saving may still fail unless permissions allow it.\nBinary files always open read-only regardless of this setting.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Editing"
        },
        "highlight_matching_brackets": {
          "description": "Highlight matching bracket pairs when cursor is on a bracket.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Bracket Matching"
        },
        "rainbow_brackets": {
          "description": "Use rainbow colors for nested brackets based on nesting depth.\nRequires highlight_matching_brackets to be enabled.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Bracket Matching"
        },
        "completion_popup_auto_show": {
          "description": "Automatically show the completion popup while typing.\nWhen false (default), the popup only appears when explicitly invoked\n(e.g. via Ctrl+Space). When true, it appears automatically after a\nshort delay while typing.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Completion"
        },
        "quick_suggestions": {
          "description": "Enable quick suggestions (VS Code-like behavior).\nWhen enabled, completion suggestions appear automatically while typing,\nnot just on trigger characters (like `.` or `::`).\nOnly takes effect when completion_popup_auto_show is true.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Completion"
        },
        "quick_suggestions_delay_ms": {
          "description": "Delay in milliseconds before showing completion suggestions.\nLower values (10-50ms) feel more responsive but may be distracting.\nHigher values (100-500ms) reduce noise while typing.\nTrigger characters (like `.`) bypass this delay.\nDefault: 150",
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 150,
          "x-section": "Completion"
        },
        "suggest_on_trigger_characters": {
          "description": "Whether trigger characters (like `.`, `::`, `->`) immediately show completions.\nWhen true, typing a trigger character bypasses quick_suggestions_delay_ms.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Completion"
        },
        "enable_inlay_hints": {
          "description": "Whether to enable LSP inlay hints (type hints, parameter hints, etc.)",
          "type": "boolean",
          "default": true,
          "x-section": "LSP"
        },
        "enable_semantic_tokens_full": {
          "description": "Whether to request full-document LSP semantic tokens.\nRange requests are still used when supported.\nDefault: false (range-only to avoid heavy full refreshes).",
          "type": "boolean",
          "default": false,
          "x-section": "LSP"
        },
        "diagnostics_inline_text": {
          "description": "Whether to show inline diagnostic text at the end of lines with errors/warnings.\nWhen enabled, the highest-severity diagnostic message is rendered after the\nsource code on each affected line.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Diagnostics"
        },
        "mouse_hover_enabled": {
          "description": "Whether mouse hover triggers LSP hover requests.\nWhen enabled, hovering over code with the mouse will show documentation.\nOn Windows, this also controls the mouse tracking mode: when disabled,\nthe editor uses xterm mode 1002 (cell motion — click, drag, release only);\nwhen enabled, it uses mode 1003 (all motion — full mouse movement tracking).\nMode 1003 generates high event volume on Windows and may cause input\ncorruption on some systems. On macOS and Linux this setting only controls\nLSP hover; the mouse tracking mode is always full motion.\nDefault: true (macOS/Linux), false (Windows)",
          "type": "boolean",
          "default": true,
          "x-section": "Mouse"
        },
        "mouse_hover_delay_ms": {
          "description": "Delay in milliseconds before a mouse hover triggers an LSP hover request.\nLower values show hover info faster but may cause more LSP server load.\nDefault: 500ms",
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 500,
          "x-section": "Mouse"
        },
        "double_click_time_ms": {
          "description": "Time window in milliseconds for detecting double-clicks.\nTwo clicks within this time are treated as a double-click (word selection).\nDefault: 500ms",
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 500,
          "x-section": "Mouse"
        },
        "auto_save_enabled": {
          "description": "Whether to enable persistent auto-save (save to original file on disk).\nWhen enabled, modified buffers are saved to their original file path\nat a configurable interval.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Recovery"
        },
        "auto_save_interval_secs": {
          "description": "Interval in seconds for persistent auto-save.\nModified buffers are saved to their original file at this interval.\nOnly effective when auto_save_enabled is true.\nDefault: 30 seconds",
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 30,
          "x-section": "Recovery"
        },
        "hot_exit": {
          "description": "Whether to preserve unsaved changes in all buffers (file-backed and\nunnamed) across editor sessions (VS Code \"hot exit\" behavior).\nWhen enabled, modified buffers are backed up on clean exit and their\nunsaved changes are restored on next startup.  Unnamed (scratch)\nbuffers are also persisted (Sublime Text / Notepad++ behavior).\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Recovery"
        },
        "confirm_quit": {
          "description": "Whether to confirm before quitting Fresh. When enabled, pressing\nthe quit shortcut surfaces a confirmation prompt even when no\nbuffers are modified. Useful for users who frequently hit\n`Ctrl+Q` by mistake. Independent of the unsaved-changes prompt,\nwhich always fires regardless of this setting.\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Startup"
        },
        "restore_previous_session": {
          "description": "Whether to auto-open previously opened files (session restore) when\nstarting Fresh in a directory.  When enabled (the default), tabs,\nsplits, cursor positions and the file explorer state are restored\nfrom the last clean exit in the same working directory.  When\ndisabled, Fresh starts with a clean workspace.  The workspace file\non disk is still written on exit, so re-enabling this setting picks\nup whatever state was saved at the most recent clean exit.  The\n`--no-restore` CLI flag is a stronger override: it skips both\nrestoring and saving the workspace.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Startup"
        },
        "skip_session_restore_when_files_passed": {
          "description": "When Fresh is launched with one or more file arguments (e.g.\n`fresh src/main.rs README.md`), skip the workspace session restore\nand open only the files passed on the command line. Hot-exit\ncontent (unsaved modified files and unnamed `[No Name]` buffers\nwith content) is still restored so in-progress work is never lost.\nPure-directory invocations (`fresh some/dir`) and bare invocations\n(`fresh` with no args) still restore the previous session normally.\nDisable this option to keep the legacy behavior of always\nrestoring the previous session even when files are passed.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Startup"
        },
        "auto_create_empty_buffer_on_last_buffer_close": {
          "description": "Whether to auto-create a fresh empty `[No Name]` buffer when the\nlast open buffer is closed. When `false`, the editor still creates\nan internal placeholder buffer (it always needs at least one) but\nhides it from the tab bar so the workspace looks blank. Combined\nwith `file_explorer.auto_open_on_last_buffer_close = false`, this\ngives a fully blank workspace where nothing opens automatically.\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Startup"
        },
        "recovery_enabled": {
          "description": "Whether to enable file recovery (Emacs-style auto-save)\nWhen enabled, buffers are periodically saved to recovery files\nso they can be recovered if the editor crashes.",
          "type": "boolean",
          "default": true,
          "x-section": "Recovery"
        },
        "auto_recovery_save_interval_secs": {
          "description": "Interval in seconds for auto-recovery-save.\nModified buffers are saved to recovery files at this interval.\nOnly effective when recovery_enabled is true.\nDefault: 2 seconds",
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 2,
          "x-section": "Recovery"
        },
        "auto_revert_poll_interval_ms": {
          "description": "Poll interval in milliseconds for auto-reverting open buffers.\nWhen auto-revert is enabled, file modification times are checked at this interval.\nLower values detect external changes faster but use more CPU.\nDefault: 2000ms (2 seconds)",
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 2000,
          "x-section": "Recovery"
        },
        "keyboard_disambiguate_escape_codes": {
          "description": "Enable keyboard enhancement: disambiguate escape codes using CSI-u sequences.\nThis allows unambiguous reading of Escape and modified keys.\nRequires terminal support (kitty keyboard protocol).\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Keyboard"
        },
        "keyboard_report_event_types": {
          "description": "Enable keyboard enhancement: report key event types (repeat/release).\nAdds extra events when keys are autorepeated or released.\nRequires terminal support (kitty keyboard protocol).\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Keyboard"
        },
        "keyboard_report_alternate_keys": {
          "description": "Enable keyboard enhancement: report alternate keycodes.\nSends alternate keycodes in addition to the base keycode.\nRequires terminal support (kitty keyboard protocol).\nDefault: true",
          "type": "boolean",
          "default": true,
          "x-section": "Keyboard"
        },
        "keyboard_report_all_keys_as_escape_codes": {
          "description": "Enable keyboard enhancement: report all keys as escape codes.\nRepresents all keyboard events as CSI-u sequences.\nRequired for repeat/release events on plain-text keys.\nRequires terminal support (kitty keyboard protocol).\nDefault: false",
          "type": "boolean",
          "default": false,
          "x-section": "Keyboard"
        },
        "snapshot_interval": {
          "description": "Undo history snapshot interval (number of edits between snapshots)",
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 100,
          "x-section": "Performance"
        },
        "highlight_context_bytes": {
          "description": "Number of bytes to look back/forward from the viewport for syntax highlighting context.\nLarger values improve accuracy for multi-line constructs (strings, comments, nested blocks)\nbut may slow down highlighting for very large files.\nDefault: 10KB (10000 bytes)",
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 10000,
          "x-section": "Performance"
        },
        "large_file_threshold_bytes": {
          "description": "File size threshold in bytes for \"large file\" behavior\nFiles larger than this will:\n- Skip LSP features\n- Use constant-size scrollbar thumb (1 char)\n\nFiles smaller will count actual lines for accurate scrollbar rendering",
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 10485760,
          "x-section": "Performance"
        },
        "estimated_line_length": {
          "description": "Estimated average line length in bytes (used for large file line estimation)\nThis is used by LineIterator to estimate line positions in large files\nwithout line metadata. Typical values: 80-120 bytes.",
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 80,
          "x-section": "Performance"
        },
        "read_concurrency": {
          "description": "Maximum number of concurrent filesystem read requests.\nUsed during line-feed scanning and other bulk I/O operations.\nHigher values improve throughput, especially for remote filesystems.\nDefault: 64",
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 64,
          "x-section": "Performance"
        },
        "file_tree_poll_interval_ms": {
          "description": "Poll interval in milliseconds for refreshing expanded directories in the file explorer.\nDirectory modification times are checked at this interval to detect new/deleted files.\nLower values detect changes faster but use more CPU.\nDefault: 3000ms (3 seconds)",
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 3000,
          "x-section": "Performance"
        }
      }
    },
    "StatusBarConfig": {
      "description": "Status bar layout and element configuration.\n\nControls which elements appear in the status bar and how they are arranged.\nElements are placed in left and right containers and can be freely reordered.\n\nExample config:\n```json\n{\n  \"status_bar\": {\n    \"left\": [\"{filename}\", \"{cursor:compact}\"],\n    \"right\": [\"{language}\", \"{encoding}\", \"{line_ending}\"]\n  }\n}\n```",
      "type": "object",
      "properties": {
        "left": {
          "description": "Elements shown on the left side of the status bar.\nDefault: [\"{filename}\", \"{cursor}\", \"{diagnostics}\", \"{cursor_count}\", \"{messages}\"]",
          "type": "array",
          "items": {
            "$ref": "#/$defs/StatusBarElement"
          },
          "default": [
            "{trust}",
            "{remote}",
            "{terminal_restart}",
            "{cursor}",
            "{diagnostics}",
            "{cursor_count}",
            "{messages}"
          ],
          "x-section": "Status Bar",
          "x-dual-list-sibling": "/editor/status_bar/right",
          "x-dynamically-extendable-status-bar-elements": true
        },
        "right": {
          "description": "Elements shown on the right side of the status bar.\nDefault: [\"{read_only}\", \"{line_ending}\", \"{encoding}\", \"{language}\", \"{lsp}\", \"{warnings}\", \"{update}\", \"{palette}\"]",
          "type": "array",
          "items": {
            "$ref": "#/$defs/StatusBarElement"
          },
          "default": [
            "{read_only}",
            "{line_ending}",
            "{encoding}",
            "{language}",
            "{lsp}",
            "{warnings}",
            "{update}",
            "{palette}"
          ],
          "x-section": "Status Bar",
          "x-dual-list-sibling": "/editor/status_bar/left",
          "x-dynamically-extendable-status-bar-elements": true
        },
        "separator": {
          "description": "Separator drawn between status bar elements on both sides, used\nverbatim. Each entry already carries a one-space margin painted in its\nown style, so the default bare `\"|\"` renders as `LF | UTF-8`. Add your\nown surrounding spaces to widen the gap. An empty string disables the\nseparator glyph entirely, leaving just the entries' own margins.",
          "type": "string",
          "default": "",
          "x-section": "Status Bar"
        }
      }
    },
    "StatusBarElement": {
      "type": "string",
      "x-dual-list-options": [
        {
          "value": "{filename}",
          "name": "Filename"
        },
        {
          "value": "{read_only}",
          "name": "Read-Only"
        },
        {
          "value": "{cursor}",
          "name": "Cursor"
        },
        {
          "value": "{cursor:compact}",
          "name": "Cursor (compact)"
        },
        {
          "value": "{diagnostics}",
          "name": "Diagnostics"
        },
        {
          "value": "{cursor_count}",
          "name": "Cursor Count"
        },
        {
          "value": "{messages}",
          "name": "Messages"
        },
        {
          "value": "{chord}",
          "name": "Chord"
        },
        {
          "value": "{line_ending}",
          "name": "Line Ending"
        },
        {
          "value": "{encoding}",
          "name": "Encoding"
        },
        {
          "value": "{language}",
          "name": "Language"
        },
        {
          "value": "{lsp}",
          "name": "LSP"
        },
        {
          "value": "{warnings}",
          "name": "Warnings"
        },
        {
          "value": "{update}",
          "name": "Update"
        },
        {
          "value": "{terminal_restart}",
          "name": "Terminal Restart"
        },
        {
          "value": "{palette}",
          "name": "Palette"
        },
        {
          "value": "{clock}",
          "name": "Clock"
        },
        {
          "value": "{remote}",
          "name": "Remote Indicator"
        },
        {
          "value": "{trust}",
          "name": "Workspace Trust"
        }
      ]
    },
    "CursorStyle": {
      "description": "Terminal cursor style",
      "type": "string",
      "enum": [
        "default",
        "blinking_block",
        "steady_block",
        "blinking_bar",
        "steady_bar",
        "blinking_underline",
        "steady_underline"
      ]
    },
    "IndentationGuideMode": {
      "description": "Indentation guide rendering mode.",
      "type": "string",
      "enum": [
        "none",
        "all",
        "active"
      ],
      "default": "none"
    },
    "VirtualSpaceMode": {
      "description": "Where the cursor may move beyond the end of a line",
      "type": "string",
      "enum": [
        "off",
        "block",
        "on"
      ],
      "default": "off"
    },
    "LineEndingOption": {
      "description": "Default line ending format for new files",
      "type": "string",
      "enum": [
        "lf",
        "crlf",
        "cr"
      ],
      "default": "lf"
    },
    "FileExplorerConfig": {
      "description": "File explorer configuration",
      "type": "object",
      "properties": {
        "respect_gitignore": {
          "description": "Whether `.gitignore` rules apply in the file explorer at all.\nWhen disabled, ignored entries are neither hidden nor grayed out and\nthe \"show gitignored files\" toggle below has nothing left to hide.\nDefault: true",
          "type": "boolean",
          "default": true
        },
        "show_hidden": {
          "description": "Whether to show hidden files (starting with .) by default",
          "type": "boolean",
          "default": false
        },
        "show_gitignored": {
          "description": "Whether to show gitignored files by default",
          "type": "boolean",
          "default": false
        },
        "custom_ignore_patterns": {
          "description": "Custom patterns to ignore (in addition to .gitignore)",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        },
        "width": {
          "description": "File explorer width. Either a percent (`\"30%\"`, 0–100) or an\nabsolute column count (`\"24\"`). Legacy numeric forms are still\naccepted on read: a bare integer is treated as percent, and a\nfractional number in `[0, 1]` is treated as a legacy percent\nfraction (e.g. `0.3` → 30%).",
          "$ref": "#/$defs/ExplorerWidth",
          "default": "30%"
        },
        "preview_tabs": {
          "description": "Open files in a \"preview\" (ephemeral) tab on single-click in the\nfile explorer. The preview tab is replaced by the next single-click\ninstead of accumulating tabs. Editing the file, double-clicking\n(or pressing Enter) on it in the explorer, or dragging its tab\npromotes the tab to a permanent tab.\nDefault: true",
          "type": "boolean",
          "default": true
        },
        "side": {
          "description": "Which side of the screen to show the file explorer on.\nDefault: left",
          "$ref": "#/$defs/FileExplorerSide",
          "default": "left"
        },
        "auto_open_on_last_buffer_close": {
          "description": "Automatically focus the file explorer when the last buffer is\nclosed. Set to `false` for a \"blank workspace\" workflow where\nnothing opens automatically and the user explicitly invokes the\nfile explorer (e.g. via keybinding or command palette).\nDefault: true",
          "type": "boolean",
          "default": true
        },
        "follow_active_buffer": {
          "description": "When the file explorer sidebar is open, automatically expand the\ntree and highlight the file that corresponds to the active buffer\nwhenever you switch tabs. Set to `true` to keep the explorer\nselection in sync with the active tab.\nDefault: false",
          "type": "boolean",
          "default": false
        },
        "compact_directories": {
          "description": "Render single-child directory chains on a single line, e.g.\n`src/main/java/com/example`. Only applies when each intermediate\ndirectory in the chain is expanded and has exactly one visible\nchild that is itself a directory. Mirrors VSCode's\n`explorer.compactFolders`.\nDefault: true",
          "type": "boolean",
          "default": true
        },
        "tree_indicator_collapsed": {
          "description": "Symbol shown next to a collapsed (closed) directory in the file\nexplorer tree. A short string (single character recommended).\nA trailing space is added automatically during rendering; the\nrenderer pads narrower indicators so collapsed/expanded rows align.\nDefault: \">\"",
          "type": "string",
          "default": ">"
        },
        "tree_indicator_expanded": {
          "description": "Symbol shown next to an expanded (open) directory in the file\nexplorer tree. A short string (single character recommended).\nA trailing space is added automatically during rendering; the\nrenderer pads narrower indicators so collapsed/expanded rows align.\nDefault: \"▼\"",
          "type": "string",
          "default": "▼"
        }
      }
    },
    "ExplorerWidth": {
      "description": "Either a percent like \"30%\" (0–100) or an absolute column count like \"24\".",
      "type": "string",
      "pattern": "^(100%|[1-9]?[0-9]%|\\d+)$"
    },
    "FileExplorerSide": {
      "description": "Side placement for the file explorer panel.",
      "type": "string",
      "enum": [
        "left",
        "right"
      ]
    },
    "FileBrowserConfig": {
      "description": "File browser configuration (for Open File dialog)",
      "type": "object",
      "properties": {
        "show_hidden": {
          "description": "Whether to show hidden files (starting with .) by default in Open File dialog",
          "type": "boolean",
          "default": false
        }
      }
    },
    "ClipboardConfig": {
      "description": "Clipboard configuration\n\nControls which clipboard methods are used for copy/paste operations.\nBy default, all methods are enabled and the editor tries them in order:\n1. OSC 52 escape sequences (works in modern terminals like Kitty, Alacritty, Wezterm)\n2. System clipboard via X11/Wayland APIs (works in Gnome Console, XFCE Terminal, etc.)\n3. Internal clipboard (always available as fallback)\n\nIf you experience hangs or issues (e.g., when using PuTTY or certain SSH setups),\nyou can disable specific methods.",
      "type": "object",
      "properties": {
        "use_osc52": {
          "description": "Enable OSC 52 escape sequences for clipboard access (default: true)\nDisable this if your terminal doesn't support OSC 52 or if it causes hangs",
          "type": "boolean",
          "default": true
        },
        "use_system_clipboard": {
          "description": "Enable system clipboard access via X11/Wayland APIs (default: true)\nDisable this if you don't have a display server or it causes issues",
          "type": "boolean",
          "default": true
        }
      }
    },
    "TerminalConfig": {
      "description": "Terminal configuration",
      "type": "object",
      "properties": {
        "jump_to_end_on_output": {
          "description": "When viewing terminal scrollback and new output arrives,\nautomatically jump back to terminal mode (default: true)",
          "type": "boolean",
          "default": true
        },
        "shell": {
          "description": "Override the shell used by the integrated terminal.\n\nWhen unset (the default), Fresh launches the shell named by the\n`$SHELL` environment variable (or the platform default if `$SHELL`\nis empty). Set this to run a different program — for example a\nwrapper script that forces an interactive shell — without having\nto change `$SHELL` for the whole process, which other features\nsuch as `format_on_save` also depend on.\n\nOnly affects local authorities; plugin-provided authorities\n(e.g. `docker exec`) keep their own wrapper.",
          "anyOf": [
            {
              "$ref": "#/$defs/TerminalShellConfig"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "skip_app_execution_alias": {
          "description": "Workaround for fresh#2077: when auto-detecting a shell on Windows,\nskip Microsoft Store **App Execution Alias** stubs (zero-byte\n`APPEXECLINK` reparse points under `%LOCALAPPDATA%\\Microsoft\\WindowsApps`).\nSpawning such a stub through ConPTY has been reported to crash with\n`0xc0000142` (STATUS_DLL_INIT_FAILED) on Windows 11 23H2.\n\nDefault `true`. Set to `false` to launch whatever `pwsh.exe`\nappears first on `PATH`, including the Store alias — useful if you\nwant the old behavior, or if you've confirmed the alias works on\nyour Windows build. No effect on non-Windows platforms or when\n`terminal.shell` is set explicitly.",
          "type": "boolean",
          "default": true
        },
        "resume_agents": {
          "description": "When restoring an Orchestrator agent session that recorded an\nagent-resume spec (e.g. `claude --session-id <id>` → resume with\n`claude --resume <id>`), rejoin the prior conversation instead of\nre-running the launch command fresh. Default `true`.\n\nSet to `false` to always re-run the launch command on restore (the\npre-resume behaviour) — useful if you'd rather a restart start each\nagent clean. No effect on sessions without a resume spec.",
          "type": "boolean",
          "default": true
        },
        "mouse_drag_selects": {
          "description": "Dragging on a live terminal selects text: the split drops into\nread-only scrollback (Ctrl+Space resumes) with a real selection\nthat the drag extends and Ctrl+C copies; a bare click still only\nfocuses the terminal. Set to `false` to make a drag on the live\ngrid inert again (default: true)",
          "type": "boolean",
          "default": true
        },
        "mouse_forwarding": {
          "description": "When to forward mouse events to the program running inside the\nterminal. `requested` (default) forwards button/drag events only\nto programs that enabled mouse reporting (DECSET 1000/1002/1003),\nbuttonless motion only under all-motion (1003), and lets\nShift+drag bypass forwarding so text can always be selected;\nwheel events additionally reach alternate-screen programs\n(alternate-scroll arrow synthesis for pagers). `alt_screen` is\nthe legacy rule: every mouse event is forwarded to any\nalternate-screen program, whether or not it asked for the mouse,\nwith no Shift bypass.",
          "$ref": "#/$defs/TerminalMouseForwarding",
          "default": "requested"
        }
      }
    },
    "TerminalShellConfig": {
      "description": "Explicit shell command + args for the integrated terminal.",
      "type": "object",
      "properties": {
        "command": {
          "description": "Executable to launch (e.g. `/usr/bin/fish`, `bash`, or a wrapper\nscript). Resolved via `$PATH` when not absolute.",
          "type": "string"
        },
        "args": {
          "description": "Arguments passed before any user input.",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        }
      },
      "required": [
        "command"
      ]
    },
    "TerminalMouseForwarding": {
      "description": "Mouse-forwarding policy for programs running inside the terminal\n(see [`TerminalConfig::mouse_forwarding`]).",
      "oneOf": [
        {
          "description": "Forward only to programs that subscribed to mouse reporting;\nShift+drag bypasses so selection always stays available.",
          "type": "string",
          "const": "requested"
        },
        {
          "description": "Legacy: forward everything to any alternate-screen program.",
          "type": "string",
          "const": "alt_screen"
        }
      ]
    },
    "Keybinding": {
      "description": "Keybinding definition",
      "type": "object",
      "properties": {
        "key": {
          "description": "Key name (e.g., \"a\", \"Enter\", \"F1\") - for single-key bindings",
          "type": "string"
        },
        "modifiers": {
          "description": "Modifiers (e.g., [\"ctrl\"], [\"ctrl\", \"shift\"]) - for single-key bindings",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "keys": {
          "description": "Key sequence for chord bindings (e.g., [{\"key\": \"x\", \"modifiers\": [\"ctrl\"]}, {\"key\": \"s\", \"modifiers\": [\"ctrl\"]}])\nIf present, takes precedence over key + modifiers",
          "type": "array",
          "items": {
            "$ref": "#/$defs/KeyPress"
          }
        },
        "action": {
          "description": "Action to perform (e.g., \"insert_char\", \"move_left\")",
          "type": "string"
        },
        "args": {
          "description": "Optional arguments for the action",
          "type": "object",
          "additionalProperties": true,
          "default": {}
        },
        "when": {
          "description": "Optional condition (e.g., \"mode == insert\")",
          "type": [
            "string",
            "null"
          ],
          "default": null
        }
      },
      "required": [
        "action"
      ],
      "x-display-field": "/action"
    },
    "KeyPress": {
      "description": "A single key in a sequence",
      "type": "object",
      "properties": {
        "key": {
          "description": "Key name (e.g., \"a\", \"Enter\", \"F1\")",
          "type": "string"
        },
        "modifiers": {
          "description": "Modifiers (e.g., [\"ctrl\"], [\"ctrl\", \"shift\"])",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        }
      },
      "required": [
        "key"
      ]
    },
    "KeymapConfig": {
      "description": "Keymap configuration (for built-in and user-defined keymaps)",
      "type": "object",
      "properties": {
        "inherits": {
          "description": "Optional parent keymap to inherit from",
          "type": [
            "string",
            "null"
          ]
        },
        "bindings": {
          "description": "Keybindings defined in this keymap",
          "type": "array",
          "items": {
            "$ref": "#/$defs/Keybinding"
          },
          "default": []
        }
      },
      "x-display-field": "/inherits"
    },
    "KeybindingMapOptions": {
      "description": "Available keybinding maps",
      "type": "string",
      "enum": [
        "default",
        "emacs",
        "vscode",
        "macos",
        "macos-gui"
      ]
    },
    "LanguageConfig": {
      "description": "Language-specific configuration",
      "type": "object",
      "properties": {
        "extensions": {
          "description": "File extensions for this language (e.g., [\"rs\"] for Rust)",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        },
        "filenames": {
          "description": "Exact filenames for this language (e.g., [\"Makefile\", \"GNUmakefile\"])",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        },
        "grammar": {
          "description": "Tree-sitter grammar name",
          "type": "string",
          "default": ""
        },
        "comment_prefix": {
          "description": "Comment prefix",
          "type": [
            "string",
            "null"
          ],
          "default": null
        },
        "auto_indent": {
          "description": "Whether to auto-indent",
          "type": "boolean",
          "default": true
        },
        "auto_close": {
          "description": "Whether to auto-close brackets, parentheses, and quotes for this language.\nIf not specified (`null`), falls back to the global `editor.auto_close` setting.",
          "type": [
            "boolean",
            "null"
          ],
          "default": null
        },
        "auto_surround": {
          "description": "Whether to auto-surround selected text with matching pairs for this language.\nIf not specified (`null`), falls back to the global `editor.auto_surround` setting.",
          "type": [
            "boolean",
            "null"
          ],
          "default": null
        },
        "textmate_grammar": {
          "description": "Path to a custom grammar file for this language (optional).\nLoaded into the grammar registry at startup and associated with this\nlanguage's `extensions`, so files matching them highlight with it.\nOnly Sublime Text `.sublime-syntax` grammars are supported —\nTextMate `.tmLanguage` is a different format syntect cannot load.",
          "type": [
            "string",
            "null"
          ],
          "default": null
        },
        "show_whitespace_tabs": {
          "description": "Whether to show whitespace tab indicators (→) for this language\nDefaults to true. Set to false for languages like Go that use tabs for indentation.",
          "type": "boolean",
          "default": true
        },
        "line_wrap": {
          "description": "Whether to enable line wrapping for this language.\nIf not specified (`null`), falls back to the global `editor.line_wrap` setting.\nUseful for prose-heavy languages like Markdown where wrapping is desirable\neven if globally disabled.",
          "type": [
            "boolean",
            "null"
          ],
          "default": null
        },
        "wrap_column": {
          "description": "Column at which to wrap lines for this language.\nIf not specified (`null`), falls back to the global `editor.wrap_column` setting.\nA value of `0` is treated as not set at this language level (inherits the global).",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0,
          "default": null
        },
        "page_view": {
          "description": "Whether to automatically enable page view (compose mode) for this language.\nPage view provides a document-style layout with centered content,\nconcealed formatting markers, and intelligent word wrapping.\nIf not specified (`null`), page view is not auto-activated.",
          "type": [
            "boolean",
            "null"
          ],
          "default": null
        },
        "page_width": {
          "description": "Width of the page in page view mode (in columns).\nControls the content width when page view is active, with centering margins.\nIf not specified (`null`), falls back to the global `editor.page_width` setting.\nA value of `0` is treated as not set at this language level (inherits the global).",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0,
          "default": null
        },
        "use_tabs": {
          "description": "Whether pressing Tab should insert a tab character instead of spaces.\nIf not specified (`null`), falls back to the global `editor.use_tabs` setting.\nSet to true for languages like Go and Makefile that require tabs.",
          "type": [
            "boolean",
            "null"
          ],
          "default": null
        },
        "tab_size": {
          "description": "Tab size (number of spaces per tab) for this language.\nIf not specified, falls back to the global editor.tab_size setting.\nA value of `0` is treated as not set at this language level (inherits the global).",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0,
          "default": null
        },
        "formatter": {
          "description": "The formatter for this language (used by format_buffer command)",
          "anyOf": [
            {
              "$ref": "#/$defs/FormatterConfig"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "format_on_save": {
          "description": "Whether to automatically format on save (uses the formatter above)",
          "type": "boolean",
          "default": false
        },
        "on_save": {
          "description": "Actions to run when a file of this language is saved (linters, etc.)\nActions are run in order; if any fails (non-zero exit), subsequent actions don't run\nNote: Use `formatter` + `format_on_save` for formatting, not on_save",
          "type": "array",
          "items": {
            "$ref": "#/$defs/OnSaveAction"
          },
          "default": []
        },
        "word_characters": {
          "description": "Extra characters (beyond alphanumeric and `_`) considered part of\nidentifiers for this language. Used by dabbrev and buffer-word\ncompletion to correctly tokenise language-specific naming conventions.\n\nExamples:\n- Lisp/Clojure/CSS: `\"-\"` (kebab-case identifiers)\n- PHP/Bash: `\"$\"` (variable sigils)\n- Ruby: `\"?!\"` (predicate/bang methods)\n- Rust (default): `\"\"` (standard alphanumeric + underscore)",
          "type": [
            "string",
            "null"
          ],
          "default": null
        },
        "indent": {
          "description": "Indentation rules for this language. Overrides (and, for unspecified\npatterns, inherits from) the built-in rules. Lets you tune auto-indent —\nor add it for a language Fresh doesn't know — without a tree-sitter\ngrammar. See `IndentRulesConfig`.",
          "anyOf": [
            {
              "$ref": "#/$defs/IndentRulesConfig"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "indentation_guide": {
          "description": "Whether to render indentation guides for this language.\nIf not specified (`null`), follows the global `editor.indentation_guide`\nsetting — except for plain text (`text`), where guides default off:\nthey are a source-code aid and plain-text indentation rarely nests\nmeaningfully. Set `false` to suppress guides for a language even when\nthey are enabled globally, or `true` under `[languages.text]` to bring\nthem back for plain text.",
          "type": [
            "boolean",
            "null"
          ],
          "default": null
        }
      },
      "x-display-field": "/grammar"
    },
    "FormatterConfig": {
      "description": "Formatter configuration for a language",
      "type": "object",
      "properties": {
        "command": {
          "description": "The formatter command to run (e.g., \"rustfmt\", \"prettier\")",
          "type": "string"
        },
        "args": {
          "description": "Arguments to pass to the formatter\nUse \"$FILE\" to include the file path",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        },
        "stdin": {
          "description": "Whether to pass buffer content via stdin (default: true)\nMost formatters read from stdin and write to stdout",
          "type": "boolean",
          "default": true
        },
        "timeout_ms": {
          "description": "Timeout in milliseconds (default: 10000)",
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 10000
        }
      },
      "required": [
        "command"
      ],
      "x-display-field": "/command"
    },
    "OnSaveAction": {
      "description": "Action to run when a file is saved (for linters, etc.)",
      "type": "object",
      "properties": {
        "command": {
          "description": "The shell command to run\nThe file path is available as $FILE or as an argument",
          "type": "string"
        },
        "args": {
          "description": "Arguments to pass to the command\nUse \"$FILE\" to include the file path",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        },
        "working_dir": {
          "description": "Working directory for the command (defaults to project root)",
          "type": [
            "string",
            "null"
          ],
          "default": null
        },
        "stdin": {
          "description": "Whether to use the buffer content as stdin",
          "type": "boolean",
          "default": false
        },
        "timeout_ms": {
          "description": "Timeout in milliseconds (default: 10000)",
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 10000
        },
        "enabled": {
          "description": "Whether this action is enabled (default: true)\nSet to false to disable an action without removing it from config",
          "type": "boolean",
          "default": true
        }
      },
      "required": [
        "command"
      ],
      "x-display-field": "/command"
    },
    "IndentRulesConfig": {
      "description": "User-overridable auto-indentation rules for a language.\n\nWhen you press Enter, Fresh looks at the line being split (the \"reference\nline\") and the text that moves down to the new line, and applies these rules\nto decide the new line's indent. Each field is a regular expression\n([`regex` crate] syntax: no look-ahead/behind or back-references). A regex is\nmatched against the line's **code view** — the text with comment and string\nspans blanked to spaces first — so a bracket or keyword inside a string or\ncomment never triggers indentation.\n\nAny field left unset inherits from the language's built-in rules, so you can\noverride just one pattern. All patterns are optional.\n\n[`regex` crate]: https://docs.rs/regex/latest/regex/#syntax",
      "type": "object",
      "properties": {
        "increase_indent_pattern": {
          "description": "If the reference line matches, the new line is indented one level deeper.\nExample — a line ending with an opening bracket: `[\\{\\[\\(]\\s*$`.\nExample — Python block headers ending in a colon: `:\\s*$`.",
          "type": [
            "string",
            "null"
          ],
          "default": null
        },
        "decrease_indent_pattern": {
          "description": "If the new line's leading text matches, that line is dedented one level.\nExample — a line starting with a closing bracket: `^\\s*[\\}\\]\\)]`.",
          "type": [
            "string",
            "null"
          ],
          "default": null
        },
        "indent_next_line_pattern": {
          "description": "Like `increase_indent_pattern`, but the extra level applies to the\nimmediately following line only (a one-shot indent that doesn't persist).\nExample — a braceless control head: `^\\s*(if|for|while)\\b.*\\)\\s*$`.",
          "type": [
            "string",
            "null"
          ],
          "default": null
        },
        "dedent_next_line_pattern": {
          "description": "If the reference line matches, the following line is dedented one level\n(a one-shot dedent). Example — Python flow-exit statements:\n`^\\s*(return|pass|raise|break|continue)\\b`.",
          "type": [
            "string",
            "null"
          ],
          "default": null
        },
        "self_close_pattern": {
          "description": "Cancels `increase_indent_pattern` when the reference line *also* closes\nthe block it opened, so one-liners don't over-indent. Example — Ruby\n`\\bend\\b` matches `def f; end` and stops it from indenting the next line.",
          "type": [
            "string",
            "null"
          ],
          "default": null
        }
      }
    },
    "LspLanguageConfig": {
      "description": "One or more LSP server configs for this language.\nAccepts both a single object and an array for backwards compatibility.",
      "type": "array",
      "items": {
        "$ref": "#/$defs/LspServerConfig"
      }
    },
    "LspServerConfig": {
      "description": "LSP server configuration",
      "type": "object",
      "properties": {
        "command": {
          "description": "Command to spawn the server.\nRequired when enabled=true, ignored when enabled=false.",
          "type": "string",
          "default": "",
          "x-order": 1
        },
        "enabled": {
          "description": "Whether the server is enabled",
          "type": "boolean",
          "default": true,
          "x-order": 2
        },
        "name": {
          "description": "Display name for this server (e.g., \"tsserver\", \"eslint\").\nDefaults to the command basename if not specified.",
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "x-order": 3
        },
        "args": {
          "description": "Arguments to pass to the server.\n\n`None` (field omitted) inherits the default server's args, while an\nexplicit list — including an empty `[]` — replaces them. This lets a\nuser swap a default server that takes args (e.g. `marksman server`)\nfor one that takes none (e.g. `markdown-oxide`) by setting `\"args\": []`.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          },
          "default": null,
          "x-order": 4
        },
        "auto_start": {
          "description": "Whether to auto-start this LSP server when opening matching files.\nDefaults to true: a server you configure is normally one you want\nused, so it starts on the next matching file open. Set to false to\nrequire a manual start via the command palette.",
          "type": "boolean",
          "default": true,
          "x-order": 5
        },
        "root_markers": {
          "description": "File/directory names to search for when detecting the workspace root.\nThe editor walks upward from the opened file's directory looking for\nany of these markers. The first directory containing a match becomes\nthe workspace root sent to the LSP server.\n\nIf empty, falls back to `[\".git\"]` as a universal marker.\nIf the walk reaches a filesystem boundary without a match, uses the\nfile's parent directory (never cwd or $HOME).",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "x-order": 6
        },
        "env": {
          "description": "Environment variables to set for the LSP server process.\nThese are added to (or override) the inherited parent environment.",
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "default": {},
          "x-section": "Advanced",
          "x-order": 10
        },
        "language_id_overrides": {
          "description": "Override the LSP languageId sent in textDocument/didOpen based on file extension.\nMaps file extension (without dot) to LSP language ID string.\nFor example: `{\"tsx\": \"typescriptreact\", \"jsx\": \"javascriptreact\"}`",
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "default": {},
          "x-section": "Advanced",
          "x-order": 11
        },
        "initialization_options": {
          "description": "Custom initialization options to send to the server\nThese are passed in the `initializationOptions` field of the LSP Initialize request",
          "default": null,
          "x-section": "Advanced",
          "x-order": 12
        },
        "only_features": {
          "description": "Restrict this server to only handle the listed features.\nMutually exclusive with `except_features`. If neither is set, all features are handled.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/$defs/LspFeature"
          },
          "default": null,
          "x-section": "Advanced",
          "x-order": 13
        },
        "except_features": {
          "description": "Exclude the listed features from this server.\nMutually exclusive with `only_features`. If neither is set, all features are handled.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/$defs/LspFeature"
          },
          "default": null,
          "x-section": "Advanced",
          "x-order": 14
        },
        "process_limits": {
          "description": "Process resource limits (memory and CPU)",
          "$ref": "#/$defs/ProcessLimits",
          "default": {
            "max_memory_percent": 50,
            "max_cpu_percent": 90,
            "enabled": true
          },
          "x-section": "Advanced",
          "x-order": 15
        }
      },
      "x-display-field": "/command"
    },
    "LspFeature": {
      "description": "LSP features that can be routed to specific servers in a multi-server setup.\n\nFeatures are classified as either \"merged\" (results from all servers are combined)\nor \"exclusive\" (first eligible server wins). This classification is used by the\ndispatch layer, not by this enum itself.",
      "oneOf": [
        {
          "description": "Diagnostics (merged: combined from all servers)",
          "type": "string",
          "const": "diagnostics"
        },
        {
          "description": "Code completion (merged: combined from all servers)",
          "type": "string",
          "const": "completion"
        },
        {
          "description": "Code actions / quick fixes (merged: combined from all servers)",
          "type": "string",
          "const": "code_action"
        },
        {
          "description": "Document symbols (merged: combined from all servers)",
          "type": "string",
          "const": "document_symbols"
        },
        {
          "description": "Workspace symbols (merged: combined from all servers)",
          "type": "string",
          "const": "workspace_symbols"
        },
        {
          "description": "Hover information (exclusive: first eligible server wins)",
          "type": "string",
          "const": "hover"
        },
        {
          "description": "Go to definition, declaration, type definition (exclusive)",
          "type": "string",
          "const": "definition"
        },
        {
          "description": "Go to implementation (exclusive)",
          "type": "string",
          "const": "implementation"
        },
        {
          "description": "Find references (exclusive)",
          "type": "string",
          "const": "references"
        },
        {
          "description": "Document formatting and range formatting (exclusive)",
          "type": "string",
          "const": "format"
        },
        {
          "description": "Rename and prepare rename (exclusive)",
          "type": "string",
          "const": "rename"
        },
        {
          "description": "Signature help (exclusive)",
          "type": "string",
          "const": "signature_help"
        },
        {
          "description": "Inlay hints (exclusive)",
          "type": "string",
          "const": "inlay_hints"
        },
        {
          "description": "Folding ranges (exclusive)",
          "type": "string",
          "const": "folding_range"
        },
        {
          "description": "Semantic tokens (exclusive)",
          "type": "string",
          "const": "semantic_tokens"
        },
        {
          "description": "Document highlight (exclusive)",
          "type": "string",
          "const": "document_highlight"
        }
      ]
    },
    "ProcessLimits": {
      "description": "Configuration for process resource limits",
      "type": "object",
      "properties": {
        "max_memory_percent": {
          "description": "Maximum memory usage as percentage of total system memory (None = no limit)\nDefault is 50% of total system memory",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0,
          "default": null
        },
        "max_cpu_percent": {
          "description": "Maximum CPU usage as percentage of total CPU (None = no limit)\nFor multi-core systems, 100% = 1 core, 200% = 2 cores, etc.",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0,
          "default": null
        },
        "enabled": {
          "description": "Enable resource limiting (can be disabled per-platform)",
          "type": "boolean",
          "default": true
        }
      }
    },
    "WarningsConfig": {
      "description": "Warning notification configuration",
      "type": "object",
      "properties": {
        "show_status_indicator": {
          "description": "Show warning/error indicators in the status bar (default: true)\nWhen enabled, displays a colored indicator for LSP errors and other warnings",
          "type": "boolean",
          "default": true
        }
      }
    },
    "PluginConfig": {
      "description": "Configuration for a single plugin",
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Whether this plugin is enabled (default: true)\nWhen disabled, the plugin will not be loaded or executed.",
          "type": "boolean",
          "default": true
        },
        "path": {
          "description": "Path to the plugin file (populated automatically when scanning)\nThis is filled in by the plugin system and should not be set manually.",
          "type": [
            "string",
            "null"
          ],
          "readOnly": true
        },
        "settings": {
          "description": "Plugin-specific settings. The shape is defined by each plugin's\n`<plugin_name>.schema.json` sidecar file; the host stores the value as\nuntyped JSON so a malformed plugin schema can't poison the rest of the\nconfig. Plugins read this via `editor.getPluginConfig()` and the\nSettings UI renders it as a sub-category under \"Plugin Settings\".",
          "readOnly": true
        }
      },
      "x-display-field": "/enabled"
    },
    "PackagesConfig": {
      "description": "Package manager configuration for plugins and themes",
      "type": "object",
      "properties": {
        "sources": {
          "description": "Registry sources (git repository URLs containing plugin/theme indices)\nDefault: [\"https://github.com/sinelaw/fresh-plugins-registry\"]",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [
            "https://github.com/sinelaw/fresh-plugins-registry"
          ]
        }
      }
    },
    "EnvConfig": {
      "description": "Environment-detection configuration: the single source of truth for which\nmarker files identify which activatable environment and how to activate it.\n\nCore does the detection; the env-manager plugin only *consumes* the\nresolved result (via `editor.detectedEnv()`) — it does not probe the\nfilesystem itself. The same detector markers also feed the Workspace Trust\nprompt, so trust and activation can never disagree about what an env file\nis. Users may add or override detectors here.",
      "type": "object",
      "properties": {
        "detectors": {
          "description": "Ordered list of detectors; the first whose markers match the workspace\nroot wins. Defaults cover venv, direnv, mise, pipenv, and poetry.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/EnvDetector"
          },
          "default": [
            {
              "name": ".venv",
              "markers": [
                ".venv"
              ],
              "kind": "path-only",
              "snippet": "source .venv/bin/activate",
              "require": [
                ".venv/bin/python",
                ".venv/bin/python3",
                ".venv/Scripts/python.exe"
              ]
            },
            {
              "name": "venv",
              "markers": [
                "venv"
              ],
              "kind": "path-only",
              "snippet": "source venv/bin/activate",
              "require": [
                "venv/bin/python",
                "venv/bin/python3",
                "venv/Scripts/python.exe"
              ]
            },
            {
              "name": "direnv",
              "markers": [
                ".envrc"
              ],
              "kind": "shell",
              "snippet": "eval \"$(direnv export bash)\"",
              "require": []
            },
            {
              "name": "mise",
              "markers": [
                "mise.toml",
                ".mise.toml",
                ".tool-versions"
              ],
              "kind": "shell",
              "snippet": "eval \"$(mise env -s bash)\"",
              "require": []
            },
            {
              "name": "pipenv",
              "markers": [
                "Pipfile"
              ],
              "kind": "shell",
              "snippet": "source \"$(pipenv --venv)/bin/activate\"",
              "require": []
            },
            {
              "name": "poetry",
              "markers": [
                "poetry.lock"
              ],
              "kind": "shell",
              "snippet": "source \"$(poetry env info --path)/bin/activate\"",
              "require": []
            }
          ]
        }
      }
    },
    "EnvDetector": {
      "description": "One environment detector: which marker files/dirs identify it, how risky\nactivation is, how to activate it, and what to call it.",
      "type": "object",
      "properties": {
        "name": {
          "description": "Short label shown in the status pill (e.g. \".venv\", \"direnv\", \"mise\").",
          "type": "string"
        },
        "markers": {
          "description": "Marker files or directories at the workspace root. The detector matches\nif any one of them exists.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "kind": {
          "description": "Activation risk class (see [`EnvKind`]).",
          "$ref": "#/$defs/EnvKind"
        },
        "snippet": {
          "description": "Shell snippet handed to `editor.setEnv` to activate. It runs with the\nworking directory set to the workspace root, so **prefer relative paths**\n(e.g. `source .venv/bin/activate`). `{dir}` expands to the absolute\nworkspace root, but interpolating it into a shell command is a\nshell-injection surface when the path is attacker-influenced\n(cf. CVE-2024-9287) — avoid it unless you control the path.",
          "type": "string"
        },
        "require": {
          "description": "Optional evidence paths (relative to the workspace root); when present,\nat least one must exist for the detector to match — e.g. a `.venv` must\nactually contain an interpreter, not just the directory. Empty means\nthe markers alone are enough.",
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        }
      },
      "required": [
        "name",
        "markers",
        "kind",
        "snippet"
      ],
      "x-display-field": "/name"
    },
    "EnvKind": {
      "description": "Activation risk class for an environment — decides whether activating it\nneeds a trust prompt first.",
      "oneOf": [
        {
          "description": "Activation only prepends to `PATH` / sets a few vars (e.g. a Python\nvirtualenv). Low-risk: auto-activates silently once trusted, and a\nfolder whose *only* env is path-only is trusted without a prompt.",
          "type": "string",
          "const": "path-only"
        },
        {
          "description": "Activation evaluates project-controlled shell (e.g. `direnv export`,\n`mise env`). Runs only after the workspace is trusted.",
          "type": "string",
          "const": "shell"
        }
      ]
    }
  }
}
