An idiomatic, pipe-friendly Clojure client for the Rocksky XRPC API.
->.query (GET) and procedure (POST) cover the whole
XRPC surface. Resource namespaces are thin wrappers on top.deps.edn:
{:deps {app.rocksky/sdk {:mvn/version "0.1.1-SNAPSHOT"}}}
Leiningen / Boot:
[app.rocksky/sdk "0.1.1-SNAPSHOT"]
Or, to track a specific commit instead of a release:
{:deps {app.rocksky/sdk {:git/url "https://github.com/tsirysndr/rocksky"
:git/sha "..."
:deps/root "sdk/clojure"}}}
(require '[rocksky.core :as rs])
(def client (rs/client)) ;; defaults to https://api.rocksky.app
(rs/get-profile client {:did "did:plc:7vdlgi2bflelz7mmuxoqjfcr"})
;; => {:handle "tsiry-sandratraina.com" :followersCount 42 ...}
For authenticated endpoints, pass a bearer token:
(def client (rs/client {:token (System/getenv "ROCKSKY_TOKEN")}))
(require '[rocksky.scrobble :as scrobble])
(scrobble/create-scrobble client
{:title "Paranoid Android"
:artist "Radiohead"
:album "OK Computer"})
Clients are immutable values; every helper that mutates state returns a new client. That makes it natural to build, authenticate, and call in one threading expression:
(require '[rocksky.client :as c]
'[rocksky.actor :as actor])
(-> (c/client {:base-url "https://api.rocksky.app"})
(c/with-token (System/getenv "ROCKSKY_TOKEN"))
(actor/get-profile {:did "did:plc:7vdlgi2bflelz7mmuxoqjfcr"})
:handle)
;; => "tsiry-sandratraina.com"
Or reshape responses inline:
(require '[rocksky.charts :as charts])
(->> (charts/get-top-tracks (c/client) {:limit 5})
:tracks
(map :title))
;; => ("Paranoid Android" "Karma Police" ...)
Anything missing from the resource namespaces is one line away — the
generic query / procedure helpers accept any NSID.
(c/query client :app.rocksky.feed.describeFeedGenerator)
(c/procedure client :app.rocksky.shout.createShout {:message "hi"})
Non-2xx responses throw ex-info. Catch it and inspect the ex-data:
(try
(album/get-album client {:uri "at://missing"})
(catch clojure.lang.ExceptionInfo e
(let [{:keys [status nsid body]} (ex-data e)]
(println status nsid body))))
A client is a value — share it across threads with pmap / future:
(pmap #(actor/get-profile client {:did %}) handles)
| Namespace | Wraps |
|---|---|
rocksky.actor | app.rocksky.actor.* |
rocksky.album | app.rocksky.album.* |
rocksky.apikey | app.rocksky.apikey.* |
rocksky.artist | app.rocksky.artist.* |
rocksky.charts | app.rocksky.charts.* |
rocksky.dropbox | app.rocksky.dropbox.* |
rocksky.feed | app.rocksky.feed.* |
rocksky.googledrive | app.rocksky.googledrive.* |
rocksky.graph | app.rocksky.graph.* |
rocksky.like | app.rocksky.like.* |
rocksky.mirror | app.rocksky.mirror.* |
rocksky.player | app.rocksky.player.* |
rocksky.playlist | app.rocksky.playlist.* |
rocksky.scrobble | app.rocksky.scrobble.* |
rocksky.shout | app.rocksky.shout.* |
rocksky.song | app.rocksky.song.* |
rocksky.spotify | app.rocksky.spotify.* |
rocksky.stats | app.rocksky.stats.* |
:start-date → startDate, :album-art → albumArt, etc., so you can
write idiomatic Clojure params. The raw HTTP body / query string still
uses camelCase, matching the lexicons under apps/api/lexicons.:limit nil and the param won't appear
on the wire — handy for building params with cond->.:enabled false is preserved (not coerced to
nil) so toggles work correctly.Browse the examples/ directory:
| File | Shows |
|---|---|
01_quickstart.clj | Smallest possible call |
02_pipe_friendly.clj | Threading construction → auth → request |
03_paginate_scrobbles.clj | Lazy pagination over offset endpoints |
04_scrobble_a_track.clj | Authenticated POST |
05_search_and_listen.clj | Search → drill down |
06_error_handling.clj | Catching ex-info from non-2xx |
07_concurrent_requests.clj | pmap across a shared client |
# Run the test suite
clojure -X:test
# Start an nREPL on localhost:7888
clojure -M:nrepl
The tests mock the HTTP layer by passing :http-fn to client, so they
run offline and finish in well under a second.
The SDK ships with a tools.build + deps-deploy pipeline. From this
directory:
clojure -T:build clean
clojure -T:build jar # build the jar in target/
clojure -T:build install # install locally to ~/.m2 for testing
clojure -T:build deploy # publish to Clojars
Deploying needs Clojars credentials in the environment:
export CLOJARS_USERNAME=your-username
export CLOJARS_PASSWORD=your-clojars-deploy-token # NOT your password
clojure -T:build deploy
Bump version in build.clj and add a new entry to CHANGELOG.md
before deploying. The default release tag pattern is
sdk-clojure-v<version>.
MIT © Tsiry Sandratraina.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |