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, thencd book && mdbook buildand openbook/build/lints/index.html(or servebook/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.
| Category | Role | Default |
|---|---|---|
correctness | Likely bugs or useless code | deny |
suspicious | Very likely unintended | warn |
style | Idiomatic / readable Move | warn |
complexity | Simpler equivalent forms | warn |
perf | Cheaper patterns | warn |
pedantic | Stricter / noisier | allow |
nursery | New or experimental | allow |
restriction | Opinionated bans | allow |
cargo | Move.toml / packaging | allow |
sui | Sui object / PTB patterns | allow |
security | Security heuristics (expect noise) | allow |
Full index
- In this book: Lint index (generated) — Markdown table (anchors
#lint_id). - Searchable page: hosted lint list on GitHub Pages (built by
.github/workflows/pages.yml). Files live underbook/src/lints/and are produced bycargo run -p sui-clippy-docgenbeforemdbook build. UX is modeled on Clippy’s hosted lint list.
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--typedis used and the binary is built with--features move_compiler.sui_move_lint— when--with-sui-lintis set and the spawnedsui move build --lintfails.
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 ID | Category | Default level | Documentation |
|---|---|---|---|
bare_abort | suspicious | warn | abort with a magic numeric code is easy to misuse; prefer named constants or structured errors. |
clock_timestamp | suspicious | warn | Clock reads can be manipulated by validators in tests; on-chain code should treat timestamps as hints, not strong security boundaries. |
dynamic_field_access | security | allow | Dynamic field APIs are easy to get wrong; verify key types, ownership, and access control. |
empty_public_entry | correctness | deny | A public entry function with an empty body is almost certainly a mistake or unsafe stub. |
git_dep_unpinned | suspicious | warn | Git dependencies without rev, branch, or tag are not reproducible builds. |
missing_move_edition | style | warn | Move.toml [package] should declare an edition (for example Move 2024) for consistent tooling and language behavior. |
public_fun_transfer | security | allow | transfer::* inside a public fun body widens who may invoke object moves; confirm this matches your capability model. |
test_only_in_sources | nursery | allow | #[test_only] in non-test paths is easy to ship accidentally; prefer tests/ modules or #[test_only] only in test-only files. |
todo_comment | suspicious | warn | Track and remove TODO/FIXME markers before release. |
tx_context_sender | suspicious | warn | Using tx_context::sender() can encourage self-transfers; prefer returning objects to callers for PTB composability where appropriate. |
wildcard_git_ref | correctness | deny | Wildcard 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 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 underbook/src/lints/, produced bycargo 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
-
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 -
Use the official
github/codeql-action/upload-sarifstep 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 -
Ensure the job has the
security-events: writepermission 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 idmove_compilerin SARIFresults[].ruleId.
Language server (sui-clippy-lsp)
The sui-clippy-lsp binary provides a minimal LSP server over stdio.
Capabilities
- After
textDocument/didOpenandtextDocument/didSavefor*.movefiles, it runs the samerun_source_lintspipeline as the CLI and publishestextDocument/publishDiagnostics. - Other requests receive
MethodNotFound(the server is intentionally small).
Editor setup
- Install the binary (
cargo install --path crates/sui-clippy-lsp). - Point your editor’s Move / custom LSP entry at
sui-clippy-lspwith stdio transport. - Open a file under a normal Move package so
Move.tomlcan be discovered upward from the file path.
Diagnostics respect sui-clippy.toml when present at the package root.