The command clj-nrepl-eval is installed on your path for evaluating Clojure code via nREPL.
Discover nREPL servers:
clj-nrepl-eval --discover-ports
Evaluate code:
clj-nrepl-eval -p <port> "<clojure-code>"
With timeout (milliseconds)
clj-nrepl-eval -p <port> --timeout 5000 "<clojure-code>"
The REPL session persists between evaluations - namespaces and state are maintained.
Always use :reload when requiring namespaces to pick up changes.
Always pick the simple solution and don't overthink. Later requirements are to be solved later. Don't optimize early.
Prefer a solution that has logic just once and references this solution before you duplicate logic.
Always use proper :require and :import declarations in the ns form instead of fully qualified names in code.
Do this:
(ns my.namespace
(:require
[clojure.string :as str])
(:import
[java.lang Math]))
(str/join "," items)
(Math/abs x)Not this:
(clojure.string/join "," items)
(java.lang.Math/abs x)Use Conventional Commits: type: description
Types: feat, fix, refactor, perf, test, docs, chore
You can run examples like the file-browser with this command
clojure -M -m examples.file-browserSee ADR 003: Testing Strategy for the full decision record.
- Unit tests for pure functions (Elm architecture:
update,view, input parsing) - Integration tests using JLine's dumb terminal with
ByteArrayInputStream/ByteArrayOutputStream - Visual tests with charmbracelet/vhs for critical user flows
When testing terminal I/O, use JLine's dumb terminal:
(let [input (java.io.ByteArrayInputStream. (.getBytes "hello\u001b[A")) ; input with up arrow
output (java.io.ByteArrayOutputStream.)
terminal (-> (org.jline.terminal.TerminalBuilder/builder)
(.dumb true)
(.streams input output)
(.build))]
(try
;; test terminal reading/writing here
(finally
(.close terminal))))- Unit test: Component logic, message handling, parsing, pure functions
- Integration test: Terminal I/O, input reading, output rendering, escape sequences
- VHS test: Critical user journeys, visual regressions (sparingly)