List Architecture Decision Records dynamically from the filesystem.
Use Case: Generate ADR index tables for README files, audit ADR status, or quickly view all architectural decisions.
Steps:
- Check for ADRs
ls docs/adrs/*.md 2>/dev/null | head -1
If no ADRs found:
No ADRs found in docs/adrs/
Run /blueprint:derive-adr to generate ADRs from project analysis.
- Generate ADR Table
ADR formats vary: some use markdown headers (## Status , ## Date ), others use YAML frontmatter (status: , date: ). The extraction handles both.
Command to generate markdown table:
printf "| ADR | Title | Status | Date |\n|-----|-------|--------|------|\n" &&
fd '^[0-9]{4}-.*.md$' docs/adrs -x awk '
Extract title from H1 header
/^# ADR-/ {gsub(/^# ADR-[0-9]+: /, ""); title=$0}
Extract status from ## Status section (next non-empty line)
/^## Status/ {p_status=1; next} p_status && NF {status=$0; p_status=0}
Extract date from ## Date section (next non-empty line)
/^## Date/ {p_date=1; next} p_date && NF {date=$0; p_date=0}
Fallback: YAML frontmatter fields
/^status:/ && !status {gsub(/^status:[[:space:]]/, ""); status=$0} /^date:/ && !date {gsub(/^date:[[:space:]]/, ""); date=$0}
END { # Extract ADR number from filename (path-depth independent) fname = FILENAME sub(/.*//, "", fname) num = substr(fname, 1, 4) if (title == "") title = "(untitled)" if (status == "") status = "-" if (date == "") date = "-" printf "| %s | %s | %s | %s |\n", num, FILENAME, title, status, date } ' {} | sort
- Display Results
Output the generated table. Example:
| ADR | Title | Status | Date |
|---|---|---|---|
| 0001 | Use React for Frontend | Accepted | 2024-01-15 |
| 0002 | Use PostgreSQL for Database | Accepted | 2024-01-20 |
| 0003 | Migrate from CRA to Vite | Accepted | 2024-02-01 |
- Optional: Extended Table with Domain
If domain tags are used, generate extended table:
printf "| ADR | Title | Status | Date | Domain |\n|-----|-------|--------|------|--------|\n" &&
fd '^[0-9]{4}-..md$' docs/adrs -x awk '
/^# ADR-/ {gsub(/^# ADR-[0-9]+: /, ""); title=$0}
/^## Status/ {p_status=1; next}
p_status && NF {status=$0; p_status=0}
/^## Date/ {p_date=1; next}
p_date && NF {date=$0; p_date=0}
/^domain:/ {gsub(/^domain:[[:space:]]/, ""); domain=$0}
/^status:/ && !status {gsub(/^status:[[:space:]]/, ""); status=$0}
/^date:/ && !date {gsub(/^date:[[:space:]]/, ""); date=$0}
END {
fname = FILENAME; sub(/.*//, "", fname); num = substr(fname, 1, 4)
if (title == "") title = "(untitled)"
if (status == "") status = "-"
if (date == "") date = "-"
if (domain == "") domain = "-"
printf "| %s | %s | %s | %s | %s |\n", num, FILENAME, title, status, date, domain
}
' {} | sort
- Summary Statistics
After the table, show summary:
echo "" echo "Summary:" echo "- Total: $(fd '^[0-9]{4}-.*.md$' docs/adrs | wc -l | tr -d ' ') ADRs" echo "- Accepted: $(grep -rl '^Accepted$|^status:.Accepted' docs/adrs/.md 2>/dev/null | wc -l | tr -d ' ')" echo "- Superseded: $(grep -rl '^Superseded|^status:.Superseded' docs/adrs/.md 2>/dev/null | wc -l | tr -d ' ')" echo "- Deprecated: $(grep -rl '^Deprecated|^status:.Deprecated' docs/adrs/.md 2>/dev/null | wc -l | tr -d ' ')"
Tip: Add the listing command to docs/adrs/README.md so anyone can regenerate the index. See the ADR README template generated by /blueprint:derive-adr .