Start typing to search the documentation.

Docs navigation

Formatters

OpenCode can format files after its write, edit, or patch tools change them. Formatters are disabled by default, so enable them in your configuration:

opencode.jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": true,
}

Enable

Set formatter to true to enable every built-in formatter. OpenCode runs a built-in only when its executable and any project-specific requirements are available.

opencode.jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": true,
}

An object also enables the built-ins and lets you override them or add custom formatters. An empty object is therefore equivalent to true.

opencode.jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {},
}

Builtins

OpenCode includes these formatter definitions. Most require the named command to be available; definitions with extra detection rules list them below.

FormatterExtensionsRequirement
gofmt.gogofmt command
mix.ex, .exs, .eex, .heex, .leex, .neex, .sfacemix command
oxfmt.js, .jsx, .mjs, .cjs, .ts, .tsx, .mts, .ctsoxfmt dependency in package.json
prettier.js, .jsx, .mjs, .cjs, .ts, .tsx, .mts, .cts, .html, .htm, .css, .scss, .sass, .less, .vue, .svelte, .json, .jsonc, .yaml, .yml, .toml, .xml, .md, .mdx, .graphql, .gqlprettier dependency in package.json
biomeSame extensions as prettier abovebiome.json or biome.jsonc and an installed @biomejs/biome binary
zig.zig, .zonzig command
clang-format.c, .cc, .cpp, .cxx, .c++, .h, .hh, .hpp, .hxx, .h++, .ino, .C, .Hclang-format command and .clang-format
ktlint.kt, .ktsktlint command
ruff.py, .pyiruff command and a Ruff config or dependency declaration
air.Rair command that identifies itself as the R formatter
uv.py, .pyiuv command with uv format support
rubocop.rb, .rake, .gemspec, .rurubocop command
standardrb.rb, .rake, .gemspec, .rustandardrb command
htmlbeautifier.erbhtmlbeautifier command
dart.dartdart command
ocamlformat.ml, .mliocamlformat command and .ocamlformat
terraform.tf, .tfvarsterraform command
latexindent.texlatexindent command
gleam.gleamgleam command
shfmt.sh, .bashshfmt command
nixfmt.nixnixfmt command
rustfmt.rsrustfmt command
pint.phplaravel/pint in composer.json
ormolu.hsormolu command
cljfmt.clj, .cljs, .cljc, .edncljfmt command
dfmt.ddfmt command

For example, enabling built-ins lets OpenCode discover and run a project-local Prettier dependency for matching files:

opencode.jsonc
{
  "formatter": true,
}

Customize

Add a named entry to change a built-in or define a custom formatter. A custom formatter needs both command and extensions to run.

opencode.jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": {
    "prettier": {
      "environment": {
        "NODE_ENV": "development",
      },
      "extensions": [".js", ".ts"],
    },
    "deno-markdown": {
      "command": ["deno", "fmt", "$FILE"],
      "extensions": [".md"],
    },
  },
}
FieldTypeBehavior
disabledbooleanRemoves the named formatter when true.
commandstring[]Replaces the built-in command or defines a custom command.
environmentRecord<string, string>Adds environment variables while preserving the parent environment.
extensionsstring[]Replaces the built-in extension list or defines the custom list. Include the leading dot.

All fields are optional. A built-in entry inherits omitted values, while a new entry without a command or extensions cannot run.

opencode.jsonc
{
  "formatter": {
    "prettier": {
      "extensions": [".md", ".mdx"],
    },
  },
}

Commands

command is an argument array, not a shell command string. OpenCode replaces $FILE with the file’s absolute path and runs the command from the active project directory.

opencode.jsonc
{
  "formatter": {
    "custom": {
      "command": ["custom-fmt", "--write", "$FILE"],
      "extensions": [".custom"],
    },
  },
}

Matching

OpenCode compares the file’s final extension with extensions. Matching is case-sensitive, and compound entries such as .part.md do not match notes.part.md because its final extension is .md.

opencode.jsonc
{
  "formatter": {
    "markdown": {
      "command": ["deno", "fmt", "$FILE"],
      "extensions": [".md"],
    },
  },
}

When several formatters match, OpenCode tries them in registered order and stops after the first successful command. Built-ins retain their built-in order; custom entries follow in object order. If one exits unsuccessfully, OpenCode logs the failure and tries the next match.

opencode.jsonc
{
  "formatter": {
    "preferred": {
      "command": ["preferred-fmt", "$FILE"],
      "extensions": [".foo"],
    },
    "fallback": {
      "command": ["fallback-fmt", "$FILE"],
      "extensions": [".foo"],
    },
  },
}

Disable

Omit formatter or set it to false to disable all formatting. An explicit false can override a lower-priority configuration that enabled formatters.

opencode.jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "formatter": false,
}

To disable one built-in while leaving the others enabled, mark its named entry as disabled.

opencode.jsonc
{
  "formatter": {
    "prettier": {
      "disabled": true,
    },
  },
}