An AI assistant writes a good share of my FileMaker calculations these days, and the logic is mostly fine. The shape is another story. One Let comes back with every variable on its own line, the next one crammed inline; operators sometimes spaced, sometimes not; the result variable called ~result today and something else tomorrow. Asking the model to “always format it like this” only helps as long as it remembers. And honestly, my own calculations drift the same way, between projects and between years.

Every other ecosystem I work in solved this long ago: prettier for TypeScript, gofmt for Go. Nobody discusses shape in those languages anymore, because a tool owns it. So I built fmstyle, the same thing for FileMaker calculations. You define your house style once in an fmstyle.json, and every calculation that goes through fmstyle format comes out in that shape, whoever or whatever wrote it.

fmstyle is also an old dream. I have wanted to build a real formatter for FileMaker for years, and a tokenizer, parser and printer for the full calculation grammar is exactly the kind of project that never survives next to client work. With an AI assistant doing the heavy lifting, it finally happened. Yes, the assistant that causes the drift also helped build the formatter that fixes it.

Formatting a FileMaker calculation in the browser at fmstyle.dev: paste a messy Let, it formats live, switch preset, copy
fmstyle.dev: paste a calculation, it formats live in your style, copy it back. Everything runs in your browser.

It must never change what a calculation computes

A formatter that could silently alter behaviour would be worse than no formatter, so this is where most of the engineering went. fmstyle re-tokenizes its own output and requires the exact same code tokens and comments as the input; if that check fails, it refuses to emit anything. If it cannot parse an expression, it changes nothing and says so. Formatting is also idempotent: running it twice gives byte-identical output to running it once, and there is a test asserting exactly that. The ≡ in the logo stands for this guarantee.

A style guide has two halves

Building the config changed how I read style guides. Our own FileMaker style guide was one prose document, but while translating it into rules I saw that it mixes two kinds of content that want to be treated differently:

  • a mechanical half: indentation, Let layout, line width, naming patterns. Rules a tool can enforce without judgment. This half becomes fmstyle.json.
  • an advisory half: what things should be named after, when a While is clearer than a recursive custom function, why a calculation should stay under a certain size. This half stays prose, written for humans and, increasingly, read by AI assistants too.

The split changes how AI-written code gets to house quality: the model handles the logic, fmstyle format fixes the shape deterministically, and fmstyle lint checks the rules that can be expressed as rules (explicit result variable, naming patterns). The prose half travels along in the prompt for everything that cannot.

The split also changes what it takes to adopt a house style in a team. Share one fmstyle.json, point everyone’s AI assistant at that same preset, and every calculation written anywhere in the team comes out in house style from day one, including from the developer who joined this morning. The mechanical half of a style guide becomes a file you hand over instead of a habit that takes months of code review to grow.

What it handles

Any calculation expression: Let, While, Case, If, Substitute, ExecuteSQL, the JSON functions, custom functions, plain operator expressions. Including the FileMaker quirks that make parsing it non-trivial: the ≤ ≥ ≠ ¶ operators, field names with spaces (Invoice Lines::Amount 2), ${quoted names}, $var and $$var, // and nestable /* */ comments, [...] argument lists. Individual functions can get their own layout rules, so JSONSetElement may explode while GetValue stays inline.

What it does not do yet: script steps. Only calculations are parsed today; script-step support is the top of the roadmap.

Installing fmstyle from the terminal, formatting a calculation from stdin, and running fmstyle lint
The CLI: install, format from stdin or files, lint. Exit codes make it pre-commit- and CI-ready.

Try it

  • Browser, no install: fmstyle.dev. Paste, format, copy; load your own fmstyle.json. Entirely client-side, no network requests. The page embeds a JS port of the Python engine, and a fixture suite requires byte-identical output between the two on every change.
  • CLI: pipx install fmstyle, then fmstyle format --write on files or stdin, and fmstyle lint in pre-commit or CI.
  • AI assistant: fmstyle install-skill teaches Claude Code to run every calculation it writes through the formatter before showing it. Any assistant with terminal access can do the same.

fmstyle is free and open source (MIT), and a sibling of fmsonar: the same philosophy of pure-stdlib Python, zero dependencies, and nothing ever leaving your machine. Source at github.com/oogi-io/fm-code-formatter.

Most house styles should be expressible as an fmstyle.json today. If yours needs a knob that does not exist yet, say a layout rule or naming pattern the config cannot describe, that is exactly the feedback I am after: open an issue on GitHub or reach me through the contact form and I will look at adding it. Style packs for real organisations are the whole point of the tool.

Further out, I would love to see a community style pack: a preset the FileMaker community maintains itself, with the rules decided by votes and pull requests. If you would contribute to something like that, don’t hesitate to ping me.