├── .typedclojure-lsp └── start ├── .gitignore ├── test └── example │ └── core_test.clj ├── src └── example │ └── core.clj ├── mise.toml ├── .github └── workflows │ ├── test.yaml │ └── typecheck.yaml ├── tests.edn ├── UNLICENSE ├── deps.edn └── README.md /.typedclojure-lsp/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | clojure -M:typedclojure-lsp 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cpcache/ 2 | .clj-kondo/ 3 | !.clj-kondo/config.edn 4 | .lsp/ 5 | .rebel_readline_history 6 | .nrepl-port 7 | target/ 8 | -------------------------------------------------------------------------------- /test/example/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns example.core-test 2 | (:require [clojure.test :as t] 3 | [example.core :as ex])) 4 | 5 | (t/deftest add 6 | (t/testing "it adds stuff" 7 | (t/is (= 2 (ex/add 1 1))))) 8 | -------------------------------------------------------------------------------- /src/example/core.clj: -------------------------------------------------------------------------------- 1 | (ns ^:typed.clojure example.core 2 | (:require [typed.clojure :as t])) 3 | 4 | (t/ann add [t/Int t/Int :-> t/Int]) 5 | (defn add 6 | "If you have https://github.com/Olical/typedclojure-lsp configured correctly you should see a type error / warning if you try to type (add :foo 10) inside this buffer." 7 | [a b] 8 | (+ a b)) 9 | 10 | #_(defn does-not-typecheck [] 11 | (add 10 :foo)) 12 | -------------------------------------------------------------------------------- /mise.toml: -------------------------------------------------------------------------------- 1 | [tools] 2 | clojure = "1.12.1" 3 | java = "temurin-21.0.6+7.0.LTS" 4 | 5 | [tasks.format] 6 | run = "clojure -M:format" 7 | 8 | [tasks.test] 9 | raw = true 10 | run = "clojure -M:dev:test" 11 | 12 | [tasks.typecheck] 13 | raw = true 14 | run = "clojure -M:typedclojure -e \"(require 'typed.clojure) (typed.clojure/check-dir-clj [\\\"src\\\"])\"" 15 | 16 | [tasks.antq] 17 | raw = true 18 | run = "clojure -M:antq" 19 | 20 | [tasks.repl] 21 | raw = true 22 | run = "clojure -M:test:dev:flowstorm" 23 | 24 | [tasks.build] 25 | run = "clojure -T:build jar" 26 | 27 | [tasks.clean] 28 | run = "clojure -T:build clean" 29 | 30 | [tasks.deploy] 31 | run = "clojure -T:build deploy" 32 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push] 4 | 5 | jobs: 6 | test: 7 | strategy: 8 | matrix: 9 | os: [ubuntu-latest] 10 | # os: [ubuntu-latest, macOS-latest, windows-latest] 11 | 12 | runs-on: ${{ matrix.os }} 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | 18 | - name: Mise 19 | uses: jdx/mise-action@v2 20 | 21 | - name: Cache 22 | uses: actions/cache@v4 23 | with: 24 | path: | 25 | ~/.m2/repository 26 | ~/.gitlibs 27 | ~/.deps.clj 28 | key: cljdeps-${{ hashFiles('deps.edn') }} 29 | restore-keys: cljdeps- 30 | 31 | - name: Execute Kaocha 32 | run: mise test 33 | -------------------------------------------------------------------------------- /.github/workflows/typecheck.yaml: -------------------------------------------------------------------------------- 1 | name: Typecheck 2 | 3 | on: [push] 4 | 5 | jobs: 6 | typecheck: 7 | strategy: 8 | matrix: 9 | os: [ubuntu-latest] 10 | # os: [ubuntu-latest, macOS-latest, windows-latest] 11 | 12 | runs-on: ${{ matrix.os }} 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | 18 | - name: Mise 19 | uses: jdx/mise-action@v2 20 | 21 | - name: Cache 22 | uses: actions/cache@v4 23 | with: 24 | path: | 25 | ~/.m2/repository 26 | ~/.gitlibs 27 | ~/.deps.clj 28 | key: cljdeps-${{ hashFiles('deps.edn') }} 29 | restore-keys: cljdeps- 30 | 31 | - name: Execute Typed Clojure 32 | run: mise typecheck 33 | -------------------------------------------------------------------------------- /tests.edn: -------------------------------------------------------------------------------- 1 | {:kaocha/tests 2 | [{:kaocha.testable/type :kaocha.type/clojure.test, 3 | :kaocha.testable/id :unit, 4 | :kaocha/ns-patterns ["-test$"], 5 | :kaocha/source-paths ["src"], 6 | :kaocha/test-paths ["test"], 7 | :kaocha.filter/skip-meta [:kaocha/skip]}], 8 | :kaocha/fail-fast? false, 9 | :kaocha/color? true, 10 | :kaocha/cli-options {:config-file "tests.edn", :print-config true}, 11 | :kaocha.plugin.randomize/seed 605325435, 12 | :kaocha.plugin.randomize/randomize? true, 13 | :kaocha/plugins 14 | [:kaocha.plugin/randomize 15 | :kaocha.plugin/filter 16 | :kaocha.plugin/capture-output 17 | :kaocha.plugin/profiling 18 | :kaocha.plugin/hooks], 19 | :kaocha.plugin.capture-output/capture-output? true, 20 | :kaocha/reporter [kaocha.report.progress/report] 21 | 22 | :kaocha.plugin.profiling/count 3 23 | :kaocha.plugin.profiling/profiling? true} 24 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src" "resources"] 2 | :deps 3 | {org.clojure/clojure {:mvn/version "1.12.1"} 4 | 5 | ;; Logging 6 | ; com.taoensso/telemere {:mvn/version "1.0.1"} 7 | 8 | ;; Schemas and type checking 9 | ; metosin/malli {:mvn/version "0.19.1"} 10 | org.typedclojure/typed.clj.runtime {:mvn/version "1.3.1-SNAPSHOT"} 11 | 12 | ;; System and state management 13 | ; mount/mount {:mvn/version "0.1.23"} 14 | 15 | ;; Error handling 16 | ; fmnoise/flow {:mvn/version "4.3.0"} 17 | 18 | ;; AWS 19 | ; com.cognitect.aws/api {:mvn/version "0.8.641"} 20 | ; com.cognitect.aws/endpoints {:mvn/version "1.1.12.398"} 21 | ; com.cognitect.aws/secretsmanager {:mvn/version "835.2.1307.0", :aws/serviceFullName "AWS Secrets Manager"} 22 | ; com.cognitect.aws/iot {:mvn/version "835.2.1307.0", :aws/serviceFullName "AWS IoT"} 23 | 24 | ;; JSON 25 | ; metosin/jsonista {:mvn/version "0.3.7"} 26 | 27 | ;; Time 28 | ; clojure.java-time/clojure.java-time {:mvn/version "1.2.0"} 29 | 30 | ;; HTTP 31 | ; hato/hato {:mvn/version "0.9.0"} 32 | } 33 | 34 | :aliases 35 | {:test {:extra-paths ["test"] 36 | :extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"} 37 | nubank/matcher-combinators {:mvn/version "3.9.1"}} 38 | :main-opts ["-m" "kaocha.runner"]} 39 | :flowstorm {:classpath-overrides {org.clojure/clojure nil} 40 | :extra-deps {com.github.flow-storm/clojure {:mvn/version "1.12.1"} 41 | com.github.flow-storm/flow-storm-dbg {:mvn/version "4.4.6"}} 42 | :jvm-opts ["-Dflowstorm.startRecording=false" 43 | "-Dclojure.storm.instrumentEnable=true" 44 | "-Dflowstorm.title=Storm" 45 | "-Dflowstorm.theme=dark"]} 46 | :dev {:extra-deps {cider/cider-nrepl {:mvn/version "0.56.0"}} 47 | :main-opts ["-m" "nrepl.cmdline" "--middleware" "[cider.nrepl/cider-middleware]"]} 48 | :antq {:deps {com.github.liquidz/antq {:mvn/version "2.11.1276"}} 49 | :main-opts ["-m" "antq.core"]} 50 | :typedclojure {:extra-deps {org.typedclojure/typed.clj.checker {:mvn/version "1.3.1-SNAPSHOT"}}} 51 | :typedclojure-lsp {:extra-deps {uk.me.oli/typedclojure-lsp {:mvn/version "0.0.7"} 52 | ;; io.github.olical/typedclojure-lsp {:git/sha "c935f8a5482d169401639c39046b97d3ed69c839"} 53 | } 54 | :main-opts ["-m" "typedclojure-lsp.main"]} 55 | :format {:deps {cljfmt/cljfmt {:mvn/version "0.9.2"}} 56 | :main-opts ["-m" "cljfmt.main" "fix"]} 57 | :build {:extra-deps {io.github.clojure/tools.build {:mvn/version "0.10.9"} 58 | slipset/deps-deploy {:mvn/version "0.2.2"}} 59 | :ns-default build}}} 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Clojure](https://clojure.org/) template 2 | 3 | A starting point for all of my Clojure projects, I hope you will find it useful too. Comes with a fully featured nREPL server, tests, formatter, CI and [debugger](https://github.com/flow-storm/flow-storm-debugger). 4 | 5 | Requires [mise](https://mise.jdx.dev/) to start various tasks which will also handle the Java and Clojure CLI versions for you automatically. Trust me, you'll love it once you try it. 6 | 7 | You can use any [nREPL](https://nrepl.org/nrepl/index.html) based Clojure editor plugins to talk to the REPL but I of course recommend my own, [Conjure](https://github.com/Olical/conjure), if you’re not sure where to start. If you’re really new to Clojure and don’t fancy diving into [Neovim](https://neovim.io/) then I’d probably recommend [Calva](https://calva.io/). 8 | 9 | Fork, copy, clone, borrow, read or browse. Do whatever you want with this repository and use it how you see fit. I like to do the following when starting a new project. 10 | 11 | > This repository is a GitHub template, so you can create a new repository based on it if you'd like! Or copy the files as shown below. 12 | 13 | ```bash 14 | # Notice the `/.` in order to copy the entire directory and it's hidden directories. 15 | cp -r clojure-template/. my-project 16 | cd my-project 17 | rm -rf .git 18 | git init 19 | ``` 20 | 21 | Let's stop talking about bike sheds and go paint some instead. Good luck, have fun! 22 | 23 | ## LSP 24 | 25 | Make sure you have a [LSP](https://microsoft.github.io/language-server-protocol/) client set up for your editor of choice and [clojure-lsp](https://clojure-lsp.io/) installed for the best experience. This will enable extra tooling like linting, in editor formatting, completion and integration with function instrumentation schemas. You can have in editor _type checking_ as you write your Clojure code if you set this up correctly. 26 | 27 | ## Tasks 28 | 29 | We use [mise](https://mise.jdx.dev/) to manage the JVM dependency and tasks we can perform on the project. 30 | 31 | ### `mise repl` 32 | 33 | Starts an nREPL server. Before you start working with the project you should run this in a terminal that you can keep safe in the background somewhere. 34 | 35 | Evaluate the keyword `:dbg` in order to open the [flowstorm](https://github.com/flow-storm/flow-storm-debugger) debugger window. How to use flowstorm is outside the scope of this README, but it's worth learning! 36 | 37 | ### `mise test` 38 | 39 | Run the test suite with [kaocha](https://github.com/lambdaisland/kaocha). Append `--watch` to execute your tests as you change files. 40 | 41 | ### `mise format` 42 | 43 | Format all of your code with [cljfmt](https://github.com/weavejester/cljfmt). 44 | 45 | ### `mise antq` 46 | 47 | Find and update dependencies with [antq](https://github.com/liquidz/antq). 48 | 49 | ```bash 50 | # Check for updates 51 | mise antq 52 | 53 | # Actually perform updates 54 | mise antq --upgrade 55 | ``` 56 | 57 | ### `mise clean / build / publish` 58 | 59 | Handles building and publishing JARs to Clojars. 60 | 61 | ### `mise typecheck` 62 | 63 | Type checking is provided by [Typed Clojure](https://github.com/typedclojure/typedclojure), my own [typedclojure-lsp](https://github.com/Olical/typedclojure-lsp) is pre-configured in this repository (see `.typedclojure-lsp/start`), you just need to add the LSP server configuration to your text editor. 64 | 65 | ## GitHub actions 66 | 67 | - Test: Runs the test suite through Kaocha. 68 | - Typecheck: Checks any marked namespaces with Typed Clojure. 69 | 70 | ## Unlicenced 71 | 72 | Find the full [unlicense](http://unlicense.org/) in the `UNLICENSE` file, but here’s a snippet. 73 | 74 | > This is free and unencumbered software released into the public domain. 75 | > 76 | > Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. 77 | --------------------------------------------------------------------------------