sui-clippy

sui-clippy is a Sui Move linter with a Clippy-shaped architecture: named lints, categories, config file overrides, and machine-readable output (JSON / SARIF).

It complements sui move build --lint and focuses on fast text-level checks plus optional Move compiler integration when built with --features move_compiler.

Where to go next

  • Installation — install the CLI (and optional LSP binary).
  • Usage — common flags, workspace mode, and sui move build --lint.
  • Lint index (generated) — table of every built-in rule (regenerate with cargo run -p sui-clippy-docgen).
  • Web-style lint list (search + category filter): on GitHub Pages after enabling the workflow (same role as rust-clippy’s lint index). Locally: cargo run -p sui-clippy-docgen, then cd book && mdbook build and open book/build/lints/index.html (or serve book/build/ over HTTP).

The layout of this book follows the Clippy book structure in a shorter form: installation, usage, configuration, lints, CI, and tooling.

Installation

sui-clippy CLI

From a clone of the repository:

cargo install --path crates/sui-clippy

You get the sui-clippy binary (and cargo-sui-clippy if your Cargo.toml installs both bins from that crate).

Optional: Move compiler integration

For --typed (compiler-backed diagnostics), build with the large Sui git dependency:

cargo install --path crates/sui-clippy --features move_compiler

Optional: LSP

cargo install --path crates/sui-clippy-lsp

Then configure your editor to run sui-clippy-lsp with stdio (see Language server).

mdBook (to read or author this book)

Install mdBook, then from the book/ directory:

mdbook build

HTML output is written to book/build/ (see book.toml).

Usage

Basic check

Run inside a Move package (directory containing Move.toml):

sui-clippy

Or point at a path:

sui-clippy path/to/package
sui-clippy path/to/module.move

Output formats

  • Human text (default): one diagnostic per block.
  • JSON: --format json — one JSON object per line (one diagnostic per line).
  • SARIF: --format sarif — single SARIF 2.1 document for CI (see GitHub Code Scanning).

Lint levels from the CLI

Same spirit as rustc -W / -A / -D:

sui-clippy --warn todo_comment --deny bare_abort .

Workspace of Move packages

If the root Move.toml defines [workspace].members, lint each member:

sui-clippy --workspace /path/to/workspace/root

The path must be a directory (the workspace root). Use --skip-manifest if you only want source rules.

Sui CLI integration

Forward output from the Sui toolchain:

sui-clippy --with-sui-lint .

Compiler-backed pass (--typed)

When sui-clippy is built with move_compiler, --typed runs the Move compiler on sources/ and attaches diagnostics (rule id move_compiler). Without the feature, --typed exits with an error telling you to rebuild with --features move_compiler.

Listing lints

sui-clippy --list-lints
sui-clippy --list-lints --format json

Manifest fixes

sui-clippy --fix-manifest          # insert default edition when missing
sui-clippy --fix                   # alias for --fix-manifest today

--fix-sources is reserved for future autofixes and is currently a no-op (with a note on stderr in text mode).

Configuration

Project-local settings live in sui-clippy.toml at the Move package root (next to Move.toml).

The file is loaded by both the sui-clippy CLI and sui-clippy-lsp. Values are defined in the sui_clippy_config crate; see the default schema in the repository’s crates/sui_clippy_config sources.

Overrides

CLI flags such as --warn LINT / --allow LINT / --deny LINT override config for a single run (see Usage).

Lint catalog

An authoritative list of lint ids and default levels is emitted by:

sui-clippy --list-lints

For a stable, linkable table and HTML index, regenerate Lint index (generated) with:

cargo run -p sui-clippy-docgen

Lint categories

sui-clippy groups rules into categories (same names as rust-clippy). Each category has a default level (allow, warn, or deny) used when neither sui-clippy.toml nor the CLI overrides a lint.

CategoryRoleDefault
correctnessLikely bugs or useless codedeny
suspiciousVery likely unintendedwarn
styleIdiomatic / readable Movewarn
complexitySimpler equivalent formswarn
perfCheaper patternswarn
pedanticStricter / noisierallow
nurseryNew or experimentalallow
restrictionOpinionated bansallow
cargoMove.toml / packagingallow
suiSui object / PTB patternsallow
securitySecurity heuristics (expect noise)allow

Full index

Rules not in the generated table

Some diagnostics are produced at run time and are not declared as static LintDef entries:

  • move_compiler — only when --typed is used and the binary is built with --features move_compiler.
  • sui_move_lint — when --with-sui-lint is set and the spawned sui move build --lint fails.

Regenerating docs

Whenever you add or change a lint’s metadata:

cargo run -p sui-clippy-docgen

Then rebuild the book (mdbook build inside book/) if you ship HTML.

Lint index (generated)

This file is produced by cargo run -p sui-clippy-docgen. Do not edit by hand.

See the Lint categories chapter for what each group means.

Lint IDCategoryDefault levelDocumentation
bare_abortsuspiciouswarnabort with a magic numeric code is easy to misuse; prefer named constants or structured errors.
clock_timestampsuspiciouswarnClock reads can be manipulated by validators in tests; on-chain code should treat timestamps as hints, not strong security boundaries.
dynamic_field_accesssecurityallowDynamic field APIs are easy to get wrong; verify key types, ownership, and access control.
empty_public_entrycorrectnessdenyA public entry function with an empty body is almost certainly a mistake or unsafe stub.
git_dep_unpinnedsuspiciouswarnGit dependencies without rev, branch, or tag are not reproducible builds.
missing_move_editionstylewarnMove.toml [package] should declare an edition (for example Move 2024) for consistent tooling and language behavior.
public_fun_transfersecurityallowtransfer::* inside a public fun body widens who may invoke object moves; confirm this matches your capability model.
test_only_in_sourcesnurseryallow#[test_only] in non-test paths is easy to ship accidentally; prefer tests/ modules or #[test_only] only in test-only files.
todo_commentsuspiciouswarnTrack and remove TODO/FIXME markers before release.
tx_context_sendersuspiciouswarnUsing tx_context::sender() can encourage self-transfers; prefer returning objects to callers for PTB composability where appropriate.
wildcard_git_refcorrectnessdenyWildcard rev or branch on a git dependency is almost never intended for production.

Continuous integration

SARIF and GitHub Code Scanning

sui-clippy can emit SARIF for GitHub’s Code Scanning workflow. See the full guide:

GitHub Code Scanning (SARIF)

GitHub Actions (minimal)

- uses: dtolnay/rust-toolchain@stable
- run: cargo install --path crates/sui-clippy
- name: sui-clippy
  run: sui-clippy --format sarif ./my-move-pkg > sui-clippy.sarif
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: sui-clippy.sarif

Adjust the package path and permissions (security-events: write) to match your org.

Documentation site (GitHub Pages)

The book and the searchable lint list are built together by .github/workflows/pages.yml (see book/README.md in the repository). After you set Settings → Pages → Source to GitHub Actions, pushes to main or master publish:

  • The mdBook at the site root.
  • The lint list at /lints/ (static files under book/src/lints/, produced by cargo run -p sui-clippy-docgen).

GitHub Code Scanning with sui-clippy SARIF

This repository emits SARIF 2.1.0 when you pass --format sarif. The document includes runs[0].tool.driver (name, version, informationUri, rules) and runs[0].tool.extensions with a secondary tool component for downstream consumers.

Upload from GitHub Actions

  1. Run sui-clippy on your Move package and write SARIF to a file, for example:

    sui-clippy --format sarif /path/to/move/package > results.sarif
    
  2. Use the official github/codeql-action/upload-sarif step so Code Scanning ingests the file:

    - name: Run sui-clippy (SARIF)
      run: sui-clippy --format sarif ./my-move-pkg > sui-clippy.sarif
    
    - name: Upload SARIF
      uses: github/codeql-action/upload-sarif@v3
      with:
        sarif_file: sui-clippy.sarif
    
  3. Ensure the job has the security-events: write permission when required by your organization’s Code Scanning defaults.

Notes

  • Paths in SARIF use file:// URIs when the diagnostic span can be canonicalized on disk.
  • Compiler-backed diagnostics from --typed (when built with --features move_compiler) use the rule id move_compiler in SARIF results[].ruleId.

Language server (sui-clippy-lsp)

The sui-clippy-lsp binary provides a minimal LSP server over stdio.

Capabilities

  • After textDocument/didOpen and textDocument/didSave for *.move files, it runs the same run_source_lints pipeline as the CLI and publishes textDocument/publishDiagnostics.
  • Other requests receive MethodNotFound (the server is intentionally small).

Editor setup

  1. Install the binary (cargo install --path crates/sui-clippy-lsp).
  2. Point your editor’s Move / custom LSP entry at sui-clippy-lsp with stdio transport.
  3. Open a file under a normal Move package so Move.toml can be discovered upward from the file path.

Diagnostics respect sui-clippy.toml when present at the package root.