REPL workflow

One of the best things about Clojure is the REPL workflow: you can change code while a game is running and see the change immediately.

Two REPL modes

Embedded (game)Standalone
Port78887999
Startbb <demo> in raylib-clj-demobb nrepl
Can open a window (macOS)YesNo

Most games start an embedded nREPL server on port 7888. Most of the raylib-clj-demo scenes do, and a few, such as pong and camera-2d, don't call nrepl/start. The commands below use its asteroids scene. This is the proper way to do live development for a game that starts the server:

sequenceDiagram
    participant Terminal
    participant Game
    participant nREPL as nREPL:7888
    participant Editor

    Terminal->>Game: bb asteroids (in raylib-clj-demo)
    Game->>nREPL: Start embedded nREPL on 7888
    Game->>Game: Open window & run
    Editor->>nREPL: Connect to localhost:7888

    loop Live Development
        Editor->>nREPL: Modify & eval function
        nREPL->>Game: Hot-reload code
        Game-->>Editor: See changes instantly!
    end

Step 1: Start a game (it launches nREPL automatically):

bb asteroids   # from the root of raylib-clj-demo

You'll see in the logs:

INFO: starting nREPL server on port 7888

Step 2: Connect your editor to localhost:7888: - VS Code/Calva: Run "Calva: Connect to a Running REPL Server" - IntelliJ/Cursive: Run → Edit Configurations → Remote REPL

Step 3: Modify code live! Try these from your connected REPL:

;; Access the running game state
@net.b12n.raylib-clj.scenes.asteroids/game-atom

;; Reset the game
(reset! net.b12n.raylib-clj.scenes.asteroids/game-atom (net.b12n.raylib-clj.scenes.asteroids/initial-state))

;; Make the ship bigger
(swap! net.b12n.raylib-clj.scenes.asteroids/game-atom assoc-in [:ship :size] 50)

;; Spawn more asteroids
(swap! net.b12n.raylib-clj.scenes.asteroids/game-atom update :asteroids 
       concat (repeatedly 5 net.b12n.raylib-clj.scenes.asteroids/make-asteroid))

Why macOS can't open windows from a standalone REPL

On macOS, you cannot open a raylib window from the standalone :dev REPL, only from a game started fresh (bb asteroids in raylib-clj-demo, say), which is why live game development connects to the game's own embedded nREPL instead of running the game from :dev. See Coffi & Panama Internals for the -XstartOnFirstThread flag and exactly what is (and isn't) verified about why this is the rule.

Standalone REPL for non-GUI work

For exploring code, testing logic, or non-GUI work, use the standalone REPL:

bb nrepl   # or: clj -M:dev (starts on port 7999)

Port note: Standalone REPL uses port 7999 to avoid conflicts with games that use 7888.

What works from standalone REPL:

;; Load and explore FFI bindings
(require '[net.b12n.raylib-clj.colors :as colors])
(require '[net.b12n.raylib-clj.enums :as enums])

;; Colors are just Clojure maps!
colors/red
;; => {:r 230, :g 41, :b 55, :a 255}

;; Create custom colors
(def my-purple {:r 128 :g 0 :b 255 :a 255})

;; Test game logic (pure functions)
(require '[net.b12n.raylib-clj.scenes.asteroids :as ast])  ; needs raylib-clj-demo's asteroids project on the classpath

(ast/vector-add [1 2] [3 4])
;; => [4 6]

(ast/check-point-circle [100 100] [100 100] 50)
;; => true (collision!)

;; Explore game state structure
(keys (ast/initial-state))
;; => (:bullets :screen :dt :alive :asteroids :ship ...)

REPL capability summary

CapabilityStandalone REPLConnected to Game
Load FFI bindings✅✅
Inspect colors/enums✅✅
Test pure game logic✅✅
Open windows/render❌ (macOS)✅
Modify running game❌✅
Hot-reload functions❌✅