Twig formatter
mago twig:fmt formats Twig templates. Directory scans select .twig files under source.paths, including index.html.twig, regardless of source.extensions. Explicit files use Twig even with no extension or a .php extension. mago fmt, mago fix, and the existing file-listing command keep their PHP behavior.
mago twig:fmt templates/
mago twig:fmt --check
mago twig:fmt --dry-run
mago twig:fmt --staged
mago twig:fmt --stdin-input --stdin-filepath templates/index.html.twig < templates/index.html.twig
The command selects the language. Stdin always uses Twig, with or without --stdin-filepath; that path controls exclusions and diagnostics only. Stdin writes to stdout, not to the buffer's disk file. --staged selects exact-case .twig files and updates only the Git index, not working copies. Explicit .TWIG files still work.
Scope
Mago formats Twig tags, expressions, comments, and indentation. Its spacing follows the Twig coding standard. It keeps each named argument's separator (name: value or name = value) so formatting does not require a newer Twig version. Macro defaults stay name = value.
It does not parse or reformat HTML, CSS, JavaScript, or other template text. It keeps string contents, interpolation text inside strings, whitespace-control markers (- and ~), and verbatim bodies intact. It leaves unknown extension tags as written. It also keeps a tag's layout if spacing would turn a name, such as not, into an operator. Syntax errors prevent changes to the affected file.
Files that use the legacy raw block also stay unchanged.
Mago does not add a final newline or change line endings in template text. end-of-line only controls line breaks that the formatter adds inside Twig tags.
Formatting changes what Twig's source() function returns for a formatted file. Use @mago-format-ignore in files whose source text must stay unchanged.
Mago uses Twig's built-in operators. Use ignore markers in files that rely on custom operators from an extension.
To bound stack use, formatting has a 32-level parser nesting limit. Inputs that exceed it return an error and stay unchanged.
Indentation
Twig renders whitespace outside its tags as text. Mago keeps every byte of that text unchanged: leading spaces, blank lines, line endings, and the final newline. It only adds indentation inside Twig tags when it wraps code. Wrapped lines follow the tag's existing indentation.
With print-width = 30:
{{
user.name|default(
'A guest with a longer name'
)
}}
There is no setting that rewrites whitespace outside tags. Tags with inline comments, ambiguous keyword names, or expression trees too deep to format safely stay as written.
Configuration
Twig settings live under [twig.formatter]. They do not inherit PHP formatter settings, exclusions, or presets. source.excludes applies to both tools; twig.formatter.excludes applies only to Twig. Use mago config --show twig or mago config --show twig.formatter; both also support --schema. Configuration layers merge through the usual extends rules. The old [formatter.twig] table is not supported.
[twig.formatter]
enabled = true
print-width = 120
tab-width = 4
use-tabs = false
end-of-line = "auto"
| Option | Default | Meaning |
|---|---|---|
enabled | true | Format .twig files. When false, leave them unchanged, including stdin and staged files. |
excludes | [] | Twig-only path prefixes or globs, using the shared source.glob settings. |
print-width | 120 | Target width for wrapping Twig expressions. Long strings stay intact. |
tab-width | 4 | Spaces per indentation level and the width of a tab. |
use-tabs | false | Use tabs for indentation. |
end-of-line | "auto" | Use auto, lf, crlf, or cr for generated line breaks. auto uses the first line ending in template text outside Twig tags, or LF if there is none. |
To disable Twig formatting:
[twig.formatter]
enabled = false
Ignore markers
Use the same markers as the PHP formatter, inside Twig comments:
{# @mago-format-ignore-next #}
{{ leave_this_alone }}
{# @mago-format-ignore-start #}
{{ leave_this_region_alone }}
{# @mago-format-ignore-end #}
@mago-format-ignore skips the whole file. -next skips the next Twig statement, including its full body when it opens a block. @mago-formatter-ignore and its suffixes work too.