Managing ADRs with adrplus
adrplus is a cross-platform .NET CLI tool for managing Architecture Decision Records. This skill teaches you how to drive it directly, without ever going through its interactive --wizard mode.
Critical rule: never use --wizard/-w, and never run bare adrplus wizard
adrplus's wizard mode is an interactive terminal UI (arrow-key menus, live text prompts) built for a human sitting at a real terminal. You cannot drive it through the Bash tool — it will hang waiting for keystrokes it will never receive. This applies both to the -w/--wizard flag on any subcommand below and to the standalone top-level adrplus wizard command (a guided-operations entry point with no non-interactive form at all — it takes no arguments besides --help). Always use the direct, non-interactive flags documented below instead. If a user explicitly asks to run the wizard themselves, tell them to run the command in their own terminal — don't attempt it yourself.
Prerequisite
adrplus must already be installed as a .NET global tool:
adrplus --version
If this fails, tell the user to run dotnet tool install -g adrplus (requires .NET 8+ runtime) before continuing. To upgrade an already-1.0.0-or-later install to a newer release, the command is dotnet tool update -g adrplus, then re-check with adrplus --version. Don't wait for a crash to mention this.
Requires v1.0.0 (final) or later — pre-releases (any -beta*/-rc* suffix) are no longer supported. 1.0.0 shipped 2026-08-27 as a breaking release: adrplus version/adrplus supersede gained -d/--domain/-s/--scope (not present on rc1-rc4) and adrplus revise lost -e/--empty (present on rc1-rc4) — one command table cannot describe both a pre-1.0.0 install and 1.0.0 correctly, which is why this skill no longer tries to. Earlier pre-releases also aren't supported for the reasons previously documented here: versions before beta1 could fall into an interactive first-run wizard unconditionally, and beta1/beta2 still crashed non-interactively on a genuinely fresh repository or a fresh adrplus install — both crashed or hung when you (Claude) run them via Bash, even with all the right non-interactive flags. If a command you run this way fails with "The handle is invalid" or similar console errors instead of a normal error message, tell the user their adrplus is too old and needs upgrading.
If the installed version predates 1.0.0, don't upgrade in place. Per AdrPlus's own 1.0.0 changelog, this is a breaking release with no compatibility shim: run dotnet tool uninstall -g adrplus then dotnet tool install -g adrplus instead of dotnet tool update -g adrplus. Afterward, any adr-config.adrplus still carrying scopes/lenscope/skipdomain/folderbyscope (see below) must be fixed by hand — the upgrade doesn't do it for you.
Scope and Domain are always plain free-text header fields with no validation, whitelist, or naming influence. If you're working in a repository whose adr-config.adrplus still carries scopes, lenscope, skipdomain, or folderbyscope — leftovers from a pre-1.0.0 config — that config is now invalid: v1.0.0 rejects it outright instead of tolerating and ignoring those keys. Don't treat their presence as harmless; see the next section for how to actually remove them.
Two config files — and neither config --repository/--template/--migrate edits either one directly
adrplus.json— application settings:language,comandopenadr(command to open a file, e.g.code {0}),withoutargs.adr-config.adrplus— repository settings: naming (prefix,lenseq,lenversion,lenrevision,separator,casetransform), status labels (statusnew,statusacc,statusrej,statussup), header labels, and plugin settings —activeplugins(names of host-installed plugins expected active for this repo, written byinitand managed viaadrplus plugins --activate/--deactivate, see below) anddisableplugins(repo-wide kill switch;trueskips all plugin dispatch regardless ofactiveplugins, without affecting the ADR operation itself).
Verified against the installed CLI: config --application/--repository/--template/--migrate — with or without --file — write to adrplus's own shared, install-level default template (next to the adrplus executable itself), never to the current repository's adrplus.json/adr-config.adrplus. Running config --repository --file <json> prints the install-directory path it actually wrote; the current repo's own adr-config.adrplus is left byte-for-byte unchanged. These commands only affect what a future adrplus init (without its own --file) will seed a new repository with — they are not a way to edit settings in a repo you've already initialized. The one command that reads that shared default back and does write it into an existing repo's own file is migrate: if the repo's own migrationpattern is empty, migrate pulls the install-level pattern (as set by config --migrate --file <json>) and persists it into that repo's adr-config.adrplus — so the migration flow under "Typical flows" below still works exactly as written.
To change a setting in a repository you've already run init in: read adr-config.adrplus (Read tool — it's plain JSON in the repo root), edit only the fields that need to change, and write it back (Write tool). This is the safe default. adrplus init --path <dir> --file <path-to-full-json> is a working alternative — it does target the repo's own file, bypassing the "already exists" confirmation — but it overwrites the entire file and resets activeplugins to every plugin currently discovered on the host, silently undoing any prior adrplus plugins --deactivate. Prefer the hand-edit unless you specifically want that reset.
init and migrate are designed to work non-interactively out of the box with just --path — no --file needed for a first run.
Command reference (verified against the actual Arguments definitions — do not invent flags not listed here)
Run adrplus help <command> yourself if anything here seems inconsistent with what you observe — the CLI's own help output is the source of truth.
| Command | Flags | Notes |
|---|---|---|
adrplus --version |
— | Prints the installed version. Not adrplus version (that's a different command, see below). |
adrplus help [command] |
||
adrplus init |
-p/--path <dir> -f/--file <config.json> |
Creates adr-config.adrplus + the ADR folder. Can be run multiple times as long as --file is given — each run overwrites the repo's config outright (see the reset-activeplugins caveat above). Without --file, a second run on an existing config fails cleanly with Configuration file already exists at: <path> instead; verified against 1.0.0. |
adrplus config --application |
-f/--file <json> |
Edits the shared install-level adrplus.json — see "Two config files" above. Requires --file to be non-interactive. |
adrplus config --repository |
-f/--file <json> |
Edits the shared install-level default template, not the current repo's adr-config.adrplus — see "Two config files" above. Requires --file to be non-interactive. |
adrplus config --template |
-f/--file <template.md> |
Sets the shared install-level default ADR template used by future init calls — not the current repo's already-set template. Requires --file. |
adrplus config --migrate |
-f/--file <json> |
Sets the shared install-level default migration pattern; migrate (see below) pulls it into a specific repo when that repo's own pattern is empty. Requires --file to be non-interactive — do NOT confuse with the migrate command itself. |
adrplus migrate |
-p/--path <dir> |
Adds AdrPlus headers to existing hand-written ADR files. Only works when no ADR has ever been created with adrplus new in that repo. Run config --migrate first if the default detection pattern doesn't fit — that's the one config mode that actually reaches this repo's file, via migrate's own fallback (see "Two config files" above). A file whose sequence/version/revision segment isn't genuinely numeric is rejected as invalid rather than silently treated as 0. Verified: the header row it writes embeds a literal <!-- Migrated --> marker inside the "Values" cell (e.g. ` |
adrplus new |
-p/--path <dir> -t/--title "<text>" -d/--domain "<text>" -s/--scope "<text>" -r/--refdate "YYYY-MM-DD" -o/--open |
Creates a new ADR with an incremental number. --scope/--domain are optional free-text fields with no validation. |
adrplus approve |
-f/--file <adr.md> -r/--refdate "YYYY-MM-DD" |
Sets status to Accepted. ADR must not already be approved/rejected. |
adrplus reject |
-f/--file <adr.md> -r/--refdate "YYYY-MM-DD" |
Sets status to Rejected. Same eligibility as approve. |
adrplus undo |
-f/--file <adr.md> |
Reverts the last status change. ADR must already be approved/rejected and not superseded. |
adrplus version |
-f/--file <adr.md> -d/--domain "<text>" -s/--scope "<text>" -r/--refdate "YYYY-MM-DD" -o/--open -e/--empty |
Creates a new major version of an approved/rejected, non-superseded ADR. --domain/--scope update those fields on the new version; omit either to keep the source ADR's current value. --empty starts from a blank template instead of copying content forward. |
adrplus revise |
-f/--file <adr.md> -r/--refdate "YYYY-MM-DD" -o/--open |
Creates a new revision (minor change) of an ADR. Only works if revisions are enabled (lenrevision > 0 in adr-config.adrplus). No --empty (removed in 1.0.0) — revise always copies the source ADR's content forward; use adrplus version --empty instead when the decision itself changed enough to warrant a blank start. |
adrplus supersede |
-f/--file <adr.md> -d/--domain "<text>" -s/--scope "<text>" -r/--refdate "YYYY-MM-DD" -o/--open |
Creates a successor ADR with a new sequence number; marks the original Superseded. Original must already be approved. --domain/--scope update those fields on the successor; omit either to keep the predecessor's current value. |
adrplus explore |
-p/--path <dir> -f/--file <report.md> -o/--open |
With both --path and --file given, generates a full Markdown table report of every ADR in the repo — fully non-interactive, includes all fields. This is the data source the adr-indexer agent uses. |
adrplus plugins |
-p/--path <dir> -l/--list -v/--validate -a/--activate <name> -d/--deactivate <name> -i/--install <zip> -u/--uninstall <name> -f/--force |
Manages AdrPlus's own plugin system — plugins implementing IAdrPlugin that react to ADR lifecycle events (e.g. the bundled AdrIndexer reference plugin, which auto-writes <folderadr>/indexadrs.md on every create/approve/reject/revise/supersede/undo). Not this Claude Code plugin — a separate, unrelated extensibility mechanism inside the adrplus CLI itself. --path is required for --list/--validate/--activate/--deactivate (repo-scoped); --install/--uninstall take no --path — they install/remove a plugin machine-wide. --force (with --install) overwrites an already-installed plugin entirely. |
adrplus sync |
-p/--path <dir> -b/--backfill |
Re-drives plugin dispatches that failed to complete for a repo. --backfill re-emits every ADR's current settled event to all active plugins — per the CLI's own help text, this is manual/occasional use only, never automate via cron/CI. |
version vs revise vs supersede, in one line each: version = a substantial update to the same decision (not just wording — that's revise); revise = fix/clarify wording, same decision; supersede = a different decision replaces this one entirely.
Omitting a command's own required argument (e.g. --file for approve/reject/undo/revise/version/supersede, --title for new) without --wizard now fails cleanly with Required argument '--x' (-x) is missing. If you see a raw The given key '...' was not present in the dictionary error instead, the installed adrplus predates this fix and is worth flagging as outdated regardless of the version-floor check above.
Typical flows
First time in a repo with no existing ADRs:
adrplus init --path .
adrplus new --path . --title "Use PostgreSQL as primary database" --domain "Backend"
Repo with existing hand-written ADRs to bring under adrplus:
adrplus init --path .
# only if the default filename pattern won't be auto-detected correctly:
adrplus config --migrate --file migration-config.json
adrplus migrate --path .
Everyday lifecycle:
adrplus approve --file "./doc/adr/ADR0001V01-UsePostgresql.md"
adrplus revise --file "./doc/adr/ADR0001V01-UsePostgresql.md"
adrplus supersede --file "./doc/adr/ADR0001V01-UsePostgresql.md" --open
When in doubt
If a user's request doesn't map cleanly onto one of the rows above, run adrplus help <command> and read its actual output before guessing at a flag. Never fall back to --wizard to sidestep uncertainty.
Before committing or opening a PR
When you're about to run git commit or open a pull request on the user's behalf, launch the adr-decision-check agent in the background first — don't wait for it, and don't let it delay the commit/PR. Proceed with the commit/PR immediately; report the agent's verdict as a follow-up once it's ready, the same way a CI check reports after a push rather than blocking it. This is advisory only — never hold up or refuse a commit because of its recommendation.