🤖 New: manage your ADRs conversationally with the AdrPlus AI Assistant Plugin — let Claude Code or GitHub Copilot create, approve, audit, and index ADRs for you. Learn more ↓
Many teams still document architectural decisions inconsistently (scattered Markdown files, no version flow, and hard-to-track status changes).
AdrPlus was created to solve this problem with a practical CLI workflow that keeps ADRs standardized, traceable, and easy to evolve over time.
AdrPlus is a cross-platform .NET command-line tool for managing Architecture Decision Records (ADRs) directly from your terminal.
It supports versioning, revision cycles, status workflows (approve / reject / undo), and an interactive wizard — all driven by a lightweight JSON configuration file.
- Motivation and Benefits
- Features
- Requirements
- Installation
- Quick Start
- Migration Guide
- Step-by-Step Guide
- Plugin Development Guide
- Using AdrPlus with AI Coding Assistants
- Advanced Configuration (Optional)
- Individual Commands (without the wizard)
- Commands
- Rules by ADR commands
- Suggested profiles
- Configuration
- Plugins
- Settings and configuration across upgrades
- Architecture Decisions of this Project
- Contributing
- Code of Conduct
- Security
- License
- Frequently Asked Questions
Using AdrPlus in an engineering repository helps you:
- 📚 Keep architectural decisions organized with a predictable structure
- 🔍 Improve traceability with version, revise, and supersede flows
- ⚡ Reduce manual effort when creating and updating ADR files
- 🛠️ Respect the repository's configuration for naming, structure, and ADR status for each team
- 🤝 Improve collaboration by making decision history visible to the whole team
- 🚀 Accelerate onboarding by exposing context behind technical choices
- 📝 Create new ADRs with auto-incremented sequential numbers
- 🔢 Version and revise existing ADRs (major version or revision bump)
- 🔄 Supersede an ADR by creating a successor with a new number
- ✅ Approve / ❌ Reject / ↩️ Undo ADR status changes
- 🧙 Interactive wizard for guided, step-by-step operations
- 🤖 AI assistant integration — manage ADRs conversationally via the official AdrPlus AI Assistant Plugin for Claude Code and GitHub Copilot
- 🧩 Plugin support for integrations that react to ADR lifecycle events — see the Plugin Development Guide
- 🔍 Explorer for viewing or Generate reports and managing ADR files in your repository
- ⚙️ Config editor for application ,repository settings and migration of existing ADRs to the standardized format
- 📂 Customizable ADR structure with user-defined templates and naming conventions
- 🔄 Migrate existing ADRs to the standardized format
- 💾 Preserve settings and configuration across upgrades and reinitializations
- 🗂️ Multiple ADR model options for different project needs and for each team
- 🌍 Multi-language support (
en-US,pt-BR,de-DE,es-ES,fr-FR,it-IT,ja-JP,ko-KR,nl-BE,ru-RU,zh-CN) for messages, UX, and ADR templates — see TRANSLATIONS.md for review status.- ADR content can be written in any language!
- 🖥️ Cross-platform (Windows, macOS, Linux)
- .NET 8 Runtime or later
AdrPlus can be used in repositories of any language or framework (C#, Java, Node.js, Python, Go, etc.), because it manages ADR files in Markdown and does not depend on your application stack.
The easiest way to install AdrPlus is directly from NuGet.org:
dotnet tool install -g adrplusTo update to the latest version:
dotnet tool update -g adrplusTo uninstall:
dotnet tool uninstall -g adrplusAfter installation, you can use adrplus from any terminal in any repository.
Check the installed version anytime with:
adrplus --versionIf you prefer to build from the repository source code:
# From repository root
dotnet restore
dotnet build -c Release
dotnet pack -c Release -o ./nupkg# Install as global tool from local package folder
dotnet tool install -g adrplus --add-source ./nupkg
# If already installed, update from the same local source
dotnet tool update -g adrplus --add-source ./nupkgAdrPlus automates the initial setup on first run!
When you run any command for the first time (except help), an interactive wizard will automatically guide you through:
- Selecting your preferred language
- Configuring your editor to open ADR files
- Setting up your ADR repository structure and naming conventions
- Creating your ADR folder and configuration files
To get started, simply run run without command, and the setup wizard will appear:
# Just run without command and the first-time setup will run
adrplus
# Or any other command - the first-time wizard will run before it executes
adrplus init --wizardThis wizard only runs in a real interactive terminal. In CI, scripts, or an AI agent driving the CLI (standard input/output redirected), it's skipped automatically and AdrPlus falls back to its built-in defaults — a team can also pre-provision a firstinstaller.adrplus seed file so that first automated run starts from approved settings instead. See Non-Interactive Setup in the Step-by-Step Guide.
After initial setup completes, you can use any command directly:
# Create a new ADR with the wizard
adrplus new --wizard
# Or explore and manage your ADRs
adrplus explore --path "path/to/repository"
adrplus approve --file "path/to/adr/ADR0001.md"Note: If you have existing ADR files in a different format, see Migration Guide for detailed prerequisites and migration instructions before creating new ADRs with the tool.
For a detailed walkthrough, see the Step-by-Step Guide.
Prefer managing ADRs in plain language instead of typing commands yourself? The official AdrPlus AI Assistant Plugin brings the same skill and agents to both Claude Code and GitHub Copilot:
- A skill (
manage-adrs) that teaches Claude the fulladrpluscommand surface, so it can create, approve, reject, version, revise, supersede, and configure ADRs without guessing at flags. - An
adr-auditoragent that audits an existing ADR repository (structural compliance, content completeness, supersede-chain integrity, status hygiene) and produces a read-only report. - An
adr-indexeragent that turnsadrplus explore's report into a readable, grouped index page. - An
adr-decision-checkagent that checks pending changes before a commit or PR (or on request) and recommends whether they need a new ADR or a version/revise/supersede of an existing one.
Requires adrplus v1.0.0-rc1 or later — earlier pre-releases (including beta1/beta2, which weren't safe to drive non-interactively) are no longer supported.
Note: The initial setup wizard runs automatically on first use in an interactive terminal (see Quick Start above for the non-interactive/CI behavior). The commands below are optional if you want to reconfigure or adjust settings after the initial setup.
You can modify application settings at any time:
# Edit language, editor preferences, and other application settings
adrplus config --application
# Edit the default template used for new ADRs
adrplus config --template
# Edit patterns for migrating existing ADRs (used with the migrate command)
adrplus config --migrate
# Edit repository-specific settings (ADR naming, statuses, structure)
adrplus config --repositoryThe init command can be run multiple times to reinitialize or update your ADR repository structure:
# Initialize repository for the first time (or with wizard guidance)
adrplus init --wizard
# Reinitialize with specific configuration file
adrplus init --path "path/to/repository" --file "path/to/config"
# Reinitialize current directory
adrplus init --path "."This is useful when:
- You need to update the folder structure for scope changes
- You want to recreate default configuration files
- You're adjusting naming conventions or patterns
You can also execute commands directly, one by one, without the wizard and without interactive prompts.
# Configure the tool (optional, you can edit the config file directly or use the config command later)
adrplus config --application --file "path/to/file-tool-config"
adrplus config --template --file "path/to/file-template.md"
# any mode can be used for repository config, the important part is to point to the correct file
adrplus config --repository --file "path/to/file-adr-config"
adrplus config --migrate --file "path/to/file-ard-config"
# Launch the ADR file viewer explorer
adrplus explore --path "path/to/repository"
# Initialize ADR structure (if the first time you set up the repository)
adrplus init --path "path/to/repository"
# Create a new ADR directly
# the parameter --open is optional and depends on the configuration for opening files after creation/update
adrplus new --title "Use PostgreSQL as primary database" --path "path/to/repository" --open
# Approve or reject a specific ADR file
adrplus approve --file "./doc/adr/ADR0001V01-use-postgresql.md"
adrplus reject --file "./doc/adr/ADR0002V01-legacy-cache.md"
# Undo last status change
adrplus undo --file "./doc/adr/ADR0001V01-use-postgresql.md"
# Create supersede flows
adrplus approve --file "./doc/adr/ADR0001V01-use-postgresql.md"
# the parameter --open is optional and depends on the configuration for opening files after creation/update
adrplus supersede --file "./doc/adr/ADR0001V01-use-postgresql.md" --open
# Create revise/version flows
# the parameter --open is optional and depends on the configuration for opening files after creation/update
adrplus revise --file "./doc/adr/ADR0001V01-use-postgresql.md" --open
adrplus version --file "./doc/adr/ADR0001V01-use-postgresql.md" --open
# Re-drive pending plugin dispatches (safe to schedule via cron/CI); --backfill sweeps every
# existing ADR and is manual-only, never scheduled
adrplus sync --path "path/to/repository"
adrplus sync --path "path/to/repository" --backfill
# Check installed plugins, or manage which ones are active for this repository; --list with no
# --path reports only what this host discovered, without any repository's active/inactive status.
# --validate never needs --path either: it only checks structural load, host-wide
adrplus plugins --list
adrplus plugins --list --path "path/to/repository"
adrplus plugins --validate
adrplus plugins --activate "PluginName" --path "path/to/repository"
adrplus plugins --deactivate "PluginName" --path "path/to/repository"
# Install or remove a plugin — host-wide, no --path: the zip must be named <name>-<version>.zip,
# matching its plugin.json; --force overwrites an existing install entirely (including plugin.json);
# neither touches any repository's activeplugins
adrplus plugins --install "./PluginName-1.0.0.zip"
adrplus plugins --uninstall "PluginName"
Use adrplus help <command> to check the available parameters for each command.
| Command | Description |
|---|---|
help |
Display help information for all commands or a specific command |
wizard |
Launch the interactive wizard for guided operations |
config |
Application configuration editor,migrate repository,repository and default ADR template |
explore |
Launch the file viewer explorer and report for the ADR repository |
migrate |
Migrate existing ADRs to use the tool |
init |
Initialize or reinitialize the ADR repository folder structure (can be run multiple times) |
new |
Create a new ADR with an incremental number |
version |
Create a new version of an ADR (increment version) |
revise |
Create a new revision of an ADR (increment revision) |
supersede |
Supersede an ADR by creating a successor with a new incremental number |
approve |
Set an ADR status to Accepted |
reject |
Set an ADR status to Rejected |
undo |
Revert the last status change of an ADR |
sync |
Re-drive pending plugin dispatches (--backfill sweeps every existing ADR and re-emits its current settled event) |
plugins |
Diagnostics for installed plugins (--list/--validate); activate/deactivate a plugin (--activate/--deactivate <name>); install/remove one from a zip (--install <path>/--uninstall <name>) — every mode also available interactively via --wizard |
Run adrplus help <command> for detailed usage of any command.
The rules below describe what must be true for a command to select its target successfully (especially in wizard mode).
For file-based commands (
approve,reject,undo,version,revise,supersede), the file must exist, be a valid ADR.md, be under the configuredFolderRepo, and the repository config file must be valid.
| Command | Successful selection rules |
|---|---|
new |
title + domain must be unique. When scope is enabled , --scope must be valid; --domain is required unless scope is listed in skipdomain. |
approve |
ADR must be eligible: not already approved/rejected and for the same sequence number not superseded. |
reject |
ADR must be eligible: not already approved/rejected. |
undo |
ADR must be eligible: already approved/rejected and for the same sequence not a superseded and not proposed. |
version |
ADR must be eligible: latest(or last approved and last rejected) ADR for the same sequence number approved/rejected and not superseded. |
revise |
ADR must be eligible: latest(or last approved and last rejected) ADR for the same sequence number approved/rejected , not superseded and revision enabled. |
supersede |
ADR must be eligible: already approved and not superseded. |
AdrPlus uses two configuration files:
adrplus.json: application-level settings (language and command to open ADR).adr-config.adrplus: repository-level settings (ADR naming, template, statuses, and structure).
You can edit the application configuration with:
adrplus config --application{
"language": "en-US",
"comandopenadr": "code {0}",
"withoutargs": "Help",
"pluginallowlist": [
{ "name": "AdrIndexer" }
]
}| Key | Description |
|---|---|
language |
UI language/culture used by the tool (en-US, pt-BR, de-DE, es-ES, fr-FR, it-IT, ja-JP, ko-KR, nl-BE, ru-RU, zh-CN, or any other valid culture code). Defines the language for all prompts and messages displayed in the wizard and command outputs, and the language of the built-in ADR templates. |
comandopenadr |
Command to open an ADR file after creation/update when supported. See examples below. |
withoutargs |
Behavior when no arguments are provided (Help, Wizard, or None). Default is Help. |
pluginallowlist |
Optional, host-wide allowlist restricting which installed plugins may load, matched by name (case-insensitive). Omit or set to null to allow every installed plugin (default); an empty array blocks all plugins. Each entry also accepts a hash field, reserved for future enforcement and not yet checked. See Plugins. |
- VS Code:
code {0}— Opens the file in VS Code. - Visual Studio:
devenv.exe {0}— Opens the file in the associated application (Windows only). - JetBrains Rider:
rider {0}— Opens the file in Rider. - Sublime Text:
subl {0}— Opens the file in Sublime Text. - Vim:
vim {0}— Opens the file in Vim. - Nano:
nano {0}— Opens the file in Nano. - Disabled:
""(empty string) — Disables automatic opening of ADR files.
Note: The command must be available as a global PATH variable in your system to work properly. Test it manually in your terminal before configuring it here.
The withoutargs setting determines how AdrPlus behaves when executed without any arguments or commands:
Help(default): Displays the help information with available commands and options.Wizard: Launches the interactive wizard for guided operations (useful for agile experienced users).None: Requires the user to explicitly provide a command; if no command is given, an error message is shown.
Example configurations:
{
"withoutargs": "Help" // Display help when no arguments provided
}{
"withoutargs": "Wizard" // Launch wizard when no arguments provided
}{
"withoutargs": "None" // Require explicit command
}AdrPlus uses the adr-config.adrplus file to control repository behavior, ADR naming, template content, and status labels.
You can edit it with:
adrplus config --repository{
"folderadr": "doc/adr",
"migrationpattern": "...",
"template": "...",
"prefix": "ADR",
"lenseq": 4,
"lenversion": 2,
"lenrevision": 0,
"lenscope": 0,
"separator": "-",
"casetransform": "PascalCase",
"statusnew": "Proposed",
"statusacc": "Accepted",
"statusrej": "Rejected",
"statussup": "Superseded",
"scopes": "",
"folderbyscope": false,
"skipdomain": "",
"headerdisclaimer": "Do not remove this comment, lines and table",
"headertitlefile": "ADR",
"headerversion": "Version",
"headerrevision": "Revision",
"headerscope": "Scope",
"headerdomain": "Domain",
"headertitlestatuscreated": "Created",
"headertitlestatuschanged": "Changed",
"headertitlestatussuperseded": "Superseded",
"headertablefields": "Fields",
"headertablevalues": "Values",
"headermigrated": "Migrated",
"activeplugins": [],
"disableplugins": false
}| Key | Description |
|---|---|
folderadr |
Folder where ADR files are stored. |
migrationpattern |
Pattern used for migrating ADR files (generated by the tool). |
template |
Base Markdown template used when creating new ADR files (generated by the tool). |
prefix |
Prefix used in ADR titles/identifiers (for example: ADR). |
lenseq |
Number of digits for the sequential ADR number (for example: 4 => 0001). |
lenversion |
Number of digits for major version formatting (for example: 2 => 01). |
lenrevision |
Number of digits for revision formatting (for example: 2 => 01; 0 disables revision numbering). |
lenscope |
Maximum scope segment length used in generated names (when scope is enabled, value > 0). |
separator |
Separator character used in generated file names (valid values: -, _, or .). |
casetransform |
Case style applied to generated name segments (for example: PascalCase, CamelCase, SnakeCase, or KebabCase). |
statusnew |
Label used for newly created ADRs. |
statusacc |
Label used for accepted ADRs. |
statusrej |
Label used for rejected ADRs. |
statussup |
Label used for superseded ADRs. |
scopes |
Semicolon-separated list of allowed scopes for organizing ADRs (for example: Enterprise;Domain;Project; can be empty when lenscope = 0). |
folderbyscope |
If true, ADR files are grouped by scope folders; if false, all ADRs remain in the flat folderadr directory. |
skipdomain |
Semicolon-separated list of scope names for which the domain segment should be omitted from the generated filename (must be a subset of scopes). |
headerdisclaimer |
Disclaimer header added to ADR template output. |
headertitlefile |
Header label for the ADR file name field in the header. |
headerversion |
Header label for ADR version field. |
headerrevision |
Header label for ADR revision field. |
headerscope |
Header label for ADR scope field. |
headerdomain |
Header label for ADR domain field. |
headertitlestatuscreated |
Header label for the "Created" status indicator. |
headertitlestatuschanged |
Header label for the "Changed" status indicator. |
headertitlestatussuperseded |
Header label for the "Superseded" status indicator. |
headertablefields |
Table header label for displaying field names in the ADR. |
headertablevalues |
Table header label for displaying field values in the ADR. |
headermigrated |
Header label for the "Migrated" indicator (used for ADRs migrated via the migrate command). |
activeplugins |
Names of the host-installed plugins (see Plugins) expected to be active for this repository. Written automatically by init from whatever's installed on the machine at the time; edit it via adrplus plugins --wizard's manage mode rather than by hand. A plugin installed but left off this list is treated as deliberately inactive (silently skipped); a name listed here with no matching installed plugin is reported as missing the next time a command dispatches. |
disableplugins |
Repository-wide kill switch. When true, no plugin ever dispatches for this repo, regardless of activeplugins — the ADR operation itself still completes normally. |
Before selecting a team profile, understand these key concepts:
-
Scopes: Define organizational boundaries for your ADRs (e.g., "Enterprise", "Backend", "Frontend"). Scopes help organize decisions by domain or team responsibility. When enabled (
lenscope > 0), the scope appears in the ADR filename. -
Folder by Scope: When enabled, ADRs are organized into separate folders for each scope (e.g.,
doc/adr/enterprise/,doc/adr/backend/). When disabled, all ADRs stay in a flat structure under the configuredfolderadrfolder. -
Skip Domain: Some scopes may not need a domain segment in the filename. For example, a "Corporate" scope might skip the domain to keep filenames shorter. You can list multiple scopes separated by semicolons.
-
Case Transform: The style applied to the title portion of generated filenames:
PascalCase:UsePostgreSQLAsDatabaseCamelCase:usePostgreSQLAsDatabaseSnakeCase:use_postgresql_as_databaseKebabCase:use-postgresql-as-database(default)
-
Separator: The character separating different parts of the filename:
-(hyphen):ADR0001V01-UsePostgreSQL.md_(underscore):ADR0001_UsePostgreSQL.md.(period):ADR0001V01.UsePostgreSQL.md
-
Version vs. Revision:
- Version: A major change to an ADR (e.g.,
V01,V02) that typically represents a significant decision update. - Revision: A minor change to an ADR (e.g.,
R01,R02) that represents clarifications or documentation improvements.
- Version: A major change to an ADR (e.g.,
Use scopes and folder grouping to keep ADRs organized by area. Each team or domain maintains its own ADR sequence.
{
"scopes": "Enterprise;Project;Backend;Frontend;Mobile;Data",
"skipdomain": "Enterprise",
"folderbyscope": true,
"lenscope": 1,
"separator": "-",
"casetransform": "PascalCase",
"lenversion": 2,
"lenrevision": 0
}Example filenames generated:
doc/adr/Enterprise/ADR0001V01E-UnifyAuthenticationStrategy.mddoc/adr/Backend/ADR0001V01B-UsePostgreSQ@MyBackEndScope.mddoc/adr/Frontend/ADR0001V01F-AdoptReactFramework@MyFrontEndScope.md
Use a simple flat structure with no scope folder split. Ideal for smaller projects or single-domain repositories.
{
"scopes": "",
"folderbyscope": false,
"lenscope": 0,
"separator": "-",
"casetransform": "PascalCase",
"lenversion": 2,
"lenrevision": 0
}Example filenames generated:
doc/adr/ADR0001V01-UsePostgreSQL.mddoc/adr/ADR0002V01-AdoptReactFramework.md
Keep revision metadata visible and standardized. Useful for teams that frequently update ADR documentation or maintain multiple versions.
{
"lenseq": 4,
"lenversion": 2,
"lenrevision": 2
}Example filenames generated:
doc/adr/ADR0001V01R01-DecisionTitle.md(created)doc/adr/ADR0001V02R01-DecisionTitle.md(after revision)doc/adr/ADR0001V03R02-DecisionTitle.md(after version bump)doc/adr/ADR0002V01R01-DecisionTitle--0001.md(after superseded bump)
Organize ADRs by department with custom headers and folder structure.
{
"scopes": "Infrastructure;Database;Platform;Security",
"skipdomain": "Platform",
"folderbyscope": true,
"lenscope": 3,
"separator": "-",
"casetransform": "PascalCase",
"lenversion": 2,
"lenrevision": 0
}Example filenames generated:
doc/adr/Infrastructure/ADR0001V01Inf-UseDockerContainers.md(Infrastructure)doc/adr/Database/ADR0001V01Dat-AdoptPostgresql.md(Database)
Tip: start with one profile, run
adrplus init, create a test ADR withadrplus new, and adjust the config iteratively.
Not every ADR-related need belongs in the core CLI. Teams often want to react to ADR lifecycle events — regenerate an index, notify a channel, sync to an external system, enforce a custom policy — without AdrPlus growing built-in support for every possible target. The plugin system exists for exactly that: any command that changes an ADR's state (create, approve, reject, revise, supersede, undo) dispatches lifecycle events that plugins can subscribe to and react to independently of the core tool.
Writing a plugin means implementing the IAdrPlugin interface from the AdrPlus.Abstractions package — see the Plugin Development Guide for the full contract and event lifecycle.
You don't need to write one to get value from the plugin system: AdrPlus.Plugins.AdrIndexer already ships bundled with AdrPlus and is discovered automatically — no install step needed. It rebuilds a linked table of your ADRs (ADR, title, version, status) every time an ADR changes, and doubles as a working reference implementation if you want to build your own.
Plugins are installed once per machine, host-wide — not per repository. Installing a third-party or hand-built plugin doesn't require manually copying files: adrplus plugins --install "./PluginName-1.0.0.zip" unpacks a zip named <name>-<version>.zip into %UserProfile%/AdrPlus.Plugins/<name>/, making it available to every repository on that machine; --uninstall <name> removes it from the machine entirely. A newly installed plugin never dispatches on its own for any given repository — activate it explicitly per repo with adrplus plugins --activate <name> --path "path/to/repository" (or deactivate one with --deactivate <name> --path "path/to/repository"), the same trust checkpoint the interactive wizard's manage mode already enforces.
Before activation even comes into play, an optional pluginallowlist in adrplus.json can restrict which installed plugin names are permitted to load at all on that host — see the Configuration section above. adrplus plugins --list reports each plugin's allowlist status alongside its active/inactive state.
Removing AdrPlus completely?
dotnet tool uninstall -g adrplusdoesn't clean up%UserProfile%/AdrPlus.Plugins/(installed plugins) or%UserProfile%/AdrPlus.History/(settings carried across upgrades) — dotnet global tools have no uninstall hook, so both are left behind by design. Delete them by hand if you want a fully clean removal.
When you upgrade AdrPlus to a new version, all your settings and configurations are automatically preserved:
# Update to the latest version
dotnet tool update -g adrplusYour configuration persists automatically:
- ✅ Application settings (
adrplus.json): Language, editor preferences, and interface behavior remain unchanged - ✅ Repository configuration (
adr-config.adrplus): ADR naming patterns, folder structure, and scope definitions are maintained
No manual reconfiguration is needed after upgrading — simply update the tool and continue using it as before.
AdrPlus is used to manage its own architecture decisions — see the ADR Index (auto-generated by the AdrIndexer plugin) for the list of decisions recorded for this repository.
Contributions are welcome! Please read CONTRIBUTING.md before submitting pull requests or issues.
Please read and follow CODE_OF_CONDUCT.md.
To report a vulnerability, please read SECURITY.md.
This project is licensed under the MIT License.