autocatalog
All your docs, events and services in one place, from every repository.
autocatalog builds one site for every team's docs, decisions, runbooks, incidents, events, services, APIs and data models, each with its owner. It reads the code and Markdown your teams already commit, so the site stays current without anyone keeping it up to date.
Everything a team commits, in one place
Each repository keeps its own docs and contracts. The site reads all of them and links them, so a service page shows its events, its API, its decisions and its runbooks together, whichever repository each one lives in.
- Docsdocs/**/*.mdWith the owner, the date git last saw each page change, and backlinks from every other repository.
- Decisions, runbooks, incidentsdocs/adr, runbooks, incidentsThe folder sets the kind. Each kind gets one index across every repository, newest first, filtered by status. Add or rename kinds in
contracts/autocatalog.conventions.json. - Eventscontracts/Schema, examples, version history and the file that defines each one.
- Servicesbuilt, not writtenMade from the events that name them, with every document whose
about:lists them. - Domainsfrom each eventThe events in a domain, the services around them and their owners, with a map.
- APIscontracts/*.openapi.*An API reference for each OpenAPI 3 spec, linked to the service it names.
- Data modelsPrisma, Drizzle, MongooseEach table and collection, its fields, and the services that read and write it.
- OwnersCODEOWNERSEach team's contact and everything it owns, also from
catalog-info.yaml.
PaymentService
about: lists it. Nobody wrote this page.How it gets the map
It reads conventions your teams probably follow already. No config file, and nothing written back to the repository. A team joins by adding the catalog topic to its GitHub repository, and the next build picks it up.
contracts/
Schema files in JSON Schema, OpenAPI, Avro or protobuf, read where they are. Events defined in Zod or Pydantic are scanned into events/ alongside them.
acme/payments-service └─ contracts/ ├─ payment-completed.json ├─ payment-refunded.json └─ payments.openapi.yaml
- Events, fields, examples, APIsExtracted from the schema itself
- Producers and consumersDeclared in
defineEvent()orx-autocatalog
docs/
Markdown your team already commits. The folder sets the kind:
adr/,runbooks/andincidents/become decisions, runbooks and incidents.acme/payments-service └─ docs/ ├─ settlement.md ├─ adr/0003-kafka-for-payment-events.md └─ runbooks/replay-payment-events.md
- Owner, status, what it is aboutDeclared in
owner:,status:,about: - Kind and freshnessExtracted from the folder and from git
- Owner, status, what it is aboutDeclared in
CODEOWNERS
Ownership comes from the file that already gates your reviews, and from
catalog-info.yamlif you use Backstage..github/CODEOWNERS /contracts/ @acme/billing /docs/ @acme/billing /src/models/ @acme/billing
- Owners and contactsExtracted from CODEOWNERS
- Who reads which tablesExtracted from Mongoose, Prisma and Drizzle models
Your company decides the kinds. contracts/autocatalog.conventions.json renames a folder, turns a kind off or adds one, such as RFCs, with its own fields and index page.The docs convention
Contracts are the spine
Events are what connect one team's service to another's, and each event's schema is the contract they build against. autocatalog drift compares the contracts on main with those on your branch and names every consumer a change would break, including teams in other repositories that declared what they read.
breaking payments/payment.completed: field `amount` (number) looks renamed to `amountMinor` → breaks LedgerService, NotificationService. Next: keep `amount` alongside `amountMinor` until consumers move off it, or bump to 2.0.0 to mark it intentional and notify LedgerService, NotificationService suspicious payments/payment.completed: schema changed but version stayed at 1.0.0 1 breaking · 1 suspicious · 0 additive
# .github/workflows/ci.yml
- run: git fetch origin main
- run: npx autocatalog drift --base-ref origin/main --root . --format githubWhat fails the check
- Removed and renamed fields
- Type changes
- Fields that become required
- Narrowed enums
- Changed delivery guarantees
checkout (payments) reads collection acme/finance/statements, which ledger owns
Start where your contracts are
Teams with schema files change nothing in their code. Teams with Zod or Pydantic add one wrapper, and the schema it returns is unchanged.
- TypeScript, with Zod
defineEvent()from autocatalog-plugin-zod - Python, with Pydantic
autocatalog-py extract - Rust, Go, Java or .NET
a test writes
contracts/with the language's own generator - JSON Schema files
autocatalog scan .reads them where they are - OpenAPI specs
an API reference for each spec under
contracts/ - AsyncAPI 2.x or 3.x
autocatalog from-asyncapi spec.yaml - Avro and protobuf
.avscand.protofiles undercontracts/ - An EventCatalog project
autocatalog from-eventcatalog ./catalog - Mongoose, Prisma and Drizzle models
which team's service reads which team's tables
Already using EventCatalog? How the two tools relate, and how to run them together.
Build the site from the repositories you already have.
Add the catalog topic to each repository you want on it, then build. With schemas in contracts/ and Markdown in docs/, no repository needs a config file. MIT licensed.
npx autocatalog site --topic catalog --owner acmenpx autocatalog site . --dev