Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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-core as 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-dir file pointing to doc/adr
  • The doc/adr directory
  • 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
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:

  1. Install adrs
  2. Run commands as usual - adrs reads the existing .adr-dir file and ADR documents

For new features like MADR format or YAML frontmatter, see the Configuration chapter.

Next Steps

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.

PlatformArchitectureDownload
Linuxx86_64adrs-x86_64-unknown-linux-gnu.tar.gz
Linuxaarch64adrs-aarch64-unknown-linux-gnu.tar.gz
macOSx86_64 (Intel)adrs-x86_64-apple-darwin.tar.gz
macOSaarch64 (Apple Silicon)adrs-aarch64-apple-darwin.tar.gz
Windowsx86_64adrs-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):

  1. Command-line flags
  2. Environment variables
  3. Project configuration file (adrs.toml or .adr-dir)
  4. Global configuration file (~/.config/adrs/config.toml)
  5. 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

VariableDescription
ADR_DIRECTORYOverride the ADR directory path
ADRS_CONFIGPath to a specific configuration file
EDITOREditor 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:

  1. Looking in the current directory for adrs.toml or .adr-dir
  2. Searching parent directories up to the git root (or filesystem root)
  3. Checking the global config at ~/.config/adrs/config.toml
  4. 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

SectionDescription
TitleNumber and title as H1 heading
DateWhen the decision was made
StatusProposed, Accepted, Deprecated, Superseded
ContextWhy is this decision needed?
DecisionWhat was decided?
ConsequencesWhat 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

FieldDescription
statusDecision status
dateDate of the decision
decision-makersList of people who made the decision
consultedList of people whose opinions were sought
informedList of people who were informed of the decision

Sections

SectionRequiredDescription
TitleYesThe decision as an H1 heading
Context and Problem StatementYesWhy is this decision needed?
Decision DriversNoFactors influencing the decision
Considered OptionsNoOptions that were evaluated
Decision OutcomeYesThe chosen option and rationale
ConsequencesNoGood and bad outcomes
ConfirmationNoHow the decision will be validated
Pros and ConsNoDetailed option comparison
More InformationNoLinks and references

Choosing a Format

Use Nygard when...Use MADR when...
Migrating from adr-toolsStarting a new project
Simplicity is preferredYou need structured metadata
Team is familiar with itYou 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:

VariantDescription
fullAll sections with guidance comments
minimalEssential sections only
bareBare 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

AspectCompatible (default)NextGen (--ng)Breaks adr-tools?
Config file.adr-diradrs.tomlYes
File formatPlain markdownYAML frontmatterYes
Status storage## Status sectionstatus: in YAMLYes
Link storageMarkdown links in Statuslinks: YAML arrayYes
Date storageDate: YYYY-MM-DD inlinedate: in YAMLYes
MADR fieldsNot availabledecision-makers, consulted, informedN/A

Key Incompatibilities with adr-tools

  1. adr-tools cannot read --ng files - YAML frontmatter breaks bash parsing
  2. adr-tools cannot write to --ng repos - Creates files without frontmatter
  3. Mixed repos don't work - adr-tools would create incompatible files
  4. Scripts break - Anything grep'ing for ## Status\n\nAccepted fails

What Still Works

  • adrs can 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 --ng does 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

FormatDescription
nygardClassic adr-tools format (default)
madrMADR 4.0.0 format

Variants

Each format has three variants:

VariantDescription
fullComplete template with all sections and guidance comments
minimalEssential sections only, no guidance
bareMinimal 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

VariableDescriptionExample
numberADR number (padded)0001
titleADR titleUse PostgreSQL
dateCurrent date2024-01-15
statusInitial statusProposed
linksArray of linksSee below

Each link in the links array has:

VariableDescription
link.kindLink type (e.g., "Supersedes")
link.targetTarget ADR number
link.descriptionOptional description

Creating a Custom Template

  1. 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 -->
  1. 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:

FilterDescriptionExample
lowerLowercase{{ status | lower }}
upperUppercase{{ 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

CommandDescription
initInitialize a new ADR repository
newCreate a new ADR
editEdit an existing ADR
listList all ADRs
searchSearch ADRs for matching content
statusChange an ADR's status
linkLink two ADRs together
exportExport ADRs to different formats
importImport ADRs from different formats
generateGenerate documentation
templateManage ADR templates
configShow configuration
doctorCheck repository health
completionsGenerate shell completions
cheatsheetShow quick reference

Global Options

These options are available for all commands:

OptionDescription
--ngUse NextGen mode (YAML frontmatter)
-C, --cwd <DIR>Run as if started in <DIR>
-h, --helpPrint help information
-V, --versionPrint 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

ArgumentDescription
[DIRECTORY]ADR directory path (default: doc/adr)

Options

OptionDescription
--ngUse NextGen mode (YAML frontmatter)
-C, --cwd <DIR>Working directory
-h, --helpPrint help

Description

The init command creates:

  1. A .adr-dir file in the current directory containing the ADR directory path
  2. The ADR directory (creates parent directories if needed)
  3. 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.

  • config - Show current configuration
  • new - Create additional ADRs

new

Create a new Architecture Decision Record.

Usage

adrs new [OPTIONS] <TITLE>

Arguments

ArgumentDescription
<TITLE>Title of the new ADR

Options

OptionDescription
-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
--ngUse NextGen mode (YAML frontmatter)
-C, --cwd <DIR>Working directory
-h, --helpPrint 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 to
  • KIND: The relationship from this ADR to the target
  • REVERSE_KIND: The reverse relationship added to the target

Common link types:

  • Amends / Amended by
  • Extends / Extended by
  • Relates to / Relates to
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:

  • vim
  • nano
  • vi

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:

  • NNNN is the zero-padded ADR number
  • Title is converted to lowercase kebab-case
  • Special characters are removed

Examples:

  • 0001-record-architecture-decisions.md
  • 0002-use-postgresql-for-persistence.md
  • 0015-api-versioning-strategy.md
  • edit - Edit an existing ADR
  • link - Link ADRs together
  • Templates - Available templates

edit

Edit an existing Architecture Decision Record.

Usage

adrs edit [OPTIONS] <ADR>

Arguments

ArgumentDescription
<ADR>ADR to edit (number or search term)

Options

OptionDescription
--ngUse NextGen mode
-C, --cwd <DIR>Working directory
-h, --helpPrint 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.

  • new - Create a new ADR
  • list - List ADRs to find the one to edit

list

List Architecture Decision Records with optional filtering.

Usage

adrs list [OPTIONS]

Options

OptionDescription
-l, --longShow 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)
--ngUse 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.

  • new - Create a new ADR
  • edit - Edit an ADR from the list
  • status - Change an ADR's status

search

Search ADRs for matching content.

Usage

adrs search [OPTIONS] <QUERY>

Arguments

ArgumentDescription
<QUERY>Search query text

Options

OptionDescription
-t, --titleSearch titles only
-s, --status <STATUS>Filter by status
-c, --case-sensitiveCase-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 -t is used
  • Combine with --status to 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

ArgumentDescription
NUMBERThe ADR number to update
STATUSNew status value

Options

OptionDescription
--by <NUMBER>For 'superseded' status: the ADR number that supersedes this one

Standard Statuses

  • proposed - Decision is proposed but not yet accepted
  • accepted - Decision has been accepted
  • deprecated - Decision is deprecated but not replaced
  • superseded - 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:

Custom status

adrs status 4 "on-hold"

Notes

  • The status command updates the ADR file in place
  • For superseded status, using --by is 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

ArgumentDescription
<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

OptionDescription
--ngUse NextGen mode
-C, --cwd <DIR>Working directory
-h, --helpPrint 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"
Forward LinkReverse LinkUse Case
AmendsAmended byModifying a previous decision
ExtendsExtended byBuilding on a previous decision
SupersedesSuperseded byReplacing a decision
Relates toRelates toGeneral relationship
Depends onDependency ofDependencies

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
---
  • new - Create ADRs with links
  • list - Find ADR numbers

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

OptionDescription
--pretty, -pPretty-print the JSON output
--dir, -dExport from a directory without requiring an initialized repository
--metadata-onlyExport 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

OptionDescription
--dir, -dImport to a directory without requiring an initialized repository
--overwrite, -oOverwrite existing files with the same number
--renumber, -rRenumber ADRs starting from next available number
--appendAlias for --renumber
--dry-runPreview import without writing files
--ngUse 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:

  1. Finds the next available number in the target directory
  2. Renumbers all imported ADRs sequentially from that number
  3. 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

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

SubcommandDescription
tocGenerate a table of contents
graphGenerate a Graphviz dependency graph
bookGenerate an mdbook

generate toc

Generate a markdown table of contents to stdout.

Usage

adrs generate toc [OPTIONS]

Options

OptionDescription
-o, --orderedUse 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
--ngUse NextGen mode
-C, --cwd <DIR>Working directory
-h, --helpPrint 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
adrs generate toc -p "wiki/adr/"

generate graph

Generate a Graphviz DOT graph showing ADR relationships.

Usage

adrs generate graph [OPTIONS]

Options

OptionDescription
-p, --prefix <PREFIX>Prefix for node URLs
-e, --extension <EXT>File extension for links (default: md)
--ngUse NextGen mode
-C, --cwd <DIR>Working directory
-h, --helpPrint 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
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

OptionDescription
-o, --output <DIR>Output directory (default: book)
-t, --title <TITLE>Book title
-d, --description <DESC>Book description
--ngUse NextGen mode
-C, --cwd <DIR>Working directory
-h, --helpPrint help

Examples

Basic Book

adrs generate book

This creates a book/ directory with:

  • book.toml - mdbook configuration
  • src/SUMMARY.md - table of contents
  • src/*.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
  • list - List ADRs
  • doctor - Check repository health

template

Manage ADR templates.

Usage

adrs template <COMMAND>

Subcommands

CommandDescription
listList available templates
showShow 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

OptionDescription
-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

VariantDescription
fullComplete template with all sections and guidance
minimalEssential sections only
bareMinimal structure, just headings

See Also

  • new - Create ADRs using templates
  • Templates - Template customization guide

config

Show the current configuration.

Usage

adrs config [OPTIONS]

Options

OptionDescription
--ngUse NextGen mode
-C, --cwd <DIR>Working directory
-h, --helpPrint 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

SourceDescription
adrs.tomlTOML configuration file
.adr-dirLegacy adr-tools configuration
global (~/.config/adrs/config.toml)User-wide configuration
environmentEnvironment variable override
defaultsBuilt-in defaults

doctor

Check the health of your ADR repository.

Usage

adrs doctor [OPTIONS]

Options

OptionDescription
--ngUse NextGen mode
-C, --cwd <DIR>Working directory
-h, --helpPrint help

Description

Runs diagnostic checks on your ADR repository and reports any issues found.

Checks Performed

CheckDescription
File NamingADR files follow the NNNN-title.md pattern
Duplicate NumbersNo two ADRs have the same number
Numbering GapsSequential numbering without gaps
Broken LinksAll referenced ADRs exist
Superseded StatusSuperseded ADRs have corresponding links
Parse ErrorsAll 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

LevelDescription
OKCheck passed
WARNPotential issue, but not critical
ERRORProblem that should be fixed

Exit Codes

CodeDescription
0All checks passed
1One or more checks failed

This allows using doctor in CI pipelines:

- name: Check ADR health
  run: adrs doctor
  • list - List ADRs
  • link - Fix broken links

completions

Generate shell completions for tab-completion support.

Usage

adrs completions <SHELL>

Arguments

ArgumentDescription
<SHELL>Shell to generate completions for

Supported Shells

ShellDescription
bashBourne Again Shell
zshZ Shell
fishFish Shell
powershellPowerShell
elvishElvish 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 cheatsheet whenever you need a quick reminder
  • Use adrs <command> --help for 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

ToolDescription
list_adrsList all ADRs with optional status/tag filters
get_adrGet full content of an ADR by number
search_adrsSearch ADR titles and content
get_adr_sectionsGet ADR with parsed sections (context, decision, consequences)
get_related_adrsGet all ADRs linked to/from a specific ADR
get_repository_infoGet repository mode, ADR count, and configuration

Write Operations

ToolDescription
create_adrCreate a new ADR (always 'proposed' status)
update_statusChange an ADR's status
link_adrsCreate bidirectional links between ADRs
update_contentUpdate ADR sections (context, decision, consequences)
update_tagsAdd or replace tags (NextGen mode only)
bulk_update_statusUpdate multiple ADR statuses at once

Analysis Tools

ToolDescription
validate_adrCheck ADR structure and report issues
compare_adrsCompare two ADRs and show differences
suggest_tagsAnalyze 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 text
  • title_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 title
  • context (optional): Context section content
  • decision (optional): Decision section content
  • consequences (optional): Consequences section content
  • supersedes (optional): ADR number this supersedes

update_status

Change an ADR's status.

Parameters:

  • number (required): ADR number
  • status (required): New status (proposed, accepted, deprecated, superseded, rejected)
  • superseded_by (optional): Required when status is 'superseded'

Create bidirectional links between ADRs.

Parameters:

  • source (required): Source ADR number
  • target (required): Target ADR number
  • link_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 number
  • adr2 (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

  1. Human Review: All ADRs created by AI are set to 'proposed' status. Review before accepting.

  2. Provide Context: Give Claude context about your architecture when asking it to create ADRs.

  3. Use Tags: In NextGen mode, use suggest_tags to maintain consistent categorization.

  4. Validate Often: Use validate_adr to ensure ADRs have complete content.

  5. Link Related Decisions: Use link_adrs to maintain decision traceability.

See Also

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

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

Templates

Books

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 thiserror for library errors
  • Use anyhow for 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

  1. Fork the repository
  2. Create a feature branch: git checkout -b feat/my-feature
  3. Make your changes
  4. Run tests and lints
  5. Commit with conventional commit messages
  6. 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.