askill
clojure-guardrails

clojure-guardrailsSafety --Repository

Reference for Guardrails library with Malli in Clojure. Use when working with `>defn`, `>defn-`, `>def`, `>fdef` macros, gspec syntax, or function validation. Triggers on guardrails imports, `com.fulcrologic.guardrails.malli`, function specs with `=>` operator, or questions about runtime validation in Clojure.

0 stars
1.2k downloads
Updated 2/22/2026

Package Files

Loading files...
SKILL.md

Clojure Guardrails (Malli)

Detection

Check if guardrails is in use:

grep -r "guardrails.enabled" deps.edn shadow-cljs.edn 2>/dev/null

Setup

deps.edn:

{:deps {com.fulcrologic/guardrails {:mvn/version "1.2.16"}
        metosin/malli             {:mvn/version "0.20.0"}}
 :aliases {:dev {:jvm-opts ["-Dguardrails.enabled=true"]}}}

See https://clojars.org/com.fulcrologic/guardrails for the latest version.

guardrails.edn (sibling to deps.edn):

{:throw? true}

This causes guardrails violations to throw exceptions instead of just logging. We want this in nearly all cases — silent validation failures defeat the purpose.

Enable at runtime: -Dguardrails.enabled=true

Import

(require '[com.fulcrologic.guardrails.malli.core :refer [>defn >defn- >def >fdef | ? =>]])

Core Macros

MacroPurpose
>defnDefine function with inline spec
>defn-Private function with spec
>defRegister malli schema
>fdefDeclare spec without body
?Nilable shorthand [:maybe schema]
|"Such that" constraints
=>Separates args from return

Gspec Syntax

[arg-specs* (| arg-preds+)? => ret-spec (| ret-preds+)?]

Basic:

(>defn add [a b]
  [:int :int => :int]
  (+ a b))

With constraints:

(>defn ranged-rand [start end]
  [:int :int | #(< start end)
   => :int | #(>= % start) #(< % end)]
  (+ start (long (rand (- end start)))))

Nilable:

(>defn find-user [id]
  [:int => (? :map)]
  (get users id))

Multi-arity:

(>defn greet
  ([name]
   [:string => :string]
   (str "Hello, " name))
  ([greeting name]
   [:string :string => :string]
   (str greeting ", " name)))

Variadic:

(>defn sum [x & more]
  [:int [:* :int] => :int]
  (apply + x more))

Map schemas:

(>defn process-user [user]
  [[:map [:name :string] [:age :int]] => :string]
  (str (:name user) " is " (:age user)))

Schema Registry

This is an optional feature.

(require '[com.fulcrologic.guardrails.malli.registry :as gr.reg])

;; Register schemas
(>def :user/name :string)
(>def :user/age :int)
(>def :user/record [:map :user/name :user/age])

;; Use in functions
(>defn get-user [id]
  [:int => (? :user/record)]
  (lookup id))

Anti-Patterns

Do NOT use :any, any?, :map, or map? in specs

These specs validate nothing meaningful and defeat the purpose of guardrails.

;; BAD - :any accepts everything, this is just ceremony
(>defn process [data]
  [:any => :any]
  ...)

;; BAD - :map only confirms it's a map, catches no real bugs
(>defn process-user [user]
  [:map => :string]
  ...)

;; GOOD - spec the keys you actually care about
;; Maps are open by default, so you only need to declare the slice
;; your function uses. Extra keys pass through fine.
(>defn process-user [user]
  [[:map [:name :string] [:age :int]] => :string]
  (str (:name user) " is " (:age user)))

If you don't know the shape yet, figure it out before writing the spec. A guardrails spec that validates nothing is worse than no spec — it creates a false sense of safety.

Detailed Reference

See gspec-syntax.md for complete syntax documentation.

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

AI review pending.

Metadata

Licenseunknown
Version-
Updated2/22/2026
PublisherRamblurr

Tags

observability