Install
openclaw skills install @afonsoft/sonarqube-autofixUse when analyzing SonarQube issues and turning them into SPEC SDDs for TDD implementation.
openclaw skills install @afonsoft/sonarqube-autofixAnalyze issues reported by SonarQube, regardless of language or framework, classify them by type, and create approved SPEC SDDs that describe the fixes. The actual implementation of each SPEC is delegated to /execute-spec.
The process is:
bug, code smell, or security.references/spec-sdd-template.md.Approved and invoke /execute-spec to implement the fixes.The skill supports multiple SonarQube editions through environment variables. Detection is automatic based on the availability of the variables (in priority order):
⚠️ IMPORTANT: For security, NEVER read, print, or inspect the value of environment variables that contain tokens. The most you may know is which variable the token is stored in. Use the variables directly in commands without accessing their contents.
SONARQUBE_CUSTOM_URL: Base URL of the custom SonarQubeSONARQUBE_CUSTOM_TOKEN: Authentication token for the custom SonarQubeSONARQUBE_CUSTOM_EDITION: Edition of the custom SonarQube (open or enterprise, default: open)SONARQUBE_ENTERPRISE_TOKEN: Authentication token for SonarQube EnterpriseSONARQUBE_ENTERPRISE_URL: Base URL of SonarQube Enterprise (required, no fallback)SONARQUBE_OPEN_TOKEN: Authentication token for SonarQube Open (preferred)SONAR_TK: Authentication token for SonarQube Open (fallback for compatibility, used only if SONARQUBE_OPEN_TOKEN is not set)SONARQUBE_OPEN_URL: Base URL of SonarQube Open (required, no fallback)Enterprise and Custom editions with enterprise edition automatically support the branch parameter in the API. The skill automatically detects the current branch using git branch --show-current.
The skill automatically detects the project's stack by analyzing configuration files. Load the script references/detect-stack.sh to determine the stack and configure the appropriate commands.
| File | Stack | Manager | Test Tool | Coverage Tool |
|---|---|---|---|---|
pom.xml | Java/Kotlin | Maven | Maven Surefire/Failsafe | JaCoCo |
build.gradle / build.gradle.kts | Java/Kotlin | Gradle | Gradle Test | JaCoCo |
package.json | JavaScript/TypeScript | npm/yarn/pnpm | Jest/Vitest/Mocha | Istanbul |
requirements.txt / pyproject.toml | Python | pip | pytest | Coverage.py |
.csproj / .sln | C#/.NET | dotnet | dotnet test | OpenCover/Cobertura |
go.mod | Go | go mod | go test | go test -cover |
Gemfile | Ruby | bundler | rspec/minitest | SimpleCov |
composer.json | PHP | composer | phpunit | phpunit |
build.sbt | Scala | sbt | sbt test | sbt coverage |
Load the script references/detect-stack.sh to automatically detect the project's stack and configure the appropriate commands.
angular.json or angular-cli.json# Tests with coverage
ng test --code-coverage --watch=false
# Linting
ng lint
# Formatting
npx prettier@<VERSION> --write src/
npx eslint@<VERSION> --fix src/
# Build for validation
ng build --configuration=production
references/validate-angular.sh — Angular validation (ng lint, ng test, prettier, eslint)references/templates/test-angular.md — Template for Karma/Jasmine tests with TestBed.csproj or .sln# Tests with coverage
dotnet test /p:CollectCoverage=true /p:CoverageFormat=cobertura
# Linting and analysis
dotnet build /p:RunAnalyzersDuringBuild=true
# Formatting
dotnet format
# Package restore
dotnet restore
references/validate-csharp.sh — C#/.NET validation (dotnet build, dotnet test, dotnet format)references/templates/test-csharp.md — Template for xUnit/Moq testsLoad the script references/sonar-local-scan.sh to run SonarQube locally and revalidate fixes before committing.
# Run local scan
bash references/sonar-local-scan.sh
The sonar-local-scan.sh script requires:
sonar-scanner installed (available at https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/)jqsonar-project.properties file in the project root (optional, script configures automatically)# Linux/macOS (manual): unzip the SonarScanner ZIP and add <path>/bin to PATH
export PATH="$HOME/sonar-scanner-<version>/bin:$PATH"
# Or use this repository's installer
./install-skill-tools.sh --sonar
sonar.projectKey=my-project
sonar.sources=src
sonar.tests=tests
sonar.exclusions=**/node_modules/**,**/dist/**,**/bin/**,**/obj/**
sonar.coverage.exclusions=**/*Tests.cs,**/Program.cs
sonar.cs.vscoveragexml.reportPaths=coverage.xml
sonar.javascript.lcov.reportPaths=coverage/lcov.info
Detect Project Stack
references/detect-stack.sh to automatically detect the stackSTACK, BUILD_TOOL, TEST_FRAMEWORK, COVERAGE_TOOLVerify issues file
Check the project name, usually it is the workspace folder name.
If it is not at the project root, create the .sonar_devin_auto_fix/ folder
⚠️ CRITICAL SECURITY: Never print the value of environment variables that contain tokens or secrets. NEVER read token values into your memory — the most you may know is which environment variable the token is stored in. Use the variables directly in bash commands without ever inspecting their contents.
Download the project's issues:
If the user specifies the project name, use it; otherwise try to use the workspace folder name, and if that is still not possible, ask the user for the project name.
If the user provides the issues to be fixed, query using the issues parameter and pass a csv list with the issue IDs; otherwise download all unresolved issues from the project using the SonarQube API.
If the user requests to fix only new issues, download the unresolved issues and add the inNewCodePeriod filter set to true.
Automatic SonarQube edition detection: The skill automatically detects which edition to use based on the available environment variables (in priority order):
$SONARQUBE_CUSTOM_URL is set$SONARQUBE_ENTERPRISE_TOKEN is set$SONARQUBE_OPEN_TOKEN or $SONAR_TK is setDownload issues with automatic detection:
Load the reference script references/download-issues.sh and execute it.
Indent the downloaded issues file using the script references/jsonf.sh
Confirm that .sonar_devin_auto_fix/sonarqube_issues.json exists and is parseable
Base all fixes exclusively on the issues listed in that JSON
Create ToDo Board
.sonar_devin_auto_fix/SONAR_FIX_TODO_BOARD.md# SonarQube Review ToDo Board
## SonarQube Issues Checklist
- [ ] Issue <ID> — Rule: <RuleKey> — File: `<path/to/file>` — Line: <line>
Summary: <short issue message>
For each downloaded issue, classify it into one of the four SonarQube types and record the classification in the ToDo Board:
| SonarQube type | SPEC type slug | SPEC metadata Type | Description |
|---|---|---|---|
BUG | bug | Bugfix | Reliability issues that are demonstrably wrong or more likely wrong than not |
CODE_SMELL | code-smell | Refactor | Maintainability issues and noisy code that should be cleaned up |
VULNERABILITY | vulnerability | Security | Security issues that could be exploited by an attacker |
SECURITY_HOTSPOT | security-hotspot | Security | Security-sensitive code that needs manual review before marking as safe |
Add the type to each line of SONAR_FIX_TODO_BOARD.md:
- [ ] Issue <ID> — Sonar type: <BUG | CODE_SMELL | VULNERABILITY | SECURITY_HOTSPOT> — Rule: <RuleKey> — File: `<path/to/file>` — Line: <line>
Summary: <short issue message>
Sort the board by: VULNERABILITY → SECURITY_HOTSPOT → BUG → CODE_SMELL, then by severity.
For each issue (or small, related group of the same SonarQube type), create an approved SPEC SDD in .specs/SPEC-{YYYYMMDD}-{issue-key}-{slug}.md using references/spec-sdd-template.md:
Status: Approved and Type based on the SonarQube type:
BUG → BugfixCODE_SMELL → RefactorVULNERABILITY → SecuritySECURITY_HOTSPOT → Security
Map the SonarQube rule, file, and the type slug (bug, code-smell, vulnerability, security-hotspot).Given...when...then plus "SonarQube no longer reports issue ".SONAR_FIX_TODO_BOARD.md.Mark each generated SPEC as Status: Approved. Do not implement the code in this skill.
/execute-specAfter all SPECs are approved, invoke /execute-spec for each one, in the order of the sorted ToDo Board. The implementation skill will follow the red-green-refactor cycle using the generated SPECs as source of truth.
Update .gitignore
.gitignore at the project root.sonar_devin_auto_fix/**Generate Review Guide
.sonar_devin_auto_fix/SONAR_FIX_REVIEW_NOTES.mdFinal validation
Generate Metrics Dashboard
.sonar_devin_auto_fix/SONAR_FIX_METRICS.htmlThe skill automatically integrates external tools per stack to validate and format the code after fixes.
| Stack | Linter | Command |
|---|---|---|
| Java/Kotlin | Checkstyle, PMD | mvn checkstyle:check pmd:check |
| JavaScript/TypeScript | ESLint | npx eslint@<VERSION> src/ |
| Python | Pylint, Flake8 | python -m pylint src/ |
| C#/.NET | StyleCop, Roslyn Analyzers | dotnet build /p:RunAnalyzersDuringBuild=true |
| Go | golint, golangci-lint | golangci-lint run |
| Ruby | RuboCop | bundle exec rubocop |
| PHP | PHPStan | vendor/bin/phpstan analyse |
| Scala | Scalastyle, Scapegoat | sbt scalastyle scapegoat |
| Stack | Formatter | Command |
|---|---|---|
| Java/Kotlin | Spotless, Google Java Format | mvn spotless:apply |
| JavaScript/TypeScript | Prettier | npx prettier@<VERSION> --write src/ |
| Python | Black, isort | python -m black src/ |
| C#/.NET | dotnet format | dotnet format |
| Go | gofmt, goimports | gofmt -w . |
| Ruby | Rufo | bundle exec rufo |
| PHP | PHP CS Fixer | vendor/bin/php-cs-fixer fix |
| Stack | Tool | Command |
|---|---|---|
| Java/Kotlin | JaCoCo | mvn jacoco:report |
| JavaScript/TypeScript | Istanbul | npx vitest@<VERSION> run --coverage |
| Python | Coverage.py | python -m coverage run -m pytest |
| C#/.NET | OpenCover, Cobertura | dotnet test /p:CollectCoverage=true /p:CoverageFormat=cobertura |
| Go | go test -cover | go test -cover ./... |
| Ruby | SimpleCov | bundle exec rspec --coverage |
| PHP | phpunit --coverage-clover | vendor/bin/phpunit --coverage-clover=coverage.xml |
| Scala | sbt coverage | sbt clean coverage test coverageReport |
The skill may use SonarLint and SonarScanner for local validation before committing:
SonarLint (IDE Integration):
SonarScanner CLI:
sonar-scanner -Dsonar.projectKey=<project> -Dsonar.sources=srcThe skill loads reference scripts for automatic validation per stack:
references/validate-java.sh — Java/Kotlin validation (Checkstyle, PMD, Spotless, JaCoCo)references/validate-js.sh — JavaScript/TypeScript validation (ESLint, Prettier, Vitest)references/validate-python.sh — Python validation (Pylint, Flake8, Black, pytest)references/validate-csharp.sh — C#/.NET validation (Roslyn Analyzers, dotnet format, dotnet test)references/validate-go.sh — Go validation (golangci-lint, gofmt, go test)references/validate-ruby.sh — Ruby validation (RuboCop, Rufo, rspec)references/validate-php.sh — PHP validation (PHPStan, PHP CS Fixer, phpunit)references/validate-scala.sh — Scala validation (Scalastyle, Scapegoat, sbt)The skill generates tests automatically based on stack-specific templates. Load the appropriate template from the references/templates/ folder:
test-java.md — Template for JUnit/Mockito teststest-kotlin.md — Template for KotlinTest/Mockk teststest-python.md — Template for pytest/unittest teststest-javascript.md — Template for Jest/Vitest teststest-typescript.md — Template for TypeScript teststest-csharp.md — Template for xUnit/Moq teststest-go.md — Template for Go teststest-ruby.md — Template for RSpec/Minitest teststest-php.md — Template for PHPUnit teststest-scala.md — Template for ScalaTest/ScalaCheck tests// NOSONAR, // no sonar, # noqa, # pragma: no cover, etc.@IgnoreCoverage, ExcludeFromCodeCoverage, @Suppress, etc.#pragma, etc.sonar-project.properties, sonar-scanner.properties, etc. Also remove other scanners, such as the SonarScanner for Maven usually present in the POM.xml, since our pipeline is autonomous and does not depend on these files to work. (For now, keep only SonarQube-related configurations in .csproj files)..sonar_devin_auto_fix/**Commands are configured to force isolated environments. The isolation prefix is required, but you may add more parameters after it.
Rule: Keep the isolation parameter (e.g. -Dmaven.repo.local=./.m2/repository), but you may add more flags.
# ✅ ALLOWED - Mandatory isolation + additional parameters
mvn -Dmaven.repo.local=./.m2/repository clean test
mvn -Dmaven.repo.local=./.m2/repository -DskipTests=false jacoco:report
mvn -Dmaven.repo.local=./.m2/repository -Dorg.slf4j.simpleLogger.defaultLogLevel=debug clean test
# ❌ NOT ALLOWED - No isolation
mvn clean test
# ✅ ALLOWED - Mandatory isolation + additional flags
gradle --gradle-user-home ./.gradle test
gradle --gradle-user-home ./.gradle test --info
gradle --gradle-user-home ./.gradle clean build -x test
# ❌ NOT ALLOWED - No isolation
gradle test
# npm ✅ ALLOWED
npm install --no-save
npm install --no-save --verbose
npm test -- --coverage --verbose
# yarn ✅ ALLOWED
yarn install --offline
yarn install --offline --verbose
# pnpm ✅ ALLOWED
pnpm install
pnpm install --verbose
# npx ✅ ALLOWED only with pinned versions
npx vitest@<VERSION> run --coverage
npx eslint@<VERSION> src/
# Create venv (if not exists) ✅ ALLOWED
python -m venv .venv
python -m venv .venv --upgrade-deps
# pip with isolation ✅ ALLOWED
python -m pip install -r requirements.txt -q
python -m pip install --target ./.venv/lib -q package-name
python -m pip install --target ./.venv/lib --upgrade package-name
# pytest and coverage ✅ ALLOWED
python -m pytest --cov=src tests/ -v
python -m pytest --cov=src tests/ --cov-report=html
python -m coverage run -m pytest
python -m coverage report --skip-covered
# ✅ ALLOWED
dotnet test
dotnet test /p:CollectCoverage=true /p:CoverageFormat=cobertura
dotnet test /p:CollectCoverage=true /p:Exclude="[*Tests]*"
# ✅ ALLOWED
go test -cover ./...
go test -cover ./... -v
go test -coverprofile=coverage.out ./... -timeout=10m
# ✅ ALLOWED
bundle install --local
bundle install --local --no-deployment
bundle exec rspec --coverage
bundle exec rspec --coverage -f progress
# ✅ ALLOWED
composer install --no-dev
composer install --no-dev --optimize-autoloader
composer install --no-dev --classmap-authoritative
vendor/bin/phpunit --coverage-clover=coverage.xml
vendor/bin/phpunit --coverage-clover=coverage.xml -v
# ✅ ALLOWED
sbt clean coverage test coverageReport
sbt clean coverage test coverageReport -Dconfig=test
sbt "test -- -Dverbose=true"
When finishing all fixes, run:
git status
Analyze the output and:
.gitignoregit restore --staged <file>.sonar_devin_auto_fix/ does not appear as staged⚠️ Do not commit. Leave the repository clean and organized so the human developer can review and decide what to commit.
If the user asks to remove isolated environments after completion, list the paths first and ask for explicit confirmation before deleting anything. Do not run rm -rf or find -exec rm -rf without consent.
# List what would be removed (do not delete automatically)
echo "The following paths could be removed: .venv .m2 node_modules .npm __pycache__ .pytest_cache"
# Ask the user to confirm before proceeding. Prefer `git clean` for tracked artifacts.
Important: Verify that the isolated environments are in .gitignore:
# Check if already in .gitignore
grep -E "^\.venv$|^\.m2$|^node_modules$|^__pycache__$" .gitignore
# If not found, add them:
echo ".venv" >> .gitignore
echo ".m2" >> .gitignore
echo "node_modules" >> .gitignore
echo ".pytest_cache" >> .gitignore
echo "__pycache__" >> .gitignore
sonarqube_issues.json. Do not refactor without need, do not improve, do not add features, do not reorganize code that is not directly related to the issue.NO COVERAGE EXCLUSIONS
No coverage exclusion may be used to bypass the lack of tests.
No exceptions:
// NOSONAR, // no sonar, # noqa, # pragma: no cover@IgnoreCoverage, ExcludeFromCodeCoverage, @Suppress#pragma for exclusions| Mistake | Consequence | How to avoid |
|---|---|---|
| Add coverage exclusions | Code without tests approved | Implement tests for all modified lines |
| Fix issues without tests | Undetected regressions | Always add unit tests for each fix |
| Change business logic without need | Bug risk | Stay within the scope of the SonarQube issue |
| Do not run linters after fixing | New violations introduced | Run stack linters after each fix |
| Do not clean environment at the end | Temporary files in repo | Run environment cleanup when finishing |
| Print environment variable values | Security violation | NEVER read or print tokens, use variables directly in commands |
Even simple code can have bugs. TDD applies to any fix, regardless of complexity.
Coverage exclusions violate the quality principle. If the code is too complex to test, refactor it.
SonarQube can have false positives, but most issues are valid. Fix them and discuss legitimate cases with the team.
Bulk fixes without tests drastically increase the risk of regressions. Fix one issue at a time with tests.
Local validation saves time and avoids pipeline rejections. Use the sonar-local-scan.sh script.
This skill follows the agent catalog standards:
license: MIT, metadata.version, metadata.author, tripartite description with explicit Do NOT use for clausefeature/{agent}-{YYYYMMDD}-{short-description}develop, PR target is develop (not main)This skill was created following patterns from obra/superpowers/skills/writing-skills and adapted for SonarQube auto-fix workflows across multiple stacks.