Skip to content

/commands/deno/deno-fmt-check

deno fmt --check: check formatting in CI without changing files

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
Deno
versions
Deno 2.x
os
any

deno fmt --check checks whether files are formatted, prints a diff for each one that is not, and exits with code 1 without changing anything. Plain deno fmt rewrites the files in place. Put deno fmt --check in CI next to deno lint so unformatted code fails the build; run deno fmt locally to fix it.

Check, fix, check again

bash
printf 'const x = {a:1,\n  b:2}\nconsole.log( x )\n' > main.ts
npx --yes deno@2 fmt --check main.ts > check.log 2>&1
echo "check exit=$?"
tail -n 1 check.log
npx --yes deno@2 fmt main.ts 2>&1
cat main.ts
npx --yes deno@2 fmt --check main.ts 2>&1
echo "check exit=$?"

Output

check exit=1
error: Found 1 not formatted file in 1 file
/tmp/work/main.ts
Checked 1 file
const x = { a: 1, b: 2 };
console.log(x);
Checked 1 file
check exit=0

Without file arguments, deno fmt walks the current directory, skipping files ignored by .gitignore and the fmt.exclude list in deno.json.

Useful options

OptionEffect
--checkReport unformatted files and exit 1; write nothing
--fail-fastWith --check, stop at the first unformatted file
--ext=tsFormat stdin or extensionless files as this type
--line-width=100Maximum line width (default 80)
--indent-width=4Spaces per indent (default 2)
--use-tabsIndent with tabs
--single-quotePrefer single quotes (default double)
--no-semicolonsOmit semicolons where possible
--ignore=dist,vendorSkip paths

The same settings can live in deno.json so every developer and CI job uses them:

deno.json
{
  "fmt": {
    "lineWidth": 100,
    "singleQuote": true,
    "exclude": ["dist/"]
  }
}

Svelte, Vue, Astro and Angular templates need --unstable-component, and SQL files --unstable-sql. Deno also reads .editorconfig for indentation settings unless you pass --no-editorconfig.

Supported files

deno fmt formats much more than TypeScript, which is why --check can fail on a file you did not expect:

TypeExtensions
JavaScript and TypeScript.js .cjs .mjs .jsx .ts .mts .cts .tsx
Data.json .jsonc .yml .yaml
Markdown.md .markdown and other Markdown extensions; fenced code blocks with a language are formatted too
Styles and markup.css .scss .less .html .xml .svg
Notebooks.ipynb
Components (unstable).astro .svelte .vue with --unstable-component
SQL (unstable).sql with --unstable-sql

To keep a generated or vendored folder out of the check, list it in fmt.exclude in deno.json or pass --ignore.

In a CI workflow

Run the check before the slower steps, so a formatting mistake fails the job in seconds:

.github/workflows/ci.yml (steps)
- run: deno fmt --check
- run: deno lint
- run: deno test

--check reports every unformatted file with a diff; add --fail-fast in large repositories to stop at the first one. A failing check is fixed by running deno fmt locally and committing the result, so pin the same Deno version locally and in CI: formatter output can change between releases.

FAQ

Can I use deno fmt in a Node.js project?

Yes. deno fmt does not need a deno.json and formats plain JavaScript, TypeScript, JSON, Markdown, CSS and YAML files; it reads its options from deno.json only if one exists.

How do I stop deno fmt from changing one block of code?

Put a // deno-fmt-ignore comment on the line before it in JavaScript or TypeScript, or // deno-fmt-ignore-file at the top to skip the whole file. Markdown, HTML and CSS use the HTML comment form, YAML uses # deno-fmt-ignore.

Why does deno fmt --check pass locally but fail in CI?

Usually a different Deno version or a missing deno.json in the CI working directory. Pin the Deno version in CI and run the check from the folder that holds the configuration.

Sources