Skip to main content

Formatters

Formatters automatically format code that the LLM writes, ensuring consistency with your project's code style. When enabled, files are formatted after the model writes or edits them, before they are presented in the diff or saved.

Enabling Formatters

Enable All Built-in Formatters

The simplest way to enable formatting is to set formatter to true in opencode.json:

{
"formatter": true
}

This enables all built-in formatters that are applicable to your project's file types.

Disable Formatters Completely

{
"formatter": false
}

Built-in Formatters

opencode includes built-in formatters for the most common languages and tools. When formatter is true, all applicable formatters are active.

FormatterDefault ExtensionsDescription
prettier.js, .ts, .jsx, .tsx, .css, .json, .md, .html, .yaml, .graphqlOpinionated code formatter
eslint.js, .ts, .jsx, .tsxLinter with auto-fix capability
rustfmt.rsOfficial Rust formatter
gofmt.goOfficial Go formatter
black.pyPython code formatter
isort.pyPython import sorter
prettier_rust.rsPrettier plugin for Rust
rubocop.rbRuby formatter
biome.js, .ts, .jsx, .tsx, .json, .cssFast unified formatter
dprint.ts, .js, .json, .mdPluggable and fast formatter
clang_format.c, .cpp, .h, .hpp, .java, .protoC/C++/Java formatter
shfmt.sh, .bashShell script formatter
terraform.tfTerraform formatter
deno_fmt.js, .ts, .jsx, .tsx, .json, .mdDeno's built-in formatter

Disabling Specific Formatters

Disable individual built-in formatters by setting them to disabled:

{
"formatter": {
"prettier": { "disabled": true },
"eslint": { "disabled": true }
}
}

The remaining formatters (rustfmt, gofmt, black, etc.) remain active.

Disable All But One

{
"formatter": {
"prettier": { "disabled": true },
"eslint": { "disabled": true },
"black": { "disabled": true }
}
}

Custom Formatters

Define custom formatters for tools not included in the built-in set.

Custom Formatter Configuration

{
"formatter": {
"custom-prettier": {
"command": ["npx", "prettier", "--write", "$FILE"],
"environment": {
"NODE_ENV": "development",
"PRETTIER_CONFIG": ".prettierrc"
},
"extensions": [".js", ".ts", ".jsx", ".tsx"]
}
}
}

Custom Formatter Fields

FieldRequiredTypeDescription
commandYesstring[]Command and arguments to execute
extensionsYesstring[]File extensions this formatter handles
environmentNoobjectEnvironment variables to set during formatting
disabledNobooleanSet to true to disable this formatter

The $FILE Placeholder

Use $FILE in the command array where the file path should be inserted. It is replaced with the absolute path of the formatted file at runtime.

{
"formatter": {
"custom-sql-formatter": {
"command": ["sql-formatter", "--config", ".sql-formatter.json", "$FILE"],
"extensions": [".sql"]
}
}
}

Multi-Extension Formatter

{
"formatter": {
"custom-php-formatter": {
"command": ["php-cs-fixer", "fix", "$FILE", "--rules=@PSR12"],
"extensions": [".php", ".phtml"]
}
}
}

Environment Variables

Set environment variables for your custom formatters to control their behavior:

{
"formatter": {
"custom-prettier": {
"command": ["npx", "prettier", "--write", "$FILE"],
"environment": {
"NODE_ENV": "production",
"PRETTIER_CONFIG": ".prettierrc.js",
"FORCE_COLOR": "1"
},
"extensions": [".js", ".ts", ".jsx", ".tsx", ".json", ".css", ".md"]
}
}
}

Environment variables are set only for the formatter subprocess and do not affect the parent opencode process.

Formatter Execution

When a file is created or modified by the LLM, opencode:

  1. Checks the file extension against all configured formatters
  2. For each matching formatter:
    • Spawns a subprocess with the formatter command
    • Replaces $FILE with the absolute file path
    • Sets any configured environment variables
    • Waits for the formatter to complete
  3. Reads the formatted file back
  4. Proceeds with the result (displayed in the diff, saved to disk)

Execution Order

Formatters are executed in the order they are defined in the config. When multiple formatters match the same file extension, they run sequentially in definition order.

For example, running isort before black for Python:

{
"formatter": {
"isort": {
"command": ["isort", "$FILE"],
"extensions": [".py"]
},
"black": {
"command": ["black", "--quiet", "$FILE"],
"extensions": [".py"]
}
}
}

Error Handling

If a formatter exits with a non-zero status code, opencode logs a warning but does not block the operation. The file content from before the failed formatting attempt is preserved.

Formatter Resolution

Formatter configuration follows this resolution order:

  1. opencode.json formatter config (project level)
  2. .opencode/tools/ formatter definitions
  3. Built-in formatters

Custom formatters with the same name as a built-in formatter override the built-in version entirely.

Checking Formatter Status

To see which formatters are active and their configurations:

opencode config show

Look for the formatter section in the output.

Advanced Patterns

Per-Project Formatter Config

Different projects can use different formatters by configuring opencode.json per project:

{
"formatter": {
"biome": { "disabled": true },
"prettier": {
"command": ["npx", "prettier", "--write", "$FILE"],
"extensions": [".js", ".ts", ".jsx", ".tsx", ".json", ".css", ".md"]
}
}
}

Formatter with Arguments from Config File

{
"formatter": {
"custom-eslint": {
"command": ["npx", "eslint", "--fix", "--config", ".eslintrc.json", "$FILE"],
"extensions": [".js", ".ts", ".jsx", ".tsx"]
}
}
}

Shell Script Formatter

{
"formatter": {
"custom-shfmt": {
"command": ["shfmt", "-w", "-i", "2", "-ci", "$FILE"],
"extensions": [".sh", ".bash", ".zsh"]
}
}
}

Swift Formatter

{
"formatter": {
"swift-format": {
"command": ["swift-format", "--configuration", ".swift-format.json", "-i", "$FILE"],
"extensions": [".swift"]
}
}
}

Disabling Formatting for Specific Agents

Control formatting at the agent level:

{
"agent": {
"reviewer": {
"formatter": false
},
"builder": {
"formatter": true
}
}
}

This is useful when you want review-only agents to skip formatting for performance while development agents always format output.

Performance Considerations

  • Formatters add latency after each write or edit operation (typically 100-500ms per formatter)
  • For large files or slow formatters, consider disabling formatting for lightweight agents
  • Use fast formatters like dprint or biome for frequently modified file types
  • Formatters run sequentially in definition order — put faster formatters first