Troubleshooting
"Library not found" error
Make sure you're running from the project root directory where libs/ folder exists.
macOS security warning
Run bb macos:sign-lib or manually sign the library:
codesign --force --sign - libs/macos/libraylib.6.0.0.dylib
See Architecture: macOS code signing for more detail.
"No matching method" or FFI errors
Ensure you're using JDK 22 or newer:
java -version # Should show 22.x.x or higher
Window doesn't appear on macOS
The -XstartOnFirstThread flag is required. This is already configured in deps.edn and project.clj.
See Coffi & Panama Internals for why this flag is necessary and what it does.
Unrecognized option: -XstartOnFirstThread (Linux)
Unrecognized option: -XstartOnFirstThread
Error: Could not create the Java Virtual Machine.
You ran a command that carries -XstartOnFirstThread on Linux, such as the :check or :dev alias in deps.edn, or a raylib-clj-demo alias. macOS requires the flag to run OpenGL on the main thread, but it is a macOS-only flag, and the JVM treats any unrecognized -X option as fatal rather than ignoring it.
Leave the flag out on Linux. A raw command for a game namespace:
clojure -J--enable-native-access=ALL-UNNAMED \
-J-Djava.library.path=libs:libs/linux_amd64:/usr/local/lib:/usr/lib \
-M -m your.game.ns
A GUI app misbehaves when launched with clj
Use clojure, not clj. clj wraps the same launcher in rlwrap for line editing, which does not play well with a GUI app holding the main thread. Every bb task here that starts a JVM shells out to clojure for this reason.
clj remains the better choice for a plain REPL, where the line editing is what you want.
WARNING: A restricted method in java.lang.foreign.Linker has been called
Harmless in itself, but it tells you something: you are running without the project's JVM flags. The :check and :dev aliases in deps.edn pass --enable-native-access=ALL-UNNAMED, which suppresses this warning entirely. Seeing it means you invoked a bare clojure -e ... or a plain REPL instead.
The full block looks like this, and appears only when the flag is missing:
WARNING: A restricted method in java.lang.foreign.Linker has been called
WARNING: java.lang.foreign.Linker::downcallHandle has been called by
coffi.ffi$downcall_handle in an unnamed module
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for
callers in this module
WARNING: Restricted methods will be blocked in a future release unless
native access is enabled
Nothing breaks today, but note the last line. A future JDK will block these calls rather than warn, so get the flag onto your command line rather than learning to ignore the message:
clojure -J--enable-native-access=ALL-UNNAMED -J-Djava.library.path=libs:libs/macos ...
Build tools comparison
This project supports both the Clojure CLI and Leiningen:
| Feature | Clojure CLI (deps.edn) | Leiningen (project.clj) |
|---|---|---|
| Compile-check every namespace | clojure -M:check (or bb check) | N/A |
| Start REPL | clj | lein repl |
| Start nREPL | bb nrepl (or clojure -M:dev) | lein repl |
clj is fine for a plain REPL; the rlwrap line editing it adds is useful there. It is only GUI apps that need clojure.