Skip to content

Config File

xlflow reads xlflow.toml from the project root. It is the single source of truth for workbook paths, source directories, VBE behaviour, and static analysis rules.

Full annotated example

This is the file produced by xlflow new. The comments are preserved so that each option is self-documenting.

toml
# Project identity and entry point.
[project]
# Project name used in output messages. Falls back to the workbook base name.
name = "sample"
# Default macro invoked by xlflow run when no positional macro is given.
entry = "Main.Run"

# Excel automation settings.
[excel]
# Path to the workbook, relative to the project root or absolute.
path = "build/Book.xlsm"
# Make the Excel application window visible during automation.
visible = false
# Suppress Excel alert dialogs (e.g. overwrite confirmations).
display_alerts = false
# Excel bridge mode. Valid values: "auto", "dotnet".
bridge = "auto"

# Source tree directories.
[src]
# Directory for standard .bas modules.
modules = "src/modules"
# Directory for class .cls modules.
classes = "src/classes"
# Directory for UserForm .frm files.
forms = "src/forms"
# Directory for workbook document module text.
workbook = "src/workbook"

# VBE component folder support (Rubberduck-style).
[vba]
# Enable @Folder("A.B") annotations and nested source paths.
folders = true
# How xlflow handles @Folder annotations during push.
# Valid values: "update", "preserve", "ignore".
#   "update"    – rewrite from source directory layout.
#   "preserve"  – keep existing annotations as-is.
#   "ignore"    – disable folder annotation read/write.
folder_annotation = "update"
# Automatically assign default folder annotations based on source paths.
default_component_folders = true

# UserForm source mode.
[userform]
# Where UserForm code-behind lives in the source tree.
# Valid values: "frm", "sidecar".
#   "frm"     – code is kept inside the exported .frm file.
#   "sidecar" – code is split into src/forms/code/<FormName>.bas.
code_source = "sidecar"

# Automatic backup retention is disabled by default.
# [backup.retention]
# enabled = false
# max_count = 20
# max_age_days = 30
# min_keep = 5
# max_total_size_mb = 2048

# Static analysis rules.
[lint]
# Disable specific lint rules by diagnostic ID.
disabled_rules = []

# VB020 unused-local-variable warnings are enabled by default.
# Add "VB020" to disabled_rules if a project intentionally keeps scratch locals.
#
# Optional project-wide lint rules. Uncomment individual rules to enable them.
# detect_scope_shadowing = true          # VB018
# detect_unused_private_procedures = true # VB021
# detect_nested_with_ambiguity = true    # VB027

# Runtime-risk analysis rules.
[analyze]
# Disable specific analyzer rules by diagnostic ID.
disabled_rules = []

Section reference

[project]

KeyTypeRequiredDefaultDescription
namestringnosampleDisplay name for the project. Falls back to the workbook base name if omitted.
entrystringyesMain.RunQualified name of the macro executed by xlflow run when no positional argument is supplied.

[excel]

KeyTypeRequiredDefaultDescription
pathstringyesbuild/Book.xlsmWorkbook, binary workbook, or add-in path. May be relative to the project root or absolute.
visibleboolnofalseWhether the Excel application window is shown during automation.
display_alertsboolnofalseWhether Excel shows its own alert dialogs (e.g. overwrite confirmation).
bridgestringno"auto"Excel bridge mode. Valid values are "auto" and "dotnet".

[src]

KeyTypeRequiredDefaultDescription
modulesstringnosrc/modulesRoot directory for standard .bas modules.
classesstringnosrc/classesRoot directory for class .cls modules.
formsstringnosrc/formsRoot directory for UserForm .frm files.
workbookstringnosrc/workbookRoot directory for workbook document module text.

When [vba].folders = true, files may be nested under these roots according to @Folder annotations.

[vba]

KeyTypeRequiredDefaultDescription
foldersboolnotrueEnable Rubberduck-style @Folder("A.B") annotations and nested source paths.
folder_annotationstringno"update"How push treats @Folder annotations.
Valid values: "update", "preserve", "ignore"
default_component_foldersboolnotrueAutomatically assign default folder annotations based on the relative source path.

[userform]

KeyTypeRequiredDefaultDescription
code_sourcestringno"sidecar"*Where UserForm code-behind lives in the source tree.
Valid values: "frm", "sidecar"

* xlflow new defaults to "sidecar". xlflow init defaults to "frm" so that existing code inside .frm files remains authoritative. Use xlflow init --userform-code-source sidecar for imported workbooks that should start with sidecar code and Designer specs.

[backup.retention]

KeyTypeRequiredDefaultDescription
enabledboolnofalseEnable automatic pruning after successful backup-producing operations.
max_countintno20Keep total valid backups within this count. 0 disables the count limit.
max_age_daysintno30Delete valid backups older than this many days. 0 disables the age limit.
min_keepintno5Always protect the newest valid backups from all automatic limits.
max_total_size_mbintno2048Keep total backup size within this decimal MB limit. 0 disables it.

Automatic retention is disabled by default and only affects backups for the configured [excel].path. Manual xlflow backup prune does not require enabled = true.

Negative numeric values are configuration errors. min_keep > max_count is also invalid when max_count is greater than zero. If all limits are disabled, automatic pruning performs no deletion. Invalid entries and legacy directories without metadata are skipped, not deleted.

[lint]

KeyTypeRequiredDefaultDescription
disabled_rulesstring[]no[]Disable configurable lint rules by diagnostic ID.

Legacy per-rule booleans such as forbid_select = false remain accepted for compatibility, but xlflow emits a deprecation warning. Prefer disabled_rules = ["VB002"].

VB020 unused-local-variable warnings are enabled by default and can be disabled with disabled_rules = ["VB020"]. Other project-wide lint rules such as detect_unused_private_procedures = true (VB021) remain disabled by default. New xlflow.toml files include commented examples so projects can opt in deliberately.

Configurable lint rule IDs:

IDLegacy key
VB001require_option_explicit
VB002forbid_select
VB003forbid_activate
VB004forbid_on_error_resume_next
VB005detect_implicit_variant
VB006forbid_public_module_fields
VB007forbid_interactive_input
VB018detect_scope_shadowing
VB019detect_multiple_declarator_clarity
VB020detect_unused_local_variables
VB021detect_unused_private_procedures
VB022detect_confusing_call_syntax
VB023detect_for_each_control_type
VB026detect_dangerous_resume
VB027detect_nested_with_ambiguity

Safety diagnostics VB008 through VB015, VB028, VB029, VB031, and VB032 are always enabled and cannot be disabled with disabled_rules.

For local exceptions, keep the rule enabled and suppress a specific source line with an apostrophe comment:

vb
' xlflow:disable-next-line VB002
Range("A1").Select
Range("A2").Select ' xlflow:disable-line VB002

Preflight-blocking lint diagnostics VB008 through VB015, VB028, VB029, VB031, and VB032 cannot be suppressed inline.

[analyze]

KeyTypeRequiredDefaultDescription
disabled_rulesstring[]no[]Disable configurable analyzer rules by diagnostic ID.

Legacy per-rule booleans such as forbid_unqualified_excel_objects = false remain accepted for compatibility, but xlflow emits a deprecation warning. Prefer disabled_rules = ["VBA205"].

Configurable analyzer rule IDs:

IDLegacy key
VBA201detect_range_find_nothing_check
VBA202detect_object_use_before_set
VBA203detect_application_state_restore
VBA204detect_error_handler_fallthrough
VBA205forbid_unqualified_excel_objects
VBA206detect_byref_argument_mismatch
VBA207detect_dictionary_collection_guard
VBA208detect_redim_preserve_dimension
VBA209detect_object_array_comparison
VBA210detect_function_return_path
VBA211detect_excel_object_member_mismatch
VBA212detect_non_short_circuit_object_guard

Analyzer diagnostics VBA101 through VBA106 are always enabled and cannot be disabled with disabled_rules.

Analyzer diagnostics can use the same inline suppression syntax:

vb
' xlflow:disable-next-line VBA205
Range("A1").Value = 1

Preflight-blocking analyzer errors such as VBA104, VBA105, VBA106, and VBA211 cannot be suppressed inline. Unknown inline IDs, unsupported IDs, and unused suppressions are reported as command warnings.

Defaults differ between new and init

  • xlflow new writes [userform].code_source = "sidecar".
  • xlflow init writes [userform].code_source = "frm" by default.
  • xlflow init --userform-code-source sidecar writes [userform].code_source = "sidecar" and generates imported UserForm specs under src/forms/specs.
  • xlflow form migrate sidecar converts an existing imported project from frm to sidecar after creating sidecar code and Designer specs.
  • xlflow new defaults to build/Book.xlsm when the workbook argument is omitted or has no extension. Use an explicit .xlam filename to create an Excel add-in project or .xlsb for an Excel Binary Workbook VBA project.
  • xlflow init preserves the copied workbook filename and extension, including .xlam and .xlsb.

All other sections use the same defaults regardless of how the project was created.

Stable contract

For the authoritative specification of configuration keys, validation rules, and exit-code contracts, see docs/specs/cli-contract.md.

Released under the MIT License.