name: scry description: > Use scry to run Clojure tests through the REPL/in-process API for structured inspection and through the CLI for final verification, process status, and failure EDN files. Trigger when debugging Clojure test failures, when an agent needs expected/actual assertion data, per-test output, stack traces, or CLI exit semantics without scraping terminal output, or when working in a project that depends on scry. lambda: "λclj_tests. (run(repl/in_process) → inspect({:summary :pass? :results :failures})) ∨ (run(cli) → verify(exit_code ∧ .scry-results)) ∧ avoid(scrape_terminal_output)" metadata: tags: ["clojure", "testing", "repl", "cli", "ci", "ai-agents", "structured-results"] language: "clojure"
Scry
Use scry to run Clojure tests and inspect structured results instead of scraping human-oriented terminal output.
Use the REPL/in-process API while iterating: it keeps the latest result available in the process and supports targeted structured inspection. Use the CLI for final verification and CI-style checks: it reports process status, live progress, summaries, and failure EDN files.
When to use this skill
Use this skill when:
- You are in a Clojure project that has
scryavailable on the classpath. - You need to know whether tests passed and which test vars failed.
- You need failure details such as
:expected,:actual,:message,:file,:line, testing contexts, or stack traces. - You need stdout/stderr captured for a targeted single test var.
- You are debugging interactively from a REPL and want machine-readable results.
- You need command-line exit semantics or failure files for final verification.
Do not scrape terminal output if scry can provide structured result maps or EDN result files.
Result shape
The top-level result shape is:
{:summary {:test 0
:pass 0
:fail 0
:error 0
:duration-ms 0.0
:var-count 0
:fail-var-count 0}
:pass? true
:results []
:failures []}
:results is the canonical formatted collection. :failures is a compatibility collection containing failing/erroring entries when the selected format includes it.
Default result detail follows invocation intent:
- Suite/multi scope (
(scry/run), multiple namespaces, or multiple vars): compact failing/erroring entries with:assertion-summary; no:assertions,:out, or:errby default. - Single namespace scope (
{:namespaces ['my.project-test]}): all executed vars, including passing vars, with all assertion details; no output keys by default. - Single var scope (
{:vars [#'my.project-test/specific-test]}): one entry with all assertion details and:out/:err.
REPL / in-process workflow
Prefer REPL/in-process runs for interactive debugging and iteration:
(require '[scry.core :as scry])
(scry/run)
scry/run stores the most recent result, so after a run you can inspect it interactively:
(scry/last-result)
(:pass? (scry/last-result))
(:summary (scry/last-result))
(:results (scry/last-result))
(scry/failures)
(scry/failed-test 'my.project-test/failing-test)
(scry/output 'my.project-test/failing-test)
(println (scry/report-string (scry/last-result)))
Targeted REPL runs
Run discovered tests using defaults:
(scry/run)
Run tests from explicit directories:
(scry/run {:dirs ["test"]})
Run namespaces matching a pattern:
(scry/run {:ns-pattern #".*-test$"})
Run explicit namespaces:
(scry/run {:namespaces ['my.project-test]})
Run explicit vars:
(scry/run {:vars [#'my.project-test/specific-test]})
Command-line workflow
Prefer the CLI for final verification, shell scripts, and CI-style status. The CLI uses the same structured result model but adds process exit behavior, live per-var progress, summaries, and .scry-results/ failure files.
Core entry points:
clojure -M:test -m scry.cli
clojure -X:test scry.cli/run
Focused core selectors:
clojure -M:test -m scry.cli --var my.project-test/specific-test
clojure -X:test scry.cli/run :vars '[my.project-test/specific-test]'
Useful namespace/directory examples:
clojure -M:test -m scry.cli --dir test --ns-pattern '.*-test$'
clojure -M:test -m scry.cli --namespace my.project-test
clojure -X:test scry.cli/run :dirs '["test"]' :namespaces '[my.project-test]'
CLI contract:
- Prints
.to stdout for each passing test var. - Prints failing/erroring unqualified var names to stderr.
- Prints a summary after the run.
- Clears and recreates
.scry-results/at run start. - Writes namespace-prefixed
.ednfiles under.scry-results/for failing/erroring vars. - Leaves
.scry-results/empty on passing runs. - Exits non-zero for failures, errors, unknown status, runner/argument errors, or zero executable tests.
Do not scrape progress text for details. For -m runs, use the process exit code and summary for status, then inspect .scry-results/*.edn for failing/erroring var details. For -X runs, inspect the returned outcome map on success; on non-zero outcomes catch/read the thrown ex-info data, especially :exit-code, :summary, :error, and :outcome.
Optional Kaocha CLI mode requires the optional adapter on the classpath:
clojure -M:test:kaocha -m scry.cli --runner kaocha --suite unit
clojure -X:test:kaocha scry.cli/run :runner :kaocha :suite :unit
Kaocha CLI mode is optional; core users do not need the Kaocha adapter. As with the adapter API, Kaocha-captured stdout/stderr are preserved as merged :out with empty :err in result files unless the adapter supplies separate streams.
Custom formatting
Configure top-level keys, entry keys, assertion inclusion, and output inclusion independently by scope:
(scry/run
{:vars [#'my.project-test/specific-test]
:result-format
{:var {:top-level-keys [:summary :pass? :results]
:entry-keys [:var :status]
:assertions? true
:output? false}}})
:assertions? and :output? are authoritative gates: true adds those keys, false removes them, even if :entry-keys says otherwise.
Interpreting failures
Detailed failing entries have this shape:
{:var 'my.project-test/failing-test
:ns 'my.project-test
:status :fail ;; or :error
:assertions [{:type :fail
:message "expected equality"
:expected '(= 1 2)
:actual '(not (= 1 2))
:file "project_test.clj"
:line 42
:contexts ["outer testing" "inner testing"]}]
:out "captured stdout"
:err "captured stderr"}
Error assertions also include :stacktrace.
Debugging loop:
- Run
(scry/run)and check:pass?. - If false, inspect
(scry/failures)or(:results (scry/last-result))rather than rerunning with noisier output. - Use
:var,:file, and:lineto locate the failing test. - Use assertion
:expected,:actual,:contexts, and:stacktraceto understand the failure when assertion details are included. - Rerun a targeted namespace or var when more detail/output is useful.
- Make the smallest fix and rerun the targeted namespace or var when possible.
- Before handoff or CI-style confidence, run the appropriate CLI command and inspect structured artifacts if it fails.
Kaocha REPL adapter
If the project uses the optional Kaocha adapter, require and run it from the REPL:
(require '[scry.kaocha :as k])
(k/run) ;; loads tests.edn when present
(k/run {:suites [:unit :integration]})
(k/run {:suite :unit}) ;; single-suite convenience
(k/run {:config full-kaocha-config}) ;; full config override
The adapter returns the same scoped result model as scry.core/run, currently in suite scope by default. Without :config, it loads the current project's tests.edn when present and otherwise uses the fallback synthetic :unit suite. With :config, the supplied Kaocha config is authoritative; scry applies suite selection and quiet runtime defaults but does not merge fallback paths into it.
Suite selectors match exact configured suite ids first, then unique string/name fallback. Use :suite for one selector; plural :suites must be a non-empty collection. Conflicts, unknown selectors, and ambiguous fallback selectors throw ex-info.
Caveat: Kaocha's capture-output plugin merges stdout and stderr into one stream. scry.kaocha puts the combined output in :out and leaves :err empty.
Agent rules
- Prefer structured
scryresults over parsing console text. - Use REPL/in-process runs for interactive debugging and targeted iteration.
- Use CLI runs for final verification and CI-style process status.
- Prefer
:resultsas canonical; usescry/failuresfor failing/erroring entries. - For CLI failures, inspect
.scry-results/*.edn(-m) or returned/thrown structured data (-X) instead of scraping progress text. - Preserve normal
clojure.testsemantics;scry.clojure-testuses a local fixture-preserving loop aroundclojure.test/test-varto retain normal:once/:eachfixture grouping and ordering while owning per-var output capture. - Use targeted
:namespacesor:varsruns while iterating on a specific failure. - After changing public behavior, update user-facing docs and tests.