mount an atproto PDS repository as a FUSE filesystem
1pdsfs - mount an atproto PDS repository as a FUSE filesystem. 2 3a PDS repository[0] contains all data published by a user to 4the atmosphere[1]. it is exportable as a CAR 5(content-addressable archive) file. pdsfs is a tool that 6mounts this CAR file as a readonly-FUSE filesystem, allowing 7quick and easy exploration. 8 9to motivate the need for such a program, we could begin by 10mounting a repository: 11 12 13 λ pdsfs oppi.li 14 mounted at "mnt" 15 hit enter to unmount and exit... 16 17 18oppi.li is my handle in the atmosphere. the tool does some 19hardwork to determine the location of my PDS repository 20given my handle, but that is not important. lets have a look 21around: 22 23 24 λ ls mnt/ 25 did:plc:qfpnj4og54vl56wngdriaxug/ 26 27 28the did:plc:stuff is my DID. lets dig deeper: 29 30 31 λ ls mnt/did\:plc\:qfpnj4og54vl56wngdriaxug/ 32 app.bsky.actor.profile/ place.stream.chat.message/ 33 app.bsky.actor.status/ place.stream.chat.profile/ 34 app.bsky.feed.generator/ place.stream.key/ 35 app.bsky.feed.like/ place.stream.livestream/ 36 app.bsky.feed.post/ sh.tangled.actor.profile/ 37 app.bsky.feed.repost/ sh.tangled.feed.reaction/ 38 app.bsky.graph.block/ sh.tangled.feed.star/ 39 app.bsky.graph.follow/ sh.tangled.graph.follow/ 40 app.rocksky.album/ sh.tangled.knot/ 41 app.rocksky.artist/ sh.tangled.knot.member/ 42 . 43 . 44 . 45 46 47we have some data from the repository now. these are 48"collections". if i want to publish a post to bluesky, i 49would write content to the "app.bsky.feed.post" collection 50in my PDS. this will then be indexed by a bluesky appview 51(bsky.app or zeppelin.social to name a few) and show up 52under my profile there. 53 54pdsfs is kind enough to deserialize the data stored (as 55CBOR) in the PDS repository to JSON: 56 57 58 λ cat sh.tangled.repo/3ljidbevrjh22 | jq 59 { 60 "$type": "sh.tangled.repo", 61 "addedAt": "2025-03-03T16:04:13Z", 62 "knot": "knot1.tangled.sh", 63 "name": "hello-world", 64 "owner": "did:plc:3danwc67lo7obz2fmdg6jxcr" 65 } 66 67 68thanks pdsfs! 69 70i publish my music listening habits to my PDS to the 71"app.rocksky.scrobble" collection, because rocksky[4] 72recognizes and indexes this collection. i have wired up my 73personal navidrome instance to write data of this form into 74my PDS everytime i listen to a track. here are my top 75artists in order: 76 77 78 λ cat app.rocksky.scrobble/* | jq -r '.artist' | sort | uniq -c | sort -nr 79 117 Thank You Scientist 80 45 FKJ 81 34 Covet 82 33 VOLA 83 23 Sam Cooke 84 22 Dark Tranquillity 85 21 Piero Piccioni 86 12 Bloodywood 87 11 Frank Sinatra 88 10 Dream Theater 89 90 91it is true, i love sam cooke. 92 93pdsfs allows mounting multiple repositories at a time. allow 94me to introduce my friends: 95 96 97 λ pdsfs icyphox.sh anil.recoil.org steveklabnik.com tangled.sh 98 using cached CAR file for...did:plc:hwevmowznbiukdf6uk5dwrrq 99 using cached CAR file for...did:plc:nhyitepp3u4u6fcfboegzcjw 100 download complete for...did:plc:3danwc67lo7obz2fmdg6jxcr 101 download complete for...did:plc:wshs7t2adsemcrrd4snkeqli 102 mounted at "mnt" 103 hit enter to unmount and exit... 104 105 106 # -- in a separate shell -- 107 108 109 λ cat ./mnt/*/app.bsky.actor.profile/* \ 110 | jq -r '"\(.displayName)\n\(.description)\n---"' \ 111 | sed '/^$/d' 112 Steve Klabnik 113 #rustlang, #jj-vcs, atproto, shitposts, urbanism. I 114 contain multitudes. Working on #ruelang but just for 115 fun. Currently in Austin, TX, but from Pittsburgh. 116 Previously in Bushwick, the Mission, LA. 117 --- 118 Anirudh Oppiliappan 119 building @tangled.sh — code collaboration platform built 120 on atproto helsinki, finland · https://anirudh.fi · 121 (somewhat) effective altruist 122 --- 123 Anil Madhavapeddy 124 Professor of Planetary Computing at the University of 125 Cambridge @cst.cam.ac.uk, where I co-lead the 126 @eeg.cl.cam.ac.uk, and am also to found at 127 @conservation.cam.ac.uk. Homepage at 128 https://anil.recoil.org 129 --- 130 Tangled 131 https://tangled.sh is a git collaboration platform built 132 on atproto. Social coding, but for real this time! 133 Discord: chat.tangled.sh IRC: #tangled @ libera.chat 134 Built by @oppi.li & @icyphox.sh 135 --- 136 137 138all my friends use tangled.sh, which requires them to 139publish their ssh public key to their PDii (PDSes?). perhaps 140i would like to add their keys to my allowed_signers file to 141verify their commit signatures: 142 143 144 λ for dir in ./*/sh.tangled.publicKey; 145 do cat $dir/$(ls -r $dir | head -n1) | jq -r '.key'; 146 done | tee allowed_signers 147 ssh-rsa AAAAB3NzaC1yc2EAAA...dHPqc= steveklabnik@DESKTOP-VV370NK 148 ssh-ed25519 AAAAC3NzaC1lZD...g9bAdk icy@wyndle 149 ssh-ed25519 AAAAC3NzaC1lZD...BqlM1u anil@recoil.org 150 151 152 153--- 154 155 156FUSE is quite liberating in that it allows you to represent 157anything as a filesystem. when applications like ls and cat 158are executed, the system calls to open and read are rerouted 159to your custom fs implementation (pdsfs in this case). the 160custom fs implementation is free to as it pleases, in fact 161the first iteration of pdsfs accessed the network for each 162open/read call to fetch live data from PDii. 163 164 165[0]: https://atproto.com/guides/data-repos 166[1]: https://atproto.com 167[2]: https://docs.bsky.app/docs/api/com-atproto-sync-get-repo 168[3]: https://tangled.sh/keys/oppi.li 169[4]: https://rocksky.app