Liking cljdoc? Tell your friends :D

Guardrails Analyzer

A static analysis tool for Clojure/ClojureScript that performs compile-time type checking and validation based on Guardrails specs. Catch type errors and spec violations during development without having to run the code.

Status: ALPHA quality. Mostly API Stable.

Documentation and nice-factors still in progress (e.g. it’s a little rough around the edges)

I was originally going to call this copilot for Guardrails when I started tinkering with this in 2020, and now obviously someone else tool that name, so I’ve renamed this project. Any stray references to copilot in this project should be read as "guardrails analyzer" instead.

Quickstart

I’m still working on the work flow. So bear with me.

Daemon

You have to first start a daemon which acts as the communication server. If you clone this project, and run make Daemon.jar. That is an uberjard (java -jar Daemon.jar), but you must currently run it from your home directory. This has to be running for the checker to be able to communicate with the IDE.

IntelliJ Plugin

Download a release from https://github.com/fulcrologic/guardrails-intellij-plugin (releases) and install it from disk

The Checker

You must be using Guardrails, of course. Also, you MUST put Guardrails in either ":all" or ":pro" mode, or it won’t emit the analysis data that the analyzer needs!

You do this by adding JVM args to startup:

clojure -J-Dguardrails.mode=:all -J-Dguardrails.enabled ...
# or
clojure -J-Dguardrails.mode=:pro ...  # ONLY static analysis, no runtime enforcement

If you add this library to your project’s development deps, you can start the checker in a REPL. Note that the checker has to reload nses as it runs to make sure it has the latest runnable specs, so you may or may not want to actually do work in that REPL. I’ve got internal code for starting the checker, but I need to finish the polish/docs.

It won’t be able to check until the code is loaded, so you should probably load your top-level entry point ns before you start the checker. That way you’ll know it’s basically ready.
(require '[com.fulcrologic.guardrails-analyzer.checkers.clojure :as cc])
;; List the source dirs you want to be able to run checks on
(cc/start {:src-dirs ["src/dev" "src/main"]})

Now you can trigger IntelliJ commands (add kb shortcuts) for guardrails actions like "Check Namespace". E.g. press your shortcut for Run Action (i.e. CMD-SHIFT-A) and type "Check Namespace".

See ~/.guardrails/logs for logs.

Overview

Guardrails Analyzer provides REPL and IDE-integrated static analysis for Clojure code that uses Guardrails' >defn macro and inline gspec syntax. It analyzes your code at development-time, providing real-time feedback on type errors, spec violations, and potential issues.

The base idea is to use generators (Clojure spec or Malli) to generate data and flow it through a simulation of your code, tracking what happens, and warning when something looks fishy. Because that requires running your specs, it means we have to run a process that has your code in it, as well as the checker.

This goes beyond pure static analysis (like clj-kondo) in that it is able to find a LOT more possible problems with your actual algorithm data flow. When used with IntelliJ you can even see the flowed values on bindings in let to see what’s going on!

In order to facilitate communication between this checker and editors this project includes a daemon that runs as both an IntelliJ and LSP server.

An IntellJ Plugin already exists, and is published as a separate project.

Key Features

  • Static Type Checking: Validates function arguments and return values against Guardrails specs without running code

  • Path-Based Analysis: Tracks execution paths through conditional branches for precise error reporting

  • IDE Integration: Language Server Protocol (LSP) support for real-time feedback in your editor

  • Sample-Based Validation: Uses spec generators to create test data and validate type correctness

  • Zero Runtime Overhead: All analysis happens at development time

  • Comprehensive Coverage: Supports control flow (if, when, cond), higher-order functions, macros, and more

How It Works

(>defn calculate-discount
  [price :- number?
   customer-type :- keyword?]
  [number? keyword? => number?]
  (if (= customer-type :premium)
    (* price 0.9)
    price))

The analyzer:

  1. Parses the gspec: [number? keyword? ⇒ number?]

  2. Generates sample values using spec generators

  3. Traces execution through conditional branches

  4. Validates that all paths conform to the return spec

  5. Reports errors with specific path information

If you accidentally return a non-number on any path, you’ll get an error like:

The Return spec is number?, but it is possible to return
a value like :invalid when (= customer-type :premium) → else

Path-Based Analysis

The analyzer tracks execution paths through your code to provide precise error reporting:

  • Determined Conditions: Pure predicates like (even? x) partition samples by branch

  • Path Tracking: Each execution path maintains its own samples and bindings

  • Precise Errors: Know exactly which conditions lead to spec violations

  • Control Flow Support: if, when, cond, and, or, cond→, some→, and more

See PATH_BASED_ANALYSIS_COMPLETE.md for comprehensive documentation.

Architecture

Core Components

  • Analyzer (src/main/com/fulcrologic/guardrails-analyzer/analysis/)

    • Multi-method dispatch system for different expression types

    • Function, macro, literal, and higher-order function analysis

    • Destructuring and conditional handling

  • Artifacts System (artifacts.cljc)

    • Central data structure definitions using clojure.spec

    • Environment tracking for bindings, problems, and analysis state

    • Path management and sample partitioning

  • Checker (checker.cljc)

    • Main entry point for editor integration

    • Gathers problems and bindings after analysis

    • Formats output for IDE/LSP consumption

  • Daemon (src/daemon/)

    • Language Server Protocol implementation

    • HTTP server and WebSocket communication

    • Real-time feedback to editors/IDEs

  • UI Formatters (src/main/com/fulcrologic/guardrails-analyzer/ui/)

    • Human-readable error messages

    • Binding information display

    • Path-based error formatting

Data Flow

Editor → Daemon → Checker → Analyzer → Type Checker → Formatter → Daemon → Editor

Development

Prerequisites

  • Clojure CLI tools

  • Node.js (for ClojureScript builds)

  • Java 21+

Relationship with Guardrails

This project has a close relationship with the Guardrails library:

  • Guardrails provides the >defn macro and inline gspec syntax

  • Guardrails Analyzer performs static analysis on code using those specs

  • Changes may require coordinated updates in both repositories

  • Core library function specs are defined in analysis/fdefs/

Documentation

See the ai/ directory and root-level markdown files for detailed documentation:

  • CLAUDE.md - Comprehensive project overview and architecture guide

  • ai/running-tests.md - Testing guidelines

Copyright 2025, Fulcrologic, LLC All Rights Reserved

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close