xlflow fmt
Format VBA source files with a conservative, structure-aware formatter backed by tree-sitter-vba.
Usage
xlflow fmt [--write | --check | --diff] [--line-numbers preserve|add|remove|renumber] [--json] [--stdin] [<path>...]Options and Arguments
| Option / argument | Description | Default |
|---|---|---|
<path>... | Files or directories to format. Defaults to project src. | project src |
--write | Write formatted source back to files. | false |
--check | Check formatting without modifying files. | false |
--diff | Show unified diff of formatting changes. | false |
--line-numbers | Line-number policy for VBA statements. | preserve |
--stdin | Read VBA source from stdin, write formatted to stdout. | false |
--json | Return structured machine-readable output. | false |
At most one of --write, --check, or --diff may be used. When none is set, fmt runs in inspect mode and reports which files would be changed.
Examples
# Show which files need formatting (inspect mode)
xlflow fmt
# Write formatted source back to files
xlflow fmt --write
# Check formatting in CI (non-zero exit if unformatted)
xlflow fmt --check
# Show unified diff of changes
xlflow fmt --diff
# Preview diagnostic VBA line numbers without writing
xlflow fmt --line-numbers add
# Apply diagnostic VBA line numbers
xlflow fmt --line-numbers add --write
# Remove diagnostic VBA line numbers
xlflow fmt --line-numbers remove --write
# Normalize existing line numbers
xlflow fmt --line-numbers renumber --write
# Format a specific file or directory
xlflow fmt --write src/modules/Main.bas
xlflow fmt --write src/modules/
# Pipe through stdin
cat MyModule.bas | xlflow fmt --stdin
# Machine-readable output
xlflow fmt --json
xlflow fmt --check --json
# Pipe through stdin with JSON envelope
cat MyModule.bas | xlflow fmt --stdin --jsonConfiguration
Operator spacing, declaration spacing, keyword casing, and known built-in casing are enabled by default:
[fmt]
operator_spacing = true
declaration_spacing = true
keyword_casing = true
builtin_casing = trueSet operator_spacing = false to keep expression/operator spacing unchanged while still applying the other formatter passes. Set declaration_spacing = false to keep declaration whitespace unchanged while still applying indentation, line-number handling, and other enabled formatter passes. Set keyword_casing = false to keep VBA keyword casing unchanged. Set builtin_casing = false to keep known VBA/Excel/Office built-in identifier casing unchanged.
Notes
IMPORTANT
fmt is source-only and does not open Excel COM. It targets .bas and .cls files under the configured project source directories plus tests/. It uses parser-backed block structure for indentation and only applies minimal text edits. [!NOTE] By default, fmt normalizes safe binary operator spacing such as x=1+2 to x = 1 + 2 and Range("A"&i).Value=x+1 to Range("A" & i).Value = x + 1. [!NOTE] Operator spacing preserves named arguments such as Filename:="C:\a.xlsx", type-declaration suffixes such as Dim n&, strings, comments, attributes, preprocessor directives, and explicit line-continuation statements. Ambiguous cases are skipped instead of rewritten. [!NOTE] Declaration spacing normalizes safe declarations such as Dim wb As Workbook to Dim wb As Workbook, Dim a As Long,b As String to Dim a As Long, b As String, and Private Function Add(a As Long,b As Long)As Long to Private Function Add(a As Long, b As Long) As Long. [!NOTE] Declaration spacing preserves type-declaration suffixes, comments, strings, attributes, preprocessor directives, Declare statements, fixed-length string declarations, and explicit line-continuation statements. Unsupported declaration shapes are skipped. [!NOTE] Keyword and built-in casing normalize conservative cases such as option explicit, dim ws as worksheet, msgbox vbexclamation, and ws.cells(...).end(xlup).row. User-defined identifiers are not intentionally recased, and ambiguous built-in/member names are skipped. [!WARNING] .frm files are skipped by default. The formatter preserves class module metadata (Attribute VB_*, VERSION, BEGIN/END blocks) verbatim. [!WARNING] Files with VBA parser errors are skipped in file-based formatting so broken source is not rewritten. With --stdin, parser errors return fmt_failed. [!NOTE] Plain xlflow fmt uses --line-numbers preserve. It does not add line numbers automatically, but it preserves existing ones where possible. [!NOTE] --line-numbers add skips Select Case, Case / Case Else, and End Select control lines. Only executable statements inside the case bodies receive diagnostic line numbers. [!NOTE] --line-numbers add also numbers only the first physical line of an explicit VBA line-continuation statement. Continuation tail lines stay unnumbered to avoid compile errors. [!NOTE] --stdin --json writes the JSON envelope to stdout instead of formatted text. The envelope includes output.changed / output.unchanged summary fields but does not include the formatted source body. --stdin cannot be combined with --line-numbers. [!NOTE] fmt --line-numbers ... still follows the normal fmt contract. Without --write, it only reports what would change. Use --write to persist the numbered or de-numbered source.
JSON Output
Successful --json output uses the xlflow envelope with command-specific fields.
{
"status": "ok",
"command": "fmt",
"target": {
"kind": "source",
"path": "src/modules, src/classes, src/workbook, tests",
"description": "source files"
},
"output": {
"mode": "inspect",
"changed": 2,
"unchanged": 5,
"skipped": 1,
"total": 8,
"line_numbers": {
"mode": "add",
"applied": false,
"files_to_change": 2,
"lines_to_add": 24,
"lines_to_remove": 0,
"lines_to_renumber": 0,
"warnings": []
},
"changed_paths": ["src/modules/Main.bas", "src/modules/Utils.bas"],
"skipped_paths": ["src/forms/UserForm1.frm"],
"skipped_reasons": [
{ "path": "src/forms/UserForm1.frm", "reason": "unsupported extension: .frm" }
]
}
}Exit Codes
| Code | Meaning |
|---|---|
0 | Success or no changes (diff mode) |
1 | --check found unformatted files |
2 | Invalid argument combination |
3 | File system or read/write failure |
Related
When to use this command
Use xlflow fmt when the task matches the command description above. For a goal-oriented workflow, start with the How-to guides and return here for exact options.
Prerequisites
Check the project configuration and run xlflow doctor --json before workbook-backed operations. Source-only commands can run without Excel; commands that read or mutate a workbook require Windows Excel and VBIDE access.
What this command reads and changes
The command reads the inputs and configuration described in its syntax and examples. Treat source files, the saved workbook, and a live session as separate states; add --session when the live workbook is authoritative. Any mutation is reversible only when a backup or explicit session save boundary exists.
Effect on source-of-truth state
Use xlflow status --json before and after the command. A source edit normally requires push; a workbook edit normally requires pull; a dirty live session requires save --session or an intentional discard.
Common workflows
Combine this command with the relevant source/workbook/session workflow, and use --json in scripts and agent loops.
Common failures
Read the structured error.code, exit code, and recovery metadata instead of scraping terminal text. The symptom-oriented troubleshooting guide maps installation, execution, session, VS Code, and WSL failures to recovery steps.