Skip to content

Getting Started

Using Claude Code?

eng-metrics-suite (and eng-metrics-suite-pro) ship a gitultra-setup skill that automates everything on this page through Generating Reports -- clone the repo, open it in Claude Code, and ask it to set up GitUltra. It detects your tier, asks only for what it can't infer (org name, provider tokens, which optional integrations to enable), and verifies the install with a real generated report before calling it done. The steps below are what it's automating, and remain the reference if you'd rather do it by hand or the skill doesn't behave as expected.

Clone eng-metrics-suite, then:

cp .env.example .env
# edit .env: set a POSTGRES_PASSWORD, and the token(s) for whichever
# provider(s) you're importing from (GitHub/GitLab/Bitbucket/Azure DevOps)

sudo mkdir -p /var/lib/eng-metrics-suite
sudo chown "$(id -u):$(id -g)" /var/lib/eng-metrics-suite
mkdir -p reports

docker compose up -d

Why the two mkdirs

/var/lib/eng-metrics-suite is where config files (not secrets — those go in .env) live: discover_repos.py's --config YAML (see Discovering Repos) and report.py's --team-map CSV (see Generating Reports) both get read from there, mounted read-only into the relevant containers at the same path. It needs to exist before docker compose up — Docker will auto-create it as root-owned otherwise, which then blocks you from writing to it without sudo.

./reports needs the same up-front mkdir, for a related but different reason: eng-reports runs as a non-root user (UID 1000) so its output isn't root-owned on the host, but that only helps once the directory already exists with the right owner. If Docker has to auto-create ./reports itself (e.g. because you skipped this step), it does so as root, and the non-root container then can't write into it at all (PermissionError: [Errno 13] Permission denied). If your host user isn't UID 1000 (check with id -u), add --user "$(id -u):$(id -g)" to the docker compose run commands in Generating Reports instead.

What docker compose up actually starts

Postgres, plus the git-processor and pr-processor workers (and issue-processor, if your compose bundle includes it — see Jira Integration). The workers exit as soon as they find nothing queued to do — that's expected, not a crash; restart: unless-stopped just means they check again periodically rather than sitting in a busy loop. Nothing happens until you queue some repos — continue to Discovering Repos.