Tom Waddington

Projects

Free and open source software that I build and maintain.

Clojure libraries

  1. bytemap.clj

    bytemap.clj on Clojars

    bytemap.clj is more or less a Clojure port of Ian Henry’s Janet library, bytemap, a text-based graphics library with functions for plotting graphs.

    (defn golden-spiral
      "Draw the golden spiral on a canvas."
      [canvas {:keys [center scale max-θ start-angle]}]
      (let [φ       1.618033988749895
            [cx cy] center
            steps   1000]
        (loop [i          0
               prev-point nil
               canvas     canvas]
          (if (>= i steps)
            canvas
            (let [θ      (+ start-angle (* max-θ (/ i (dec steps))))
                  r      (* scale (Math/pow φ (/ θ (/ Math/PI 2))))
                  x      (+ cx (* r (Math/cos (- θ))))
                  y      (+ cy (* r (Math/sin (- θ))))
                  point  [(int x) (int y)]
                  canvas (if prev-point
                           (bm/draw-line canvas prev-point point)
                           canvas)]
              (recur (inc i) point canvas))))))
    
    (-> (bm/new-canvas 60 20)
        (golden-spiral {:center      [60 45]
                        :max-θ       (* 6 Math/PI)
                        :scale       0.5
                        :start-angle (* 0.75 Math/PI)})
        (bm/print-canvas!))
    
    =>⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡠⠤⠔⠒⠒⠒⠒⠒⠒⠒⠒⠤⠤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠔⠒⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠢⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠖⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠢⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⢀⠤⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠣⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⡔⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⡰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⡜⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⡜⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠞⠉⠀⠀⠈⢳⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⢯⣠⠞⠀⠀⠀⠀⠀⠀⠀⠀⠀⡼⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡼⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠦⣄⣀⡀⠀⢀⣀⡠⠔⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    
  2. skivi

    skivi on Clojars

    skivi is a Clojure/PostgreSQL job scheduling library, a bit like Graphile Worker but for Clojure.

    The code started life in 2012 as the mailer component of an application I was building at Games Workshop, called Bernard. It was called Bernard for ease of handwaving out of conversations with my non-technical line manager, who neither wanted nor needed to hear the specific details of how our backend was going to work, beyond “how’s Bernard coming along?”

    That project never saw the light of day, but I’ve been copying these 3 .clj and .sql files from one side-project to another ever since, migrating it from Oracle to PostgreSQL and gradually modifying and extending it to various mail services along the way.

    At Medicspot, we used Graphile Worker pretty extensively to run our COVID-19 operation. I realised last year that my old mailer component was actually most of the way to being a generic job scheduling library and started refactoring it as a Polylith library.

    I used Claude Code with the juxt/allium skill to get it over the line.

  3. still

    still on Clojars

    still is a Clojure self-modifying snapshot testing library inspired by Ian Henry’s My Kind of REPL.

    still/snap! statements will automatically populate with the snapshot result when evaluated in the REPL, behave as an assert during runtime, and act like an (is (=)) test inside deftest.

    An asciinema recording of using still in Helix via nrepl.hx
    An asciinema recording of using still in Helix, via nrepl.hx.

Command-line tools

  1. dathan

    dathan leverages the Helix runtime to render code to syntax-highlighted HTML, CSS, or ANSI escape codes.

    Think Pygments, but the output matches your editor exactly (assuming your editor is Helix). And it has a Hiccup output mode.

  2. quipu

    quipu is a terminal keyboard entry scripting tool written in Rust. I use it to script asciinema recordings and generate demo GIFs for projects, pull requests, etc.

    There are lots of tools out there like this, but everything else I tried had some problem with my environment, or couldn’t script modified keys, or didn’t work with TUIs. So, I fired up Claude Code and built my own.

    The quipu repo also includes a tree-sitter grammar, so editing the scripts looks nice.

Helix plug-ins

Helix is my favourite text editor. There’s currently a fork in progress, adding support for plug-ins via Steel, a dialect of Scheme.

  1. Juju

    Juju is a git/jj UI. Sort of like Magit for Emacs, but with Helix idioms and support for a VCS I enjoy using.

    Very early alpha of software that could potentially nobble your repo if there are any bugs, although I haven’t managed to break anything yet in testing.

    Interactive rebase of a git repo with Juju.
    An asciinema recording of interactively rebasing a git repo with Juju in Helix.
  2. emotional.hx

    Additional motions for Helix: moving lines, motions that respect line boundaries, word motions where a count selects everything it passes over, and matching the next or previous character pair.

  3. eval.hx

    A persistent scratch buffer for :eval-string wrappers: eval at prompt, by selection(s), or the entire buffer.

    An asciinema recording of evaluating code to the eval.hx buffer in Helix
    An asciinema recording of evaluating code to the eval.hx buffer in Helix
  4. extend-sibling.hx

    :extend_next_sibling/:extend_prev_sibling counterparts to :select_next_sibling/:select_prev_sibling, because the select variants’ behaviour is surprising for many people in select mode.

  5. http.hx

    http.hx is a plug-in for Helix that lets you trigger http requests via curl, getting the response back in a *scratch* buffer. It effectively mimics VSCode’s REST client plug-in and uses the same syntax, without needing its own backend. So, you can store queries in plain text in your repo like this:

    # HTTP requests with variable substitution
    
    @protocol = https
    @baseUrl = {{protocol}}://httpbin.io
    @token = test-token-123
    @userId = 42
    
    # GET with variable in URL
    GET {{baseUrl}}/get
    
    ###
    
    # GET with authorization header
    GET {{baseUrl}}/bearer
    Authorization: Bearer {{token}}
    
    ###
    
    # GET with query parameter using variable
    GET {{baseUrl}}/anything/{{userId}}
    
    ###
    

    Then highlight and execute them via curl, viewing the response in a scratch buffer:

    An asciinema recording of interacting with an HTTP API in Helix
    An asciinema recording of interacting with an HTTP API in Helix

    Also serves as an example of shelling out to a command from Steel with support for potentially long-running and lengthy stdout/stderr output. That functionality is extracted to a library, run-command.scm, if you have a similar requirement.

  6. insert-literal.hx

    Insert the next keypress literally, or just suppress auto-pairing.

  7. matte.hx

    Zen mode for Helix: commands to centre buffers, and zoom/restore splits, plus a convenience function to do both at once. Configurable width, soft wrapping, and bufferline hiding.

    An asciinema recording of matte.hx in action
    An asciinema recording of matte.hx in action.
  8. nREPL.hx

    I wrote the nREPL.hx client in Steel and Rust to enable Clojure REPL integration in Helix. But it’s a generic nREPL client with dedicated adapters for Janet and Steel Scheme too.

    An asciinema recording of interacting with a Clojure nREPL in Helix
    An asciinema recording of interacting with a Clojure nREPL in Helix.
  9. paredit.hx

    A tree-sitter-based Paredit implementation for Helix (with the Steel plug-in system), inspired by nvim-paredit.

    Just the bits Helix doesn’t already do with tree-sitter nodes and textobjects: slurping, barfing, dragging, raising and splicing, for Clojure, Common Lisp, Fennel, Janet, and Scheme.

    Barfing and slurping in Helix with paredit.hx
    Barfing and slurping in Helix with paredit.hx
  10. previously.hx

    A unified history picker for yanks, searches, and typed commands.

  11. select-ts.hx

    Create selections in Helix based on ad hoc tree-sitter queries. Narrows existing selections if they exist.

    Selecting all Go function names with a tree-sitter query
    Selecting all Go function names with a tree-sitter query
  12. switch-case.hx

    Additional text case conversion commands (kebab/camel/snake case, etc.)

    Essentially a Scheme port from an abandoned PR to the core editor, as a demonstration of the plug-in system.

LLM tools

Toll the great bell thrice.

  1. Nautilos

    Nautilos is a CLI/MCP server/skill/plugin for coding harnesses, improving nREPL interaction.

    I noticed three persistent issues with how coding harnesses use REPL-y languages:

    • Running one-off commands repeatedly, with ever-growing state recreated every time.
    • Inability to maintain state with servers that scope it to the connection, due to lack of persistence between commands.
    • Starting a REPL via tmux, typically leaving a trail of abandoned but still-running sessions behind as it goes.

    Nautilos is a small (~1-2MB depending on platform/architecture), native, Janet binary for macOS/Linux that opens a connection to any nREPL server as a daemon, maintaining the connection between commands.

    An LLM can then issue commands as their preferred single CLI calls, receiving each response as a single JSON object, including support for lookups/completions to allow for exploring the codebase/library functions.

    Obviously the command will work just fine if issued by a human too, the response is just tailored for agents. You could maybe pipe it through jq or something.

Steel/Helix libraries

Shared libraries for Helix plug-ins.

  1. run-command.scm

    Library function for shelling out on POSIX platforms.

  2. steel-test

    A Steel Scheme unit testing library inspired by clojure.test.

  3. ts-utils.hx

    Helper functions for tree-sitter traversal.

  4. ui-utils.hx

    A library of the shared UI helper functions used by nREPL.hx and Juju.

nREPL servers

nREPL is a language-agnostic protocol for networked REPLs.

  1. nrepl-janet

    A reasonably fully-featured nREPL client/server library for the Janet programming language.

  2. nrepl-steel

    A minimal nREPL server library for the Steel Scheme programming language.