quality is one fast, predictable code-quality workflow for repositories that
contain Rust, Swift, Android/Kotlin, Python, JavaScript, and Astro projects. It does not replace the
ecosystem's best analyzers. It detects, runs, and explains them through one CLI.
Website and documentation: https://quality.santi020k.com
Documentation · GitHub Action · Compatibility · Releases · Changelog · Issues · Contributing
Status:
1.xstable. Public CLI, configuration, report, and Action contracts follow the documented compatibility policy for this major release.
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: santi020k/quality@v1.3.0
with:
version: v1.3.0
changed-only: true
report-level: warning
fail-level: warningThe Action verifies the downloaded release checksum, adds pull-request annotations, writes a job summary, and produces SARIF for GitHub code scanning.
Reusable pnpm projects can also call
.github/workflows/reusable-pnpm-ci.yml for frozen installs, build or test commands,
optional task-output and Playwright browser caching, and failure artifacts. Individual jobs can use
santi020k/quality/actions/setup-pnpm@<full-commit-sha> to share setup while keeping deployment
credentials, migrations and smoke checks project-owned. Pin shared automation to a
reviewed full commit SHA.
$ quality init
Created quality.yml
Next: quality doctor && quality check
$ quality doctor
Project: /work/mobile-app
Config: quality.yml
✓ SwiftLint swiftlint
✓ SwiftFormat swiftformat
✓ Android Lint /work/mobile-app/gradlew
✓ detekt detekt
✓ ktlint ktlint
$ quality check
✓ SwiftLint 0.42s
✓ SwiftFormat 0.18s
✓ Android Lint 5.31s
✓ detekt 1.24s
✓ ktlint 0.39s
Quality checks passed (5 tools).Checks run concurrently by default. Use --fail-fast when a quick first
failure is more useful than the complete report.
Bound resource use with --jobs, configure per-adapter timeout_seconds, or
override all timeouts with --timeout-seconds. Each analyzer retains at most
1 MiB of combined output by default; change it with --max-output-bytes.
CI can use --require-checks to prevent an empty policy from passing while
changed-file runs may still skip every configured adapter when no input applies.
cargo install --path crates/quality-cliUnix users can install a checksum-verified native binary without Rust:
curl --proto '=https' --tlsv1.2 -fsSL \
https://raw.githubusercontent.com/santi020k/quality/main/install.sh \
| sh -s -- santi020k/quality v1.3.0Omit the version to install the latest release. Native archives are published for Intel and Apple Silicon macOS, x86-64 and ARM64 Linux, and x86-64 Windows.
Then run these commands from any repository:
quality init # Write an explicit policy based on detected files
quality init --dry-run # Preview adoption without writing quality.yml
quality init --gate fast # Prefer the repository's fast local gate
quality init --gate full # Prefer the repository's complete gate
quality preset list # Compare built-in setup profiles
quality preset apply recommended --dry-run # Preview language configs and dependencies
quality preset apply recommended # Generate configs without overwriting existing files
quality preset apply strict --install # Generate strict configs and install pinned JS tools
quality doctor # Explain what is enabled, installed, or missing
quality check # Run applicable linters concurrently
quality check --format agent # Emit compact Markdown for an AI coding agent
quality --root ~/Projects repositories audit # Audit a folder of repositories
quality --root ~/Projects repositories audit --fail-on invalid,missing-configuration # Enforce audit findings in CI
quality --root ~/Projects repositories apply # Configure missing repositories
quality format # Run applicable formatters
quality format --check # Check formatting without modifying files
quality fix # Apply fixes supported by the configured tools
quality baseline create # Record existing findings and block new regressions
quality completions zsh # Generate native shell completions
quality instructions --format agents # Print a section for a repository AGENTS.md
quality ci github --install '…' # Generate a runnable GitHub Actions workflow
quality ci plan # Compare PR workflow steps with the local pre-push gate
quality ci local # Run and time the local pre-push gate
quality hooks install # Install the Git hooks declared in quality.yml
quality hooks status # Verify that every configured hook is installedFor quick local feedback, scope checks, formatting, or fixes to Git changes:
quality check --changed # Staged, unstaged, and untracked files
quality check --changed origin/main # Branch changes plus local changes
quality format --changed
quality fix --changedFile-capable tools receive only relevant changed files. Project analyzers such as Android Lint still run at project scope when Android files change. Changing a rules or configuration file—including deleting one—triggers the corresponding full check. Deleted source paths can trigger project-wide checks but are never passed to file-scoped tools.
Select adapters by ID for focused local or CI runs. Flags can be repeated or
receive comma-separated IDs, and work with check, format, and fix:
quality check --only eslint,astro-check
quality check --exclude cargo-clippy
quality fix --changed --only eslintSelection details are retained in JSON and SARIF reports.
Every command accepts --root PATH. Check results support pretty, agent,
json, sarif, and github output. The agent format emits compact, bounded
Markdown with file-grouped findings, environment failures, and focused rerun
commands. The GitHub format emits native workflow commands
that become inline annotations on pull requests:
quality doctor --format agent
quality check --format agent
quality check --format githubWrite SARIF while keeping readable terminal or GitHub output with --report:
quality check --report quality.sarif
quality check --format github --report artifacts/quality.sarif| Ecosystem | Analyzer | Check | Format/fix |
|---|---|---|---|
| Rust | Cargo fmt | yes | yes |
| Rust | Clippy | yes | — |
| Swift | SwiftLint | yes | fix |
| Swift | SwiftFormat | yes | yes |
| Android | Android Lint | yes | — |
| Kotlin | detekt | yes | — |
| Kotlin | ktlint | yes | yes |
| JavaScript/TypeScript | ESLint | yes | fix |
| Astro | Astro Check | yes | — |
| JavaScript/TypeScript | Prettier | yes | yes |
| Content | CSpell | yes | — |
| Content | Codespell | yes | fix |
| Content | Typos | yes | fix |
| JavaScript/TypeScript | Knip | yes | — |
| GitHub Actions | Actionlint | yes | — |
| Web metadata | @santi020k/og |
yes | — |
Presets can bootstrap the analyzer configuration that quality runs. They are
explicit generators: the resulting files and pinned dependency command remain
visible in the repository, and no preset logic participates in the checking
path.
quality preset list
quality preset show recommended
quality preset apply recommended --dry-run
quality preset apply recommended
quality preset diff
quality preset update --dry-run
quality preset setupminimal installs the essential ecosystem checks, recommended adds balanced
formatting, spelling, and unused-code policy, and strict tightens thresholds
and promotes warnings where the underlying analyzer supports it. JavaScript
presets use @santi020k/eslint-config-basic: minimal selects its basic
preset, recommended uses its recommended severity mode, and strict selects
pedantic mode.
Generation supports JavaScript/TypeScript/Astro, Python, Rust, Swift,
Kotlin/Android, and GitHub Actions. Limit an application with --only, preview
all proposed contents with --dry-run, or explicitly replace differing
generated targets with --force:
quality preset apply strict --only rust,github-actions
quality preset apply minimal --only javascriptJavaScript dependencies are pinned in the displayed install command. Pass
--install to run that command with the package manager declared by the root
project. Explicit framework packs are selected for detected Angular, Astro,
Expo, Hono, Lit, Nest, Next, Nuxt, Preact, Qwik, React, React Router, Slidev,
Solid, Svelte, TanStack Start, Vite, and Vue projects.
Each application records its catalog version, profile, ecosystems, managed
file fingerprints, and dependency pins in .quality-preset.json. Use
quality preset diff to detect catalog updates, dependency drift, or edited
files, then quality preset update --dry-run and quality preset update to
refresh untouched generated output. quality doctor reports current,
update-available, and incompatible preset states.
Preset updates merge tool policy into quality.yml without removing existing
tasks, hooks, or custom adapters. Kotlin rules use a marked managed block in
.editorconfig, leaving unrelated editor settings intact. Whole generated
files are replaced only while their recorded fingerprint proves they were not
edited, unless --force is explicitly supplied.
Run quality preset setup for platform-aware Python, Rust, Swift, Kotlin,
Android, spelling, and Actionlint setup guidance. Add --install to execute
supported commands.
Presets select one spelling adapter: CSpell for JavaScript repositories,
Codespell for Python repositories, and Typos for other recommended or strict
native-language repositories. Explicit quality.yml configuration can enable
a different combination.
The adapters use repository-local executables where that is conventional:
./gradlew for Android and node_modules/.bin for JavaScript. Other tools are
resolved from PATH or can be overridden in quality.yml.
Add an organization-specific or emerging analyzer without changing quality:
version: 1
output: pretty
baseline: .quality-baseline.json
tools: {}
custom:
acme-lint:
name: ACME Lint
command: ./tools/acme-lint
extensions: [swift, kt]
config_files: [.acme-lint.yml]
check_args: [scan]
format_check_args: [format, --check]
format_args: [format]
fix_args: [fix]
file_mode: append
parser: genericWith file_mode: append, changed source paths are appended to the configured
arguments. Use project for analyzers that must always inspect the whole
project. Supported parsers are generic, codespell, eslint-json,
swiftlint-json, ktlint-json, santi-og-json, and typos-json. Generic
diagnostics use the familiar format:
path/to/file:line:column: warning: Message (rule-id)
External adapters participate in doctor, concurrent execution, changed-file
filtering, JSON/SARIF reports, GitHub annotations, and baselines. Commands are
executed directly without a shell, so arguments remain explicit and portable.
When a JavaScript workspace declares @santi020k/og, the built-in santi-og
adapter runs its deterministic check --json command. Missing or stale social
images become normalized diagnostics; generation remains an explicit
santi-og generate operation that never runs as part of quality check.
Run only this adapter with:
quality check --only santi-ogSee the @santi020k/og package guide for
generation, caching, and built-site auditing.
quality init enables a tool only when the repository shows intent to use it,
such as an analyzer configuration, dependency, or package script. Merely
containing JavaScript or Swift files does not opt a repository into ESLint,
Prettier, SwiftLint, or SwiftFormat.
Use quality init --dry-run to review the complete generated policy before
writing or replacing quality.yml.
When the root package defines verify:quality, verify, validate, check,
pre-push, or prepush, initialization preserves the first matching script as a
repository-check task. Direct analyzer checks are disabled to avoid running
the same work twice, while their format and fix operations remain available:
version: 1
output: pretty
tools:
swiftlint:
enabled: true
check: false
required: true
tasks:
repository-check:
name: Repository check (verify)
command: pnpm
args: [run, verify]
required: trueIf no composite gate exists, a root typecheck or type-check script is
imported as a change-aware typecheck task. This preserves Turborepo and
workspace-specific TypeScript semantics instead of replacing them with a raw
root tsc invocation.
Set check: false to keep an adapter available to quality format and
quality fix without also running it during quality check. Each adapter also
accepts command, check_args, format_args, and fix_args. Set
working_directory when a tool belongs to one workspace in a monorepo. This
provides an escape hatch for Gradle tasks, monorepo wrappers, and teams that pin
tools in a custom directory:
version: 1
output: pretty
tools:
detekt:
enabled: true
required: true
working_directory: apps/android
command: ./gradlew
check_args: [detekt]
ktlint:
enabled: falseSet required: false to keep a locally optional tool from failing the run.
Repository-defined tasks preserve canonical gates such as type-checking,
package validation, tests, or builds. Tasks run during quality check, support
workspace directories, and can be skipped in changed-file mode when their
configured extensions and files are unaffected:
tasks:
typecheck:
name: TypeScript
command: pnpm
args: [run, typecheck]
extensions: [ts, tsx, astro]
config_files: [package.json, tsconfig.json, pnpm-lock.yaml]For an existing repository with many findings, record the current state once:
quality baseline create
git add .quality-baseline.json quality.ymlAfter that, quality check suppresses matching existing findings and fails for
new ones. Fingerprints deliberately exclude line and column numbers, so moving
code does not create noise. Duplicate occurrences are counted, meaning a new
copy of an existing violation is still reported. Missing tools, crashes, and
unstructured execution failures can never be baselined.
Refresh intentionally after paying down findings:
quality baseline create --forceGenerate completions for Bash, Zsh, Fish, PowerShell, or Elvish. For example:
mkdir -p ~/.config/fish/completions
quality completions fish > ~/.config/fish/completions/quality.fishThe release workflow builds native archives for Linux, Apple Silicon and Intel
macOS, and Windows whenever a version tag such as v1.3.0 is pushed.
Workflow generation requires an explicit installation command, preventing the generated CI from assuming a crate or repository that does not exist. It selects macOS for Swift repositories and Linux otherwise, then derives package manager setup, dependency installation, and relevant native toolchain setup from repository files, including Actionlint when its use is detected:
quality ci github --install \
'cargo install --git https://github.com/your-org/quality --tag v1.3.0 --locked'Run the configured pre-push gate before spending a GitHub-hosted runner:
quality ci plan
quality ci plan --strict
quality ci local
quality ci local --step 2
quality ci local --hook pre-commitci plan inventories pull-request workflows and marks exact local-command
matches as covered, uses: actions and GitHub expressions as GitHub-only, and
plain run: commands missing from the selected hook as uncovered. ci local
runs hook steps in order, reports wall time for every step, retains bounded
failure output, and prints a focused rerun command. Git hooks use the same timed
runner automatically. quality init and presets import existing pre-commit,
precommit, pre-push, or prepush package scripts without replacing a hook
already present in quality.yml. Wrapper steps can declare exact workflow
commands under covers so the planner records intentional equivalence without
guessing from script names.
The latest 20 metadata-only runs are retained under .git/quality/local-ci/;
output is omitted from automatic history. Pass --report PATH when a complete,
versioned JSON report is needed. That explicit report can contain command
output and should not be committed when checks may print sensitive data.
Local execution is an early feedback gate, not proof of the GitHub environment. Hosted actions, secrets, permissions, services, deployments, releases, and the authoritative check for the exact pushed commit remain in GitHub Actions.
The stable core is deliberately small:
- detect project ecosystems;
- resolve native tools reproducibly;
- execute independent checks concurrently;
- normalize diagnostics and exit behavior;
- integrate with CI through SARIF.
Future adapters can implement a documented plugin protocol. AI integrations
can consume the same normalized diagnostics through --format agent to explain
or propose fixes, without putting AI inside the deterministic checking path.
The repository keeps the Rust CLI and its website/documentation together:
quality/
├── crates/quality-cli/ # Rust binary
├── apps/site/ # Astro + Starlight website and docs
├── Cargo.toml # Cargo workspace
├── pnpm-workspace.yaml
└── turbo.json
Install workspace dependencies and use the shared commands:
pnpm install
pnpm dev # Start the documentation site
pnpm check # Rust and web checks
pnpm test # Automated tests plus the disposable playground workflow
pnpm build # Release CLI and production site
pnpm run ci # Affected-only pipeline used by GitHub ActionsCargo remains available directly for Rust-only work. Turborepo coordinates Cargo and Astro, caches deterministic tasks, and scopes CI to affected projects.
The repository includes a disposable playground with mock analyzers, so CLI features can be exercised without installing Swift, Android, or JavaScript tooling. It requires the same Rust, Git, and POSIX shell tools used for local development:
pnpm playground:setup
pnpm playground -- doctor
pnpm playground -- check
pnpm playground -- fix
pnpm playground -- format --check
pnpm playground -- formatThe first check and format --check intentionally fail to demonstrate
diagnostics. The sandbox is a standalone Git repository, so changed-file mode,
baselines, JSON output, and SARIF reports work as they would in a real project.
See playground/README.md for the complete walkthrough.
Run pnpm playground:verify to create a temporary sandbox and verify the whole
playground workflow automatically.
MIT. See LICENSE.