Per-manager overrides¶
Each built-in manager exposes a small set of attributes that can be overridden from the configuration file. Add a [mpm.overrides.<id>] section (or [tool.mpm.overrides.<id>] in pyproject.toml) for each manager you want to tune. Values from the file take precedence over the built-in defaults and over the matching global [mpm] settings or --<flag> command-line values when both apply to the same field.
Overridable fields¶
Field |
Type |
Description |
|---|---|---|
|
list of strings |
CLI binary names to look for, in order of priority. |
|
list of strings |
Extra directories searched before |
|
string |
Per-manager cooldown posture: |
|
boolean |
Simulate CLI calls without performing any action, only for this manager. |
|
table of strings |
Environment variables added to those the manager sets, on every CLI call. A variable the manager sets takes the value given here. Every call also runs in the |
|
table |
Arguments added to the commands of one operation alone, keyed by operation name. See per-operation arguments. |
|
boolean |
Print the state-changing commands instead of running them, only for this manager. See inspect the plan before running. |
|
list of strings |
Arguments appended after every CLI invocation. |
|
list of strings |
Arguments inserted before every CLI invocation. |
|
list of strings |
Commands prepended to every CLI invocation (typically |
|
string |
PEP 440-style version requirement the manager must satisfy to be considered available. |
|
boolean |
Stop on the first CLI error from this manager instead of continuing. |
|
boolean |
Run this manager’s privileged operations through |
|
integer |
Maximum duration in seconds for each CLI call from this manager. |
|
boolean |
Mark a manager as unmaintained, hiding it from default selection. |
|
list of strings |
CLI options used to extract the manager’s reported version. |
|
list of strings |
Regular expressions tried in order to extract the version from CLI output. |
Important
List-valued fields use replace semantics: an override fully supersedes the built-in default rather than merging with it. For example, setting cli_search_path = ["/opt/bin"] on a manager that ships with cli_search_path = ("/usr/local/bin",) results in ("/opt/bin",), not the union of both. The extra_env and operations tables add to what the manager sets instead.
Discover the override template¶
Run mpm config-template to print the current overridable attributes of every maintained manager as a ready-to-paste config block. Pass one or more manager IDs to narrow the output:
$ mpm config-template winget > my-overrides.toml
$ mpm config-template brew pip cargo
The output lists every overridable field with its current value, so it doubles as the canonical reference for what each manager exposes. Prune the rows that don’t apply and customize the rest. The output is valid TOML; redirect it directly into a config file or merge it into your existing [mpm] section.
Example: bypass a Windows app-store placeholder¶
Modern Windows ships placeholder executables under %LOCALAPPDATA%\Microsoft\WindowsApps\ that, when invoked, open the Microsoft Store rather than running the real CLI. If you have installed the genuine winget somewhere else, point cli_search_path at that directory so mpm finds it first:
[mpm.overrides.winget]
cli_search_path = [
"C:\\Program Files\\WindowsApps\\Microsoft.DesktopAppInstaller_1.27.0_x64",
]
The override directories are searched before $PATH, so the real binary wins over the store placeholder.
Example: relax a version requirement¶
Most managers gate themselves behind a minimum version. If you ship a custom build that reports an unconventional version string, override requirement:
[mpm.overrides.guix]
requirement = ">=0.0"
Example: per-manager timeout and quiet mode¶
Slow managers can be given a longer timeout without affecting the rest of the pool. Combine with pre_args to silence chatty output:
[mpm.overrides.brew]
timeout = 900
[mpm.overrides.cargo]
pre_args = ["--quiet", "--color", "never"]
Per-operation arguments¶
pre_args and post_args reach every command of a manager. To add arguments to the commands of one operation alone, use the operations table of the override section:
[mpm.overrides.cask]
operations.outdated.extra_args = ["--greedy"]
operations.upgrade_all.extra_args = ["--greedy"]
mpm then runs brew outdated --json=v2 --greedy --cask and brew upgrade --quiet --yes --greedy --cask. The brew list command, which rejects --greedy, stays as it is.
Each entry has the name of an operation, as in the
operationstable of a manager definition:installed,outdated,search,install,upgrade_one,upgrade_all,remove,sync,cleanup_cache, and so on. A manager accepts the operations whose commands it builds, andmpm config-template <id>lists them.An entry takes one key,
extra_args: a list of strings thatmpmadds after the arguments of the command, beforepost_args.The helper commands of an operation get none of its arguments, like the
brew tapthat runs before abrew install.A manager with no command to upgrade all packages upgrades them one by one, with its
upgrade_onecommand: it has noupgrade_allentry, so setupgrade_one.Run
mpm --planto print the state-changing commands with their arguments, without running them.
Validation¶
mpm checks each override section when it loads the configuration. It stops with an error that names the faulty key: an unknown manager ID, an unknown field, a value of the wrong type (a single string where a list is expected), or an operations entry the manager does not build. Run mpm --validate-config <file> to check a file without running a command.
Define a new manager¶
A [mpm.overrides.<id>] section whose ID is not a built-in manager defines a brand-new manager rather than overriding one. mpm builds it at startup and treats it like any built-in: it gets its own --<id> / --no-<id> selectors, joins the default set on its supported platforms, and is driven by every subcommand it implements.
Important
A manager definition makes mpm run the commands you declare. Definitions are only loaded from a trusted, local configuration file: the file and its folder belong to you or to root, and neither is writable by a group or by others. A remote --config URL never qualifies. Read Security model before adding one.
Required keys¶
Key |
Type |
Description |
|---|---|---|
|
list of strings |
Platform or group IDs the manager runs on (like |
|
table |
At least one operation (see below). A manager with no operations does nothing. |
These overridable fields may also be set: cli_names, cli_search_path, extra_env, post_args, pre_args, pre_cmds, requirement, timeout, unmaintained, version_cli_options and version_regexes. A definition rejects the other overridable fields: cooldown_policy, dry_run, plan, stop_on_error and sudo. Its operations table is the one described below, not the extra_args table of an override. A definition may also set name, homepage_url, documentation_url (the entry point of the tool’s own documentation: its manual, its docs site, or the man page of the CLI mpm drives), repository_url (the repository holding the tool’s code), wikipedia_url (the English Wikipedia article about the tool) and logo (the slug of a brand mark vendored under docs/assets/managers/, inlined at the top of that page). When cli_names is omitted it defaults to the manager ID.
Twelve definition-only fields have no override counterpart:
Key |
Type |
Description |
|---|---|---|
|
string |
Name of the Homebrew Bundle DSL entry this manager maps to, so its installed packages join a |
|
string |
Warning emitted when this manager’s installed packages are deliberately left out of a Brewfile export, where staying silent would mislead. Supports a |
|
boolean |
The manager’s built-in escalation policy: operations marked |
|
boolean |
Marks a manager whose CLI invokes |
|
list of strings |
The operations in which an |
|
list of strings |
Well-known names of the manager its ID does not already carry, merged into the PyPI keywords and the issue labeller rules. |
|
string |
A watch note about a still-maintained upstream whose activity is slowing, rendered as a note atop the manager’s page. |
|
table |
One-sentence hints filling the Notes column of the manager page’s Operations table, keyed by operation name: why an operation is missing, or what makes a declared one partial. |
|
boolean |
Marks an |
|
string |
Evidence and rationale for the |
|
string |
Alternate binary probed for the manager’s version, for tool suites whose own binaries report none (OpenBSD’s |
|
boolean |
Search |
Operations¶
Each entry under [mpm.overrides.<id>.operations] declares one operation. Every operation takes an args list appended after the resolved binary. An operation may also name its own cli (a sibling binary resolved on the same search path), so one definition can span a multi-binary suite: urpmq searching while urpmi installs and urpme removes. Without cli, the operation runs the manager’s main binary.
Command operations run a CLI and need nothing else. Any operation may add sudo = true to mark itself privileged, mirroring the escalation flag built-in managers set in code: whether it actually escalates follows the usual policy (the definition’s default_sudo, then the global --sudo/--no-sudo flag). Command operations are the usual bearers; a query may also carry it, for the rare tool that gates even its read-only listings behind root (deb-get’s upgradable check).
Operation |
Required placeholder |
Maps to |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
single-package |
|
none |
|
|
none |
|
|
none |
|
|
none |
|
|
none |
|
|
none |
|
There is no cleanup operation to declare: a plain mpm cleanup runs the declared cleanup_cache and cleanup_repair categories, and mpm cleanup --orphans the declared cleanup_orphan, so a definition carrying the old monolithic cleanup key is rejected with an error naming the three category keys. Declare cleanup_cache for a cache-pruning command, cleanup_orphan for an orphan sweep.
Query operations (installed, outdated, orphans, search) parse the command’s output. orphans backs mpm orphans, the read-only listing of packages installed as dependencies that nothing requires anymore. search may embed the {query} placeholder in its args; omitting it is also valid for tools with no real search command, whose search then lists the whole catalog (opkg list, swupd bundle-list --all) and relies on mpm’s client-side refiltering to narrow the results. Provide either a regex matched against each output line, or a JSON parser (format = "json" with a fields mapping and optional list_path). Both map these recognized fields to a package:
package_id(always required),installed_version(optional: some tools track no per-package version, likeswupd’s Clear Linux bundles),latest_version(required byoutdated),name(optional: the bare name of a package whose ID carries a namespace, like thegzipofapp-arch/gzip, which an exact query then matches too).
A JSON field maps to a key name, optionally suffixed with a [N] list index to pick one element out of a list-valued key: installed_version = "installed_versions[0]" reads the first entry of each package’s version array.
When the tool has native switches for mpm search’s refinements, search can declare them as argument templates: exact_args (spliced in when --exact is requested), extended_args (when --extended reaches into descriptions) and id_name_only_args (for tools whose unrestricted search is the default and take a flag to narrow it to IDs and names, like Chocolatey’s --by-id-only). Each declared list must pair with a {exact_args}-style marker in args, standing as its own argument, that expands in place when the refinement is active and to nothing otherwise. mpm still refilters the results client-side either way, exactly as for built-in managers.
Any {token} in an operation’s args outside that operation’s recognized placeholders is rejected at load time, so a typo like {qeury} surfaces immediately instead of reaching the tool as a literal argument.
Todo
Make version pinning expressible in a manager definition. install and upgrade on a config-defined manager always let the manager choose the version today, and a {version} placeholder is not substituted.
Example¶
[mpm.overrides.deno]
name = "Deno"
platforms = ["linux", "macos", "windows"]
homepage_url = "https://deno.land"
cli_names = ["deno"]
requirement = ">=1.40"
version_regexes = ['deno (?P<version>\S+)']
[mpm.overrides.deno.operations.installed]
args = ["list"]
regex = '^(?P<package_id>\S+)@(?P<installed_version>\S+)$'
[mpm.overrides.deno.operations.outdated]
args = ["outdated", "--json"]
format = "json"
list_path = "packages"
fields = { package_id = "name", installed_version = "current", latest_version = "latest" }
[mpm.overrides.deno.operations.install]
args = ["install", "{package_id}"]
[mpm.overrides.deno.operations.upgrade_one]
args = ["install", "--force", "{package_id}"]
After this, mpm --deno installed, mpm outdated, and mpm install jq --deno all work, and --deno appears in mpm --help.
Tip
A definition covers managers whose listings parse line-by-line or as a flat JSON array. When the real CLI needs multi-line records, pagination, or stateful parsing, the regex/JSON DSL is not enough: write a real manager and upstream it instead.
Note
mpm ships many of its own managers as such definitions, the .toml files of meta_package_manager/managers/. One worked and tested example: meta_package_manager/managers/gh_ext.toml defines the gh-ext manager (GitHub CLI extensions) using exactly the schema above, and mpm loads it at startup like a built-in. Bundled definitions are the same mechanism as a personal definition, only read from trusted package data instead of your configuration file.
Help improve detection upstream¶
When mpm cannot use a manager you name, mpm --<manager_id> managers prints an override to test under its table. The override holds the current value of the field that controls the cause:
Cause |
Field to test |
|---|---|
No binary found |
|
The version probe printed nothing |
|
No pattern reads a version in the probe output |
|
The version is below the floor |
|
For a version that no pattern reads, the suggestion also quotes the first lines of the probe output, and --verbosity DEBUG logs all of it. Edit the value in your configuration file, then run the same command again. A version above a ceiling gets no suggestion: a ceiling is deliberate.
Once an override works, mpm prints an invitation to file a bug report so the heuristics can be improved for everyone. The fields that trigger an invitation are: cli_names, cli_search_path, requirement, version_cli_options, and version_regexes. Overrides on preference fields like timeout or operations never trigger an invitation.
The invitation is a pre-filled GitHub new-issue URL targeting the bug-report.yml template. Clicking it opens the bug-report form with the manager ID and field in its description, and the override and what mpm detected without it in its Override experiment field. The user only has to add the diagnostic command outputs the form requests (mpm --params, mpm --verbosity DEBUG --all-managers managers) before submitting.
When an AI agent runs mpm, the suggestion tells it to test in a scratch configuration file passed with --config, and the invitation tells it to ask its user before it files the report.
To silence the invitation, pass --no-suggest-contribs on the command line, set the MPM_SUGGEST_CONTRIBS environment variable to false, or add to your config file:
[mpm]
suggest_contribs = false
See also¶
Configuration — global
[mpm]settings and configuration-file precedence rules.Security model — the trust model behind overrides and definitions, and why configuration is code.
Add a new package manager — for contributors who want to upstream a new manager rather than override or define one privately.