MCPcopy Index your code
hub / github.com/asamarts/alint

github.com/asamarts/alint @v0.13.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.13.0 ↗ · + Follow
3,644 symbols 11,783 edges 259 files 615 documented · 17%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

alint

Crates.io CI License

Fast, language-agnostic linter for repository structure, files, and content. Declare the shape your repo should have (required files, filename conventions, content patterns, values inside package.json / Cargo.toml / GitHub workflows, cross-file relationships) in a single .alint.yml. alint enforces it.

  • Fast at scale. ~1.1 s on a 100K-file workspace bundle, ~12 s at 1M files. Public benchmarks per release.
  • 🤖 Agent-aware. First-class agent output format with per-violation agent_instruction strings; bundled agent-hygiene and agent-context rulesets for AI-touched repos.
  • 🧰 Powerful + extensible. 89 rule kinds across 13 families, 22 bundled ecosystem rulesets, 12 auto-fix ops, 8 output formats, structured-query rules with full RFC 9535 JSONPath, cross-file relational rules, conditional when: gates over per-run facts, and extends: composition with SRI-pinned URLs.
  • 📦 One static Rust binary. Any language, any repo. No plugin install, no Node/JVM/Python runtime needed.

Working .alint.yml configs for 30 OSS repos (single-language workspaces, polyglot monorepos, scale stress-tests) live under examples/, each with a writeup of what alint catches that the repo's existing tooling misses.

60-second quickstart

# Install (Linux + macOS + Windows tarballs):
curl -sSL https://raw.githubusercontent.com/asamarts/alint/main/install.sh | bash

# Initialise a config in the current repo (uses bundled oss-baseline + auto-detected ecosystem rulesets):
cat > .alint.yml <<'YAML'
version: 1
extends:
  - alint://bundled/oss-baseline@v1
  - alint://bundled/rust@v1                  # auto-skips when not a Rust repo
  - alint://bundled/ci/github-actions@v1
YAML

# Check:
alint check

# Auto-fix what's mechanically fixable (preview first):
alint fix --dry-run
alint fix

Bundled rulesets are gated by ecosystem facts (has_rust, has_node, has_python, …), so listing one for an ecosystem you don't have is a silent no-op. See docs/rules.md for the full rule catalogue and alint.org for narrative docs.

Core capabilities

  • 89 rule kinds across 13 families: existence, content, naming, structured query (RFC 9535 JSONPath over JSON/YAML/TOML/XML), text hygiene, security/unicode, encoding, structure, portable metadata, Unix metadata, git hygiene, cross-file relations, plugin (command shellout). Full reference: docs/rules.md.
  • 22 bundled rulesets: oss-baseline (a strict superset of Repolinter's default ruleset for users migrating from that tool, archived 2026-02), language sets (rust, node, python, go, java, dotnet, php), ci/github-actions, monorepo overlays (cargo-workspace, pnpm-workspace, yarn-workspace), hygiene (no-tracked-artifacts, lockfiles), tooling (editorconfig), docs (adr), compliance (reuse, apache-2), apache/governance (Apache TLP governance discipline), agent (hygiene, context). Built into the binary, no network round-trip; ecosystem-gated, so listing one for an absent ecosystem is a silent no-op.
  • Auto-fix: 12 ops covering content edits (whitespace, newlines, line endings, BOM/bidi/zero-width strip, blank-line collapse) and path ops (create/remove/rename/prepend/append). Preview with alint fix --dry-run. Configurable fix_size_limit (default 1 MiB) skips oversize files rather than rewriting them.
  • Conditional rules: a bounded when: expression language (boolean logic, comparisons, matches, in) gates rules on facts evaluated once per run (any_file_exists, all_files_exist, count_files).
  • Composition: extends: pulls in other configs by local path, HTTPS URL (SRI-pinned), or alint://bundled/<name>@<rev>. Children override field-by-field. Monorepos can opt into nested_configs: true for auto-discovered subtree-scoped .alint.yml files.
  • 10 subcommands: check (default; supports --changed for PR-fast-path linting), fix, init (auto-detect ecosystem + scaffold), validate-config (parse-only; for editor LSP / pre-commit / fail-fast CI), explain <rule>, list, suggest (scan for antipatterns and propose rules), facts (debug when: clauses), export-agents-md (sync AGENTS.md from active rules), lsp (language server over stdio for editor integrations).
  • 8 output formats: human, json (stable schema), sarif (GitHub Code Scanning), github (inline PR annotations), markdown (PR comments), junit (CI test reports), gitlab (Code Quality), agent (LLM-shaped JSON with agent_instruction per violation).
  • JSON Schemas: config at schemas/v1/config.json for editor autocomplete; report shapes at schemas/v1/check-report.json and schemas/v1/fix-report.json for downstream tooling.
  • Telemetry-free. No network access at runtime, except the user-explicit extends: https://... URLs (SRI-pinned). Reproducible builds (Cargo.lock committed, pinned toolchain). See SECURITY.md for the threat model.
  • Official GitHub Action: asamarts/alint@v0.13.0.

Where alint shines

alint isn't trying to be everything to everyone. The validation pass across 30 OSS repos surfaced five distinct shapes of project where alint earns its keep:

  1. Repos with verify-script sprawl. "Replaces the structural subset of N hand-rolled validation scripts." Best fit: kubernetes (50 verify scripts → 17 declarative rules), apache/airflow (109 pre-commit hooks → ~40% map cleanly), python/cpython (12 validation surfaces consolidated into 1 alint config), microsoft/vscode (build/hygiene.ts → ~75% covered declaratively).
  2. Repos that rely on convention without explicit checks. "Catches the conventions your pipeline assumes but doesn't verify." Best fit: tokio (zero hand-rolled scripts; alint catches 15 conventions tokio's pipeline silently assumes), uv (67-crate workspace conventions enforced nowhere in CI today), pnpm (replaces the in-tree meta-updater plugin), facebook/react, nodejs/node.
  3. Repos with mature tooling that lacks a structural layer. "Adds a structural floor on top of mature tooling." Best fit: microsoft/typescript (eslint + dprint + knip already tight), astral-sh/ruff (900+ Python lint rules but zero rules for ruff's own internal-crate publish = false discipline), prettier, helm, dotnet/runtime (~2,300 XML manifests with structural invariants no existing tool covers).
  4. Repos that built their own lint-orchestration tool. "Replaces the structural subset of your custom orchestration layer." Best fit: pytorch (≈86% of pytorch's 57 lintrunner.toml adapters are structural; alint sits beneath, lintrunner keeps the AST-aware tail), bazel (alint replaces the structural subset of bazel's hand-rolled CI scripts).
  5. Tightly-curated minimal-tooling projects. "Encodes conventions enforced only by code-review discipline." Best fit: golang/go (zero .github/workflows/, zero Makefile, zero .golangci.yml; the 31-rule alint config encodes the project's structural contract for the first time anywhere).

Polyglot wins as a sixth shape: when a single tree spans languages or platforms (apache/arrow's 6 languages, vercel/next.js's TS+Rust, NixOS/nixpkgs at 39k files, flutter's Dart-framework-with-6-native-embedders, protobuf's 11 language bindings), no per-language linter sees the cross-cutting conventions; alint is the layer that does.

If your repo doesn't match one of these shapes, alint is probably still useful (the rule catalogue is broad), but you may want to start by reading the closest case study above to see what a working config looks like in your shape.

Non-goals

alint is deliberately not:

Scope is the filesystem shape and contents of a repository, not the semantics of the code inside it.

Install

install.sh (Linux + macOS + Windows tarballs)

curl -sSL https://raw.githubusercontent.com/asamarts/alint/main/install.sh | bash

Detects platform (Linux / macOS, x86_64 / aarch64), downloads the matching tarball, verifies the SHA-256, and installs to $INSTALL_DIR (default ~/.local/bin). Windows users download the Windows tarball from the Releases page.

Homebrew (macOS + Linuxbrew)

brew tap asamarts/alint
brew install alint

The asamarts/homebrew-alint tap is auto-updated on every alint release. The formula downloads the matching pre-built binary, verifies its SHA-256, and installs to the Homebrew cellar.

From crates.io

cargo install alint

From npm

# project-local
npm install --save-dev @asamarts/alint
npx alint check

# global (puts `alint` on PATH)
npm install -g @asamarts/alint
alint check

The @asamarts/alint package is a thin shim that downloads the matching pre-built binary at install time, verifies its SHA-256 against the same .sha256 companion install.sh and Homebrew use, and stages it under the package's bin-platform/. The package itself ships zero JS runtime behaviour. Set ALINT_SKIP_INSTALL=1 to suppress the postinstall network hop in CI environments that snapshot node_modules.

From source

git clone https://github.com/asamarts/alint
cd alint
cargo build --release -p alint
./target/release/alint --help

Docker

A distroless multi-arch image (linux/amd64, linux/arm64) is published to ghcr.io on each release:

# Lint the current directory:
docker run --rm -v "$PWD:/repo" ghcr.io/asamarts/alint:latest

# Pin to an exact version:
docker run --rm -v "$PWD:/repo" ghcr.io/asamarts/alint:v0.13.0 check

The image runs as the distroless nonroot user (UID 65532); host files must be world-readable. To apply fixes and preserve host ownership, pass -u:

docker run --rm -u $(id -u):$(id -g) -v "$PWD:/repo" ghcr.io/asamarts/alint:latest fix

Also published: :<major>.<minor> (e.g. :0.10) and the raw git tag (:v0.13.0).

Quick start

The fastest on-ramp is alint init. It scans your repo for the obvious markers (Cargo.toml, package.json, pnpm-workspace.yaml, …) and writes a .alint.yml with the right extends: lines:

alint init             # ecosystem-aware (rust@v1, node@v1, …)
alint init --monorepo  # plus workspace overlays for Cargo / pnpm / Yarn

For an existing repo with prior debt, follow up with alint suggest. It scans for *.bak files, scratch docs at root, console.log residue in production source, and TODO markers older than 180 days, then proposes the bundled rulesets and rule entries that would catch them. Output is review-only; suggest never edits your config:

alint suggest                       # human-readable proposal table
alint suggest --format yaml         # paste-ready config snippet
alint suggest --format json         # stable shape for agent consumption
alint suggest --explain             # show file-level evidence per proposal

For agent-driven workflows where AGENTS.md / CLAUDE.md / .cursorrules carries the directives the agent reads at session start, alint export-agents-md renders the active rule set as a markdown directive block. alint becomes the single source of truth, and the agent reads what alint enforces:

alint export-agents-md                                # to stdout
alint export-agents-md --inline --output AGENTS.md    # splice between alint markers

--inline writes only between / markers; everything else in AGENTS.md is human-owned prose. Re-runs are idempotent (when the on-disk content already matches, no write happens), and missing markers auto-init with a stderr warning so the second run splices cleanly.

The generated file is editable: start there, override or extend as needed. If you'd rather hand-roll, the minimum viable shape is:

# .alint.yml
# yaml-language-server: $schema=https://raw.githubusercontent.com/asamarts/alint/main/schemas/v1/config.json
version: 1
extends:
  - alint://bundled/oss-baseline@v1   # README/LICENSE/SECURITY.md, merge markers, hygiene

Then run:

``bash alint check # run all rules against the current directory alint fix --dry-run # preview the auto-fixes that would be applied alint fix # apply every fixable violation in place alint list # list effective rules (useful after extends / overrides) alint explain <id> # show a rule's full, resolved definition alint facts # evaluate facts against the repo; debugwhen:clauses alint init [--monorepo] # scaffold a.alint.yml` based on detected ecosystem + workspace shape alint suggest # scan for known antipatterns and pr

Extension points exported contracts — how you extend this code

Rule (Interface)
Trait every built-in and plugin rule implements. [74 implementers]
crates/alint-core/src/rule.rs
PerFileRule (Interface)
File-major dispatch entry-point for a per-file rule. Rules that can evaluate one file at a time given a pre-loaded byte [29 …
crates/alint-core/src/rule.rs
Fixer (Interface)
A mechanical corrector for a specific rule's violations. [12 implementers]
crates/alint-core/src/rule.rs

Core symbols most depended-on inside this repo

collect
called by 348
crates/alint/src/suggest/scan.rs
len
called by 223
crates/alint-core/src/facts.rs
is_empty
called by 176
crates/alint-core/src/facts.rs
get
called by 152
crates/alint-core/src/git.rs
as_str
called by 130
crates/alint-core/src/level.rs
insert
called by 108
crates/alint-core/src/facts.rs
with_path
called by 105
crates/alint-core/src/rule.rs
register
called by 97
crates/alint-core/src/registry.rs

Shape

Function 2,615
Method 600
Class 323
Enum 103
Interface 3

Languages

Rust98%
Kotlin1%
TypeScript1%
Python1%

Modules by API surface

crates/alint-rules/src/cross_file.rs78 symbols
crates/alint-dsl/src/lib.rs69 symbols
crates/alint-rules/src/file_graph.rs63 symbols
crates/alint-rules/src/structured_path.rs61 symbols
crates/alint-core/src/config.rs60 symbols
crates/alint-core/src/walker.rs59 symbols
crates/alint-core/src/engine.rs59 symbols
crates/alint-core/src/when/mod.rs58 symbols
crates/alint-lsp/src/lib.rs55 symbols
crates/alint/src/main.rs52 symbols
xtask/src/docs_export.rs51 symbols
crates/alint-core/src/rule.rs48 symbols

For agents

$ claude mcp add alint \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page