Skip to content

Format on Save

BMO can format agent file edits before workspace history and read snapshots are recorded. Direct local text edits format a private candidate before publishing it. A source change detected during formatting refuses the write, and formatter failure never restores old content over another writer’s changes.

Format on save is opt-in:

[options.format_on_save]
enabled = true
fail_on_error = false
[[options.format_on_save.rules]]
id = "go"
extensions = [".go"]
command = "gofumpt -w {{path}}"
timeout_seconds = 30

Rules match by file extension, case-insensitively, and the first matching rule wins. Command templates support {{path}} for the file being formatted and {{cwd}} for the workspace directory. For direct local text edits, {{path}} is a private copy with the original basename beneath the nearest existing source ancestor. Parent configuration files remain discoverable, but rules tied to an exact relative pathname may need explicit configuration. The built-in Go rule tries gofumpt -w and falls back to gofmt -w when gofumpt is unavailable.

The default is fail-open. If a formatter is missing, times out, or exits non-zero, the file mutation still succeeds and BMO records a bounded metadata event. Set fail_on_error = true for repositories that prefer failed writes over unformatted content.

These save points run formatters: write, edit, multiedit, semantic LSP symbol edits, and staged_accept / staged_accept_all. Structural LSP edits and staged acceptance use their separate in-place formatting paths. apply_patch proposals format when accepted, not while they are only staged.

Inspect the detached configuration posture with:

Terminal window
bmo config show-format-on-save --format=json