Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/letstri/druk/llms.txt

Use this file to discover all available pages before exploring further.

Druk ships no formatters of its own. Instead, it delegates to whatever external tools you have installed, running them automatically after a file is saved. Any command that rewrites a file in place — Prettier, gofmt, rustfmt, Black, or a custom script — can be wired up through the formatters setting.

Enabling format on save

Set formatOnSave: true in your config to activate formatting. Without it, the formatters map is stored but never invoked.
~/.config/druk/config.json
{
  "formatOnSave": true
}

Configuring formatters

The formatters setting is a map keyed by comma-separated file extensions (without dots) or the special wildcard "*". Each value is a command array. Druk appends the saved file’s path as the last argument before running the command.
The formatter command receives the file path as its last argument automatically. So configuring ["prettier", "--write"] runs prettier --write src/main.ts — you never need to write the path into the command array yourself.If your tool needs the path somewhere other than the end, use the {} token as a placeholder anywhere in the arguments array: ["my-tool", "--file", "{}", "--flag"] becomes my-tool --file src/main.ts --flag.
The command must rewrite the file in place. Druk does not pipe stdin or capture stdout — it re-reads the file from disk after the command exits. A formatter that only prints to stdout (without --write or -w) will have no effect.
~/.config/druk/config.json
{
  "formatOnSave": true,
  "formatters": {
    "ts,tsx,js,jsx": ["prettier", "--write"],
    "go": ["gofmt", "-w"],
    "rs": ["rustfmt"],
    "py": ["black"],
    "*": ["my-formatter"]
  }
}

Wildcard *

The "*" key matches any file extension that no more-specific entry covers. It acts as a catch-all fallback — a file with a .ts extension uses the "ts,tsx,js,jsx" entry, not "*". A file whose extension has no specific entry uses "*" if it is present.

Disabling an entry

Set the command array to [] to disable a formatter entry without removing the key:
{
  "formatters": {
    "ts,tsx,js,jsx": ["prettier", "--write"],
    "py": []
  }
}

trimOnSave

trimOnSave is a separate setting from formatOnSave. When true, Druk strips trailing whitespace from every line and ensures the file ends with exactly one newline — before the formatter runs. It defaults to false.
{
  "trimOnSave": true,
  "formatOnSave": true,
  "formatters": {
    "go": ["gofmt", "-w"]
  }
}
Both can be active at the same time. The order is: trim → save → format → re-read buffer from disk.

Per-project formatter config

Put a formatters key in <project>/.druk/settings.json to override the user-level formatter map for that project. Because formatters is an object-valued setting, it replaces your user-level map entirely for that project — it is not merged entry by entry.
<project>/.druk/settings.json
{
  "formatOnSave": true,
  "formatters": {
    "py": ["autopep8", "--in-place"]
  }
}
In this example, the project uses autopep8 instead of whatever Python formatter is in your user config. The user-level entries for ts, go, and any other extensions are not inherited — if you need them in the project, include them explicitly.

Formatter timeout

A formatter that hangs is killed after 10 seconds. If this happens, an error message appears in the status bar and the buffer is not reloaded. The editor remains fully usable while waiting.

Build docs developers (and LLMs) love