rootly-catalog-sync is a standalone CLI tool that reconciles external sources of truth into Rootly’s Catalog. It pulls data from your existing systems — GitHub repos, Backstage, internal APIs, CSV files, or any command — and syncs it one-way into Rootly, keeping services, teams, and metadata up to date automatically.

Why use Catalog Sync?
- Single source of truth — your service catalog lives in GitHub, Backstage, or a database. Rootly mirrors it automatically.
- No manual data entry — add a service to your repo, it appears in Rootly on the next sync.
- Safe by default — deletes are opt-in, empty sources abort, prune ratio thresholds prevent mass deletion.
- Terraform-style workflow —
planto preview,applyto execute,statusto check drift.
Install
Quick start
Authentication
Two methods are supported, in priority order:API key (CI / non-interactive)
OAuth 2.0 (interactive)
ROOTLY_API_KEY is set, it always takes precedence over OAuth tokens.
Configuration
The sync tool uses a declarative config file that defines pipelines — each pipeline connects sources to catalog outputs..yaml (default), .jsonnet, or .hcl. Credentials use $(ENV_VAR) substitution.
Sources
Inline source
Local source
GitHub source
repos to scan all repositories in the org. Set archived: true to include archived repos.
Backstage source
Exec source
GraphQL source
CSV source
URL source
HTTP source
Output targets
Each pipeline maps source entries to one or more outputs. Outputs can target custom catalogs or native Rootly resources.Custom catalog
The default output type. Creates entities in a named Rootly catalog with arbitrary fields.Native resources
Sync directly to built-in Rootly resource types by setting thetype field.
description, pagerduty_id, github_repository_name) are set directly on the resource. Any field not in the known-attribute list is automatically routed to catalog properties on the resource.
Template syntax
Field mappings use Go template syntax to transform source entries into output fields.Field access
Conditionals
missingkey=error — a missing field in the source data causes an immediate error rather than a silent empty string.
Commands
Safety guarantees
- Deletes are opt-in —
--allow-prunerequired, off by default - Empty source aborts — never wipes a catalog on a source failure
- Prune ratio threshold — aborts if deletes exceed 20% of live entities (configurable via
--prune-threshold) - Manual entries are safe — only entries with
external_id(created by sync) are prunable - Order: create/update first, delete last — no window where entries are missing
- Plan freshness —
applyvalidates that live state hasn’t changed since the plan was created
CI/CD integration
GitHub Actions
Dry-run on PRs
Nightly drift detection
Environment variables
Interactive TUI
Thetui command launches a full-screen terminal UI for reviewing and selectively applying changes:
- Browse changes with colored badges (CREATE/UPDATE/DELETE/NOOP)
- Toggle individual changes with
space, expand field diffs withenter - Filter by operation type (
c/u/d) or search (/) - Detail pane shows full entity fields on wide terminals
- Apply only selected changes with
A