> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vorto-editor.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# How to add and configure a custom language in Vorto

> Configure a language that isn't built in, wire up a tree-sitter grammar and LSP server, set a formatter, and override built-in language defaults.

Vorto's language system is fully open: anything you can express in the built-in language table you can also define or override in your `config.toml`. You add a `[languages.<name>]` block for the language definition and, if it needs an LSP server, a matching `[lsp.<server-name>]` block. Vorto merges your entries onto the built-in defaults at startup, so a partial block changes only the fields you specify.

## Add a new language

The minimal definition for a language that isn't already built in is a name, a list of file extensions, and optionally a comment token:

```toml theme={null}
[languages.fish]
extensions = ["fish"]
comment_token = "#"
```

With just this, Vorto will recognise `.fish` files and enable comment toggling. Add more fields as needed.

## Full example: Fish shell

The following block configures Fish shell with a tree-sitter grammar, a custom LSP server, and a non-default indent width:

```toml theme={null}
[languages.fish]
extensions = ["fish"]
comment_token = "#"
indent_width = 4
lsp = ["fish-lsp"]

[lsp.fish-lsp]
command = "fish-lsp"
args = ["--stdio"]
root_markers = [".git"]
```

<Steps>
  <Step title="Define the language block">
    Add a `[languages.<name>]` section to `~/.config/vorto/config.toml`. Set `extensions` to the file extensions that should trigger this language, and `comment_token` to the single-line comment prefix:

    ```toml theme={null}
    [languages.fish]
    extensions = ["fish"]
    comment_token = "#"
    indent_width = 4
    ```

    Per-language editor settings (`indent_width`, `tab_width`, `use_tabs`, etc.) go directly in the language block — they are not nested under a sub-table.
  </Step>

  <Step title="Reference a tree-sitter grammar">
    By default Vorto looks for a grammar whose filename stem matches the language name. If the grammar has a different name, set it explicitly:

    ```toml theme={null}
    [languages.fish]
    extensions = ["fish"]
    grammar = "fish-shell"
    ```

    Install the grammar before opening files of this type:

    ```sh theme={null}
    vorto grammar install fish-shell
    ```

    <Note>
      If the language has a built-in recipe (check `vorto grammar list`), that's all you need. For a grammar outside the built-in catalog, add a `[grammars.<name>]` recipe so `vorto grammar install` can build it — see [Grammars outside the built-in catalog](/languages/grammars#grammars-outside-the-built-in-catalog). You can still install a prebuilt library by hand instead, dropping it in the grammar directory shown by `vorto grammar list`.
    </Note>
  </Step>

  <Step title="Define the LSP server">
    If your language has an LSP server, define it in a `[lsp.<server-name>]` block. `command` is required for any server that isn't already built in:

    ```toml theme={null}
    [lsp.fish-lsp]
    command = "fish-lsp"
    args = ["--stdio"]
    root_markers = [".git"]
    ```

    `root_markers` is a list of filenames that Vorto looks for when walking up the directory tree to find the workspace root. The server starts when any of these files is found.
  </Step>

  <Step title="Attach the server to the language">
    Set the `lsp` field on the language block to a list of server names. The names must match keys in the `[lsp]` table:

    ```toml theme={null}
    [languages.fish]
    extensions = ["fish"]
    comment_token = "#"
    indent_width = 4
    lsp = ["fish-lsp"]
    ```
  </Step>

  <Step title="Configure a formatter (optional)">
    Set `formatter` to run an external command on save. The buffer's text is piped on stdin and the command's stdout replaces the buffer:

    ```toml theme={null}
    [languages.fish]
    extensions = ["fish"]
    comment_token = "#"
    formatter = { command = "fish_indent", args = [] }
    ```

    When `formatter` is set, it takes precedence over `textDocument/formatting` from the LSP.
  </Step>
</Steps>

## Override a built-in language

You don't need to re-state every field to change a built-in language — only the fields you include are changed. For example, to swap Python's formatter from the default (none) to `black`:

```toml theme={null}
[languages.python]
formatter = { command = "black", args = ["-"] }
```

To change only the indent width for Go without touching anything else:

```toml theme={null}
[languages.go]
indent_width = 4
tab_width = 4
```

<Warning>
  The `lsp` field is replaced whole, not merged. If you set `lsp = ["my-server"]` on a built-in language, the built-in servers for that language are dropped. Re-state any built-in server names you still want:

  ```toml theme={null}
  [languages.python]
  lsp = ["pyright", "my-extra-server"]
  ```
</Warning>

## Workspace-local config

Place a `.vorto` file (or a `.vorto/config.toml` directory form) at your project root to apply language overrides only within that project. The workspace config takes precedence over `~/.config/vorto/config.toml`. This is useful for project-specific formatters or indent settings without affecting your global config.
