Configuration

repomatic reads two kinds of pyproject.toml configuration. Its own settings live in [tool.repomatic], documented below. The third-party tools it runs are configured through their own standard [tool.*] sections ([tool.ruff], [tool.mypy], [tool.typos], [tool.nuitka], and so on); repomatic discovers and resolves these through its tool runner, where they are documented.

[tool.repomatic] configuration

Downstream projects can customize workflow behavior by adding a [tool.repomatic] section in their pyproject.toml. These options control the defaults for the corresponding CLI commands.

The [tool.repomatic] section is powered by Click Extra’s pyproject.toml configuration. Click Extra handles CWD-first discovery (walking up to the VCS root), key normalization (kebab-case to snake_case), and typed dataclass schemas (nested sub-tables, opaque dict fields, strict validation).

[tool.repomatic]
pypi-package-history = ["old-name", "older-name"]

awesome-template.sync = false
bumpversion.sync = false
cache.max-age = 14
dev-release.sync = false
gitignore.sync = false
labels.sync = false
mailmap.sync = false
setup-guide = false
uv-lock.sync = false

dependency-graph.output = "./docs/assets/dependencies.mmd"
dependency-graph.all-groups = true
dependency-graph.all-extras = true
dependency-graph.no-groups = []
dependency-graph.no-extras = []
dependency-graph.level = 0

gitignore.location = "./.gitignore"
gitignore.extra-categories = ["terraform", "go"]
gitignore.extra-content = '''
junit.xml

# Claude Code
.claude/
'''

exclude = ["skills", "workflows/debug.yaml", "zizmor"]

labels.extra-files = ["https://example.com/my-labels.toml"]

nuitka.enabled = false
nuitka.entry-points = ["mpm"]
nuitka.unstable-targets = ["linux-arm64", "windows-arm64"]

workflow.sync = false
workflow.source-paths = ["extra_platforms"]
workflow.extra-paths = ["install.sh", "dotfiles/**"]
workflow.ignore-paths = ["uv.lock"]

[[tool.repomatic.labels.file-rules]]
label = "📚 docs"
any-glob-to-any-file = ["docs/**"]

[[tool.repomatic.labels.content-rules]]
label = "🛡️ security"
patterns = ["(CVE|vulnerability)"]

[tool.repomatic.workflow.paths]
"tests.yaml" = ["install.sh", "packages.toml", ".github/workflows/tests.yaml"]

Option

Description

Default

abandoned-versions

Versions documented in the changelog but never published.

[]

agents.location

Directory prefix for Claude Code agent files, relative to the repository root.

"./.claude/agents/"

awesome-template.sync

Whether awesome-template sync is enabled for this project.

true

bumpversion.sync

Whether bumpversion config sync is enabled for this project.

true

cache.dir

Override the binary cache directory path.

""

cache.github-release-ttl

Freshness TTL for cached single-release bodies (seconds).

604800

cache.github-releases-ttl

Freshness TTL for cached all-releases responses (seconds).

86400

cache.max-age

Auto-purge cached entries older than this many days.

30

cache.pypi-ttl

Freshness TTL for cached PyPI metadata (seconds).

86400

changelog.bullet-word-threshold

Word count above which lint-changelog warns about a changelog bullet.

40

changelog.location

File path of the changelog, relative to the root of the repository.

"./changelog.md"

dependency-graph.all-extras

Whether to include all optional extras in the graph.

true

dependency-graph.all-groups

Whether to include all dependency groups in the graph.

true

dependency-graph.level

Maximum depth of the dependency graph.

(none)

dependency-graph.no-extras

Optional extras to exclude from the graph.

[]

dependency-graph.no-groups

Dependency groups to exclude from the graph.

[]

dependency-graph.output

Path where the dependency graph Mermaid diagram should be written.

"./docs/assets/dependencies.mmd"

dev-release.sync

Whether dev pre-release sync is enabled for this project.

true

docs.apidoc-exclude

Glob patterns for modules to exclude from sphinx-apidoc.

[]

docs.apidoc-extra-args

Extra arguments appended to the sphinx-apidoc invocation.

[]

docs.update-script

Path to a Python script run after sphinx-apidoc to generate dynamic content.

"./docs/docs_update.py"

exclude

Additional components and files to exclude from repomatic operations.

[]

gitignore.extra-categories

Additional gitignore template categories to fetch from gitignore.io.

[]

gitignore.extra-content

Additional content to append at the end of the generated .gitignore file.

(see example)

gitignore.location

File path of the .gitignore to update, relative to the root of the repository.

"./.gitignore"

gitignore.sync

Whether .gitignore sync is enabled for this project.

true

include

Components and files to force-include, overriding default exclusions.

[]

labels.content-rules

Structured per-label rules for the content-based labeller.

[]

labels.extra

Inline label definitions applied at sync time under the default profile.

[]

labels.extra-files

URLs of additional label definition files (JSON, JSON5, TOML, or YAML).

[]

labels.file-rules

Structured per-label rules for the file-based labeller.

[]

labels.sync

Whether label sync is enabled for this project.

true

mailmap.sync

Whether .mailmap sync is enabled for this project.

true

manpages.asset-name

Filename stem (without the .tar.gz extension) for the man-page tarball uploaded to the GitHub release.

""

manpages.script

Click command target whose tree gets rendered as roff .1 files and attached as a tarball asset on every GitHub release.

""

notification.unsubscribe

Whether the unsubscribe-threads workflow is enabled.

false

nuitka.enabled

Whether Nuitka binary compilation is enabled for this project.

true

nuitka.entry-points

Which [project.scripts] entry points produce Nuitka binaries.

[]

nuitka.extras

[project.optional-dependencies] extras to install before the Nuitka build.

[]

nuitka.unstable-targets

Nuitka build targets allowed to fail without blocking the release.

[]

pypi-package-history

Former PyPI package names for projects that were renamed.

[]

setup-guide

Whether the setup guide issue is enabled for this project.

true

skills.location

Directory prefix for Claude Code skill files, relative to the repository root.

"./.claude/skills/"

test-matrix.exclude

Extra exclude rules applied to both full and PR test matrices.

[]

test-matrix.full-include

Full-matrix-only job rows, added as standalone matrix combinations.

[]

test-matrix.include

Extra include directives applied to both full and PR test matrices.

[]

test-matrix.remove

Per-axis value removals applied to both full and PR test matrices.

{}

test-matrix.replace

Per-axis value replacements applied to both full and PR test matrices.

{}

test-matrix.unstable

Full-matrix-only combinations to flag continue-on-error in CI.

[]

test-matrix.variations

Extra matrix dimension values added to the full test matrix only.

{}

uv-lock.sync

Whether uv.lock sync is enabled for this project.

true

vulnerable-deps.sources

Advisory databases to consult for known vulnerabilities.

['uv-audit', 'github-advisories']

vulnerable-deps.sync

Whether the fix-vulnerable-deps job is enabled for this project.

true

workflow.extra-paths

Literal entries to append to every workflow’s paths: filter.

[]

workflow.ignore-paths

Literal entries to strip from every workflow’s paths: filter.

[]

workflow.paths

Per-workflow override of the paths: filter, keyed by filename.

{}

workflow.source-paths

Source code directory names for workflow trigger paths: filters.

(none)

workflow.sync

Whether workflow sync is enabled for this project.

true

abandoned-versions

Versions documented in the changelog but never published.

Type: list[str] | Default: []

A version reached only its [changelog] Release vX.Y.Z freeze and was then skipped per CLAUDE.md § Skip and move forward (botched build, broken artifact, bad metadata) without rewriting history. List those versions here so lint-changelog reports them as skipped (an info log line) instead of flagging them every run as X.Y.Z: not found on PyPI. Applies to both PyPI lookups and the git-tag fallback.

Example:

[tool.repomatic]
abandoned-versions = []

agents.location

Directory prefix for Claude Code agent files, relative to the repository root.

Type: str | Default: "./.claude/agents/"

Agent files are written as {agents_location}/{agent-id}.md. Useful for repositories where .claude/ is not at the root (like dotfiles repos that store configs under a subdirectory).

Example:

[tool.repomatic]
agents.location = "./.claude/agents/"

awesome-template.sync

Whether awesome-template sync is enabled for this project.

Type: bool | Default: true

Repositories whose name starts with awesome- get their boilerplate synced from files bundled in repomatic. Set to false to opt out.

Example:

[tool.repomatic]
awesome-template.sync = true

bumpversion.sync

Whether bumpversion config sync is enabled for this project.

Type: bool | Default: true

Projects that manage their own [tool.bumpversion] section and do not want the autofix job to overwrite it can set this to false.

Example:

[tool.repomatic]
bumpversion.sync = true

cache.dir

Override the binary cache directory path.

Type: str | Default: ""

When empty (the default), the cache uses the platform convention: ~/Library/Caches/repomatic on macOS, $XDG_CACHE_HOME/repomatic or ~/.cache/repomatic on Linux, %LOCALAPPDATA%\repomatic\Cache on Windows. The REPOMATIC_CACHE_DIR environment variable takes precedence over this setting.

Example:

[tool.repomatic]
cache.dir = ""

cache.github-release-ttl

Freshness TTL for cached single-release bodies (seconds).

Type: int | Default: 604800

GitHub release bodies are immutable once published, so a long TTL (7 days) is safe. Set to 0 to disable caching for single-release lookups.

Example:

[tool.repomatic]
cache.github-release-ttl = 604800

cache.github-releases-ttl

Freshness TTL for cached all-releases responses (seconds).

Type: int | Default: 86400

New releases can appear at any time, so a shorter TTL (24 hours) balances freshness with API savings.

Example:

[tool.repomatic]
cache.github-releases-ttl = 86400

cache.max-age

Auto-purge cached entries older than this many days.

Type: int | Default: 30

Set to 0 to disable auto-purge. The REPOMATIC_CACHE_MAX_AGE environment variable takes precedence over this setting.

Example:

[tool.repomatic]
cache.max-age = 30

cache.pypi-ttl

Freshness TTL for cached PyPI metadata (seconds).

Type: int | Default: 86400

PyPI metadata changes when new versions are published. A 24-hour TTL avoids redundant API calls while keeping data reasonably current.

Example:

[tool.repomatic]
cache.pypi-ttl = 86400

changelog.bullet-word-threshold

Word count above which lint-changelog warns about a changelog bullet.

Type: int | Default: 40

A changelog entry is a release note, not a commit message: ideally one short sentence stating what changed (see CLAUDE.md § Changelog entry length). lint-changelog emits a non-fatal warning for every bullet in the unreleased section longer than this many words, nudging verbose, implementation-heavy entries back toward a user-facing summary. Released sections are immutable and never flagged. Set to 0 to disable the check.

Example:

[tool.repomatic]
changelog.bullet-word-threshold = 40

changelog.location

File path of the changelog, relative to the root of the repository.

Type: str | Default: "./changelog.md"

Example:

[tool.repomatic]
changelog.location = "./changelog.md"

dependency-graph.all-extras

Whether to include all optional extras in the graph.

Type: bool | Default: true

When True, the update-deps-graph command behaves as if --all-extras was passed.

Example:

[tool.repomatic]
dependency-graph.all-extras = true

dependency-graph.all-groups

Whether to include all dependency groups in the graph.

Type: bool | Default: true

When True, the update-deps-graph command behaves as if --all-groups was passed. Projects that want to exclude development dependency groups (docs, test, typing) from their published graph can set this to false.

Example:

[tool.repomatic]
dependency-graph.all-groups = true

dependency-graph.level

Maximum depth of the dependency graph.

Type: int | Default: (none)

None means unlimited. 1 = primary deps only, 2 = primary + their deps, etc. Equivalent to --level.

dependency-graph.no-extras

Optional extras to exclude from the graph.

Type: list[str] | Default: []

Equivalent to passing --no-extra for each entry. Takes precedence over dependency-graph.all-extras.

Example:

[tool.repomatic]
dependency-graph.no-extras = []

dependency-graph.no-groups

Dependency groups to exclude from the graph.

Type: list[str] | Default: []

Equivalent to passing --no-group for each entry. Takes precedence over dependency-graph.all-groups.

Example:

[tool.repomatic]
dependency-graph.no-groups = []

dependency-graph.output

Path where the dependency graph Mermaid diagram should be written.

Type: str | Default: "./docs/assets/dependencies.mmd"

The dependency graph visualizes the project’s dependency tree in Mermaid format.

Example:

[tool.repomatic]
dependency-graph.output = "./docs/assets/dependencies.mmd"

dev-release.sync

Whether dev pre-release sync is enabled for this project.

Type: bool | Default: true

Projects that do not want a rolling draft pre-release maintained on GitHub can set this to false.

Example:

[tool.repomatic]
dev-release.sync = true

docs.apidoc-exclude

Glob patterns for modules to exclude from sphinx-apidoc.

Type: list[str] | Default: []

Passed as positional exclude arguments after the source directory (e.g., ["setup.py", "tests"]).

Example:

[tool.repomatic]
docs.apidoc-exclude = []

docs.apidoc-extra-args

Extra arguments appended to the sphinx-apidoc invocation.

Type: list[str] | Default: []

The base flags --no-toc --module-first are always applied. Use this for project-specific options (e.g., ["--implicit-namespaces"]).

Example:

[tool.repomatic]
docs.apidoc-extra-args = []

docs.update-script

Path to a Python script run after sphinx-apidoc to generate dynamic content.

Type: str | Default: "./docs/docs_update.py"

Resolved relative to the repository root. Must reside under the docs/ directory for security. Set to an empty string to disable.

Example:

[tool.repomatic]
docs.update-script = "./docs/docs_update.py"

exclude

Additional components and files to exclude from repomatic operations.

Type: list[str] | Default: []

Additive to the default exclusions (labels, skills). Bare names exclude an entire component (e.g., "workflows"). Qualified component/identifier entries exclude a specific file within a component (e.g., "workflows/debug.yaml", "skills/repomatic-audit", "labels/labeller-content-based.yaml").

Affects repomatic init, workflow sync, and workflow create. Explicit CLI positional arguments override this list.

Example:

[tool.repomatic]
exclude = []

gitignore.extra-categories

Additional gitignore template categories to fetch from gitignore.io.

Type: list[str] | Default: []

List of template names (e.g., ["Python", "Node", "Terraform"]) to combine with the generated .gitignore content.

Example:

[tool.repomatic]
gitignore.extra-categories = []

gitignore.extra-content

Additional content to append at the end of the generated .gitignore file.

Type: str | Default: (see example)

Example:

[tool.repomatic]
gitignore.extra-content = '''
junit.xml

# Claude Code local files.
.claude/scheduled_tasks.lock
.claude/settings.local.json

# Sphinx linkcheck output.
docs/_linkcheck/
'''

gitignore.location

File path of the .gitignore to update, relative to the root of the repository.

Type: str | Default: "./.gitignore"

Example:

[tool.repomatic]
gitignore.location = "./.gitignore"

gitignore.sync

Whether .gitignore sync is enabled for this project.

Type: bool | Default: true

Projects that manage their own .gitignore and do not want the autofix job to overwrite it can set this to false.

Example:

[tool.repomatic]
gitignore.sync = true

include

Components and files to force-include, overriding default exclusions.

Type: list[str] | Default: []

Use this to opt into components that are excluded by default (labels, skills). Each entry is subtracted from the effective exclude set (defaults + user exclude) and bypasses RepoScope filtering, so scope-restricted components (like awesome-only skills or Python-only publish-pypi-action) are included regardless of repository type. Qualified entries (component/file) implicitly select the parent component. Same syntax as exclude.

Example:

[tool.repomatic]
include = []

labels.content-rules

Structured per-label rules for the content-based labeller.

Type: list[dict[str, str | list[str]]] | Default: []

Each [[tool.repomatic.labels.content-rules]] entry has:

  • label (required): label name to apply when any pattern matches.

  • patterns (required): list of regex patterns evaluated against the issue or PR title and body by github/issue-labeller.

Repeating the same label across entries merges their patterns. Serialized to YAML at export time and appended to the bundled labeller-content-based.yaml.

Example:

[tool.repomatic]
labels.content-rules = []

labels.extra

Inline label definitions applied at sync time under the default profile.

Type: list[dict[str, str]] | Default: []

Each entry is a mapping with name, color, and description keys, matching labelmaker’s label specification. Entries are serialized into a temporary TOML file as [[profiles.default.labels]] blocks and applied by labelmaker apply. This avoids committing a lonely extra-labels/*.toml file when the downstream project only needs the basic three fields.

For label sets that need labelmaker’s advanced features (rename-from, multi-profile, multi-color), commit a hand-written file under extra-labels/ or download one via extra-files instead.

Example:

[tool.repomatic]
labels.extra = []

labels.extra-files

URLs of additional label definition files (JSON, JSON5, TOML, or YAML).

Type: list[str] | Default: []

Each URL is downloaded into extra-labels/ and applied separately by labelmaker. For inline definitions that need no external file, use extra instead.

Example:

[tool.repomatic]
labels.extra-files = []

labels.file-rules

Structured per-label rules for the file-based labeller.

Type: list[dict[str, str | list[str]]] | Default: []

Each [[tool.repomatic.labels.file-rules]] entry defines one match group for one label. Required key:

  • label: label name to apply when this group’s conditions match.

Optional matcher keys (all conditions in the same entry are AND’d):

  • any-glob-to-any-file: any pattern matches any changed file.

  • any-glob-to-all-files: any pattern matches every changed file.

  • all-globs-to-any-file: every pattern matches any changed file.

  • all-globs-to-all-files: every pattern matches every changed file.

  • head-branch: regex patterns matched against the PR head branch.

  • base-branch: regex patterns matched against the PR base branch.

  • any: list of nested sub-groups, OR’d together.

  • all: list of nested sub-groups, AND’d together.

Repeating the same label across entries OR’s the resulting groups, the same as listing multiple top-level groups under one label in actions/labeler. Together with any / all wrappers this covers the full actions/labeler v5+ schema.

Example:

[tool.repomatic]
labels.file-rules = []

labels.sync

Whether label sync is enabled for this project.

Type: bool | Default: true

Projects that manage their own repository labels and do not want the labels workflow to overwrite them can set this to false.

Example:

[tool.repomatic]
labels.sync = true

mailmap.sync

Whether .mailmap sync is enabled for this project.

Type: bool | Default: true

Projects that manage their own .mailmap and do not want the autofix job to overwrite it can set this to false.

Example:

[tool.repomatic]
mailmap.sync = true

manpages.asset-name

Filename stem (without the .tar.gz extension) for the man-page tarball uploaded to the GitHub release.

Type: str | Default: ""

Defaults to <package-name>-manpages when left empty and manpages.script is set. Has no effect when manpages.script is empty.

Example:

[tool.repomatic]
manpages.asset-name = ""

manpages.script

Click command target whose tree gets rendered as roff .1 files and attached as a tarball asset on every GitHub release.

Type: str | Default: ""

Same shape the click-extra wrap --man CLI accepts: a module:function path (preferred for projects whose console-script entry point dispatches through a wrapper), an entry-point name, a .py file path, or a plain importable module name. Leave empty to disable release-attached man pages.

Example:

[tool.repomatic]
manpages.script = ""

notification.unsubscribe

Whether the unsubscribe-threads workflow is enabled.

Type: bool | Default: false

Notifications are per-user across all repos. Enable on the single repo where you want scheduled cleanup of closed notification threads. Requires a classic PAT with notifications scope stored as REPOMATIC_NOTIFICATIONS_PAT.

Example:

[tool.repomatic]
notification.unsubscribe = false

nuitka.enabled

Whether Nuitka binary compilation is enabled for this project.

Type: bool | Default: true

Projects with [project.scripts] entries that are not intended to produce standalone binaries (e.g., libraries with convenience CLI wrappers) can set this to false to opt out of Nuitka compilation.

Example:

[tool.repomatic]
nuitka.enabled = true

nuitka.entry-points

Which [project.scripts] entry points produce Nuitka binaries.

Type: list[str] | Default: []

List of CLI IDs (e.g., ["mpm"]) to compile. When empty (the default), deduplicates by callable target: keeps the first entry point for each unique module:callable pair. This avoids building duplicate binaries when a project declares alias entry points (like both mpm and meta-package-manager pointing to the same function).

Example:

[tool.repomatic]
nuitka.entry-points = []

nuitka.extras

[project.optional-dependencies] extras to install before the Nuitka build.

Type: list[str] | Default: []

List of extra names (like ["sbom"]) to sync into the build venv before invoking Nuitka. By default the binary build only sees the project’s base dependencies, which matches a bare pip install <package> and excludes optional features. Listing an extra here calls uv sync --frozen --extra <name> before the Nuitka build so the binary can bundle the optional feature’s third-party packages (paired with --include-package in [tool.nuitka] for imports guarded behind try/except).

Example:

[tool.repomatic]
nuitka.extras = []

nuitka.unstable-targets

Nuitka build targets allowed to fail without blocking the release.

Type: list[str] | Default: []

List of target names (e.g., ["linux-arm64", "windows-x64"]) that are marked as unstable. Jobs for these targets will be allowed to fail without preventing the release workflow from succeeding.

Example:

[tool.repomatic]
nuitka.unstable-targets = []

pypi-package-history

Former PyPI package names for projects that were renamed.

Type: list[str] | Default: []

When a project changes its PyPI name, older versions remain published under the previous name. List former names here so lint-changelog can fetch release metadata from all names and generate correct PyPI URLs.

Example:

[tool.repomatic]
pypi-package-history = []

setup-guide

Whether the setup guide issue is enabled for this project.

Type: bool | Default: true

Projects that do not need REPOMATIC_PAT or manage their own PAT setup can set this to false to suppress the setup guide issue.

Example:

[tool.repomatic]
setup-guide = true

skills.location

Directory prefix for Claude Code skill files, relative to the repository root.

Type: str | Default: "./.claude/skills/"

Skill files are written as {skills_location}/{skill-id}/SKILL.md. Useful for repositories where .claude/ is not at the root (like dotfiles repos that store configs under a subdirectory).

Example:

[tool.repomatic]
skills.location = "./.claude/skills/"

test-matrix.exclude

Extra exclude rules applied to both full and PR test matrices.

Type: list[dict[str, str]] | Default: []

Each entry is a dict of GitHub Actions matrix keys (like {"os": "windows-11-arm"}) that removes matching combinations. Additive to the upstream default excludes.

Example:

[tool.repomatic]
test-matrix.exclude = []

test-matrix.full-include

Full-matrix-only job rows, added as standalone matrix combinations.

Type: list[dict[str, str]] | Default: []

Each entry is a dict of GitHub Actions matrix keys fully describing one job (like {"os": "ubuntu-24.04-arm", "python-version": "3.10", "click-version": "8.3.1"}). Unlike include, these are appended as independent rows of the full matrix, never merged into the base cross-product, so a cell can’t overwrite a shipped-config job that shares its os and python-version. Keys left out inherit the matrix defaults (the single-key include entries, plus state: stable), so a cell lists only what differs from the shipped configuration.

Use this for heterogeneous coverage, like pinning each release of a dependency to its own runner and Python, where carving the same shape from the base cross-product with exclude would take many rules. Like variations and unstable, it touches the full matrix only; the PR matrix stays a curated reduced set. Adding any entry makes the full matrix emit as a flat job list ({"include": [...]}), which GitHub runs verbatim with no cross-product expansion.

Example:

[tool.repomatic]
test-matrix.full-include = []

test-matrix.include

Extra include directives applied to both full and PR test matrices.

Type: list[dict[str, str]] | Default: []

Each entry is a dict of GitHub Actions matrix keys that adds or augments matrix combinations. Additive to the upstream default includes.

Because includes apply to both matrices, a directive whose keys are not PR base axes is risky. In the PR matrix only os and python-version are base axes, so a key like click-version (injected by another include) has nothing to match and GitHub’s expansion adds the directive to every PR job, overwriting it. To flag a value continue-on-error, prefer unstable over an include carrying state: unstable.

Example:

[tool.repomatic]
test-matrix.include = []

test-matrix.remove

Per-axis value removals applied to both full and PR test matrices.

Type: dict[str, list[str]] | Default: {}

Outer key is the variation/axis ID (e.g., os, python-version). Inner list contains values to drop from that axis. Applied after replacements but before excludes, includes, and variations.

test-matrix.replace

Per-axis value replacements applied to both full and PR test matrices.

Type: dict[str, dict[str, str]] | Default: {}

Outer key is the variation/axis ID (e.g., os, python-version). Inner dict maps old values to new values. Applied before removals, excludes, includes, and variations.

test-matrix.unstable

Full-matrix-only combinations to flag continue-on-error in CI.

Type: list[dict[str, str]] | Default: []

Each entry is a dict of GitHub Actions matrix keys (like {"click-version": "main"}). Every full-matrix combination matching an entry gets a state: unstable value, which tests.yaml reads to set continue-on-error. Like variations, this applies to the full matrix only; the PR matrix stays a curated stable set.

Prefer this over an include entry carrying state: unstable. include applies to both matrices, and in the PR matrix a key like click-version is not a base axis (another include injects it), so GitHub’s expansion would add the directive to every PR job and overwrite it. unstable only touches the full matrix, sidestepping that hijack.

Example:

[tool.repomatic]
test-matrix.unstable = []

test-matrix.variations

Extra matrix dimension values added to the full test matrix only.

Type: dict[str, list[str]] | Default: {}

Each key is a dimension ID (e.g., os, click-version) and its value is a list of additional entries. For existing dimensions, values are merged with the upstream defaults. For new dimension IDs, a new axis is created. Only affects the full matrix; the PR matrix stays a curated reduced set.

uv-lock.sync

Whether uv.lock sync is enabled for this project.

Type: bool | Default: true

Projects that manage their own lock file strategy and do not want the sync-uv-lock job to run uv lock --upgrade can set this to false.

Example:

[tool.repomatic]
uv-lock.sync = true

vulnerable-deps.sources

Advisory databases to consult for known vulnerabilities.

Type: list[str] | Default: ['uv-audit', 'github-advisories']

Recognized values:

  • "uv-audit": PyPA Advisory Database via uv audit (works locally and in CI without a GitHub token).

  • "github-advisories": GitHub Advisory Database via the repository’s Dependabot alerts (CI-only, requires a token with Dependabot alerts: Read-only).

Sources are unioned and deduplicated per package by advisory identity: entries sharing an advisory_id or a cross-referenced CVE/GHSA/PYSEC alias are merged. Repositories that distrust GHSA — or have no Dependabot alerts enabled — can opt out with sources = ["uv-audit"].

Example:

[tool.repomatic]
vulnerable-deps.sources = ["uv-audit", "github-advisories"]

vulnerable-deps.sync

Whether the fix-vulnerable-deps job is enabled for this project.

Type: bool | Default: true

Projects that manage their own vulnerability remediation flow can set this to false to skip the autofix job.

Example:

[tool.repomatic]
vulnerable-deps.sync = true

workflow.extra-paths

Literal entries to append to every workflow’s paths: filter.

Type: list[str] | Default: []

Applies to thin-caller and header-only sync. Useful for repo-specific files that should re-trigger CI but are not detected by the canonical paths: filter (e.g., install.sh, dotfiles/**).

Per-workflow overrides in paths ignore this list: when an entry exists for a given filename, that entry is treated as the complete list.

Example:

[tool.repomatic]
workflow.extra-paths = []

workflow.ignore-paths

Literal entries to strip from every workflow’s paths: filter.

Type: list[str] | Default: []

Useful for canonical entries that don’t exist downstream (e.g., tests/**, uv.lock in repos with no Python tests or lockfile). Match is by exact string equality. Applies before extra_paths.

Per-workflow overrides in paths ignore this list.

Example:

[tool.repomatic]
workflow.ignore-paths = []

workflow.paths

Per-workflow override of the paths: filter, keyed by filename.

Type: dict[str, list[str]] | Default: {}

When a workflow filename appears here, its paths: blocks (in push, pull_request, etc.) are replaced wholesale with the listed entries. source_paths, extra_paths, and ignore_paths do not apply when a per-workflow override is set: the list is treated as authoritative.

Override only takes effect on triggers that already have a paths: filter in the canonical workflow. Workflows without paths: upstream keep their unrestricted trigger semantics.

Example:

[tool.repomatic.workflow.paths]
"tests.yaml" = ["install.sh", "packages.toml", ".github/workflows/tests.yaml"]

workflow.source-paths

Source code directory names for workflow trigger paths: filters.

Type: list[str] | Default: (none)

When set, thin-caller and header-only workflows include paths: filters using these directory names (as name/** globs) alongside universal paths like pyproject.toml and uv.lock.

When None (default), source paths are auto-derived from [project.name] in pyproject.toml by replacing hyphens with underscores — the universal Python convention. For example, name = "extra-platforms" automatically uses ["extra_platforms"].

workflow.sync

Whether workflow sync is enabled for this project.

Type: bool | Default: true

Projects that manage their own workflow files and do not want the autofix job to sync thin callers or headers can set this to false.

Example:

[tool.repomatic]
workflow.sync = true

[tool.X] bridge and tool runner

repomatic run also bridges the gap for tools that can’t read pyproject.toml natively: write your config in [tool.<name>] and repomatic translates it to the tool’s native format at invocation time. See the tool runner page for the full list of supported tools, config resolution precedence, binary caching, and a tutorial.

repomatic.config API

Configuration schema and loading for [tool.repomatic] in pyproject.toml.

Defines the Config dataclass, its TOML serialization helpers, and the load_repomatic_config function that reads, validates, and returns a typed Config instance.

class repomatic.config.CacheConfig(dir='', github_release_ttl=604800, github_releases_ttl=86400, max_age=30, pypi_ttl=86400)[source]

Bases: object

Nested schema for [tool.repomatic.cache].

dir: str = ''

Override the binary cache directory path.

When empty (the default), the cache uses the platform convention: ~/Library/Caches/repomatic on macOS, $XDG_CACHE_HOME/repomatic or ~/.cache/repomatic on Linux, %LOCALAPPDATA%\repomatic\Cache on Windows. The REPOMATIC_CACHE_DIR environment variable takes precedence over this setting.

github_release_ttl: int = 604800

Freshness TTL for cached single-release bodies (seconds).

GitHub release bodies are immutable once published, so a long TTL (7 days) is safe. Set to 0 to disable caching for single-release lookups.

github_releases_ttl: int = 86400

Freshness TTL for cached all-releases responses (seconds).

New releases can appear at any time, so a shorter TTL (24 hours) balances freshness with API savings.

max_age: int = 30

Auto-purge cached entries older than this many days.

Set to 0 to disable auto-purge. The REPOMATIC_CACHE_MAX_AGE environment variable takes precedence over this setting.

pypi_ttl: int = 86400

Freshness TTL for cached PyPI metadata (seconds).

PyPI metadata changes when new versions are published. A 24-hour TTL avoids redundant API calls while keeping data reasonably current.

class repomatic.config.DependencyGraphConfig(all_extras=True, all_groups=True, level=None, no_extras=<factory>, no_groups=<factory>, output='./docs/assets/dependencies.mmd')[source]

Bases: object

Nested schema for [tool.repomatic.dependency-graph].

all_extras: bool = True

Whether to include all optional extras in the graph.

When True, the update-deps-graph command behaves as if --all-extras was passed.

all_groups: bool = True

Whether to include all dependency groups in the graph.

When True, the update-deps-graph command behaves as if --all-groups was passed. Projects that want to exclude development dependency groups (docs, test, typing) from their published graph can set this to false.

level: int | None = None

Maximum depth of the dependency graph.

None means unlimited. 1 = primary deps only, 2 = primary + their deps, etc. Equivalent to --level.

no_extras: list[str]

Optional extras to exclude from the graph.

Equivalent to passing --no-extra for each entry. Takes precedence over dependency-graph.all-extras.

no_groups: list[str]

Dependency groups to exclude from the graph.

Equivalent to passing --no-group for each entry. Takes precedence over dependency-graph.all-groups.

output: str = './docs/assets/dependencies.mmd'

Path where the dependency graph Mermaid diagram should be written.

The dependency graph visualizes the project’s dependency tree in Mermaid format.

class repomatic.config.DocsConfig(apidoc_exclude=<factory>, apidoc_extra_args=<factory>, update_script='./docs/docs_update.py')[source]

Bases: object

Nested schema for [tool.repomatic.docs].

apidoc_exclude: list[str]

Glob patterns for modules to exclude from sphinx-apidoc.

Passed as positional exclude arguments after the source directory (e.g., ["setup.py", "tests"]).

apidoc_extra_args: list[str]

Extra arguments appended to the sphinx-apidoc invocation.

The base flags --no-toc --module-first are always applied. Use this for project-specific options (e.g., ["--implicit-namespaces"]).

update_script: str = './docs/docs_update.py'

Path to a Python script run after sphinx-apidoc to generate dynamic content.

Resolved relative to the repository root. Must reside under the docs/ directory for security. Set to an empty string to disable.

class repomatic.config.GitignoreConfig(extra_categories=<factory>, extra_content=<factory>, location='./.gitignore', sync=True)[source]

Bases: object

Nested schema for [tool.repomatic.gitignore].

extra_categories: list[str]

Additional gitignore template categories to fetch from gitignore.io.

List of template names (e.g., ["Python", "Node", "Terraform"]) to combine with the generated .gitignore content.

extra_content: str

Additional content to append at the end of the generated .gitignore file.

location: str = './.gitignore'

File path of the .gitignore to update, relative to the root of the repository.

sync: bool = True

Whether .gitignore sync is enabled for this project.

Projects that manage their own .gitignore and do not want the autofix job to overwrite it can set this to false.

class repomatic.config.LabelsConfig(content_rules=<factory>, extra=<factory>, extra_files=<factory>, file_rules=<factory>, sync=True)[source]

Bases: object

Nested schema for [tool.repomatic.labels].

content_rules: list[dict[str, str | list[str]]]

Structured per-label rules for the content-based labeller.

Each [[tool.repomatic.labels.content-rules]] entry has:

  • label (required): label name to apply when any pattern matches.

  • patterns (required): list of regex patterns evaluated against the issue or PR title and body by github/issue-labeller.

Repeating the same label across entries merges their patterns. Serialized to YAML at export time and appended to the bundled labeller-content-based.yaml.

extra: list[dict[str, str]]

Inline label definitions applied at sync time under the default profile.

Each entry is a mapping with name, color, and description keys, matching labelmaker’s label specification. Entries are serialized into a temporary TOML file as [[profiles.default.labels]] blocks and applied by labelmaker apply. This avoids committing a lonely extra-labels/*.toml file when the downstream project only needs the basic three fields.

For label sets that need labelmaker’s advanced features (rename-from, multi-profile, multi-color), commit a hand-written file under extra-labels/ or download one via extra-files instead.

extra_files: list[str]

URLs of additional label definition files (JSON, JSON5, TOML, or YAML).

Each URL is downloaded into extra-labels/ and applied separately by labelmaker. For inline definitions that need no external file, use extra instead.

file_rules: list[dict[str, str | list[str]]]

Structured per-label rules for the file-based labeller.

Each [[tool.repomatic.labels.file-rules]] entry defines one match group for one label. Required key:

  • label: label name to apply when this group’s conditions match.

Optional matcher keys (all conditions in the same entry are AND’d):

  • any-glob-to-any-file: any pattern matches any changed file.

  • any-glob-to-all-files: any pattern matches every changed file.

  • all-globs-to-any-file: every pattern matches any changed file.

  • all-globs-to-all-files: every pattern matches every changed file.

  • head-branch: regex patterns matched against the PR head branch.

  • base-branch: regex patterns matched against the PR base branch.

  • any: list of nested sub-groups, OR’d together.

  • all: list of nested sub-groups, AND’d together.

Repeating the same label across entries OR’s the resulting groups, the same as listing multiple top-level groups under one label in actions/labeler. Together with any / all wrappers this covers the full actions/labeler v5+ schema.

sync: bool = True

Whether label sync is enabled for this project.

Projects that manage their own repository labels and do not want the labels workflow to overwrite them can set this to false.

class repomatic.config.TestMatrixConfig(exclude=<factory>, full_include=<factory>, include=<factory>, remove=<factory>, replace=<factory>, unstable=<factory>, variations=<factory>)[source]

Bases: object

Nested schema for [tool.repomatic.test-matrix].

Keys inside replace and variations are GitHub Actions matrix identifiers (e.g., os, python-version) and must not be normalized to snake_case. Click Extra’s click_extra.normalize_keys = False metadata on the parent field prevents this.

exclude: list[dict[str, str]]

Extra exclude rules applied to both full and PR test matrices.

Each entry is a dict of GitHub Actions matrix keys (like {"os": "windows-11-arm"}) that removes matching combinations. Additive to the upstream default excludes.

full_include: list[dict[str, str]]

Full-matrix-only job rows, added as standalone matrix combinations.

Each entry is a dict of GitHub Actions matrix keys fully describing one job (like {“os”: “ubuntu-24.04-arm”, “python-version”: “3.10”, “click-version”: “8.3.1”}`). Unlike include`, these are appended as independent rows of the full matrix, never merged into the base cross-product, so a cell can't overwrite a shipped-config job that shares its ``os and python-version. Keys left out inherit the matrix defaults (the single-key include entries, plus state: stable), so a cell lists only what differs from the shipped configuration.

Use this for heterogeneous coverage, like pinning each release of a dependency to its own runner and Python, where carving the same shape from the base cross-product with exclude would take many rules. Like variations and unstable, it touches the full matrix only; the PR matrix stays a curated reduced set. Adding any entry makes the full matrix emit as a flat job list ({"include": [...]}), which GitHub runs verbatim with no cross-product expansion.

include: list[dict[str, str]]

Extra include directives applied to both full and PR test matrices.

Each entry is a dict of GitHub Actions matrix keys that adds or augments matrix combinations. Additive to the upstream default includes.

Because includes apply to both matrices, a directive whose keys are not PR base axes is risky. In the PR matrix only os and python-version are base axes, so a key like click-version (injected by another include) has nothing to match and GitHub’s expansion adds the directive to every PR job, overwriting it. To flag a value continue-on-error, prefer unstable over an include carrying state: unstable.

remove: dict[str, list[str]]

Per-axis value removals applied to both full and PR test matrices.

Outer key is the variation/axis ID (e.g., os, python-version). Inner list contains values to drop from that axis. Applied after replacements but before excludes, includes, and variations.

replace: dict[str, dict[str, str]]

Per-axis value replacements applied to both full and PR test matrices.

Outer key is the variation/axis ID (e.g., os, python-version). Inner dict maps old values to new values. Applied before removals, excludes, includes, and variations.

unstable: list[dict[str, str]]

Full-matrix-only combinations to flag continue-on-error in CI.

Each entry is a dict of GitHub Actions matrix keys (like {"click-version": "main"}). Every full-matrix combination matching an entry gets a state: unstable value, which tests.yaml reads to set continue-on-error. Like variations, this applies to the full matrix only; the PR matrix stays a curated stable set.

Prefer this over an include entry carrying state: unstable. include applies to both matrices, and in the PR matrix a key like click-version is not a base axis (another include injects it), so GitHub’s expansion would add the directive to every PR job and overwrite it. unstable only touches the full matrix, sidestepping that hijack.

variations: dict[str, list[str]]

Extra matrix dimension values added to the full test matrix only.

Each key is a dimension ID (e.g., os, click-version) and its value is a list of additional entries. For existing dimensions, values are merged with the upstream defaults. For new dimension IDs, a new axis is created. Only affects the full matrix; the PR matrix stays a curated reduced set.

class repomatic.config.VulnerableDepsConfig(sources=<factory>, sync=True)[source]

Bases: object

Nested schema for [tool.repomatic.vulnerable-deps].

sources: list[str]

Advisory databases to consult for known vulnerabilities.

Recognized values:

  • "uv-audit": PyPA Advisory Database via uv audit (works locally and in CI without a GitHub token).

  • "github-advisories": GitHub Advisory Database via the repository’s Dependabot alerts (CI-only, requires a token with Dependabot alerts: Read-only).

Sources are unioned and deduplicated per package by advisory identity: entries sharing an advisory_id or a cross-referenced CVE/GHSA/PYSEC alias are merged. Repositories that distrust GHSA — or have no Dependabot alerts enabled — can opt out with sources = ["uv-audit"].

sync: bool = True

Whether the fix-vulnerable-deps job is enabled for this project.

Projects that manage their own vulnerability remediation flow can set this to false to skip the autofix job.

class repomatic.config.WorkflowConfig(source_paths=None, extra_paths=<factory>, ignore_paths=<factory>, paths=<factory>, sync=True)[source]

Bases: object

Nested schema for [tool.repomatic.workflow].

source_paths: list[str] | None = None

Source code directory names for workflow trigger paths: filters.

When set, thin-caller and header-only workflows include paths: filters using these directory names (as name/** globs) alongside universal paths like pyproject.toml and uv.lock.

When None (default), source paths are auto-derived from [project.name] in pyproject.toml by replacing hyphens with underscores — the universal Python convention. For example, name = "extra-platforms" automatically uses ["extra_platforms"].

extra_paths: list[str]

Literal entries to append to every workflow’s paths: filter.

Applies to thin-caller and header-only sync. Useful for repo-specific files that should re-trigger CI but are not detected by the canonical paths: filter (e.g., install.sh, dotfiles/**).

Per-workflow overrides in paths ignore this list: when an entry exists for a given filename, that entry is treated as the complete list.

ignore_paths: list[str]

Literal entries to strip from every workflow’s paths: filter.

Useful for canonical entries that don’t exist downstream (e.g., tests/**, uv.lock in repos with no Python tests or lockfile). Match is by exact string equality. Applies before extra_paths.

Per-workflow overrides in paths ignore this list.

paths: dict[str, list[str]]

Per-workflow override of the paths: filter, keyed by filename.

When a workflow filename appears here, its paths: blocks (in push, pull_request, etc.) are replaced wholesale with the listed entries. source_paths, extra_paths, and ignore_paths do not apply when a per-workflow override is set: the list is treated as authoritative.

Override only takes effect on triggers that already have a paths: filter in the canonical workflow. Workflows without paths: upstream keep their unrestricted trigger semantics.

Example:

[tool.repomatic.workflow.paths]
"tests.yaml" = ["install.sh", "packages.toml", ".github/workflows/tests.yaml"]
sync: bool = True

Whether workflow sync is enabled for this project.

Projects that manage their own workflow files and do not want the autofix job to sync thin callers or headers can set this to false.

class repomatic.config.Config(awesome_template_sync=True, bumpversion_sync=True, cache=<factory>, changelog_bullet_word_threshold=40, changelog_location='./changelog.md', dependency_graph=<factory>, dev_release_sync=True, docs=<factory>, exclude=<factory>, gitignore=<factory>, include=<factory>, labels=<factory>, mailmap_sync=True, manpages_script='', manpages_asset_name='', notification_unsubscribe=False, nuitka_enabled=True, nuitka_entry_points=<factory>, nuitka_extras=<factory>, nuitka_unstable_targets=<factory>, pypi_package_history=<factory>, abandoned_versions=<factory>, setup_guide=True, agents_location='./.claude/agents/', skills_location='./.claude/skills/', test_matrix=<factory>, uv_lock_sync=True, vulnerable_deps=<factory>, workflow=<factory>)[source]

Bases: object

Configuration schema for [tool.repomatic] in pyproject.toml.

This dataclass defines the structure and default values for repomatic configuration. Each field has a docstring explaining its purpose.

awesome_template_sync: bool = True

Whether awesome-template sync is enabled for this project.

Repositories whose name starts with awesome- get their boilerplate synced from files bundled in repomatic. Set to false to opt out.

bumpversion_sync: bool = True

Whether bumpversion config sync is enabled for this project.

Projects that manage their own [tool.bumpversion] section and do not want the autofix job to overwrite it can set this to false.

cache: CacheConfig

Binary cache configuration.

changelog_bullet_word_threshold: int = 40

Word count above which lint-changelog warns about a changelog bullet.

A changelog entry is a release note, not a commit message: ideally one short sentence stating what changed (see CLAUDE.md § Changelog entry length). lint-changelog emits a non-fatal warning for every bullet in the unreleased section longer than this many words, nudging verbose, implementation-heavy entries back toward a user-facing summary. Released sections are immutable and never flagged. Set to 0 to disable the check.

changelog_location: str = './changelog.md'

File path of the changelog, relative to the root of the repository.

dependency_graph: DependencyGraphConfig

Dependency graph generation configuration.

dev_release_sync: bool = True

Whether dev pre-release sync is enabled for this project.

Projects that do not want a rolling draft pre-release maintained on GitHub can set this to false.

docs: DocsConfig

Sphinx documentation generation configuration.

exclude: list[str]

Additional components and files to exclude from repomatic operations.

Additive to the default exclusions (labels, skills). Bare names exclude an entire component (e.g., "workflows"). Qualified component/identifier entries exclude a specific file within a component (e.g., "workflows/debug.yaml", "skills/repomatic-audit", "labels/labeller-content-based.yaml").

Affects repomatic init, workflow sync, and workflow create. Explicit CLI positional arguments override this list.

gitignore: GitignoreConfig

.gitignore sync configuration.

include: list[str]

Components and files to force-include, overriding default exclusions.

Use this to opt into components that are excluded by default (labels, skills). Each entry is subtracted from the effective exclude set (defaults + user exclude) and bypasses RepoScope filtering, so scope-restricted components (like awesome-only skills or Python-only publish-pypi-action) are included regardless of repository type. Qualified entries (component/file) implicitly select the parent component. Same syntax as exclude.

labels: LabelsConfig

Repository label sync configuration.

mailmap_sync: bool = True

Whether .mailmap sync is enabled for this project.

Projects that manage their own .mailmap and do not want the autofix job to overwrite it can set this to false.

manpages_script: str = ''

Click command target whose tree gets rendered as roff .1 files and attached as a tarball asset on every GitHub release.

Same shape the click-extra wrap --man CLI accepts: a module:function path (preferred for projects whose console-script entry point dispatches through a wrapper), an entry-point name, a .py file path, or a plain importable module name. Leave empty to disable release-attached man pages.

manpages_asset_name: str = ''

Filename stem (without the .tar.gz extension) for the man-page tarball uploaded to the GitHub release.

Defaults to <package-name>-manpages when left empty and manpages.script is set. Has no effect when manpages.script is empty.

notification_unsubscribe: bool = False

Whether the unsubscribe-threads workflow is enabled.

Notifications are per-user across all repos. Enable on the single repo where you want scheduled cleanup of closed notification threads. Requires a classic PAT with notifications scope stored as REPOMATIC_NOTIFICATIONS_PAT.

nuitka_enabled: bool = True

Whether Nuitka binary compilation is enabled for this project.

Projects with [project.scripts] entries that are not intended to produce standalone binaries (e.g., libraries with convenience CLI wrappers) can set this to false to opt out of Nuitka compilation.

nuitka_entry_points: list[str]

Which [project.scripts] entry points produce Nuitka binaries.

List of CLI IDs (e.g., ["mpm"]) to compile. When empty (the default), deduplicates by callable target: keeps the first entry point for each unique module:callable pair. This avoids building duplicate binaries when a project declares alias entry points (like both mpm and meta-package-manager pointing to the same function).

nuitka_extras: list[str]

[project.optional-dependencies] extras to install before the Nuitka build.

List of extra names (like ["sbom"]) to sync into the build venv before invoking Nuitka. By default the binary build only sees the project’s base dependencies, which matches a bare pip install <package> and excludes optional features. Listing an extra here calls uv sync –frozen –extra <name> before the Nuitka build so the binary can bundle the optional feature’s third-party packages (paired with --include-package in [tool.nuitka] for imports guarded behind try/except).

nuitka_unstable_targets: list[str]

Nuitka build targets allowed to fail without blocking the release.

List of target names (e.g., ["linux-arm64", "windows-x64"]) that are marked as unstable. Jobs for these targets will be allowed to fail without preventing the release workflow from succeeding.

pypi_package_history: list[str]

Former PyPI package names for projects that were renamed.

When a project changes its PyPI name, older versions remain published under the previous name. List former names here so lint-changelog can fetch release metadata from all names and generate correct PyPI URLs.

abandoned_versions: list[str]

Versions documented in the changelog but never published.

A version reached only its [changelog] Release vX.Y.Z freeze and was then skipped per CLAUDE.md § Skip and move forward (botched build, broken artifact, bad metadata) without rewriting history. List those versions here so lint-changelog reports them as skipped (an info log line) instead of flagging them every run as X.Y.Z: not found on PyPI. Applies to both PyPI lookups and the git-tag fallback.

setup_guide: bool = True

Whether the setup guide issue is enabled for this project.

Projects that do not need REPOMATIC_PAT or manage their own PAT setup can set this to false to suppress the setup guide issue.

agents_location: str = './.claude/agents/'

Directory prefix for Claude Code agent files, relative to the repository root.

Agent files are written as {agents_location}/{agent-id}.md. Useful for repositories where .claude/ is not at the root (like dotfiles repos that store configs under a subdirectory).

skills_location: str = './.claude/skills/'

Directory prefix for Claude Code skill files, relative to the repository root.

Skill files are written as {skills_location}/{skill-id}/SKILL.md. Useful for repositories where .claude/ is not at the root (like dotfiles repos that store configs under a subdirectory).

test_matrix: TestMatrixConfig

Per-project customizations for the GitHub Actions CI test matrix.

Keys inside this section are GitHub Actions matrix identifiers (e.g., os, python-version) and must not be normalized to snake_case.

uv_lock_sync: bool = True

Whether uv.lock sync is enabled for this project.

Projects that manage their own lock file strategy and do not want the sync-uv-lock job to run uv lock --upgrade can set this to false.

vulnerable_deps: VulnerableDepsConfig

Vulnerable dependency detection and remediation configuration.

workflow: WorkflowConfig

Workflow sync configuration.

repomatic.config.SUBCOMMAND_CONFIG_FIELDS: Final[frozenset[str]] = frozenset({'abandoned_versions', 'agents_location', 'awesome_template_sync', 'bumpversion_sync', 'cache', 'changelog_location', 'dependency_graph', 'dev_release_sync', 'docs', 'exclude', 'gitignore', 'include', 'labels', 'mailmap_sync', 'notification_unsubscribe', 'pypi_package_history', 'setup_guide', 'skills_location', 'test_matrix', 'uv_lock_sync', 'vulnerable_deps', 'workflow'})

Config fields consumed directly by subcommands, not needed as metadata outputs.

These fields are read directly from [tool.repomatic] in pyproject.toml by their respective subcommands (e.g. deps-graph), so they no longer need to be passed through workflow metadata outputs.

repomatic.config.escape_type_for_gfm_table(ftype)[source]

Escape outer brackets of nested generics for raw GFM table cells.

Nested generics like list[dict[str, str]] would otherwise be interpreted by mdformat as a markdown link reference and re-escaped on every reformat. Escaping the outermost brackets up front keeps the cell stable under mdformat. Simple generics like list[str] have no nested brackets and stay unescaped.

Apply this only when the value lands directly in a raw GFM table cell (e.g. CLI show-config output). Do not apply when wrapping the value in inline code backticks: inside a code span, backslashes are literal characters in CommonMark and would render visibly as \[.

Return type:

str

repomatic.config.CONFIG_REFERENCE_HEADER_DEFS: tuple[tuple[str, str], ...] = (('Option', 'option'), ('Type', 'type'), ('Default', 'default'), ('Description', 'description'))

Column definitions for the [tool.repomatic] configuration reference table.

repomatic.config.config_full_descriptions()[source]

Return full attribute docstrings keyed by TOML option name.

Unlike config_reference() which truncates to a one-line summary suitable for the show-config CLI table, this returns the entire docstring for use in long-form documentation.

Return type:

dict[str, str]

repomatic.config.config_reference()[source]

Build the [tool.repomatic] configuration reference as table rows.

Introspects the Config dataclass fields, their type annotations, defaults, and attribute docstrings. Nested dataclass fields are expanded into individual rows with dotted keys. Returns a list of (option, type, default, description) tuples suitable for click_extra.table.print_table.

Return type:

list[tuple[str, str, str, str]]

repomatic.config.load_repomatic_config(pyproject_data=None)[source]

Load [tool.repomatic] config merged with Config defaults.

Delegates to click-extra’s schema-aware dataclass instantiation, which handles normalization, flattening, nested dataclasses, and opaque field extraction automatically based on field metadata and type hints.

Parameters:

pyproject_data (dict[str, Any] | None) – Pre-parsed pyproject.toml dict. If None, reads and parses pyproject.toml from the current working directory.

Return type:

Config