TLDR overview
- Sonar Vortex connects GitHub Copilot CLI to SonarQube's full analysis engine, delivering your project's coding guidelines and architectural constraints to the agent before it writes code, and verifying every file it changed before it replies.
- Vortex fits teams running GitHub Copilot CLI against a codebase SonarQube Cloud already analyzes in CI, who want project standards enforced during generation rather than after a pull request triggers a pipeline.
- Verification inside the agent loop returns CI-depth findings in seconds, so the agent corrects its own output before a human opens a diff.
- The SonarQube plugin for GitHub Copilot CLI installs from the pre-packaged
awesome-copilotcatalog, and itssonar-integrateskill wires up the SonarQube MCP Server, apreToolUsesecrets hook, a context augmentation skill, and a managed Vortex analysis protocol in.github/instructions/sonarqube.instructions.md.
Sonar Vortex delivers project context to your AI coding agents and runs SonarQube analysis inside that agent's loop, and in GitHub Copilot CLI you enable it through the SonarQube plugin for GitHub Copilot CLI. Coding agents generate code without knowledge of a project's established standards, architectural boundaries, or issue history, and oftentimes nothing verifies their output until CI runs after a pull request. This blueprint configures Vortex to supply context before the agent writes and trigger verification as it writes: installing and activating the plugin, running the integration, reviewing what the integration configured, guiding the agent with context and constraints, verifying the agentic loop on a real edit, and running multi-file DEEP analysis from the CLI. Every example runs against a fork of aws-cli, a large Python codebase analyzed in SonarQube Cloud through CI.
When to use this
You want GitHub Copilot CLI to abide by your project's existing coding standards and catch issues as it writes code, not after a pull request triggers CI. Reach for this blueprint when:
- You run GitHub Copilot CLI against a codebase that SonarQube Cloud already analyzes.
- You want the agent following your project's conventions instead of generic language defaults.
- You want issues surfaced inside the agentic coding loop rather than by a CI-blocked pull request.
This blueprint covers the GitHub Copilot CLI plugin path. If you're only using the SonarQube CLI, the Install Vortex for Copilot guide documents both paths.
What you'll achieve
- The SonarQube plugin for GitHub Copilot CLI installed from the
awesome-copilotcatalog, with the SonarQube MCP Server running in a container viasonar run mcp. - A context augmentation skill at
.github/skills/sonar-context-augmentation/SKILL.mddelivering coding guidelines, architectural constraints, semantic code navigation, and, where enabled, dependency health checks before the agent writes. - A managed Vortex analysis protocol in
.github/instructions/sonarqube.instructions.mdthat runssonar analyze agentic --depth DEEPacross every file the agent changed before it replies, plus apreToolUsesecrets hook that denies reads when secrets are detected.
Architecture

The integration splits across two layers:
The plugin layer contributes skills and owns no runtime infrastructure. It installs from the pre-packaged awesome-copilot catalog, which is registered by default in GitHub Copilot CLI, so there's no marketplace to add first. The source bundle lives at .github/plugin/ in SonarSource/sonarqube-agent-plugins, and it ships nine sonar-* skills including sonar-integrate.
The SonarQube CLI layer does the work. sonar auth login holds your authenticated session in the OS keychain. sonar run mcp starts the SonarQube MCP Server container, which Copilot CLI talks to over stdio. The secrets hook script is a four-line shell that calls sonar hook copilot-pre-tool-use, so it reuses that same keychain session, and sonar context powers context augmentation.
sonar integrate copilot registers exactly one hook, preToolUse, and it's for secrets detection. Vortex analysis runs from a managed instructions block.
What makes the analysis fast enough to sit in a coding loop is that it recomputes nothing. A CI run stores your project's dependencies, compiled artifacts, type information, and build configuration, tagged by project key and branch. Vortex restores that context on demand, so a check returns in seconds at the same depth as a full scan.
Context augmentation doesn't travel the MCP path. It runs through a local sonar context daemon over a Unix domain socket on Linux and macOS, or a named pipe on Windows, which gives it direct filesystem access. Its tools won't appear in your MCP tool list.
Vortex covers the Guide and Verify stages of Sonar's Agent Centric Development Cycle. It guides the agent with project context and constraints, then verifies the agentic loop's output with CI-level precision.
Prerequisites
- GitHub Copilot CLI installed and operational
- SonarQube Cloud on Enterprise, or Team with an annual plan, plus a Sonar Agent Essentials subscription active for your organization
- A container runtime running: Docker, Podman, or nerdctl. The MCP server runs as a container
- (Optional) SonarQube CLI (
sonar) 1.6.0 or later. Thesonar-integrateskill installs or self-updates it, so you can skip this going in
To follow along exactly, fork aws/aws-cli, import it into SonarQube Cloud with CI-based analysis, and analyze it on a branch. Vortex analysis restores the CI analysis context and Vortex context combines SonarQube Cloud project data with the local semantic nav.
Step 1 — Install and activate the plugin
Open a Copilot CLI session from your project root and install the plugin:
/plugin install sonarqube@awesome-copilot
Confirm it’s registered:
/plugin list
Then list what it brought with it:
/skills
All nine sonarqube:sonar-* skills are available, from sonar-analyze through sonar-integrate. At this point the plugin is loaded, but nothing is wired to your project yet.
Step 2 — Configure the integration
Run the integration skill:
/sonarqube:sonar-integrateIt walks four checks:
- CLI check. Verifies the SonarQube CLI is installed and runs
sonar self-update. If the CLI isn't on your machine, it shows the install commands. - Auth check. Runs
sonar auth status. If you're already authenticated to SonarQube Cloud, it skips ahead. - Auth login. Select your region (EU or US), enter your organization key, and complete browser-based authentication. The token lands in your OS keychain. The skill hands this step back to you deliberately, because
sonar auth loginopens a browser. - Integration. Choose whether to configure the current project or install globally. Choose Current project only. The skill runs
sonar integrate copilot --non-interactiveunder the hood.
The summary confirms what was configured:

Vortex installs as a single prompt covering both context and analysis. That unification shipped in SonarQube CLI 1.5.0. On older versions you'll see two separate prompts for agentic analysis and context augmentation.
Watch for a silent partial setup. Vortex is skipped on --global, on SonarQube Server, and without organization entitlement, while secrets detection still installs in all three cases.
Restart Copilot CLI before continuing. The hook and MCP config are read at startup.
Step 3 — Review what the integration configured
Five artifacts landed in your project:
.mcp.json registers the MCP server at your project root:
{
"mcpServers": {
"sonarqube": {
"command": "sonar",
"args": ["run", "mcp", "--project", "<your-project-key>"]
}
}
} The server starts through the CLI rather than a raw docker run, which is how the CLI detects your container runtime and hands off the keychain session.
.github/hooks/hooks.json registers the one hook:
{
"version": 1,
"hooks": {
"preToolUse": [
{
"type": "command",
"timeoutSec": 60,
"bash": ".github/hooks/sonar-secrets/build-scripts/pretool-secrets.sh"
}
]
}
} The hook script is five lines and it exits silently when the CLI isn't on PATH.
#!/bin/bash
if ! command -v sonar &> /dev/null; then
exit 0
fi
sonar hook copilot-pre-tool-use.github/instructions/sonarqube.instructions.md carries two managed blocks, each delimited by HTML comments. The first, sonar:begin:copilot-prompt-secrets, tells the agent to scan prompt text for credentials before acting, corroborate with sonar analyze secrets --stdin when it's uncertain, refuse the request on a hit, and advise you to rotate the credential.
The second, sonar:begin:sonarqube-agentic-analysis-protocol, is titled "Vortex analysis protocol" and governs end-of-turn verification:
Trigger: the moment before you send your final reply for the turn.
Preferred: pass every path you modified this turn in a single invocation
(repeat --file for each path)... For end-of-turn analysis, always pass
--depth DEEP — even when you changed only one file — so cross-file
findings are included.sonar analyze agentic --project <your-project-key> --depth DEEP --file <path1> --file <path2>.github/skills/ holds the skill definitions. The plugin delivers eight of them, from sonar-analyze through sonar-quality-gate. The integration adds one more: .github/skills/sonar-context-augmentation/SKILL.md is the context augmentation skill, and it's the one Vortex artifact in that directory. Its description tells the agent to invoke it on the first prompt, and it defines three mandatory workflows: sonar context guidelines get before generating or editing source code, sonar context dependencies check --purl <purl> before modifying a manifest or lockfile, and the sonar context navigation family in place of grep and find for locating symbols and tracing callers. Step 1 reported nine skills, which is the plugin's own set. With context augmentation installed, you now have ten.
Step 4 — Guide the agent with context and constraints
You don't invoke the context skill directly. Give the agent a natural language prompt and watch it reach for the skill on its own.
what are the coding guidelines for this project?
The agent calls skill(sonar-context-augmentation), shells out to sonar context guidelines get, and comes back with nine guidelines that belong to this codebase rather than to Python generally. Five are Python rules: remove unused local variables, never hard-code credentials, don't leave functions or methods empty, don't create temporary files in publicly writable directories, and don't set world-accessible file permissions. Three cover GitHub Actions: avoid read-all and write-all permissions, don't execute Python package manager scripts during installation, and lock Python dependencies to verified versions. The last is general: commit the dependency lock file to source control.
Each one derives from this project's real SonarQube issue history, filtered by what the agent is about to do. Guidelines get selected two ways, from the prompt itself and from historical issues in the files the agent plans to touch.
Now the second query:
show me the top-level architecture of this project
The agent runs sonar context architecture get-current --depth 0 for the overview, then drills in with --depth 2 --path-prefix awscli. It returns the five top-level modules, awscli/, tests/, doc/source/, scripts/performance/, and setup.py, with the role of each. Inside awscli/ it identifies clidriver.py as the central driver that orchestrates the argument parser, commands, help, plugins, and formatting, and flags customizations/ as the largest sub-tree. It characterizes the whole thing as a driver, command, customization layered pattern.
Four capability categories back these answers. Intelligent guidelines come from issue history. Architectural awareness exposes the current dependency graph and any constraints you've defined. Semantic navigation resolves call stacks, class hierarchies, and references using abstract syntax trees and control flow rather than keyword matching. Third-party dependency guidance assesses vulnerabilities, supply-chain malware, and license compliance before a package gets added, where SonarQube Advanced Security is available.
Step 5 — Verify the agentic loop
One prompt exercises the whole loop. What follows is a walkthrough from this project, so your findings will differ.
Add s3_helper.py at the project root with an upload_with_retry(
bucket, key, file_path, max_retries=3
) function.
Implement a small boto3-based S3 upload helper using the standard upload_file
transfer API. Retry transient upload failures with exponential backoff, log each
attempt, and raise a clear error after all retries fail. Keep the public function
signature as specified. Include a TODO for adding metric emission later.Before touching the filesystem, the agent retrieves the project's coding guidance, narrowed to what it's about to write:
sonar context guidelines get --languages python --categories "Exception & Error Handling" …Then it writes the file. Following the managed instructions protocol, and with no hook involved, it runs analysis on its own output:
sonar analyze agentic --project <your-project-key> --depth DEEP …Two findings come back. S1135 flags the TODO comment. S7608 recommends passing ExpectedBucketOwner in ExtraArgs to verify bucket ownership.
The agent triages rather than complying blindly. It keeps the TODO, because you asked for it, and says so. python:S7608 it treats as real: the rule raises when an S3 operation runs without verifying bucket ownership, and Sonar rates its security impact high. Without ExpectedBucketOwner, a naming collision or a dynamically constructed bucket name can send the upload to a bucket in a different AWS account, which matters most in multi-account setups where bucket names look alike.
The fix adds an optional keyword parameter, which widens the signature the prompt told it to keep. The agent called that deviation out rather than making it silently, and every call written against the original four arguments still behaves the same:
def upload_with_retry(bucket, key, file_path, max_retries=3, expected_bucket_owner=None):
...
extra_args = {}
if expected_bucket_owner is not None:
extra_args["ExpectedBucketOwner"] = expected_bucket_ownerThen it re-runs analysis on the same scope, as rule 3 requires:

Only the intentional TODO remains. Two things are worth pulling out of that sequence. First, no hook fired at any point. The instructions require the agent to run one DEEP pass across everything it changed before replying, and to re-run after each fix until the lines it touched come back clean. That is end-of-turn rather than per-edit, and the agent is the one invoking it. Second, the division of labor holds throughout: Vortex flagged, the model decided and fixed, inside a single turn, with nobody reviewing a diff in between.
Step 6 — Run multi-file DEEP analysis
Single-file analysis won't catch issues that only appear across boundaries. Pass repeated --file flags to widen the scope:
sonar analyze agentic --file awscli/clidriver.py --file s3_helper.py --file awscli/customizations/s3/subcommands.py! awscli/clidriver.py · 1 issue
[1] line 289 Complete the task associated to this "TODO" comment. python:S1135
! s3_helper.py · 1 issue
[1] line 27 Complete the task associated to this "TODO" comment. python:S1135
! awscli/customizations/s3/subcommands.py · 10 issues
[1] line 903 Define a constant instead of duplicating this literal "%s\nError: Invalid argument type" 3 times. python:S1192
[2] line 555 Define a constant instead of duplicating this literal 's3://' 8 times. python:S1192
[3] line 771 Define a constant instead of duplicating this literal "<S3Uri>" 4 times. python:S1192
[4] line 429 Using HTTP protocol is insecure. Use HTTPS instead. python:S5332
[5] line 925 Complete the task associated to this "TODO" comment. python:S1135
[6] line 1096 Refactor this function to reduce its Cognitive Complexity from 24 to the 15 allowed. python:S3776
[7] line 1248 Either merge this branch with the identical one on line "1230" or change one of the implementations. python:S1871
[8] line 1474 Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed. python:S3776
[9] line 1510 Use the opposite operator ("!=") instead. python:S1940
[10] line 1594 Replace the unused local variable "bucket" with "_". python:S1481
3 files analyzed · 3 with issues · 12 issues found · DEEP analysisThe s3_helper.py finding is the same intentional TODO from Step 5. The subcommands.py findings are pre-existing issues in the upstream codebase, which is exactly the category the protocol tells the agent to leave alone unless you ask.
Five things govern this command:
- Two or more
--fileflags activateDEEPautomatically. Notice there's no--depthflag above. The default isSTANDARDfor a single--fileandDEEPotherwise. --depthacceptsSTANDARDandDEEP, so you can force a deep pass on one file.--projectand--branchare inferred from your project configuration when you run inside the project directory.- Oversized payloads batch automatically, which can reduce cross-file context for that run. A change set above 50 files prompts for confirmation;
--forceskips it. - Exit code
51signals that issues were reported, which is useful if you script around this.
Verify the setup
Run through this checklist to confirm every layer is live.
sonar auth status # authenticated session against SonarQube Cloud
sonar --version # 1.6.0 or later
sonar system status # Vortex section shows entitlement and usage state
copilot plugin list # sonarqube@awesome-copilot, installed
docker ps --filter "ancestor=sonarsource/sonarqube-mcp"sonar system status arrived in CLI 1.6.0 and is the fastest answer to "why isn't Vortex installing?" A genuine entitlement loss surfaces as an unhealthy status; hitting a usage limit stays healthy.
Then, in a fresh Copilot CLI session:
/mcp showlistssonarqubeas connected. Context augmentation tools won't appear there; they run through the local daemon.- Put a credential-shaped value in a throwaway file and ask the agent to read it. The
preToolUsehook blocks the read before it reaches the model. Obvious placeholders likeEXAMPLE_TOKENget filtered by the scanner's entropy check and won't trigger it, so the value has to look plausible. Delete the file afterward. - After a file edit, the agent runs a
DEEPanalysis before its final reply. The managed instructions direct this rather than a hook enforcing it, so you're confirming the agent followed them.
Your project should now carry these artifact
What to know
- Vortex analysis restores stored CI analysis context, and context augmentation draws its guidelines and architecture graph from prior analysis. For Java projects analyzed through Automatic Analysis, only basic results come back.
- The integration installs one hook,
preToolUsefor secrets, and runs Vortex analysis from managed instructions at end of turn atDEEPdepth. - Vortex is project-scoped, and it's skipped silently on
sonar integrate copilot --global, on SonarQube Server, and without organization entitlement, while secrets detection still installs. Entitlement gates installation and consumption gates runtime, so your hooks can be present while analysis is blocked until your limit resets.sonar system statustells you which case applies. - Language coverage differs per capability. Vortex analysis spans 25 languages including Python, but taint analysis is limited to Java, JavaScript, TypeScript, C#, and VB.NET, and semantic navigation to Java, C#, JavaScript, TypeScript, Python, and Rust.
- Re-running
sonar integrate copilotis idempotent and it's your recovery path. Running it interactively against a configured project also lets you keep or remove individual features, and Vortex comes out as one unit.
Verified against SonarQube plugin for GitHub Copilot CLI 2.5.0, SonarQube CLI 1.6.0, and GitHub Copilot CLI 1.0.80, August 2026.
Next steps
- How to set up Sonar Vortex in Claude Code
- Introducing Sonar Vortex and the SonarQube Remediation Agent
- SonarQube agent plugins
- The future is AC/DC: the Agent Centric Development Cycle
Consult the docs:
