clj-kondo

clj-kondoEPL-1.0活跃维护

Clojure/ClojureScript 静态代码分析器和 linter,能在不运行代码的情况下检查未定义变量、未使用绑定等问题,帮你在编码阶段就发现错误。

Static analyzer and linter for Clojure code that sparks joy

v2026.10.26发布于 2026-10-26 14:07 UTC1,865star313fork同步于 2026-11-11 05:44 UTC

怎么上手

由 README 提炼,执行前请确认
clj-kondo --lint src
clj-kondo --lint "$(lein classpath)" --dependencies --parallel --copy-configs
硬件要求按 README 说明

README 未说明具体硬件要求;作为静态分析器不需要运行时,可编译为原生代码运行,也支持在 JVM 上运行和通过 Docker 运行。

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

Clojure 静态分析与 linter,不执行代码就能在编码时发现潜在错误

Clojure/ClojureScript 静态代码分析器和 linter,能在不运行代码的情况下检查未定义变量、未使用绑定等问题,帮你在编码阶段就发现错误。

核心能力

  • 静态分析 Clojure、ClojureScript 和 EDN,无需运行程序
  • 检测 arity 错误、未使用 var、未解析符号等常见问题
  • 支持 clojure.core.async、schema 等常用宏的语法识别
  • 输出分析数据,可据此编写自定义 linter
  • 用 GraalVM 编译为原生代码,可脱离 JVM 运行

容易踩的坑

跨命名空间检测需要先建 .clj-kondo 目录并 lint 整个 classpath 填充缓存,否则会漏报;依赖库的配置需用 --copy-configs 导入;不支持的宏需通过配置或 hooks 补充,否则相关代码无法正确分析

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v2026.10.26
  1. v2026.10.26最新正式版2026-10-26 · 2026-10-26 14:07 UTC

    What's Changed

    Full Changelog: https://github.com/clj-kondo/clj-kondo/compare/v2026.10.20...v2026.10.26

  2. v2026.10.202026-10-20 · 2026-10-20 08:23 UTC
    查看更新说明

    What's Changed

    New Contributors

    • @willcohen made their first contribution i
  3. v2026.08.042026-08-04 · 2026-08-04 14:33 UTC
    查看更新说明

    What's Changed

    Full Changelog: https://github.com/clj-kondo/clj-kondo/compare/v2026.08.03...v2026.08.04

  4. v2026.08.032026-08-03 · 2026-08-03 11:02 UTC
    查看更新说明

    What's Changed

    Full Changelog: https://github.com/clj-kondo/clj-kondo/compare/v2026.07.24...v2026.08.03

  5. v2026.07.242026-07-24 · 2026-07-24 11:00 UTC
    查看更新说明

    What's Changed

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Clojars Project Financial Contributors on Open Collective CircleCI Build status cljdoc badge project chat twitter

    A static analyzer and linter for Clojure code that sparks joy.

    Rationale

    Clj-kondo performs static analysis on Clojure, ClojureScript and EDN. It informs you about potential errors while you are typing (without executing your program).

    Features

    Clj-kondo detects:

    • inline def expressions
    • redundant do and let wrappings
    • arity errors:
      • within the same namespace and across namespaces
      • of static Java method calls
      • of local let and letfn binding calls
      • of recursive calls (including recur)
      • conflicting arities in overloaded functions
    • unused private vars
    • private and deprecated var usage
    • required but unused namespaces
    • unsorted required namespaces
    • referred but unused vars
    • duplicate requires
    • unused function arguments and let bindings
    • marked as unused, but used arguments and let bindings (optional)
    • unused imports
    • redefined vars
    • unresolved symbols, vars and namespaces
    • misplaced docstrings
    • duplicate map keys and set elements
    • duplicates and quoting in case test constants
    • missing map keys
    • invalid number of forms in binding vectors
    • missing assertions in clojure.test/deftest
    • alias consistency
    • type checking
    • Datalog syntax checking
    • format string argument mismatches
    • shadowed vars
    • 2 argument usage of reduce (optional)

    before your form hits the REPL.

    It suggests several style guide recommendations, such as:

    It has support for syntax of commonly used macros like clojure.core.async/alt!!, schema.core/defn and potemkin/import-vars.

    It detects common errors in deps.edn and bb.edn

    It provides analysis data so you build your own custom linters.

    View all available linters here.

    This linter is:

    • compatible with .clj, .cljs, .cljc and .edn files
    • build tool and editor agnostic
    • a static code analyzer
    • compiled to native code using GraalVM

    Try clj-kondo at the interactive playground.

    Watch the talk:

    Clj-kondo at ClojuTRE 2019

    Support :heart:

    You can support this project via Github Sponsors, OpenCollective, Ko-fi or indirectly via Clojurists Together.

    Installation

    Running on the JVM

    Running with Docker

    Usage

    Command line

    Lint from stdin:

    $ echo '(def x (def x 1))' | clj-kondo --lint -
    <stdin>:1:8: warning: inline def
    

    Lint a file:

    $ echo '(def x (def x 1))' > /tmp/foo.clj
    $ clj-kondo --lint /tmp/foo.clj
    /tmp/foo.clj:1:8: warning: inline def
    

    Lint a directory:

    $ clj-kondo --lint src
    src/clj_kondo/test.cljs:7:1: warning: redundant do
    src/clj_kondo/calls.clj:291:3: error: Wrong number of args (1) passed to clj-kondo.calls/analyze-calls
    

    Lint a project classpath:

    $ clj-kondo --lint "$(lein classpath)"
    

    Help:

    $ clj-kondo --help
    clj-kondo v2024.11.14
    
    Options:
    
    --lint <file>: a file can either be a normal file, directory or classpath. In the
    case of a directory or classpath, only .clj, .cljs and .cljc will be
    processed. Use - as filename for reading from stdin.
    
    --lang <lang>: if lang cannot be derived from the file extension this option will be
    used. Supported values: clj, cljs, cljc.
    
    --filename <file>: in case stdin is used for linting, use this to set the
    reported filename.
    
    --cache-dir: when this option is provided, the cache will be resolved to this
    directory. If --cache is false, this option will be ignored.
    
    --cache: if false, won't use cache. Otherwise, will try to resolve cache
    using `--cache-dir`. If `--cache-dir` is not set, cache is resolved using the
    nearest `.clj-kondo` directory in the current and parent directories.
    
    --config <config>: extra config that is merged. May be a file or an EDN expression. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md.
    
    --config-dir <config-dir>: use this config directory instead of auto-detected
    .clj-kondo dir.
    
    --parallel: lint sources in parallel.
    
    --dependencies: don't report any findings. Useful for populating cache while linting dependencies.
    
    --copy-configs: copy configs from dependencies while linting.
    
    --skip-lint: skip lint/analysis, still check for other tasks like copy-configs.
    
    --fail-level <level>: minimum severity for exit with error code.  Supported values:
    warning, error.  The default level if unspecified is warning.
    
    --report-level <level>: minimum severity for which to report.  Supported values:
    info, warning, error.  The default level if unspecified is info.
    
    --debug: print debug information.
    

    Project setup

    To detect lint errors across namespaces in your project, a cache is needed. To let clj-kondo know where to create one, make a .clj-kondo directory in the root of your project, meaning on the same level as your project.clj, deps.edn or build.boot:

    $ mkdir -p .clj-kondo
    

    A cache will be created inside of it when you run clj-kondo. Before linting inside your editor, it is recommended to lint the entire classpath to teach clj-kondo about all the libraries you are using, including Clojure and/or ClojureScript itself. Some libraries come with configurations. To import them, first run:

    $ clj-kondo --lint "<classpath>" --dependencies --copy-configs --skip-lint
    

    The --copy-configs flag will search and copy configurations from dependencies into the .clj-kondo directory, while linting (see config.md).

    With the configurations in place, now we can analyze the dependencies properly:

    $ clj-kondo --lint "<classpath>" --dependencies --parallel
    

    The --dependencies flag indicates that clj-kondo is used to analyze sources to populate the cache. When enabled, clj-kondo will suppress warnings and skips over already linted .jar files for performance.

    The --parallel option will use multiple threads to lint your sources, going through them faster.

    NOTE: in the version after 2024.05.24 copying configs and linting dependencies can be done in one go using:

    $ clj-kondo --lint "<classpath>" --dependencies --parallel --copy-configs
    

    Build tool specific ways to get a classpath:

    • lein classpath
    • boot with-cp -w -f -
    • clojure -Spath
    • npx shadow-cljs classpath

    So for lein the entire command would be:

    $ clj-kondo --lint "$(lein classpath)" --dependencies --parallel --copy-configs
    

    Now you are ready to lint single files using editor integration. A simulation of what happens when you edit a file in your editor:

    $ echo '(select-keys)' | clj-kondo --lang cljs --lint -
    <stdin>:1:1: error: Wrong number of args (0) passed to cljs.core/select-keys
    

    Since clj-kondo now knows about your version of ClojureScript via the cache, it detects that the number of arguments you passed to select-keys is invalid. Each time you edit a file, the cache is incrementally updated, so clj-kondo is informed about new functions you just wrote.

    If you want to use a different directory to read and write the cache, use the --cache-dir option. To disable the cache even if you have a .clj-kondo directory, use --cache false.

    For your project's version control, we recommend that you commit everything under the ./.clj-kondo/ dir, except for the cache dir. Add .cache to your .gitignore to ignore all .cache dirs, including the one under ./.clj-kondo. Adjust accordingly if you are using a different --cache-dir.

    Configuration

    Editor integration

    Exit codes

    Exit codes can be controlled by the --fail-level <level> option. The default fail level is warning which returns exit codes as follows:

    • 0: no errors or warnings were found
    • 2: one or more warnings were found
    • 3: one or more errors were found

    If --fail-level error is supplied, warnings do not lead to a non-zero exit code:

    • 0: no errors were found
    • 0: one or more warnings were found
    • 3: one or more errors were found

    All exit codes other than 0, 2 and 3 indicate an error because of a bug in clj-kondo or some other unexpected error beyond the control of clj-kondo.

    CI Integration

    Analysis data

    Developer documentation

    Companies using clj-kondo

    Macros

    As clj-kondo is a static analyzer is does not need a runtime (JVM, browser, Node.js, etc.). It doesn't execute your code. As such it can be a faster alternative to linters that do use a runtime, like eastwood. This approach comes with the limitation that clj-kondo cannot execute your macros as macros can use arbitrary features from a runtime. Clj-kondo has support for clojure core macros and some popular libraries from the community. Macros that are not supported out of the box can be supported using configuration. One of the ways to configure macros is to write hooks for them (also see this blogpost). For many libraries there is already a configuration available that you can import. Also check out clj-kondo configs which contains configurations for third party libraries.

    Babashka pod

    Clj-kondo can be invoked as a babashka pod.

    #!/usr/bin/env bb
    (ns script
      (:require [babashka.pods :as pods]))
    
    (pods/load-pod "clj-kondo")
    (require '[pod.borkdude.clj-kondo :as clj-kondo])
    
    (clj-kondo/merge-configs
     '{:linters {:unresolved-symbol {:exclude [(foo1.bar)]}}}
     '{:linters {:unresolved-symbol {:exclude [(foo2.bar)]}}})
    ;;=> {:linters {:unresolved-symbol {:exclude [(foo1.bar) (foo2.bar)]}}}
    
    (-> (clj-kondo/run! {:lint ["src"]})
        :summary)
    ;;=> {:error 0, :warning 0, :info 0, :type :summary, :duration 779}
    

    Podcasts

    Articles

    Thanks to:

    License

    Copyright © 2019 - 2023 Michiel Borkent

    Distributed under the EPL License, same as Clojure. See LICENSE.

    The directory inlined contains source from tools.reader which is licensed under the EPL license.

    The directory parser contains modified source from rewrite-clj which is licensed under the MIT license.