Skip to content

forge.toml Reference

Full schema reference for forge.toml.

[execution]

Repository-wide execution defaults.

toml
[execution]
default_backend = "ddev"   # "host" | "ddev" | custom Docker container name
parallel        = false    # run tools within a hook concurrently
cache           = false    # skip tools whose inputs are unchanged
tool_timeout    = "60s"    # default per-tool timeout (Go duration)
KeyTypeDefaultDescription
default_backendstring(auto)Default backend for all tools. When omitted, forge auto-detects DDEV (uses it if the container is running, else host). Set "host" to force host and disable auto-detection
parallelboolfalseRun a hook's tools concurrently (respecting depends_on)
cacheboolfalseEnable the run cache — unchanged inputs skip the tool
tool_timeoutstringDefault timeout for every tool, as a Go duration ("30s", "2m")
cache_ttlstringMax age of a cache entry before eviction (Go duration; empty = never)
cache_max_sizeint0Max cache entries kept; oldest evicted first (0 = unlimited)

[update]

Controls the forge update self-updater.

toml
[update]
pin_version = "v2.0.0"   # warn when the running binary differs
channel     = "stable"   # "stable" (default) or "rc"
KeyTypeDefaultDescription
pin_versionstringPrint a non-blocking warning when the running binary differs from this version
channelstring"stable"Release channel to update from: "stable" or "rc"

[workspace]

toml
[workspace]
members = ["apps/*", "packages/*"]
KeyTypeDefaultDescription
members[]string[]Glob patterns for workspace members (relative to repo root)

[hooks.<name>]

toml
[hooks.pre-commit]
enabled  = true
parallel = false   # optional: override [execution].parallel for this hook
KeyTypeDefaultDescription
enabledboolfalseWhether this hook is active
parallelbool(inherits [execution])Run this hook's tools concurrently

Supported hook names: pre-commit, commit-msg, prepare-commit-msg, pre-push, post-commit, post-merge, post-rewrite.


[hooks.<name>.tools.<key>]

toml
[hooks.pre-commit.tools.gofmt]
command          = "gofmt"
args             = ["-w"]
type             = "system"
backend          = "host"
extensions       = [".go"]
include_patterns = []
exclude_patterns = []
pass_files       = true
run_per_file     = false
restage          = true
on_failure       = ""
group            = ""
KeyTypeDefaultDescription
commandstringrequiredBinary name or path
args[]string[]Extra arguments
typestring"system""system" | "node" | "php" — affects binary resolution
backendstringglobal default"host" | "ddev" | <container-name>
extensions[]stringallRun only on files with these extensions
include_patterns[]stringallGlob allowlist for file paths (supports **)
exclude_patterns[]stringnoneGlob blocklist for file paths (supports **)
pass_filesbooltrueAppend staged file paths as arguments
run_per_fileboolfalseInvoke the tool once per matching file
restageboolfalseRe-stage modified files after tool runs
on_failurestring""Set to "stop" to abort remaining tools on error
groupstring""Used with HOOKS_ONLY / SKIP_GROUP_* to run a subset of tools
depends_on[]string[]Tool names that must run before this one (ordering under parallel)
timeoutstring(inherits [execution])Per-tool timeout as a Go duration ("30s", "2m")
cacheboolfalseEnable the run cache for this tool (or set [execution] cache)
envtable{}Extra environment variables for the tool process
stage_outputs[]string[]Paths to git add after the tool runs (for generated files)
show_outputboolfalseAlways print the tool's output, even on success
check_args[]string(uses args)Args to use instead of args in --check / forge ci mode
check_fail_if_outputboolfalseIn check mode, treat any output as a failure

Tool sections are executed in the order they appear in forge.toml (or by depends_on when parallel = true). forge validate rejects unknown or unsupported fields.

Glob patterns

include_patterns and exclude_patterns use double-star (**) glob syntax:

toml
exclude_patterns = ["vendor/**/*", "*.generated.php"]
include_patterns = ["src/**/*.php"]
  • * matches any sequence of characters within a single path segment.
  • ** matches zero or more path segments (i.e. any depth of subdirectories).
  • Paths are always matched as forward-slash-separated strings regardless of OS.

Tool name case sensitivity

Tool names in forge.toml are matched case-insensitively by --tool, --skip-tool, SKIP_<NAME>=1, and related flags. The name as defined in forge.toml is used in output; the comparison is always case-folded.


[hooks.commit-msg.policy]

toml
[hooks.commit-msg.policy]
conventional_commits = true
append_ticket_footer = false
require_ticket       = false
KeyTypeDefaultDescription
conventional_commitsboolfalseEnforce Conventional Commits prefix
append_ticket_footerboolfalseAppend Closes: TICKET footer from branch name
require_ticketboolfalseFail if branch has no ticket ID
ticket_patternstring([A-Z]+-[0-9]+)Regex with capture group matched against the branch name to extract a ticket ID. Default matches Jira/Linear style (e.g. PRJ-123). Use (#[0-9]+) for GitHub issues.
allowed_typesarray(default set)Custom list of allowed Conventional Commits types. Overrides the default set (feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert). Only active when conventional_commits = true.

Complete example

toml
[execution]
default_backend = "ddev"

[workspace]
members = ["apps/*"]

[hooks.pre-commit]
enabled = true

[hooks.pre-commit.tools.prettier]
command    = "prettier"
args       = ["--write"]
type       = "node"
extensions = [".ts", ".vue", ".json"]
restage    = true
group      = "format"

[hooks.pre-commit.tools.eslint]
command    = "eslint"
args       = ["--fix"]
type       = "node"
extensions = [".ts", ".vue"]
restage    = true
group      = "lint"

[hooks.pre-commit.tools.phpcs]
command    = "vendor/bin/phpcs"
args       = ["--standard=PSR12"]
type       = "php"
extensions = [".php"]

[hooks.commit-msg]
enabled = true

[hooks.commit-msg.policy]
conventional_commits = true
append_ticket_footer = true
require_ticket       = false

Released under the MIT License.