Introduction
adrs is a command line tool for creating and managing Architecture Decision Records (ADRs).
What are ADRs?
Architecture Decision Records are short documents that capture important architectural decisions made during a project. Each ADR describes a single decision, including the context, the decision itself, and its consequences.
Features
- adr-tools compatible: Works with existing ADR repositories created by adr-tools
- Multiple formats: Supports both Nygard (classic) and MADR 4.0.0 formats
- Template variants: Full, minimal, and bare templates for each format
- Cross-platform: Binaries available for Linux, macOS, and Windows
- Library support: Use
adrs-coreas a Rust library in your own tools
Quick Start
Installation
Using the shell installer (Linux/macOS):
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/joshrotenberg/adrs/releases/latest/download/adrs-installer.sh | sh
Using PowerShell (Windows):
powershell -ExecutionPolicy Bypass -c "irm https://github.com/joshrotenberg/adrs/releases/latest/download/adrs-installer.ps1 | iex"
Using Homebrew:
brew install joshrotenberg/brew/adrs
Using Cargo:
cargo install adrs
Initialize a Repository
adrs init
This creates:
- A
.adr-dirfile pointing todoc/adr - The
doc/adrdirectory - An initial ADR:
0001-record-architecture-decisions.md
Create a New ADR
adrs new "Use PostgreSQL for persistence"
This opens your editor with a new ADR from the default template. Save and close to create the record.
List ADRs
adrs list
Link ADRs
adrs link 2 "Amends" 1 "Amended by"
Migration from adr-tools
adrs is designed to be a drop-in replacement for adr-tools. Your existing ADR repository will work without changes:
- Install
adrs - Run commands as usual -
adrsreads the existing.adr-dirfile and ADR documents
For new features like MADR format or YAML frontmatter, see the Configuration chapter.
Next Steps
- Configuration - Learn about configuration options
- Commands - Detailed command reference
- Templates - Customize ADR templates
- Formats - Nygard vs MADR format comparison
Installation
Pre-built Binaries
Pre-built binaries are available for Linux, macOS, and Windows.
Shell Installer (Linux/macOS)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/joshrotenberg/adrs/releases/latest/download/adrs-installer.sh | sh
PowerShell Installer (Windows)
powershell -ExecutionPolicy Bypass -c "irm https://github.com/joshrotenberg/adrs/releases/latest/download/adrs-installer.ps1 | iex"
Homebrew (macOS/Linux)
brew install joshrotenberg/brew/adrs
Manual Download
Download the appropriate binary from the releases page.
| Platform | Architecture | Download |
|---|---|---|
| Linux | x86_64 | adrs-x86_64-unknown-linux-gnu.tar.gz |
| Linux | aarch64 | adrs-aarch64-unknown-linux-gnu.tar.gz |
| macOS | x86_64 (Intel) | adrs-x86_64-apple-darwin.tar.gz |
| macOS | aarch64 (Apple Silicon) | adrs-aarch64-apple-darwin.tar.gz |
| Windows | x86_64 | adrs-x86_64-pc-windows-msvc.zip |
From Source
Using Cargo
cargo install adrs
Building from Git
git clone https://github.com/joshrotenberg/adrs
cd adrs
cargo build --release
The binary will be at target/release/adrs.
Docker
A Docker image is available for running adrs in containers:
docker pull ghcr.io/joshrotenberg/adrs:latest
Mount your project directory to use it:
docker run --rm -v $(pwd):/workspace -w /workspace ghcr.io/joshrotenberg/adrs list
Verify Installation
adrs --version
Shell Completions
Generate shell completions for your shell:
# Bash
adrs completions bash > ~/.local/share/bash-completion/completions/adrs
# Zsh
adrs completions zsh > ~/.zfunc/_adrs
# Fish
adrs completions fish > ~/.config/fish/completions/adrs.fish
# PowerShell
adrs completions powershell > $PROFILE.CurrentUserAllHosts
Note: Shell completions require rebuilding after updating adrs.
Configuration
adrs supports multiple configuration methods with the following priority (highest to lowest):
- Command-line flags
- Environment variables
- Project configuration file (
adrs.tomlor.adr-dir) - Global configuration file (
~/.config/adrs/config.toml) - Default values
Project Configuration
Legacy Format (.adr-dir)
For compatibility with adr-tools, adrs reads the .adr-dir file:
doc/adr
This single-line file specifies the directory where ADRs are stored.
TOML Format (adrs.toml)
For more options, use adrs.toml in your project root:
# ADR storage directory (relative to project root)
adr_dir = "doc/adr"
# Operation mode: "compatible" or "nextgen"
# - compatible: adr-tools compatible output (default)
# - nextgen: YAML frontmatter with enhanced features
mode = "compatible"
# Template configuration
[templates]
# Default format: "nygard" or "madr"
format = "nygard"
# Default variant: "full", "minimal", or "bare"
variant = "full"
# Path to custom template file (optional)
# custom = "templates/custom.md"
Global Configuration
Create ~/.config/adrs/config.toml for user-wide defaults:
# Default mode for new repositories
mode = "nextgen"
[templates]
format = "madr"
variant = "minimal"
Project configuration overrides global configuration.
Environment Variables
| Variable | Description |
|---|---|
ADR_DIRECTORY | Override the ADR directory path |
ADRS_CONFIG | Path to a specific configuration file |
EDITOR | Editor to use for adrs new and adrs edit |
Example:
export ADR_DIRECTORY="decisions"
adrs new "Use Redis for caching"
Configuration Discovery
When you run an adrs command, it searches for configuration by:
- Looking in the current directory for
adrs.tomlor.adr-dir - Searching parent directories up to the git root (or filesystem root)
- Checking the global config at
~/.config/adrs/config.toml - Using defaults if nothing is found
This means you can run adrs commands from any subdirectory of your project.
Modes
Compatible Mode (default)
Produces output identical to adr-tools:
- Status in the document body
- Links as markdown text
- No YAML frontmatter
NextGen Mode
Enables enhanced features:
- YAML frontmatter for metadata
- Structured status and links
- MADR 4.0.0 fields (decision-makers, consulted, informed)
Enable with --ng flag or in configuration:
mode = "nextgen"
Show Current Configuration
adrs config
Output:
Project root: /path/to/project
Config source: adrs.toml
ADR directory: doc/adr
Full path: /path/to/project/doc/adr
Mode: Compatible
Formats
adrs supports two ADR formats: Nygard (the original adr-tools format) and MADR 4.0.0.
Nygard Format
The classic format from adr-tools, based on Michael Nygard's blog post.
Structure
# 1. Record architecture decisions
Date: 2024-01-15
## Status
Accepted
## Context
We need to record the architectural decisions made on this project.
## Decision
We will use Architecture Decision Records, as described by Michael Nygard.
## Consequences
See Michael Nygard's article for a detailed description.
Sections
| Section | Description |
|---|---|
| Title | Number and title as H1 heading |
| Date | When the decision was made |
| Status | Proposed, Accepted, Deprecated, Superseded |
| Context | Why is this decision needed? |
| Decision | What was decided? |
| Consequences | What are the implications? |
MADR 4.0.0 Format
Markdown Architectural Decision Records version 4.0.0 provides a more structured format with additional metadata.
Structure
---
status: accepted
date: 2024-01-15
decision-makers:
- Alice
- Bob
consulted:
- Carol
informed:
- Dave
---
# Use PostgreSQL for Persistence
## Context and Problem Statement
We need a database for storing user data.
## Decision Drivers
* Need ACID compliance
* Team has PostgreSQL experience
* Open source preferred
## Considered Options
* PostgreSQL
* MySQL
* MongoDB
## Decision Outcome
Chosen option: "PostgreSQL", because it meets all requirements and the team is familiar with it.
### Consequences
* Good, because we have team expertise
* Bad, because it requires more infrastructure than SQLite
### Confirmation
We will confirm this decision after the first production deployment.
## Pros and Cons of the Options
### PostgreSQL
* Good, because ACID compliant
* Good, because team experience
* Neutral, because requires server setup
### MySQL
* Good, because widely used
* Bad, because different SQL dialect
### MongoDB
* Good, because flexible schema
* Bad, because not ACID compliant by default
YAML Frontmatter Fields
| Field | Description |
|---|---|
status | Decision status |
date | Date of the decision |
decision-makers | List of people who made the decision |
consulted | List of people whose opinions were sought |
informed | List of people who were informed of the decision |
Sections
| Section | Required | Description |
|---|---|---|
| Title | Yes | The decision as an H1 heading |
| Context and Problem Statement | Yes | Why is this decision needed? |
| Decision Drivers | No | Factors influencing the decision |
| Considered Options | No | Options that were evaluated |
| Decision Outcome | Yes | The chosen option and rationale |
| Consequences | No | Good and bad outcomes |
| Confirmation | No | How the decision will be validated |
| Pros and Cons | No | Detailed option comparison |
| More Information | No | Links and references |
Choosing a Format
| Use Nygard when... | Use MADR when... |
|---|---|
| Migrating from adr-tools | Starting a new project |
| Simplicity is preferred | You need structured metadata |
| Team is familiar with it | You want decision-maker tracking |
| You need detailed option comparison |
Specifying Format
Per-command
adrs new --format madr "Use PostgreSQL"
adrs new --format nygard "Use PostgreSQL"
In Configuration
[templates]
format = "madr"
Template Variants
Both formats support three variants:
| Variant | Description |
|---|---|
full | All sections with guidance comments |
minimal | Essential sections only |
bare | Bare structure, no comments |
adrs new --format madr --variant minimal "Use PostgreSQL"
See Templates for more details.
Compatibility
This page explains the differences between compatible mode (default) and NextGen mode (--ng), including what breaks adr-tools compatibility.
Mode Comparison
| Aspect | Compatible (default) | NextGen (--ng) | Breaks adr-tools? |
|---|---|---|---|
| Config file | .adr-dir | adrs.toml | Yes |
| File format | Plain markdown | YAML frontmatter | Yes |
| Status storage | ## Status section | status: in YAML | Yes |
| Link storage | Markdown links in Status | links: YAML array | Yes |
| Date storage | Date: YYYY-MM-DD inline | date: in YAML | Yes |
| MADR fields | Not available | decision-makers, consulted, informed | N/A |
Key Incompatibilities with adr-tools
- adr-tools cannot read --ng files - YAML frontmatter breaks bash parsing
- adr-tools cannot write to --ng repos - Creates files without frontmatter
- Mixed repos don't work - adr-tools would create incompatible files
- Scripts break - Anything grep'ing for
## Status\n\nAcceptedfails
What Still Works
adrscan read both formats regardless of mode (parser auto-detects)- Filename format is the same (
NNNN-slug.md) - JSON-ADR export works from either format
File Format Examples
Compatible Mode
# 1. Use PostgreSQL
Date: 2024-01-15
## Status
Accepted
Supersedes [2. Use MySQL](0002-use-mysql.md)
## Context
We need a database for our application.
## Decision
We will use PostgreSQL.
## Consequences
We need to learn PostgreSQL administration.
NextGen Mode
---
number: 1
title: Use PostgreSQL
date: 2024-01-15
status: accepted
links:
- target: 2
kind: supersedes
---
# 1. Use PostgreSQL
## Context
We need a database for our application.
## Decision
We will use PostgreSQL.
## Consequences
We need to learn PostgreSQL administration.
When to Use Each Mode
Use Compatible Mode when:
- Working with teams using adr-tools
- Need shell scripts to parse ADRs
- Want maximum simplicity
- Migrating from an existing adr-tools repository
Use NextGen Mode when:
- Want MADR 4.0.0 metadata (decision-makers, consulted, informed)
- Need machine-readable structured metadata
- Building tooling that consumes ADRs programmatically
- Starting a new project without adr-tools dependency
Migration Notes
- Switching to
--ngdoes NOT auto-migrate existing files - The parser reads both formats, so mixed repos work for reading
- Writing/updating ADRs uses the configured mode
- No automated migration tool yet (potential future feature)
Enabling NextGen Mode
For a new repository
adrs init --ng
For individual commands
adrs --ng new "My Decision"
Via configuration
Create adrs.toml in your repository root:
adr_dir = "doc/adr"
mode = "nextgen"
Templates
adrs uses templates to generate new ADR documents. You can use built-in templates or create custom ones.
Built-in Templates
Formats
| Format | Description |
|---|---|
nygard | Classic adr-tools format (default) |
madr | MADR 4.0.0 format |
Variants
Each format has three variants:
| Variant | Description |
|---|---|
full | Complete template with all sections and guidance comments |
minimal | Essential sections only, no guidance |
bare | Minimal structure with placeholders |
Using Built-in Templates
# Default: nygard format, full variant
adrs new "My Decision"
# MADR format, full variant
adrs new --format madr "My Decision"
# Nygard format, minimal variant
adrs new --variant minimal "My Decision"
# MADR format, bare variant
adrs new --format madr --variant bare "My Decision"
Template Examples
Nygard Full
# {{ number }}. {{ title }}
Date: {{ date }}
## Status
{{ status }}
## Context
<!-- Describe the issue motivating this decision and any context -->
## Decision
<!-- What is the change that we're proposing and/or doing? -->
## Consequences
<!-- What becomes easier or more difficult to do because of this change? -->
MADR Full
---
status: {{ status | lower }}
date: {{ date }}
---
# {{ title }}
## Context and Problem Statement
<!-- Describe the context and problem statement -->
## Decision Drivers
<!-- List the decision drivers -->
## Considered Options
<!-- List the options considered -->
## Decision Outcome
Chosen option: "", because ...
### Consequences
* Good, because ...
* Bad, because ...
Custom Templates
Create custom templates using Jinja2 syntax.
Template Variables
| Variable | Description | Example |
|---|---|---|
number | ADR number (padded) | 0001 |
title | ADR title | Use PostgreSQL |
date | Current date | 2024-01-15 |
status | Initial status | Proposed |
links | Array of links | See below |
Link Variables
Each link in the links array has:
| Variable | Description |
|---|---|
link.kind | Link type (e.g., "Supersedes") |
link.target | Target ADR number |
link.description | Optional description |
Creating a Custom Template
- Create a template file:
# {{ number }}. {{ title }}
**Date**: {{ date }}
**Status**: {{ status }}
**Author**: [Your Name]
## Problem
<!-- What problem does this solve? -->
## Solution
<!-- What is the solution? -->
## Alternatives Considered
<!-- What alternatives were considered? -->
## References
<!-- Any relevant links or documents -->
- Use it when creating ADRs:
adrs new --template path/to/template.md "My Decision"
Or configure it in adrs.toml:
[templates]
custom = "templates/my-template.md"
Conditional Sections
Use Jinja2 conditionals for optional content:
{% if links %}
## Related Decisions
{% for link in links %}
* {{ link.kind }} [ADR {{ link.target }}]({{ link.target | pad(4) }}-*.md)
{% endfor %}
{% endif %}
Filters
Available filters:
| Filter | Description | Example |
|---|---|---|
lower | Lowercase | {{ status | lower }} |
upper | Uppercase | {{ title | upper }} |
pad(n) | Zero-pad number | {{ number | pad(4) }} |
Default Configuration
Set defaults in adrs.toml:
[templates]
# Default format for new ADRs
format = "madr"
# Default variant
variant = "minimal"
# Custom template path (optional)
# custom = "templates/custom.md"
NextGen Mode Templates
When using --ng flag or mode = "nextgen", templates generate YAML frontmatter:
---
status: proposed
date: 2024-01-15
links:
- kind: Supersedes
target: 1
---
# Use PostgreSQL for Persistence
...
Commands
adrs provides commands for managing Architecture Decision Records.
Overview
| Command | Description |
|---|---|
| init | Initialize a new ADR repository |
| new | Create a new ADR |
| edit | Edit an existing ADR |
| list | List all ADRs |
| search | Search ADRs for matching content |
| status | Change an ADR's status |
| link | Link two ADRs together |
| export | Export ADRs to different formats |
| import | Import ADRs from different formats |
| generate | Generate documentation |
| template | Manage ADR templates |
| config | Show configuration |
| doctor | Check repository health |
| completions | Generate shell completions |
| cheatsheet | Show quick reference |
Global Options
These options are available for all commands:
| Option | Description |
|---|---|
--ng | Use NextGen mode (YAML frontmatter) |
-C, --cwd <DIR> | Run as if started in <DIR> |
-h, --help | Print help information |
-V, --version | Print version information |
Usage
adrs [OPTIONS] <COMMAND>
Commands:
init Initialize a new ADR repository
new Create a new ADR
edit Edit an existing ADR
list List all ADRs
search Search ADRs for matching content
link Link two ADRs together
status Change an ADR's status
config Show configuration
doctor Check repository health
generate Generate documentation
export Export ADRs to different formats
import Import ADRs from different formats
template Manage ADR templates
completions Generate shell completions
cheatsheet Show quick reference for common workflows
help Print this message or the help of the given subcommand(s)
Options:
--ng Use next-gen mode (YAML frontmatter, enhanced features)
-C, --cwd <WORKING_DIR> Working directory (defaults to current directory)
-h, --help Print help
-V, --version Print version
init
Initialize a new ADR repository.
Usage
adrs init [OPTIONS] [DIRECTORY]
Arguments
| Argument | Description |
|---|---|
[DIRECTORY] | ADR directory path (default: doc/adr) |
Options
| Option | Description |
|---|---|
--ng | Use NextGen mode (YAML frontmatter) |
-C, --cwd <DIR> | Working directory |
-h, --help | Print help |
Description
The init command creates:
- A
.adr-dirfile in the current directory containing the ADR directory path - The ADR directory (creates parent directories if needed)
- An initial ADR:
0001-record-architecture-decisions.md
Examples
Basic Initialization
adrs init
Creates:
.adr-dir # Contains "doc/adr"
doc/
adr/
0001-record-architecture-decisions.md
Custom Directory
adrs init decisions
Creates:
.adr-dir # Contains "decisions"
decisions/
0001-record-architecture-decisions.md
Nested Directory
adrs init docs/architecture/decisions
Creates the full directory path.
NextGen Mode
adrs init --ng
Creates the initial ADR with YAML frontmatter:
---
status: accepted
date: 2024-01-15
---
# Record Architecture Decisions
...
Error Handling
If the repository is already initialized (.adr-dir exists), the command will fail:
Error: ADR repository already initialized
To reinitialize, remove the .adr-dir file first.
Related
new
Create a new Architecture Decision Record.
Usage
adrs new [OPTIONS] <TITLE>
Arguments
| Argument | Description |
|---|---|
<TITLE> | Title of the new ADR |
Options
| Option | Description |
|---|---|
-f, --format <FORMAT> | Template format: nygard or madr (default: nygard) |
-v, --variant <VARIANT> | Template variant: full, minimal, or bare (default: full) |
--status <STATUS> | Initial status (default: Proposed) |
-s, --supersedes <N> | ADR number(s) this supersedes |
-l, --link <LINK> | Link to another ADR |
--ng | Use NextGen mode (YAML frontmatter) |
-C, --cwd <DIR> | Working directory |
-h, --help | Print help |
Description
Creates a new ADR file with the next available number. Opens your $EDITOR to edit the document. The ADR is saved when you close the editor.
Examples
Basic Usage
adrs new "Use PostgreSQL for persistence"
Creates 0002-use-postgresql-for-persistence.md and opens it in your editor.
With MADR Format
adrs new --format madr "Use PostgreSQL for persistence"
Minimal Template
adrs new --variant minimal "Use PostgreSQL for persistence"
With Initial Status
adrs new --status Accepted "Use PostgreSQL for persistence"
Superseding an ADR
adrs new --supersedes 2 "Use MySQL instead of PostgreSQL"
This creates a new ADR and:
- Adds a "Supersedes" link in the new ADR
- Adds a "Superseded by" link in ADR #2
- Changes ADR #2's status to "Superseded"
Superseding Multiple ADRs
adrs new --supersedes 2 --supersedes 3 "Consolidated database decision"
Linking to Another ADR
adrs new --link "2:Amends:Amended by" "Clarify database choice"
The link format is TARGET:KIND:REVERSE_KIND:
TARGET: The ADR number to link toKIND: The relationship from this ADR to the targetREVERSE_KIND: The reverse relationship added to the target
Common link types:
Amends/Amended byExtends/Extended byRelates to/Relates to
Multiple Links
adrs new --link "2:Amends:Amended by" --link "3:Extends:Extended by" "Combined decision"
NextGen Mode with MADR
adrs new --ng --format madr "Use PostgreSQL for persistence"
Creates an ADR with YAML frontmatter:
---
status: proposed
date: 2024-01-15
---
# Use PostgreSQL for Persistence
## Context and Problem Statement
...
Editor
The new command uses the $EDITOR environment variable. If not set, it tries common editors:
vimnanovi
Set your preferred editor:
export EDITOR="code --wait" # VS Code
export EDITOR="nano" # Nano
export EDITOR="vim" # Vim
File Naming
ADR files are named using the pattern:
NNNN-title-in-kebab-case.md
Where:
NNNNis the zero-padded ADR number- Title is converted to lowercase kebab-case
- Special characters are removed
Examples:
0001-record-architecture-decisions.md0002-use-postgresql-for-persistence.md0015-api-versioning-strategy.md
Related
edit
Edit an existing Architecture Decision Record.
Usage
adrs edit [OPTIONS] <ADR>
Arguments
| Argument | Description |
|---|---|
<ADR> | ADR to edit (number or search term) |
Options
| Option | Description |
|---|---|
--ng | Use NextGen mode |
-C, --cwd <DIR> | Working directory |
-h, --help | Print help |
Description
Opens an existing ADR in your editor. The ADR can be specified by:
- Number (e.g.,
1,12) - Partial title match (fuzzy search)
Examples
By Number
adrs edit 1
Opens 0001-record-architecture-decisions.md in your editor.
By Title
adrs edit postgresql
Finds and opens the ADR with "postgresql" in its title.
Fuzzy Matching
adrs edit "database"
Opens the best matching ADR containing "database".
Editor
Uses the $EDITOR environment variable. See new for configuration.
Related
list
List Architecture Decision Records with optional filtering.
Usage
adrs list [OPTIONS]
Options
| Option | Description |
|---|---|
-l, --long | Show detailed output (number, status, date, title) |
-s, --status <STATUS> | Filter by status (e.g., proposed, accepted, deprecated, superseded) |
--since <DATE> | Show ADRs from this date onwards (YYYY-MM-DD) |
--until <DATE> | Show ADRs up to this date (YYYY-MM-DD) |
--decider <NAME> | Filter by decision maker (MADR format) |
--ng | Use NextGen mode |
-C, --cwd <DIR> | Working directory |
Examples
Basic Usage
adrs list
Output (paths):
doc/adr/0001-record-architecture-decisions.md
doc/adr/0002-use-postgresql.md
doc/adr/0003-api-versioning.md
Detailed Output
adrs list -l
Output:
1 Accepted 2024-01-15 Record architecture decisions
2 Accepted 2024-01-20 Use PostgreSQL for persistence
3 Proposed 2024-02-01 API versioning strategy
4 Superseded 2024-01-10 Use MySQL for persistence
Filter by Status
# Show accepted ADRs
adrs list --status accepted -l
# Show ADRs needing review
adrs list --status proposed -l
# Show superseded ADRs
adrs list --status superseded -l
Filter by Date
# ADRs from 2024 onwards
adrs list --since 2024-01-01 -l
# ADRs before 2024
adrs list --until 2023-12-31 -l
# ADRs in a date range
adrs list --since 2024-01-01 --until 2024-06-30 -l
Filter by Decision Maker
For ADRs using MADR format with decision-makers metadata:
# Find ADRs decided by Alice (case-insensitive substring match)
adrs list --decider alice -l
# Find ADRs by team
adrs list --decider "Security Team" -l
Combined Filters
Multiple filters are AND'd together:
# Accepted ADRs from 2024 decided by Alice
adrs list --status accepted --since 2024-01-01 --decider alice -l
Output Format
Default: File paths, one per line
Long format (-l): Columns showing:
- ADR number (4 chars)
- Status (12 chars)
- Date (YYYY-MM-DD)
- Title
ADRs are sorted by number.
Related
search
Search ADRs for matching content.
Usage
adrs search [OPTIONS] <QUERY>
Arguments
| Argument | Description |
|---|---|
<QUERY> | Search query text |
Options
| Option | Description |
|---|---|
-t, --title | Search titles only |
-s, --status <STATUS> | Filter by status |
-c, --case-sensitive | Case-sensitive search |
Examples
# Search all content for 'postgres'
adrs search postgres
# Search titles only
adrs search -t database
# Search accepted ADRs for 'auth'
adrs search --status accepted auth
# Case-sensitive search
adrs search -c PostgreSQL
Output
Returns matching ADRs with their number, title, and status.
$ adrs search database
1: Use PostgreSQL for persistence (accepted)
5: Add Redis for caching (proposed)
Tips
- Search is case-insensitive by default
- Searches both title and full content unless
-tis used - Combine with
--statusto narrow results - Use quotes for multi-word searches:
adrs search "event sourcing"
status
Change an ADR's status.
Usage
adrs status <NUMBER> <STATUS>
adrs status <NUMBER> superseded --by <NUMBER>
Arguments
| Argument | Description |
|---|---|
NUMBER | The ADR number to update |
STATUS | New status value |
Options
| Option | Description |
|---|---|
--by <NUMBER> | For 'superseded' status: the ADR number that supersedes this one |
Standard Statuses
proposed- Decision is proposed but not yet acceptedaccepted- Decision has been accepteddeprecated- Decision is deprecated but not replacedsuperseded- Decision has been replaced by another ADR
You can also use custom status values for your workflow (e.g., draft, rejected, on-hold).
Examples
Accept a proposed ADR
adrs status 5 accepted
Deprecate an ADR
adrs status 3 deprecated
Supersede an ADR
When superseding, use --by to create a bidirectional link:
adrs status 2 superseded --by 5
This updates ADR 2's status and creates links:
- ADR 2: "Superseded by 5. New Approach"
- ADR 5: "Supersedes 2. Old Approach"
Custom status
adrs status 4 "on-hold"
Notes
- The status command updates the ADR file in place
- For superseded status, using
--byis recommended to maintain traceability - Status values are case-insensitive when parsing but preserved as written
link
Link two Architecture Decision Records together.
Usage
adrs link [OPTIONS] <SOURCE> <LINK> <TARGET> <REVERSE_LINK>
Arguments
| Argument | Description |
|---|---|
<SOURCE> | Source ADR number |
<LINK> | Link description from source to target |
<TARGET> | Target ADR number |
<REVERSE_LINK> | Reverse link description from target to source |
Options
| Option | Description |
|---|---|
--ng | Use NextGen mode |
-C, --cwd <DIR> | Working directory |
-h, --help | Print help |
Description
Creates bidirectional links between two ADRs. The link is added to the status section of both ADRs.
Examples
Amends Relationship
adrs link 3 "Amends" 1 "Amended by"
Result in ADR #3:
## Status
Proposed
Amends [1. Record architecture decisions](0001-record-architecture-decisions.md)
Result in ADR #1:
## Status
Accepted
Amended by [3. Clarify decision format](0003-clarify-decision-format.md)
Extends Relationship
adrs link 4 "Extends" 2 "Extended by"
Custom Relationship
adrs link 5 "Depends on" 3 "Dependency of"
Common Link Types
| Forward Link | Reverse Link | Use Case |
|---|---|---|
| Amends | Amended by | Modifying a previous decision |
| Extends | Extended by | Building on a previous decision |
| Supersedes | Superseded by | Replacing a decision |
| Relates to | Relates to | General relationship |
| Depends on | Dependency of | Dependencies |
Superseding
For superseding relationships, prefer using adrs new --supersedes:
# Instead of:
adrs new "New approach"
adrs link 3 "Supersedes" 2 "Superseded by"
# Use:
adrs new --supersedes 2 "New approach"
The --supersedes option also updates the target ADR's status to "Superseded".
NextGen Mode
In NextGen mode (--ng), links are stored in YAML frontmatter:
---
status: proposed
date: 2024-01-15
links:
- kind: Amends
target: 1
---
Related
export
Export ADRs to different formats for integration with other tools.
JSON Export
Export ADRs to JSON-ADR format, a machine-readable interchange format.
adrs export json # All ADRs as JSON
adrs export json --pretty # Pretty-printed output
adrs export json 5 # Single ADR by number
adrs export json -d path/to/adrs # Export from directory (no repo needed)
Options
| Option | Description |
|---|---|
--pretty, -p | Pretty-print the JSON output |
--dir, -d | Export from a directory without requiring an initialized repository |
--metadata-only | Export metadata without content fields (context, decision, consequences) |
--base-url <URL> | Set base URL for source_uri field (for federation) |
Output Format
{
"$schema": "https://raw.githubusercontent.com/joshrotenberg/adrs/main/schema/json-adr/v1.json",
"version": "1.0.0",
"generated_at": "2024-01-15T10:30:00Z",
"tool": {
"name": "adrs",
"version": "0.5.0"
},
"repository": {
"adr_directory": "doc/adr"
},
"adrs": [
{
"number": 1,
"title": "Record architecture decisions",
"status": "Accepted",
"date": "2024-01-15",
"context": "We need to record architectural decisions...",
"decision": "We will use ADRs...",
"consequences": "See Michael Nygard's article...",
"links": [],
"path": "doc/adr/0001-record-architecture-decisions.md"
}
]
}
Federation Support
Use --base-url to add source_uri fields for referencing ADRs across repositories:
adrs export json --metadata-only --base-url "https://github.com/org/repo/blob/main/doc/adr"
This produces lightweight exports that reference the source files:
{
"number": 1,
"title": "Use PostgreSQL",
"status": "Accepted",
"date": "2024-01-15",
"source_uri": "https://github.com/org/repo/blob/main/doc/adr/0001-use-postgresql.md"
}
Use Cases
- Integration: Feed ADRs into documentation systems or dashboards
- Backup/Migration: Export ADRs for archival or moving between projects
- CI/CD: Validate ADRs exist for certain features in pipelines
- AI Context: Provide codebase context to LLMs
- Federation: Create organization-wide ADR indexes across repositories
import
Import ADRs from different formats into your repository.
JSON Import
Import ADRs from JSON-ADR format files.
adrs import json exported.json # Import to repository
adrs import json exported.json --dry-run # Preview without writing
adrs import json - < exported.json # Read from stdin
Options
| Option | Description |
|---|---|
--dir, -d | Import to a directory without requiring an initialized repository |
--overwrite, -o | Overwrite existing files with the same number |
--renumber, -r | Renumber ADRs starting from next available number |
--append | Alias for --renumber |
--dry-run | Preview import without writing files |
--ng | Use NextGen mode with YAML frontmatter |
Merging ADR Sets with --renumber/--append
The --renumber option (also available as --append) enables merging ADRs from different sources without number conflicts. It automatically:
- Finds the next available number in the target directory
- Renumbers all imported ADRs sequentially from that number
- Updates cross-references between imported ADRs
Example: Merging Projects
If your target repository has ADRs 1-5:
# Imported ADRs become 6, 7, 8...
adrs import json external-adrs.json --renumber
# Or use the --append alias for clarity
adrs import json external-adrs.json --append
Example: Migration Scenario
Combine with --dir for migrating ADRs:
adrs import json acquired-project.json --dir doc/adr --append
Preview Before Importing
Use --dry-run to see what would happen:
adrs import json external.json --append --dry-run
Output shows the renumber mapping:
Would import 3 ADRs:
ADR 1 -> ADR 6 (0006-use-postgresql.md)
ADR 2 -> ADR 7 (0007-use-redis.md)
ADR 3 -> ADR 8 (0008-api-design.md)
Cross-references updated:
ADR 7 link to ADR 1 -> ADR 6
Link Handling
When renumbering, internal links between imported ADRs are automatically updated. For example:
- Source ADR 2 links to ADR 1 with "Supersedes"
- After renumbering to 7 and 6, the link now points to ADR 6
Links to ADRs outside the imported set generate warnings:
Warning: ADR 7 links to ADR 5 which is not in the import set
Input Formats
The import command accepts multiple JSON-ADR formats:
Bulk export (from adrs export json):
{
"version": "1.0.0",
"adrs": [...]
}
Single ADR wrapper:
{
"version": "1.0.0",
"adr": { ... }
}
Bare ADR object:
{
"number": 1,
"title": "...",
"status": "...",
...
}
Use Cases
- Project mergers: Combine ADRs when acquiring or merging codebases
- Migration: Move ADRs between repositories
- Backup restoration: Restore from JSON exports
- Cross-team sharing: Import relevant decisions from other teams
generate
Generate documentation from ADRs.
Usage
adrs generate <SUBCOMMAND>
Subcommands
| Subcommand | Description |
|---|---|
toc | Generate a table of contents |
graph | Generate a Graphviz dependency graph |
book | Generate an mdbook |
generate toc
Generate a markdown table of contents to stdout.
Usage
adrs generate toc [OPTIONS]
Options
| Option | Description |
|---|---|
-o, --ordered | Use ordered list (1. 2. 3.) instead of bullets |
-i, --intro <FILE> | Prepend content from file |
-O, --outro <FILE> | Append content from file |
-p, --prefix <PREFIX> | Prefix for ADR links |
--ng | Use NextGen mode |
-C, --cwd <DIR> | Working directory |
-h, --help | Print help |
Examples
Basic Table of Contents
adrs generate toc
Output:
* [1. Record architecture decisions](0001-record-architecture-decisions.md)
* [2. Use PostgreSQL for persistence](0002-use-postgresql-for-persistence.md)
* [3. API versioning strategy](0003-api-versioning-strategy.md)
Ordered List
adrs generate toc --ordered
Output:
1. [1. Record architecture decisions](0001-record-architecture-decisions.md)
2. [2. Use PostgreSQL for persistence](0002-use-postgresql-for-persistence.md)
3. [3. API versioning strategy](0003-api-versioning-strategy.md)
Save to File
adrs generate toc > doc/adr/README.md
With Intro and Outro Files
adrs generate toc -i intro.md -O outro.md > doc/adr/README.md
Link Prefix for Wikis
adrs generate toc -p "wiki/adr/"
generate graph
Generate a Graphviz DOT graph showing ADR relationships.
Usage
adrs generate graph [OPTIONS]
Options
| Option | Description |
|---|---|
-p, --prefix <PREFIX> | Prefix for node URLs |
-e, --extension <EXT> | File extension for links (default: md) |
--ng | Use NextGen mode |
-C, --cwd <DIR> | Working directory |
-h, --help | Print help |
Examples
Basic Graph
adrs generate graph
Output:
digraph {
node [shape=plaintext];
_1 [label="1. Record architecture decisions"; URL="0001-record-architecture-decisions.md"];
_2 [label="2. Use PostgreSQL"; URL="0002-use-postgresql.md"];
_3 [label="3. Use MySQL instead"; URL="0003-use-mysql-instead.md"];
edge [style=dotted, weight=10];
_1 -> _2;
_2 -> _3;
edge [style=solid, weight=1];
_3 -> _2 [label="Supersedes"];
}
Save to File
adrs generate graph > doc/adr/graph.dot
Render as PNG
Using Graphviz:
adrs generate graph | dot -Tpng -o doc/adr/graph.png
Render as SVG
adrs generate graph | dot -Tsvg -o doc/adr/graph.svg
HTML Links with Custom Extension
adrs generate graph -e html -p "/docs/adr/"
Graph Features
- Each ADR is a node with its number and title
- Sequential ADRs are connected with dotted lines
- Explicit links between ADRs shown as solid edges with labels
- Nodes link to their ADR files (clickable in SVG)
generate book
Generate an mdbook from your ADRs.
Usage
adrs generate book [OPTIONS]
Options
| Option | Description |
|---|---|
-o, --output <DIR> | Output directory (default: book) |
-t, --title <TITLE> | Book title |
-d, --description <DESC> | Book description |
--ng | Use NextGen mode |
-C, --cwd <DIR> | Working directory |
-h, --help | Print help |
Examples
Basic Book
adrs generate book
This creates a book/ directory with:
book.toml- mdbook configurationsrc/SUMMARY.md- table of contentssrc/*.md- copies of all ADR files
Custom Output Directory
adrs generate book -o docs/decisions
Custom Title and Description
adrs generate book -t "Project Architecture" -d "Key decisions for the project"
Build and Serve
After generating:
adrs generate book
cd book
mdbook serve
Integration with CI
Generate and deploy the book automatically:
- name: Generate ADR book
run: |
adrs generate book
cd book && mdbook build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./book/book
Related
template
Manage ADR templates.
Usage
adrs template <COMMAND>
Subcommands
| Command | Description |
|---|---|
list | List available templates |
show | Show a template's content |
list
List all available template formats and variants.
adrs template list
Output:
Available templates:
nygard (default)
Variants: full (default), minimal, bare
madr
Variants: full (default), minimal, bare
show
Display the content of a specific template.
adrs template show <FORMAT> [--variant <VARIANT>]
Options
| Option | Description |
|---|---|
-v, --variant <VARIANT> | Template variant: full, minimal, bare |
Examples
# Show default Nygard template (full variant)
adrs template show nygard
# Show minimal MADR template
adrs template show madr --variant minimal
# Show bare template
adrs template show nygard --variant bare
Template Formats
Nygard (Classic)
The original ADR format by Michael Nygard with sections:
- Status
- Context
- Decision
- Consequences
MADR 4.0.0
Markdown Any Decision Record format with additional sections:
- Status
- Deciders
- Date
- Context and Problem Statement
- Decision Drivers
- Considered Options
- Decision Outcome
- Consequences
Template Variants
| Variant | Description |
|---|---|
full | Complete template with all sections and guidance |
minimal | Essential sections only |
bare | Minimal structure, just headings |
See Also
config
Show the current configuration.
Usage
adrs config [OPTIONS]
Options
| Option | Description |
|---|---|
--ng | Use NextGen mode |
-C, --cwd <DIR> | Working directory |
-h, --help | Print help |
Description
Displays the current configuration, including where it was loaded from.
Examples
Basic Usage
adrs config
Output:
Project root: /home/user/myproject
Config source: adrs.toml
ADR directory: doc/adr
Full path: /home/user/myproject/doc/adr
Mode: Compatible
Without Initialization
adrs config
Output when no ADR repository is found:
Project root: /home/user/myproject
Config source: defaults
ADR directory: doc/adr
Full path: /home/user/myproject/doc/adr
Mode: Compatible
Config Sources
| Source | Description |
|---|---|
adrs.toml | TOML configuration file |
.adr-dir | Legacy adr-tools configuration |
global (~/.config/adrs/config.toml) | User-wide configuration |
environment | Environment variable override |
defaults | Built-in defaults |
Related
- Configuration - Configuration options
- init - Initialize a repository
doctor
Check the health of your ADR repository.
Usage
adrs doctor [OPTIONS]
Options
| Option | Description |
|---|---|
--ng | Use NextGen mode |
-C, --cwd <DIR> | Working directory |
-h, --help | Print help |
Description
Runs diagnostic checks on your ADR repository and reports any issues found.
Checks Performed
| Check | Description |
|---|---|
| File Naming | ADR files follow the NNNN-title.md pattern |
| Duplicate Numbers | No two ADRs have the same number |
| Numbering Gaps | Sequential numbering without gaps |
| Broken Links | All referenced ADRs exist |
| Superseded Status | Superseded ADRs have corresponding links |
| Parse Errors | All ADRs can be parsed correctly |
Examples
Healthy Repository
adrs doctor
Output:
Checking ADR repository health...
[OK] File naming: All 5 ADRs follow naming convention
[OK] Duplicate numbers: No duplicates found
[OK] Numbering gaps: Numbers are sequential
[OK] Broken links: All links are valid
[OK] Superseded status: All superseded ADRs have links
[OK] Parse errors: All ADRs parsed successfully
Health check passed!
Repository with Issues
adrs doctor
Output:
Checking ADR repository health...
[OK] File naming: All 5 ADRs follow naming convention
[WARN] Numbering gaps: Gap after ADR 3 (next is 5)
[ERROR] Broken links: ADR 4 links to non-existent ADR 99
[WARN] Superseded status: ADR 2 is superseded but has no "Superseded by" link
Health check found 3 issue(s)
Severity Levels
| Level | Description |
|---|---|
| OK | Check passed |
| WARN | Potential issue, but not critical |
| ERROR | Problem that should be fixed |
Exit Codes
| Code | Description |
|---|---|
| 0 | All checks passed |
| 1 | One or more checks failed |
This allows using doctor in CI pipelines:
- name: Check ADR health
run: adrs doctor
Related
completions
Generate shell completions for tab-completion support.
Usage
adrs completions <SHELL>
Arguments
| Argument | Description |
|---|---|
<SHELL> | Shell to generate completions for |
Supported Shells
| Shell | Description |
|---|---|
bash | Bourne Again Shell |
zsh | Z Shell |
fish | Fish Shell |
powershell | PowerShell |
elvish | Elvish Shell |
Installation
Bash
# Generate completions
adrs completions bash > ~/.bash_completion.d/adrs
# Add to ~/.bashrc
source ~/.bash_completion.d/adrs
Zsh
# Generate completions
adrs completions zsh > ~/.zfunc/_adrs
# Add to ~/.zshrc (before compinit)
fpath=(~/.zfunc $fpath)
autoload -Uz compinit && compinit
Fish
# Generate completions (loaded automatically)
adrs completions fish > ~/.config/fish/completions/adrs.fish
PowerShell
# Generate completions
adrs completions powershell > _adrs.ps1
# Add to your PowerShell profile
. _adrs.ps1
Elvish
# Generate completions
adrs completions elvish > ~/.elvish/lib/adrs.elv
# Add to ~/.elvish/rc.elv
use adrs
Examples
After installation, you can use tab completion:
# Complete commands
adrs <TAB>
init new edit list search link status ...
# Complete options
adrs new --<TAB>
--format --variant --tags --supersedes --no-edit ...
# Complete formats
adrs new --format <TAB>
nygard madr
Homebrew Users
If you installed via Homebrew, completions may already be configured. Check with:
# Bash (Homebrew)
$(brew --prefix)/etc/bash_completion.d/adrs
# Zsh (Homebrew)
$(brew --prefix)/share/zsh/site-functions/_adrs
cheatsheet
Show a quick reference for common ADR workflows.
Usage
adrs cheatsheet
Alias: adrs qr
Output
Displays a comprehensive quick reference covering:
- Getting started
- Creating ADRs
- Superseding and linking
- Managing status
- Viewing and searching
- Generating documentation
- Import/export
- Configuration
Example Output
ADR Quick Reference
===================
GETTING STARTED
adrs init Initialize ADR repository
adrs --ng init Initialize with NextGen mode (YAML frontmatter)
CREATING ADRS
adrs new "Title" Create new ADR
adrs new --format madr Use MADR 4.0.0 format
adrs new --variant minimal Use minimal template
adrs new -t tag1,tag2 Add tags (NextGen mode)
adrs new --no-edit Create without opening editor
SUPERSEDING AND LINKING
adrs new -s 2 "New title" Supersede ADR #2
adrs link 3 Amends 1 Link ADR #3 amends #1
MANAGING STATUS
adrs status 1 accepted Accept ADR #1
adrs status 2 deprecated Deprecate ADR #2
adrs status 3 superseded 4 Mark #3 superseded by #4
VIEWING AND SEARCHING
adrs list List all ADRs
adrs list --status accepted Filter by status
adrs search postgres Search content
adrs search -t database Search titles only
DOCUMENTATION
adrs generate toc Generate table of contents
adrs generate graph Generate Graphviz diagram
adrs generate book Generate mdbook
IMPORT/EXPORT
adrs export json Export to JSON-ADR
adrs import file.json Import from JSON-ADR
CONFIGURATION
adrs config Show current config
adrs doctor Check repository health
More: adrs --help, adrs <command> --help
Tips
- Run
adrs cheatsheetwhenever you need a quick reminder - Use
adrs <command> --helpfor detailed command documentation - Full documentation at joshrotenberg.github.io/adrs-book
MCP Server
adrs includes an MCP (Model Context Protocol) server for AI agent integration. This allows AI assistants like Claude to read, search, create, and manage ADRs directly.
Installation
The MCP server is an optional feature. Install with:
cargo install adrs --features mcp
Or build from source:
cargo build --release --features mcp
For HTTP transport support (independent server mode):
cargo install adrs --features mcp-http
Configuration
Claude Desktop
Add to your claude_desktop_config.json:
{
"mcpServers": {
"adrs": {
"command": "adrs",
"args": ["mcp", "serve"],
"cwd": "/path/to/your/project"
}
}
}
HTTP Mode
For independent server operation:
adrs mcp serve --http 127.0.0.1:3000
Then configure Claude with:
{
"mcpServers": {
"adrs": {
"url": "http://127.0.0.1:3000/mcp"
}
}
}
Available Tools
The MCP server provides 15 tools organized by function:
Read Operations
| Tool | Description |
|---|---|
list_adrs | List all ADRs with optional status/tag filters |
get_adr | Get full content of an ADR by number |
search_adrs | Search ADR titles and content |
get_adr_sections | Get ADR with parsed sections (context, decision, consequences) |
get_related_adrs | Get all ADRs linked to/from a specific ADR |
get_repository_info | Get repository mode, ADR count, and configuration |
Write Operations
| Tool | Description |
|---|---|
create_adr | Create a new ADR (always 'proposed' status) |
update_status | Change an ADR's status |
link_adrs | Create bidirectional links between ADRs |
update_content | Update ADR sections (context, decision, consequences) |
update_tags | Add or replace tags (NextGen mode only) |
bulk_update_status | Update multiple ADR statuses at once |
Analysis Tools
| Tool | Description |
|---|---|
validate_adr | Check ADR structure and report issues |
compare_adrs | Compare two ADRs and show differences |
suggest_tags | Analyze content and suggest relevant tags |
Tool Details
list_adrs
List all ADRs with optional filtering.
Parameters:
status(optional): Filter by status (proposed, accepted, deprecated, superseded)tag(optional): Filter by tag (NextGen mode)
Example response:
[
{
"number": 1,
"title": "Use PostgreSQL for persistence",
"status": "accepted",
"date": "2026-01-15",
"tags": ["database", "infrastructure"]
}
]
get_adr
Get the full content of a specific ADR.
Parameters:
number(required): The ADR number
Returns: Complete ADR including title, status, content, and links.
search_adrs
Search ADRs for matching text.
Parameters:
query(required): Search texttitle_only(optional): Only search titles (default: false)
create_adr
Create a new ADR. Always creates with 'proposed' status for human review.
Parameters:
title(required): ADR titlecontext(optional): Context section contentdecision(optional): Decision section contentconsequences(optional): Consequences section contentsupersedes(optional): ADR number this supersedes
update_status
Change an ADR's status.
Parameters:
number(required): ADR numberstatus(required): New status (proposed, accepted, deprecated, superseded, rejected)superseded_by(optional): Required when status is 'superseded'
link_adrs
Create bidirectional links between ADRs.
Parameters:
source(required): Source ADR numbertarget(required): Target ADR numberlink_type(required): Link type (Supersedes, Amends, "Relates to")
validate_adr
Validate an ADR's structure and content.
Parameters:
number(required): ADR number to validate
Returns: Validation results with severity levels (error/warning).
compare_adrs
Compare two ADRs side by side.
Parameters:
adr1(required): First ADR numberadr2(required): Second ADR number
Returns: Structural comparison of title, status, and content sections.
suggest_tags
Analyze ADR content and suggest relevant tags.
Parameters:
number(required): ADR number to analyze
Returns: Suggested tags with confidence scores and reasons.
Usage Examples
Ask Claude to list your ADRs
"What architectural decisions have been made in this project?"
Claude will use list_adrs to retrieve and summarize your ADRs.
Search for specific topics
"Are there any decisions about authentication?"
Claude will use search_adrs with "authentication" to find relevant ADRs.
Create a new ADR
"Create an ADR for using Redis as our caching layer"
Claude will use create_adr with the title and may populate initial content based on your discussion.
Review and accept ADRs
"Accept ADRs 5, 6, and 7"
Claude will use bulk_update_status to accept multiple ADRs.
Analyze decisions
"Compare ADR 2 with ADR 8 to see how our database choice evolved"
Claude will use compare_adrs to show the differences.
Best Practices
-
Human Review: All ADRs created by AI are set to 'proposed' status. Review before accepting.
-
Provide Context: Give Claude context about your architecture when asking it to create ADRs.
-
Use Tags: In NextGen mode, use
suggest_tagsto maintain consistent categorization. -
Validate Often: Use
validate_adrto ensure ADRs have complete content. -
Link Related Decisions: Use
link_adrsto maintain decision traceability.
See Also
- Configuration - Repository configuration
- Formats - ADR format options
- Compatibility - NextGen vs Compatible mode
Library Usage
The adrs-core crate provides a Rust library for working with ADRs programmatically.
Installation
Add to your Cargo.toml:
[dependencies]
adrs-core = "0.4"
Basic Usage
Opening a Repository
use adrs_core::Repository; use std::path::Path; fn main() -> anyhow::Result<()> { // Open existing repository let repo = Repository::open(Path::new("."))?; // Or create with defaults if it doesn't exist let repo = Repository::open_or_default(Path::new("."))?; Ok(()) }
Listing ADRs
use adrs_core::Repository; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; for adr in repo.list()? { println!("{}: {} [{}]", adr.number, adr.title, adr.status); } Ok(()) }
Creating an ADR
use adrs_core::{Repository, Adr, AdrStatus}; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; let adr = Adr::new( repo.next_number()?, "Use PostgreSQL for persistence".to_string(), ); let path = repo.create(&adr)?; println!("Created: {}", path.display()); Ok(()) }
Finding an ADR
use adrs_core::Repository; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; // By number let adr = repo.get(1)?; // By search term (fuzzy) let adr = repo.find("postgresql")?; Ok(()) }
Linking ADRs
use adrs_core::{Repository, LinkKind}; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; repo.link( 3, // source LinkKind::Amends, // link type 1, // target LinkKind::AmendedBy, // reverse link type )?; Ok(()) }
Configuration
Loading Configuration
use adrs_core::{Config, discover}; use std::path::Path; fn main() -> anyhow::Result<()> { // Discover configuration from current directory let discovered = discover(Path::new("."))?; println!("Project root: {}", discovered.root.display()); println!("ADR directory: {}", discovered.config.adr_dir.display()); println!("Source: {:?}", discovered.source); Ok(()) }
Creating Configuration
#![allow(unused)] fn main() { use adrs_core::Config; let config = Config { adr_dir: "decisions".into(), mode: adrs_core::ConfigMode::NextGen, ..Default::default() }; }
Templates
Using Built-in Templates
use adrs_core::{TemplateEngine, TemplateFormat, TemplateVariant, Adr}; fn main() -> anyhow::Result<()> { let engine = TemplateEngine::new(TemplateFormat::Madr, TemplateVariant::Minimal); let adr = Adr::new(1, "My Decision".to_string()); let content = engine.render(&adr)?; println!("{}", content); Ok(()) }
Custom Templates
use adrs_core::{TemplateEngine, Adr}; use std::path::Path; fn main() -> anyhow::Result<()> { let engine = TemplateEngine::from_file(Path::new("templates/custom.md"))?; let adr = Adr::new(1, "My Decision".to_string()); let content = engine.render(&adr)?; Ok(()) }
Parsing ADRs
Parse from File
use adrs_core::Parser; use std::path::Path; fn main() -> anyhow::Result<()> { let parser = Parser::new(); let adr = parser.parse_file(Path::new("doc/adr/0001-record-decisions.md"))?; println!("Title: {}", adr.title); println!("Status: {}", adr.status); println!("Date: {:?}", adr.date); for link in &adr.links { println!("Link: {} -> ADR {}", link.kind, link.target); } Ok(()) }
Parse from String
use adrs_core::Parser; fn main() -> anyhow::Result<()> { let content = r#" 1. Use PostgreSQL Date: 2024-01-15 # Status Accepted # Context We need a database. # Decision Use PostgreSQL. # Consequences None significant. "#; let parser = Parser::new(); let adr = parser.parse(content, Some(1))?; Ok(()) }
Health Checks
use adrs_core::{Repository, doctor_check}; fn main() -> anyhow::Result<()> { let repo = Repository::open(Path::new("."))?; let report = doctor_check(&repo)?; for diagnostic in &report.diagnostics { println!("[{:?}] {}: {}", diagnostic.severity, diagnostic.check, diagnostic.message ); } if report.has_errors() { std::process::exit(1); } Ok(()) }
Types
AdrStatus
#![allow(unused)] fn main() { use adrs_core::AdrStatus; let status = AdrStatus::Accepted; let status = AdrStatus::Superseded; let status = AdrStatus::Custom("In Review".to_string()); }
LinkKind
#![allow(unused)] fn main() { use adrs_core::LinkKind; let kind = LinkKind::Supersedes; let kind = LinkKind::AmendedBy; let kind = LinkKind::Custom("Depends on".to_string()); }
Error Handling
The library uses thiserror for error types:
use adrs_core::{Repository, Error}; fn main() { match Repository::open(Path::new(".")) { Ok(repo) => { /* use repo */ } Err(Error::NotFound(path)) => { eprintln!("ADR repository not found at {}", path.display()); } Err(e) => { eprintln!("Error: {}", e); } } }
Feature Flags
The adrs-core crate has no optional features currently. All functionality is included by default.
API Documentation
Full API documentation is available on docs.rs.
Resources
ADR Background
- Architectural Decision Records - The official ADR homepage
- Documenting Architecture Decisions - Michael Nygard's original blog post
- MADR - Markdown Architectural Decision Records
Tools
- adr-tools - The original bash-based ADR tool
- adrs - This project (Rust rewrite)
- adr-log - Generate an ADR log from MADR files
- pyadr - Python ADR tool
Articles
- When Should I Write an Architecture Decision Record - Spotify Engineering
- ADR Process - AWS Prescriptive Guidance
- Architecture Decision Records - ThoughtWorks Technology Radar
Templates
- MADR Templates - Official MADR templates
- ADR Templates - Collection of ADR templates
Books
- Documenting Software Architectures - Clements et al.
- Design It! - Michael Keeling
Contributing
Contributions are welcome! See issues for ideas or open a new issue to discuss your proposal.
Development Setup
git clone https://github.com/joshrotenberg/adrs
cd adrs
cargo build
Running Tests
# Library tests
cargo test --lib --all-features
# Integration tests
cargo test --test '*' --all-features
# All tests
cargo test --all-features
Code Quality
Before submitting a PR, ensure:
# Format code
cargo fmt --all
# Run lints
cargo clippy --all-targets --all-features -- -D warnings
# Run tests
cargo test --all-features
Guidelines
Compatibility
The v2 rewrite maintains compatibility with adr-tools repositories. Changes should not break existing ADR directories.
New features that extend beyond adr-tools compatibility should:
- Work in both Compatible and NextGen modes where possible
- Be opt-in via flags or configuration
- Be documented
Code Style
- Follow Rust 2024 edition idioms
- Use
thiserrorfor library errors - Use
anyhowfor CLI errors - Add doc comments to public APIs
- Keep functions focused and testable
Testing
- Add unit tests for new functionality
- Add integration tests for CLI changes
- Test both Compatible and NextGen modes
- Test edge cases (empty files, special characters, etc.)
Commits
Use conventional commits:
feat: add new feature
fix: resolve bug
docs: update documentation
test: add tests
refactor: restructure code
chore: maintenance tasks
Pull Requests
- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Make your changes
- Run tests and lints
- Commit with conventional commit messages
- Push and open a PR
Project Structure
adrs/
├── crates/
│ ├── adrs-core/ # Library crate
│ │ ├── src/
│ │ │ ├── config.rs # Configuration handling
│ │ │ ├── parse.rs # ADR parsing
│ │ │ ├── template.rs # Template engine
│ │ │ ├── repository.rs # Repository operations
│ │ │ ├── doctor.rs # Health checks
│ │ │ └── types.rs # Core types
│ │ └── Cargo.toml
│ └── adrs/ # CLI crate
│ ├── src/
│ │ ├── main.rs
│ │ └── commands/ # CLI commands
│ └── Cargo.toml
├── book/ # mdbook documentation
└── Cargo.toml # Workspace manifest
Documentation
- Update the mdbook in
book/for user-facing changes - Add doc comments to public APIs
- Update CHANGELOG.md (handled by release-plz)
License
See LICENSE-MIT or LICENSE-APACHE.