Style checker with Rust syntax and semantic analysis, first-batch Swift checks, and a safe auto-fixer for deterministic code layout.
vibe-style enforces a strict Rust style contract with stable rule IDs (RUST-STYLE-*).
It also includes a conservative first batch of read-only Swift checks with stable
SWIFT-STYLE-* rule IDs.
It supports:
curate: check and report violations.tune: apply safe automatic fixes, then re-check.coverage: print implemented rule IDs.
The checker implementation is the source of truth for parser- and AST-level edge cases.
Methods are listed from easiest to most advanced.
VERSION="$(curl -fsSL https://api.github.com/repos/hack-ink/vibe-style/releases/latest | grep -oE '"tag_name": "v[^"]+"' | cut -d'"' -f4)"
OS="$(uname -s)"
ARCH="$(uname -m)"
case "${OS}:${ARCH}" in
Linux:x86_64) TARGET="x86_64-unknown-linux-gnu" ;;
Darwin:arm64) TARGET="aarch64-apple-darwin" ;;
*) echo "Unsupported platform: ${OS}/${ARCH}" >&2; exit 1 ;;
esac
ASSET="vibe-style-${TARGET}-${VERSION}.tgz"
curl -fsSLO "https://github.com/hack-ink/vibe-style/releases/download/${VERSION}/${ASSET}"
tar -xzf "${ASSET}"
INSTALL_DIR="$HOME/.cargo/bin"
mkdir -p "${INSTALL_DIR}"
install -m 0755 "vibe-style-${TARGET}-${VERSION}/vstyle" "${INSTALL_DIR}/vstyle"
install -m 0755 "vibe-style-${TARGET}-${VERSION}/cargo-vstyle" "${INSTALL_DIR}/cargo-vstyle"$Repo = "hack-ink/vibe-style"
$Version = (Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases/latest").tag_name
$Target = "x86_64-pc-windows-msvc"
$Asset = "vibe-style-$Target-$Version.zip"
Invoke-WebRequest -Uri "https://github.com/$Repo/releases/download/$Version/$Asset" -OutFile $Asset
Expand-Archive -Path $Asset -DestinationPath .
$InstallDir = "$env:USERPROFILE\.cargo\bin"
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
Copy-Item "vibe-style-$Target-$Version\vstyle.exe" "$InstallDir\vstyle.exe" -Force
Copy-Item "vibe-style-$Target-$Version\cargo-vstyle.exe" "$InstallDir\cargo-vstyle.exe" -Force
setx PATH "$env:PATH;$InstallDir"Open a new terminal after running setx.
Supported prebuilt targets:
x86_64-unknown-linux-gnuaarch64-apple-darwinx86_64-pc-windows-msvc
Use the composite action to install a prebuilt release and run a read-only style check:
- uses: actions/checkout@v6
- uses: hack-ink/vibe-style@v1
with:
language: rust
workspace: true
args: --all-featuresThe action runs vstyle curate --language <language>, adds --workspace when
workspace: true, and appends args. Use language: swift for Swift checks, and use
version: v0.2.3 when CI should pin a specific vibe-style release. Use
version: checkout only when the workflow should build vibe-style from the action
checkout, such as this repository's own local uses: ./ workflow.
# Install both binaries (`vstyle` and `cargo-vstyle`).
cargo install vibe-styleAfter installation, you can use both vstyle ... and cargo vstyle ....
# Optional: install cargo-binstall once.
cargo install cargo-binstall
# Then install prebuilt binaries for this crate.
cargo binstall vibe-stylegit clone https://github.com/hack-ink/vibe-style
cd vibe-style
cargo build --releaseBinaries:
target/release/vstyletarget/release/cargo-vstyle
cargo install --path . --bin cargo-vstyleAfter installation, you can run cargo vstyle ....
curate and tune require an explicit --language.
# Check style.
vstyle curate --language rust
# Apply safe fixes, then re-check.
vstyle tune --language rust
# Same as tune, but fail if violations remain.
vstyle tune --language rust --strict
# Include verbose cache diagnostics in addition to tune progress.
vstyle tune --language rust --verbose
# Print implemented rule IDs.
vstyle coveragetune prints progress telemetry to stderr for the initial scan, each fix round, scoped
fix batches, semantic validation, and the final scan when fixes were applied. This
output is emitted even when stderr is redirected so long-running workspace repairs
remain observable in logs.
# Workspace-wide.
vstyle curate --language rust --workspace
# Swift workspace-wide.
vstyle curate --language swift --workspace
# Selected packages.
vstyle tune --language rust -p api -p db-service
# Feature flags.
vstyle tune --language rust -p api --features serde,tracing
vstyle tune --language rust -p api --all-features --no-default-featurescurate- Exit
0: no violations. - Exit
1: violations found.
- Exit
tune- Exit
0: even if unresolved violations remain. - Exit
1: unresolved violations remain and--strictis used.
- Exit
Use --language rust to check Rust files and --language swift to check Swift files.
File discovery scans every selected *.rs or *.swift file that is not matched by Git ignore
rules inside that package scope. Git tracking state is not part of file discovery. With
--workspace, Rust files are selected from workspace package roots and Swift files are selected
from the Cargo workspace root.
CI runs the checked-out action for Rust read-only style verification to keep feedback fast and
deterministic. Use vstyle tune locally when you want to apply safe automatic fixes (for example,
via cargo make lint).
Release-performance acceptance is based on the locally built vstyle binary, not on an installed
cargo-vstyle subcommand and not on debug-profile timings.
Use the checked-in harness:
cargo make bench-release-vstyleBy default the harness builds the shipping final-release profile from Cargo.toml and runs both
vstyle curate --language rust --workspace and
vstyle tune --language rust --workspace --verbose inside a disposable Git
worktree at the current commit. This keeps tune from rewriting the primary checkout while still
preserving the Git ignore boundary used for file discovery.
Treat the checked-in self-host benchmark as a release-path regression guard, not as a universal
microbenchmark for every hotspot. On the current workspace it is usually a no-op tune; if
--verbose reports Semantic cache: 0 hit(s), 0 miss(es), that run did not enter semantic
validation and should not be used to judge semantic-path changes in src/style/semantic.rs.
Use a semantic-positive workload before drawing conclusions about semantic validation performance.
Historical benchmark baseline artifacts are not kept in this repository. Use fresh local runs or
the non-blocking Benchmarks workflow artifacts when benchmark evidence matters.
To compare the plain release profile diagnostically:
VSTYLE_BENCH_PROFILE=release cargo make bench-release-vstylecargo make lint-vstyle remains the repo-native style gate, but it is not the release benchmark
source of truth because it routes through language-specific cargo vstyle curate tasks and can
resolve to an installed subcommand outside the locally built binary under test.
Use the semantic-specific harness when a change targets src/style/semantic.rs or semantic
validation fallback behavior:
cargo make bench-semantic-vstyleThis harness builds the local release binary once, creates a disposable Git fixture crate
based on the tests/let_mut_reorder.rs semantic-validation shape, generates a local Cargo.lock,
and runs vstyle tune --language rust --verbose twice:
- a cold run after clearing
target/vstyle-cache/semantic - a warm rerun after restoring the original fixture sources while keeping the cache directory
Use this semantic benchmark to judge XY-95-style work; do not compare semantic-path changes only
against the self-host no-op benchmark above.
Historical semantic benchmark artifacts are not kept in this repository. Use fresh local runs or
the non-blocking Benchmarks workflow artifacts when semantic evidence matters.
The repository also tracks both benchmark harnesses through a non-blocking GitHub Actions workflow.
Use the Benchmarks workflow for periodic project-level tracking, scheduled baseline refreshes, and
manual reruns when you want artifact-backed evidence without turning performance into a PR gate.
Use direct current-worktree timings first when a local rule change makes the repository's own
sources newly fixable. The checked-in bench-release-vstyle harness builds the current binary but
benchmarks a detached HEAD worktree, so self-host drift in uncommitted files must be fixed and
committed before the harness becomes authoritative again.
Use the release benchmark for general workspace-scan, fix-engine, import, module, spacing, or
quality-path changes. Use the semantic benchmark for src/style/semantic.rs, semantic cache key
changes, or semantic-validation fallback changes. Run both when a change touches both lanes.
The operational runbook for selecting the right benchmark evidence lives in
docs/runbook/benchmark_tracking.md.
There is currently no user configuration file. Rules are built into the checker.
VSTYLE_MAX_IMPORT_SUGGESTION_ROUNDS- Controls how many semantic missing-import suggestion rounds
vstyle tunewill perform. - Default:
2. - Increasing this may fix more missing-import cases but will run additional
cargo check --message-format=jsonrounds.
- Controls how many semantic missing-import suggestion rounds
--verboseprints semantic cache hit/miss statistics for each command.- Cache files are written under
target/vstyle-cache/semantic/and keyed by:- vstyle version metadata,
rustc -Vvoutput,Cargo.lockhash,- selected cargo options,
- selected
*.rsstyle file fingerprints.
RUST-STYLE-FILE-001: Do not usemod.rs; use flat module files.
RUST-STYLE-MOD-001: Keep top-level item order asmod,use,macro_rules!,type,const,static,trait,enum,struct,impl,fn.RUST-STYLE-MOD-002: Placepubitems before non-pubitems within the same kind. Visibility boundaries define separate batches and must be separated by exactly one blank line.RUST-STYLE-MOD-003: Place non-asyncfunctions beforeasyncfunctions at the same visibility.RUST-STYLE-MOD-004: Do not document modules with outer doc comments on themoddeclaration; place module docs inside the module with//!.RUST-STYLE-MOD-005: Keep each type adjacent to relatedimplblocks, with no blank line between the type and its firstimpl.RUST-STYLE-MOD-007: In#[cfg(test)] mod tests, remove unuseduse super::*;keep-alive imports duringtune.
RUST-STYLE-SERDE-001: Do not use#[serde(default)]onOption<T>fields.
RUST-STYLE-IMPORT-001: Group imports in this order: standard library, third-party, self/workspace/local-module roots.RUST-STYLE-IMPORT-002: Use exactly one blank line between groups; do not use import-group header comments; normalizeuse a::{b, b::c}touse a::{b::{self, c}}.RUST-STYLE-IMPORT-003: Do not alias imports, exceptas _keep-alive imports. Trait imports used only for method resolution must useas _.RUST-STYLE-IMPORT-004: Do not import free functions or macros into scope; use qualified paths. If imported symbols are ambiguous, use fully qualified paths.RUST-STYLE-IMPORT-005: Inerror.rs, do not adduseimports.RUST-STYLE-IMPORT-006: Keepuseitems only at file top level or module top level.RUST-STYLE-IMPORT-007: Do not use glob imports (use ...::*or equivalent). Use explicit imports only.RUST-STYLE-IMPORT-008: For non-function, non-macro symbols in type paths and#[derive(...)]attributes, prefer unqualified usage withuseimports when unambiguous; keep fully qualified paths when ambiguous.RUST-STYLE-IMPORT-009: If a symbol is both imported and also used via other qualified type paths, stop importing that symbol and use fully qualified paths consistently.RUST-STYLE-IMPORT-010: Do not usesuperorselfimport prefixes. Rewritesuperimports to crate-absolute imports (use crate::...) when module depth allows it, and rewriteself::...imports to direct module paths.RUST-STYLE-IMPORT-011: Order#[derive(...)]entries like imports:std/core/allocfirst, then third-party derives, then workspace derives; alphabetize within each group.RUST-STYLE-IMPORT-012: Do not add crate keep-alive importsuse dep as _;unless another path in the same package uses that crate.
RUST-STYLE-IMPL-001: UseSelfinstead of concrete type names inimplmethod signatures.RUST-STYLE-IMPL-003: Keepimplblocks contiguous and ordered as inherent, standard-library traits, third-party traits, then workspace-member traits.RUST-STYLE-GENERICS-001: Move trait bounds towhere; do not use inline bounds.RUST-STYLE-GENERICS-002: Remove unnecessary turbofish when the type is already explicit in aletbinding.RUST-STYLE-GENERICS-003: Canonicalize turbofish paths toType::<Args>::Assocform.RUST-STYLE-TYPE-001: Do not add type aliases that are only pure renames.RUST-STYLE-LET-001: Place immutableletbindings before mutable ones when the reorder is semantically safe.
RUST-STYLE-LOG-002: Use structured logging fields and complete-sentence log messages.RUST-STYLE-RUNTIME-001: Do not useunwrap()in non-test code.RUST-STYLE-RUNTIME-002:expect()must use a clear, user-actionable string literal message.
RUST-STYLE-NUM-001: Separate numeric literal suffixes with an underscore (for example,10_f32).RUST-STYLE-NUM-002: Use underscore grouping for integers with more than three digits.
RUST-STYLE-READ-002: Keep functions at or under 120 lines.RUST-STYLE-SPACE-003: Do not insert blank lines within the same statement type. Use exactly one blank line between different statement types. Keep constant declaration groups compact only within the same visibility batch.RUST-STYLE-SPACE-004: Insert exactly one blank line before eachreturnand before final tail expressions unless the body is a single expression.
RUST-STYLE-TEST-001: Use descriptivesnake_casetest names.RUST-STYLE-TEST-002: Reserve#[cfg(test)] mod _testfor keep-alive imports only.
SWIFT-STYLE-FILE-001: Do not usemod.swift; use flat Swift entry files.SWIFT-STYLE-IMPORT-004: Do not import individual Swift symbols; import modules instead.SWIFT-STYLE-TYPE-001: Do not addtypealiasdeclarations that are only pure renames.SWIFT-STYLE-RUNTIME-001: Do not use force unwraps, force casts, ortry!in non-test Swift code.SWIFT-STYLE-NUM-002: Use underscore grouping for integers with more than three digits.SWIFT-STYLE-READ-002: Keep functions at or under 120 lines.
The governing Swift applicability map lives in docs/spec/swift_style_rule_applicability.md.
This repository uses cargo make tasks from Makefile.toml.
# Format.
cargo make fmt
cargo make fmt-check
# Full read-only verification.
cargo make check
# Rust-only clippy check.
cargo make check-rust
# vibe-style read-only check.
cargo make check-vstyle
# Apply lint fixes (clippy + vibe-style).
cargo make lint
# Apply vibe-style fixes.
cargo make lint-vstyle
# Rust tests.
cargo make test-rustDurable repository docs start at docs/index.md.
Documentation placement and naming rules live in docs/policy.md.
Licensed under GPL-3.0.