# Sonar

> Inspect SonarQube quality gates, issues, and measures for a Bitbucket pull request or main branch from the command line. Use when checking SonarQube gate status on a PR, reviewing new issues introduced by a branch, or wiring quality gates into CI scripts.

- Skill: `avantmedialtd/sonar` (Agent Skill)
- Install (CLI): `npx skillmds@latest add avantmedialtd/sonar`
- Raw SKILL.md: https://api.skillmd.com/api/skills/avantmedialtd/sonar/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: avantmedialtd (https://skillmd.com/u/avantmedialtd)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/avantmedialtd/sonar

---


# SonarQube CLI

Read-only command-line tool for inspecting a self-hosted SonarQube instance via `af sonar`. Intentionally companion-shaped to `af bb pr` — the same numeric PR id identifies both sides.

## Setup

SonarQube uses its own bearer token. Atlassian and Bitbucket credentials are **not** interchangeable. Add the following to your project's `.env`:

- `SONAR_TOKEN` — User token from `<sonar>/account/security` (required)
- `SONAR_BASE_URL` — Sonar instance URL (optional; falls back to `sonar.host.url` in `sonar-project.properties`)

## Project Key Resolution

Walks the same path `sonar-scanner` does:

1. `--project <key>` flag (highest priority)
2. `sonar.projectKey` in `sonar-project.properties` (walking up from cwd)

There is intentionally no `af.json` block for Sonar — the properties file is the canonical source of truth.

## Quick Reference

Run bare `af sonar` (no subcommand) for the full command and flag reference. Note `af sonar --help` is intercepted by af's router and prints only a short stub.

- `af sonar pr <id>` — Quality gate + top new issues + measures for a Bitbucket PR
- `af sonar pr` — Same, auto-detecting the PR id from the current branch's open Bitbucket PR
- `af sonar pr <id> --issues` — List every fetched new issue instead of the top 4
- `af sonar pr <id> --json` — Raw JSON for scripting
- `af sonar gate` — Quality gate status for the main branch
- `af sonar prs` — All PRs known to SonarQube

## Output Formats

- Default: colourised, indented terminal text — gate status, issues, key measures, and a dashboard link. Not Markdown; don't paste it into a PR comment expecting it to render.
- JSON: Add `--json` for raw SonarQube API responses

## Issue Limits

`af sonar pr` always fetches **one page of at most 100 new issues** — there is no pagination. `--issues` changes only the rendering: it prints every issue on that page instead of the top 4. On a PR with more than 100 new issues, `--issues` shows the first 100, not all of them. Use the dashboard link for the true full list.

## Exit Codes

`af sonar pr` and `af sonar gate` exit **non-zero when the quality gate status is `ERROR`** — safe to drop into shell scripts and CI as a gate.

- `0` — Gate `OK` (or command completed successfully)
- `1` — Gate `ERROR`, or a command error

## Common Workflows

### Check the gate on a PR you're reviewing

```bash
# Explicit PR id — same number as af bb pr get 42
af sonar pr 42

# Auto-detect from the current branch
git checkout feature/auth-rewrite
af sonar pr
```

### See the new issues in full

```bash
# Default trims to the top 4 — pass --issues to print the whole fetched page (max 100)
af sonar pr 42 --issues
```

### Gate the main branch

```bash
af sonar gate
# Exits 1 if the gate is red — wire into a deploy script
```

### Browse all PRs SonarQube has analysed

```bash
af sonar prs
```

### CI / script integration

```bash
# Block a deploy on red gate
if ! af sonar gate >/dev/null; then
  echo "Sonar gate is red — refusing to deploy"
  exit 1
fi

# Extract a specific measure with jq.
# `measures` is the raw /api/measures/component body, so the metrics live in
# .measures.component.measures[] as {metric, value} pairs — there is no .measures.new_coverage.
af sonar pr 42 --json | jq -r '.measures.component.measures[] | select(.metric=="new_coverage") | .value'
```

The `--json` payload for `af sonar pr` is `{project, pullRequest, gate, issues, measures, dashboardUrl}`, each of `gate`/`issues`/`measures` being the untouched SonarQube API response. `af sonar gate --json` prints the quality gate response on its own (`.projectStatus.status`), and `af sonar prs --json` the raw PR list.

## PR Auto-Detection

`af sonar pr` (no id) uses the bundled Bitbucket client to find the current git branch's open PR. It returns distinct errors for:

- Zero PRs open for the branch
- Multiple open PRs (ambiguous)
- Missing Bitbucket credentials
- Detached `HEAD`

Each error message suggests `af sonar pr <id>` as the explicit escape hatch. Auto-detection requires the same `BITBUCKET_*` env vars as the `bitbucket` skill.

## Tips

- **Pair with `af bb pr get <id>`** — same numeric id, complementary views (code review vs. quality gate)
- **`--issues` for full noise** — the trimmed default is for at-a-glance review; reach for `--issues` when triaging, remembering the 100-issue page cap
- **Exit codes are scriptable** — `af sonar pr 42 && echo ok || echo red` is idiomatic
- **No mutations** — this command is read-only by design; issue assign/transition and hotspot management are deferred

## Out of Scope

The following are intentionally not part of `af sonar`:

- SonarCloud support (self-hosted SonarQube only)
- Mutating operations (issue assign, transition, hotspot review)
- Scanner wrapping (`sonar-scanner` is invoked separately, typically in CI)
- Inline Sonar gate status in `af bb pr` output

## Error Handling

- Without `--json`: errors print to **stderr** as red text
- With `--json`: config errors, PR auto-detection failures, and SonarQube API errors are emitted as `{"error": "message"}` on **stdout** instead — so redirecting stdout captures them, and `2>/dev/null` will not suppress them. Parse the JSON for `.error` rather than assuming a successful payload.
- Argument-parse errors (an unknown flag, or `--project` with no value) and an unknown subcommand ignore `--json` and always print plain text to stderr
- Exit codes: `0` success / gate OK, `1` error / gate ERROR (in every error case above)

