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

tip

Formatters run sequentially in the order they are defined. For Python, put isort before black.

Execution 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

Formatter Resolution

Formatter configuration follows this resolution order:

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

Checking Formatter Status

note

Formatters only run on files that match their configured extensions. Unmatched file types are skipped.

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
}
}
}

Performance Considerations