--- title: "Python" description: "Python SDK for Rocksky — native bindings to the shared Rust core." icon: "python" --- `rocksky` is native bindings to the shared Rocksky Rust core (via UniFFI): AppView reads, AT Protocol PDS writes, a local dedup index, and the identity hashes — the same engine behind every Rocksky SDK. ## Install ```bash uv uv add rocksky==0.6.0 ``` ```bash pip pip install rocksky==0.6.0 ``` The wheel is pure-Python; the native library is fetched from the GitHub release on first import and cached. ## Quickstart ```python from rocksky import AppView, Agent, ScrobbleInput, song_hash # Reads — unauthenticated. AppView() uses https://api.rocksky.app. av = AppView() print(av.global_stats().scrobbles) for t in av.top_tracks(10, 0): print(t.artist, "—", t.title) # Writes — log in with an app password. agent = Agent.login_password("session.json", "alice.bsky.social", "app-password", None, None) out = agent.scrobble(ScrobbleInput( title="Chaser", artist="Calibro 35", album="Jazzploitation", album_artist="Calibro 35", duration_ms=182320, )) print(out.scrobble_uri) ``` ## API **Reads — `AppView(base=None, token=None)`** (pass `token` to send `Authorization: Bearer` on auth-gated queries). Typed views: `profile`, `scrobbles`, `songs`, `albums`, `artists`, `loved_songs`, `catalog_albums` / `catalog_artists` / `catalog_songs`, `album_tracks`, `artist_albums` / `artist_tracks`, `scrobble_feed`, `scrobble` (single), `follows` / `followers` / `known_followers`, `top_tracks`, `top_artists`, `global_stats`. Date-window charts `top_tracks_interval(limit, offset, interval)` and `top_artists_interval(...)` take a `DateInterval` (`ALL_TIME`, `LAST_DAYS(days=7)`, `LAST_WEEKS`, `LAST_MONTHS`, `LAST_YEARS`, `RANGE(start=..., end=...)`). `match_song(title, artist, mb_id, isrc)` resolves a bare title+artist to canonical metadata. A raw-JSON long tail (`album`, `artist`, `song`, `playlists`, `playlist`, `stats`, `wrapped`, `scrobbles_chart`, `recommendations`, `neighbours`, shouts, …) returns JSON strings, and `av.get(nsid, params)` (a `dict[str, str]`) calls **any** read query by NSID. **Writes — `Agent`**: `login_password(...)`, then `scrobble` (full metadata) or `scrobble_match(ScrobbleMatchInput(title, artist, album=None, mb_id=None, isrc=None, timestamp=None))` (resolve via `match_song`, then fan out — `title`/ `artist` required, `timestamp` is scrobbled-at Unix seconds; `ScrobbleMatchInput` imports from `rocksky`), `create_song` / `create_album` / `create_artist`, `like` / `unlike`, `follow` / `unfollow`, `shout` / `reply_shout`, `set_now_playing` / `clear_now_playing`, `sync_repo` (dedup backfill, returns per-collection counts as JSON), `hydrate_from_jetstream` (live dedup off the firehose). **Identity hashes**: `song_hash`, `album_hash`, `artist_hash`. ## Duplicate prevention Pass a `dedup_path` to `Agent.login_password` to enable the local index, then `agent.sync_repo()` to backfill it from the repo. With it, write verbs skip records that already exist.