CLI Reference
Interactive first-run on a TTY is the same setup questions as chat/MCP (first run and questions). There is not a CLI questionnaire. CI and a non-TTY never ask.
Audit
maintainability-agent --config maintainability-agent.json
Aliases:
maintainability-agentmaintainability-audit
MCP server
Install the optional extra, then start the same local MCP server through the package CLI (it writes only the five disclosed config/state artifacts — never source, never a report). The MCP audit_repository tool does not audit until configuration is answered and action is run; see first run and questions:
python3 -m pip install "maintainability-agent[mcp]"
maintainability-agent mcp --allow-root /absolute/path/to/repository
Repeat --allow-root to authorize unrelated repository directories. With no explicit root, the server permits only its launch directory. The standalone maintainability-agent-mcp console script remains available for existing IDE configurations.
Options
| Option | Purpose |
|---|---|
--root |
Repository root to scan. Defaults to current directory. |
--version |
Print the CLI version and exit. |
--config |
JSON config path. Optional economic_context (ADR 004 v1) is described in config schema. |
--format |
markdown, json or html. Omitted at a terminal, the CLI asks which presentation you want — chat (Enter), markdown, html or json; in CI it defaults to markdown and never asks (ADR 011). json emits the report dictionary the other presentations render, computing no score of its own. |
--output |
Report output path. |
--html-output |
Write the single-file HTML report (inlined CSS, deterministic SVG charts from the recorded history; opens offline). |
--prompt-output |
AI remediation prompt output path. |
--comment-output |
PR comment body output path. |
--agent-instructions-output |
Audit-specific agent instructions output path. |
--attestation-output |
Write the attestation: an independent, reproducible record of what was measured, what the change was told to do, what it did, and what moved. Populated by --conformance and --fail-on-regression; a question nobody asked renders as not asked, never as a pass. Reproducible and not signed — the digest is over the record's own content and nothing here holds a key. |
--hostile-prompt-output |
Adversarial audit brief seeded from this run (ADR 013). Text only: it does not gate, score, or send anything. |
--transformation |
Name the class of work this scan followed, e.g. react-18. Records the name on the scan and reports how this run of it compares with earlier ones — the movement in estimate between the previous recorded scan and this one, per run. A report, never a gate, and it changes no score. What it measures is the interval, not the transformation's effect: nothing in a tree says which transformation produced it, so the name is your claim and anything else that happened in the same interval is inside the number. It refuses across an instrument change and says how many runs it refused. |
--sarif-input |
External SARIF file to summarize in the report. Repeatable. |
--changed-only |
Git revspec for changed-file-only mode, e.g. main...HEAD. |
--check PATH |
Read proposed content on stdin and report what its budgets say — the in-loop door, for an agent mid-edit. Needs no repository and no git: PATH names the content (it decides the language and appears in the output) and is never opened, so the content you pass is what gets measured rather than whatever is already on disk. Reports breaches, and for what still fits, how much room is left in every budget it can be failed on — length, cyclomatic and cognitive complexity, banded on whichever is worst, because a short function sitting on the complexity warn line has no room left in the budget that matters. A gate says no once it is too late to be cheap. Never scores: one file has no population to draw a rate from. A unified diff is refused in every language — by its format, not by a parser — because piping a diff instead of file content is the likeliest mistake at this door and it used to read as clean. A language with no declaration scanner says so rather than reporting nothing and looking clean. Refuses the flags it would have to ignore, sharing one list with --staged: a flag accepted and ignored teaches the caller it was honoured. Exit 1 on a breach, silently 0 when clear; --format json for agents. |
--staged |
Scan what the git index will commit and exit — the pre-commit path. Reads the index rather than the working tree, so a half-staged file is measured as it will land. Reports threshold breaches and added suppression markers only, and never a score: a diff has no population to draw a rate from. Applies no repository gates, writes nothing, and never runs the opt-in test suite. Exit 1 blocks, 0 passes silently, 2 means the index could not be read — which also blocks, because a scan that could not be taken has not found nothing. Refuses the flags it would have to ignore rather than accepting them. Honours --format json. |
--install-precommit-hook |
Write a git pre-commit hook that runs --staged, and exit. Refuses to replace a hook this tool did not write and prints the line to add to that hook instead; replaces its own without asking, because that is an upgrade rather than a clobber. Honours core.hooksPath and works in a linked worktree. |
--baseline |
Existing baseline JSON file. |
--write-baseline |
Write current findings as a baseline JSON file. |
--fail-on-new |
Exit nonzero only for findings not in baseline. |
--fail-on-gate |
Exit nonzero when hard gates fail. |
--conformance |
Git revspec, e.g. main...HEAD. Reports how a diff relates to the work order it was given: which changed files the work order named, which are tests pairing to a named file, and which are neither — and any suppression marker (# noqa, eslint-disable, a skipped test) the diff added, flagging those landing on a file the work order named. The bounded prompt says fix exactly these and refactor nothing else; without this the bound is an instruction nothing checks. Reports only — it never scores, and it does not fail a build on its own. clean fails on a suppression directive the diff added to a file the work order named, and — since 3.11.0 — on any test file in the diff made unable to fail: a skip or suppression, an assertion that cannot fail, the assertion API replaced, a failing assertion swallowed, or assertions deleted with nothing in their place (_oracle, reported as oracle_weakened). Held to a precision bar frozen before the detector was written. --ask supplies an operator's ask in place of the work order. |
--ask |
With --conformance, a file you name listing the paths and globs a task was asked to change, one per line (# for comments). The diff is read against this ask instead of the work order, for work this tool did not order: every change outside it — other than a test pairing to an asked file — is reported out of scope, production and tests counted apart. * matches across directories, and a glob that matched nothing is listed under ask_unmatched. An ask that names nothing is a usage error (exit 2). Read from your path, never discovered in the audited tree; shape, not correctness (Decision 13). Refused without --conformance. |
--fail-on-regression |
Exit 1 when any scoring category is lower than the previous comparable scan. Reads the recorded history. Refuses — exit 2 — rather than comparing across an instrument change: two scans taken under different calibration or a different analyzer population cannot be subtracted, and 2.0.0 moving CALIBRATION_C would otherwise have read as a catastrophic regression everywhere. |
--fail-on-out-of-scope |
With --conformance, exit 1 when the diff touched files the work order did not name and that are not a named file's test, or when it added a suppression to a flagged file. Scope alone is satisfiable by adding # noqa to the named file and changing nothing else, so the gate reads both. Opt-in, because a finding can legitimately require touching a caller nobody flagged. |
--analyzers |
Force the external analyzer pool on, overriding analyzers.run. A configured repository runs its pool by default. A complete concept set moves the point estimate; otherwise the built-in fallback stands and the range widens. Missing-tool acquisition is separately controlled by analyzers.acquire_tools and defaults off. See the analyzer pool. |
--no-analyzers |
Force the external analyzer pool off for this invocation, overriding analyzers.run. |
--work AXIS=VALUE |
Narrow the work order. Repeatable; every criterion must match. Axes: band, finding_class, path, verification. Narrowing changes what is shown and never what anything scored. |
--record-history |
Create or append this scan to .maintainability/history.jsonl. Once the file exists, every later successful scan appends to it and reads the resulting history without another flag. |
--backfill REVSPEC |
Scan each commit in a range into the history and exit, e.g. HEAD~50..HEAD. Each commit is checked out in a temporary worktree; the working tree is never touched. Expensive, so it never runs as part of a normal scan. |
--backfill-interval N |
With --backfill, scan every Nth commit instead of all of them. |
--sarif-output |
Write SARIF report for GitHub code scanning. |
--security-pillar |
Use this security-pillar.json, written by secure-code-agent --security-pillar, instead of running the tool. Without it, every audit runs secure-code-agent for the security pillar itself (ADR 007, D177); CI passes the document so the tool runs once, as its own gated step. A document sitting in the audited tree is not read on its own authority. |
--init-agent-standards |
Generate model/tool-specific instruction files and exit without running an audit. |
--install-skill |
Copy the packaged agent skill into the skills directory and exit. Re-run after every upgrade: an installed skill that drifts from the shipped one teaches agents a dead workflow. What it writes is the _skill_data payload inside the distribution; the command reads that payload and compares it against what is already installed, and it does not consult the repository. That the payload matches the reviewed skills/maintainability-agent/SKILL.md is held by the suite — tests/test_wheel_contents.py asserts it byte-for-byte against a staged build — not by a check at run time. |
--skills-dir |
Where --install-skill writes (default ~/.claude/skills). |
--update |
Upgrade this install to the newest release and exit. The installer resolves the version (uv pip install --upgrade, or pip without uv), so it never moves backwards; a lower result is refused and named. On an upgrade it re-syncs the skill (--install-skill) and records that the MCP server, which holds the code it loaded at spawn, needs a restart (D230). |
--install-updater |
Write the macOS launch agent io.github.marshallguillory86.maintainability-agent.update, which runs --update hourly, load it, and exit. Removes the legacy com.marshallguillory.maintainability-agent-update agent so two updaters never run. |
--home |
With --install-updater: the home directory to write the launch agent into (default ~). |
--no-launchctl |
With --install-updater: write the launch agent without loading it. |
--force-skill |
With --install-skill: overwrite a differing installed copy and remove files the package no longer ships. Without it, a differing copy is refused with the list of differences against the packaged payload. |
--target |
Instruction target. Repeatable. Any name is accepted; one this tool has no built-in convention for must bring its own --target-path. |
--target-path |
TARGET=PATH — where that agent reads its standing instructions, relative to --instructions-output-dir. Repeatable. Required for an agent with no built-in convention, and overrides the built-in path for one that has. The built-in list will always trail the market, and guessing a path writes a plausible file the agent never opens — so an unknown target is refused with the flag to use, rather than given a generated filename. |
--instructions-output-dir |
Output directory for generated instruction files. |
Examples
maintainability-agent \
--config maintainability-agent.json \
--output maintainability-report.md \
--prompt-output maintainability-remediation-prompt.md \
--comment-output maintainability-pr-comment.md
maintainability-agent \
--config maintainability-agent.json \
--changed-only main...HEAD \
--fail-on-gate
maintainability-agent \
--config maintainability-agent.json \
--init-agent-standards \
--target codex \
--target claude-code \
--target cursor