bluesky-social

Stars and mentions

Last 30 days, Oct 4 – Nov 2

GitHub stars155
mentions294
015304560Oct 4Oct 18Nov 2
UTC days · repositories bluesky-social owns11 repositories

Package downloads

Cumulative recorded downloads · since 2025-10-19

npm42.2M
010.6M21.1M31.7M42.2MOct 4Oct 18Nov 2
Oct 29npm: 27/29 packages observed

Across 29 known packages in repositories bluesky-social owns. Cumulative totals include recorded downloads before the selected range. Missing observations leave gaps; totals may be incomplete.

Top repositories

bluesky-social’s repositories ranked by new forks, as on trending.

Loading

Contributes to

Repositories outside bluesky-social’s account where bluesky-social opened or reviewed pull requests in the past 365 days.

Who noticed bluesky-social

Everyone who starred or forked bluesky-social’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

294posts
Nov 32 posts
  1. Can Someone See Who You Blocked on Bluesky? Yes. Here's How to Check Every account you've blocked on Bluesky is sitting in a public JSON endpoint. So is every post you've liked, everyone you follow, and every list you've added someone to. You don't need an account, an API key or a scraper to read it, just one curl. So can someone see who you blocked on Bluesky? Yes, and that includes the person you blocked. Is Bluesky private? For your social graph, no. Most people who came over from X assume blocks and likes work like they did there, visible to you and the platform and nobody else. On AT Protocol they're records in your public repository, and anyone can download that repository. This came up again on October 29, when Melanie Kat published Do At-Proto Users Know This Is Public?. She looked at Skyreader, an RSS reader built on atproto, which stores each feed you subscribe to as a record in your repo. Without logging in anywhere, she pulled over 1,300 feed URLs, including someone's private Club MacStories feed, paywalled 404 Media full-text feeds, Patreon backer-only feeds and private GitLab repo feeds. With feeds like these the URL works as the password, and Kat says the MacStories one gave her full access to the paid content. The Lobsters thread got heated fast. One commenter described the privacy model as "none". What anyone can read from your PDS with curl Your account lives on a PDS (Personal Data Server). For most people that's a server run by Bluesky, but the data model is the same everywhere. Your repo is split into collections, and each collection holds records. Here's how you look yourself up: HANDLE=yourname.bsky.social # handle -> DID DID=$(curl -s "https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle=$HANDLE" | jq -r .did) # DID -> which PDS hosts you (works for did:plc, which is almost everyone) PDS=$(curl -s "https://plc.directory/$DID" | jq -r '.service[] | select(.id=="#atproto_pds") | .serviceEndpoint') # what collections exist in your repo curl -s "$PDS/xrpc/com.atproto.repo.describeRepo?repo=$DID" | jq .collections # everyone you've blocked curl -s "$PDS/xrpc/com.atproto.repo.listRecords?repo=$DID&collection=app.bsky.graph.block&limit=100" \ | jq -r '.records[] | "\(.value.createdAt) \(.value.subject)"' That last command prints a timestamp and a DID for every block (the first 100 of them; the response includes a cursor if there are more). Swap the collection for app.bsky.feed.like and you get every post you've liked, with dates. If you'd rather grab the whole thing at once: curl -s -o repo.car "$PDS/xrpc/com.atproto.sync.getRepo?did=$DID" The official docs for com.atproto.sync.getRepo list one required parameter, the DID. You get back an application/vnd.ipld.car archive of your entire repo, and the call usually needs no auth. If clicking is more your thing, pdsls.dev does the same in a browser. Type a handle and browse every collection. That's the tool Kat used. Reading one person's repo is the small version of the problem. A relay can also answer "which accounts have any records in collection X?" through com.atproto.sync.listReposByCollection: curl -s "https://bsky.network/xrpc/com.atproto.sync.listReposByCollection?collection=app.bsky.graph.block&limit=2" That's the kind of relay query Kat describes. It took her from a few reviewers' handles to every DID with Skyreader subscriptions, and then she pulled each one's records from their PDS. She says a few Discord clones store every message openly too, and that you can watch and search chat across Stream.place. Third-party sites like ClearSky build on the same data to show who is blocking whom. Public vs private on Bluesky | Data | Where it lives | Who can read it | |---|---|---| | Posts, reposts | app.bsky.feed.post, app.bsky.feed.repost | Anyone | | Likes | app.bsky.feed.like | Anyone | | Follows | app.bsky.graph.follow | Anyone | | Blocks | app.bsky.graph.block | Anyone | | Lists you made, and who's on them | app.bsky.graph.list, app.bsky.graph.listitem | Anyone | | Blocklists you subscribe to | app.bsky.graph.listblock | Anyone | | Records from third-party atproto apps | Whatever lexicon the app picked | Anyone, unless the app keeps it off your PDS | | Mutes | Bluesky App, not your PDS | You | | Bookmarks | Bluesky App, not your PDS | You | | Preferences (muted words, saved feeds) | Your PDS, behind auth | You | | DMs | Bluesky's chat service | You, the other person, and Bluesky | The mutes and bookmarks rows come straight from Bluesky's docs: "Mutes are private — like Bookmarks, they are stored in the Bluesky App, rather than in your PDS." The same page has a short line on blocks: "Blocks are public." DMs aren't in your repo, though that doesn't make them private. Native Bluesky DMs are not end-to-end encrypted. Coverage of the launch said E2EE was coming "down the line" and that Bluesky's moderation team may need to open your DMs to investigate abuse. If you need E2EE, Germ is a separate MLS-based messenger that shows up inside the Bluesky app. The official app hides this a little. You can see the Likes tab on your own profile and nobody else's. That's purely a UI choice, and the records are still served to anyone who asks the API. Why Bluesky blocks are public The atproto team explained this in June 2023 in Why are blocks on Bluesky public?. The short version: a block has to be enforced by servers you don't control. Your PDS, the AppView, feed generators and any third-party client all need to know that A blocked B, or B's replies still show up under A's posts. As the post puts it, "all servers across the network need to know that they exist in order to respect the user's request." Mutes skip the problem because a mute only changes what you see, so the client can handle it alone. The team listed alternatives they considered: Bloom filters, keeping block data on a small set of trusted AppViews, and zero-knowledge proofs like SNARKBlock. Their objection to Bloom filters was that they "don't fully prevent enumerating blocks", on top of the storage and bandwidth cost. In the end they shipped public blocks and said they hadn't ruled the others out. That was more than three years ago, and blocks are still public. I think the engineering reasoning holds up. The way the app presents it doesn't. The block button looks exactly like the one on X. Nothing tells you that you're writing a timestamped, permanent public record saying "I don't want to hear from this person." For someone blocking a stalker or an ex, that matters, because the person they blocked can find out. Is Bluesky fixing it? Permissioned data Sort of. Bluesky is working on "permissioned data", which would let records live on your PDS without being broadcast to the whole network. Daniel Holmgren's February 2026 design diary describes it as data that "isn't broadcasted out over the firehose" and that only users and services with explicit permission can read. His examples include private groups, paywalled content, mutes, bookmarks, drafts and DMs. He rules out end-to-end encryption as the base design, mostly because search, notifications and moderation all need servers that can read the data, and leaves E2EE to individual apps that need it. Blocks aren't on that list. Even when permissioned data ships, I wouldn't expect block records to move off the public repo, because the enforcement problem from 2023 is still there. What you can do today 1. Audit your own repo. Run the commands above or open pdsls.dev and look at every collection. The third-party ones from apps you tried once and forgot are where the surprises are. 2. Mute when you don't want it to be known. A mute is private and a block is not. If the goal is to stop seeing someone without them being able to find out, mute them. 3. Treat list membership as public speech. Adding someone to a moderation list publishes that they're on it and that you put them there. 4. Delete old likes, with realistic expectations. Unliking deletes the record from your repo, so listRecords and getRepo stop returning it. But the like went out over the relay firehose when you made it, and Jetstream rebroadcasts the same records as JSON that anyone can filter by collection or DID (FeatherReader's network notes walk through both). The delete is just another event. Any indexer or archive that was listening keeps its copy unless it chooses to honor the delete. Deleting helps against casual snooping. It won't stop someone who was already collecting. 5. Check third-party apps before you sign in. In the Lobsters thread, Skyreader's developer said subscription syncing is already off by default "with a big warning that enabling it will make your subscriptions public," and that the real fix is moving subscriptions to atproto spaces once they're ready. Other apps make their own choices. If an app writes custom records to your PDS, assume they're public. 6. Don't self-host a PDS for privacy. A lot of people suggest it, and it doesn't help. A self-hosted PDS serves the same public repo through the same getRepo endpoint, and it has to, or the rest of the network can't see your posts or enforce your blocks. Self-hosting gives you control over where your data lives and who can take your account down, and that's about it. You'll also need a server with a public IP, DNS and ports 80/443 open (the bluesky-social/pds README covers the setup). 7. Or accept it. Bluesky is a public broadcast network with a nice moderation UI on top. If you post on the assumption that anyone can read everything you do, including who you've blocked and what you liked at 2am, you won't be surprised by it. I don't think "everything is public" is a bug. AT Protocol made that trade on purpose, in exchange for account portability and an open firehose, and documented it. The bug is that millions of people signed up through an app that looks like Twitter and never got told. Did you know your Bluesky blocks were public? And for a social network, do you see "everything is public" as a feature, or did the protocol skip a problem it should have solved on day one? Sources - Do At-Proto Users Know This Is Public? by Melanie Kat, October 29, 2026, plus the Lobsters discussion - Why are blocks on Bluesky public? by the AT Protocol team, June 8, 2023 - Bluesky docs: Following, muting, and blocking - com.atproto.sync.getRepo API reference - Permissioned Data Diary 1 by Daniel Holmgren, February 11, 2026 - Write-up of the Skyreader findings (Ecosistema Startup) - FeatherReader network spec (firehose and Jetstream) - pdsls.dev

  2. Claude Code に React Native アプリを触らせるなら agent-device の CLI はじめに AI に React Native のバグを直させると、コードはそれらしく直してくれます。ただ、シミュレータで本当に直ったかを確かめさせようとすると、何かツールを入れる必要があります。React Native の有名どころの会社からも、Callstack が agent-device、Software Mansion が Argent を出していて、ほかに mobile-mcp もあります。 どれを入れればいいのか。比べた記事を探したら、英語でも日本語でも機能表の比較しか見つかりませんでした。Expo 自身もブログで「検証ツールの比較は今後の実験」と書いています。そこで、Bluesky の公式アプリで実際に直されたバグを使って、180回測りました。 ! 検証環境は Claude Code 2.1.310、Opus 5.5、Xcode 27.1、iOS 26.5 のシミュレータ (iPhone 17) です。アプリは Bluesky の公式アプリ (コミット 61c7cad、Expo SDK 57) を使い、計測は2026年10月に行いました。ほかのアプリやエージェント、Android では試していません。 React Native なら agent-device の CLI を入れればいい 比べたのは、Callstack の agent-device、Software Mansion の Argent、Mobile Next の mobile-mcp の3つです。3つとも CLI と MCP の両方の入口があるので、6通りで測り、1回あたりの費用と、画面で再現から確認までやり切れたかを見ました。作業時間も参考に測っています。 早速結論ですが、自分のアプリに入れるなら agent-device の CLI を選びます。理由は2つです。 一番安い。1回あたり $0.70 で、mobilecli (mobile-mcp の CLI) と並んで最安。同じ agent-device の MCP より3割近く安い React Native 向けの機能がある。コンポーネントの props や state を調べる React DevTools や、Metro の再読み込みをコマンドで使える。mobilecli には無い 費用だけなら mobilecli も同じくらい安く済みます。React Native のアプリなら、機能の分だけ agent-device の CLI が上だと判断しました。 MCP しか使えない環境なら、mobile-mcp を選びます。タップや入力をまとめて1回で送れ、画面を読んだ結果も短いので、MCP の3つの中で一番安く済みました。 速さを重視する場合は、Argent の MCP が選択肢になります。6通りの中で作業時間が一番短く済みました。ただし費用は一番高く、agent-device の CLI の1.6倍かかります。タップするたびにスクショが返ってくるので、やり取りは少なく済む一方、受け取る画像が多くなるためです。 Bluesky の実バグで180回測った 比べた3つのツール どれも、エージェントにシミュレータの画面を読ませ、タップや入力をさせるためのツールです。違いは、画面をエージェントにどう渡すかにあります。 ツール 開発元 画面の渡し方 agent-device Callstack ボタンや文字を @e2 [button] "Add" のような参照の一覧で返す。操作のあとは、変わった部分だけを差分で返す Argent Software Mansion タップなどの操作のたびに、結果のスクショを自動で返す。画面の要素の一覧も別に取れる mobile-mcp Mobile Next 画面の要素を1行1個の一覧で返し、座標を指定してタップする。複数の操作をまとめて1回で送れる CLI はエージェントがシェルでコマンドを打って使い、MCP は Claude Code にツールとして登録して使います。mobile-mcp の CLI は、中で動いている mobilecli というエンジンをそのまま使う形です。この画面の渡し方の違いが、あとで見る費用の差になって表れます。 比べた6つの条件 3つのツールの CLI と MCP で6条件です。ツールはどれも公式ドキュメントが勧める入れ方にしました。 条件 入れたもの agent-device CLI CLI 0.21.31、公式の skill 4つ、公式が勧めるプロジェクトのルール文 agent-device MCP agent-device mcp、同じルール文 Argent MCP argent init が入れるもの一式 (MCP、skill 18個、rules) 0.30.1 Argent CLI 上から MCP の設定だけを外したもの mobile-mcp MCP @mobilenext/mobile-mcp 1.0.13 mobile-mcp CLI 中のエンジンの mobilecli 1.0.21 と公式の skill xcrun simctl の起動・スクショ・URL を開く操作は、どの条件でも使えるようにしました。テレメトリは全ツールで切っています。 この6条件に、次のお題5問 × testID とアクセシビリティのラベルの有無 × 3回を掛けて、全部で180回測りました。 お題は Bluesky で実際に直された5件 Bluesky の公式アプリは Expo SDK 57 のアプリで、E2E テスト用のモックサーバーが付いています。毎回同じデータでアプリを立ち上げられるので、計測に向いています。 お題は、Bluesky で実際にマージされた PR を戻して作りました。選んだのは、モックサーバーで症状を出せて、直ったかを Maestro で判定できる PR です。比べるツールを一度も動かす前に決めたので、結果を見てお題を選び直してはいません。 お題 症状 症状を出すのに必要な操作 #10132 画像に ALT を付けても案内が消えない 画像の添付、ALT の入力と保存 #10163 モデレーションリストが開けない URL でリストを開く #11503 存在しないユーザーのプロフィールが読み込み中のまま止まる URL でプロフィールを開く #8502 引用を禁止した投稿でも、リポストの長押しで引用の作成画面が開く 別のアカウントで引用禁止の投稿を作り、リポストを長押し #11820 (機能追加) 新規登録の生年月日を入力必須にする 新規登録のフォームに入力して Next を押す エージェントには、バグの症状と環境を伝えたうえで「シミュレータで再現して、直して、直ったことを確かめて」と頼みました。条件ごとに変えたのは、使うツールを指定する1文だけです。ALT の案内のバグだけは、Bluesky の issue の英文をそのまま貼っています。「このバグを直して」とだけ頼んだときに、エージェントが自分から画面で確かめに行くかは測っていません。 実際に渡した指示の例このリポジトリは Bluesky の公式アプリです。次のバグに対応してください。 存在しないハンドルのプロフィール (例: bluesky://profile/nobody.test) を開くと、エラー画面にならず、読み込み中の表示のまま止まってしまう。 アプリは iOS シミュレータ「BlueskyLab iPhone 17」(UDID 2B6D50B9-95B8-4FD8-8EFB-37FFE605ACF2) で起動していて、Metro (localhost:8081) とローカルのテストサーバー (localhost) につながっています。alice でサインインしています。このシミュレータ以外は別の作業で使っているので、触らないでください。ファイルを保存すると、Metro がアプリを自動で再読み込みします。 シミュレータの操作には agent-device の CLI を使ってください。 シミュレータでバグを再現し、コードを直して、直ったことをシミュレータで確かめてください。Web 検索はしないでください。終わったら、原因と直した内容を短く報告してください。 バグが直ったかどうかは、エージェントの作業が終わったあとに、アプリが Bluesky の修正と同じ動きになるかを Maestro のフローで確かめました。エージェントが画面で確かめたかどうかは、ログを Sonnet 5.5 に読ませて判定し、食い違った箇所はコードとログを自分で読んで確認しています。それでも見落としはありえます。 エージェントに答えを見せない仕掛け Bluesky は公開リポジトリなので、直し方がエージェントの手の届くところに残っています。答えを見て直せてしまうと、画面で再現する前に作業が終わり、ツールの差を測れません。比べたいツールを通らずに画面を操作できる道も同じです。そこで、次のように塞ぎました。 git の履歴と差分には、修正そのものが残っている。バグを入れた状態を1コミットだけのリポジトリにして、回ごとに作り直した 公式の E2E テストには、どの testID を押せばいいかが書いてある。テストのフォルダを外した アプリには E2E テスト用に、ログインや画面の移動を1回で済ませる隠しボタンがある。描画しないようにした Maestro が入っていると、比べたいツールを使わずに画面を操作できる。Maestro をコマンドとして呼べなくした Web で検索すると、元の PR が見つかる。Web 検索を禁止した 実際の開発ではエージェントが git の履歴や E2E テストも読めるので、費用や時間はこの記事の数字より軽く済むかもしれません。外したものはどの条件でも同じなので、ツールどうしの順位には響かないと見ています。 agent-device の CLI を選ぶ2つの理由 再現から確認までは、6条件すべてが30回中30回やり切りました。差が出たのは費用です。agent-device の CLI を選ぶ理由は、一番安いことと、React Native 向けの機能があることの2つです。 CLI は画面を読む量が少ないので一番安い 条件 1回の費用 (平均) 作業時間 (平均) 再現・確認まで終えた agent-device CLI $0.70 2分05秒 30 mobile-mcp CLI (mobilecli) $0.70 2分08秒 30 mobile-mcp MCP $0.80 1分53秒 30 Argent CLI $0.91 3分04秒 30 agent-device MCP $0.95 1分53秒 30 Argent MCP $1.11 1分41秒 30 agent-device の CLI は、mobilecli と並んで一番安く、Argent の MCP の6割ほどで済みました。同じお題・ラベル・回の組で比べると、agent-device の MCP には30組中29組、Argent の MCP には30組すべてで安くなっています。mobilecli とは30組中18組で、差はありません。 費用は API の料金に換算した値です。トークンの96%はキャッシュの読み込みで、1回平均142万トークンでも費用は $1 前後に収まりました。計測の順番によっては前の回のキャッシュを使えて安く出るので、どの回もキャッシュが空の状態から始めたとして計算し直しています。同じ組み合わせ3回の間のばらつきは、どの条件も6〜14%でした。 作業時間は参考にとどめてください。計測の途中に、同じ Mac で別の作業をしていた時間帯があります。 安さのわけは、画面を読む量にあります。CLI はシェルで動くので、エージェントが | grep や | head で必要な部分だけを読めます。同じツールの CLI と MCP を比べると、3つとも CLI の方が安くなりました。agent-device で3割近く、Argent で2割弱、mobile-mcp で1割強です。 画面を読む量の内訳 agent-device の2つをログで比べると、差は画面を読み取る量から来ていました。 条件 やり取り 画面を1回読んだ結果の長さ 受け取った画像 agent-device CLI 26回 約580文字 3.5枚 agent-device MCP 26回 約5,300文字 2.5枚 やり取りの回数は同じで、1回に読む画面の長さが9倍ほど違います。MCP は、ツールが返したものを丸ごと受け取るしかありません。mobile-mcp でも、CLI の約620文字に対して MCP は約2,300文字でした。 Argent の MCP が1回の作業で受け取った画像は平均9.5枚で、agent-device の CLI (3.5枚) の3倍近くでした。画像は文字よりトークンが重いので、そのぶん費用がかさみます。 なお、「画面を読み取った回」はツールの名前やコマンドの文字で拾う簡易な数え方です。傾向は見えますが、厳密な内訳ではありません。 React Native 向けの機能がある 費用で並んだ mobilecli との違いは、React Native 向けの機能です。agent-device には、React Native のアプリを調べるためのコマンドがあります。 できること コマンドの例 コンポーネントの木、props、state、hooks を見る agent-device react-devtools tree / inspect 遅い描画や再描画の原因を調べる agent-device react-devtools profile start JS だけの変更を Metro で読み込み直す agent-device metro reload LogBox や RedBox の表示を閉じる agent-device react-native dismiss-overlay React DevTools は、Metro につながった開発ビルド (React Native 0.74 以上) なら、アプリに手を入れずに使えます。mobilecli のコマンドは画面の操作と端末の管理が中心で、React Native に特化したものはありません。 ただし、今回の計測ではこの差は測れていません。お題はどれも画面に症状が出るバグで、agent-device の CLI の回でも、ログや通信を見るコマンドが数回使われただけでした。再描画が多すぎて重い、のように画面だけでは原因が分からないバグでどれだけ効くかは、試していません。 作りから予想できたことと、外れたこと ここまでの結果のうち2つは、ツールの作りから予想がつきます。Argent の MCP はタップのたびにスクショを返すので、受け取る画像が増えて高くなります。CLI はエージェントが要る部分だけを読めるので、ツールの返すものを丸ごと受け取る MCP より安くなります。予想と違ったのは、次の2つでした。 testID やラベルを外しても、費用も時間も変わらない testID とアクセシビリティのラベルをアプリから全部外した版でも測りました。アイコンだけのボタンが、名前の無いただの「Button」になる状態です。エージェントがボタンを探しにくくなり、費用がかさむと予想していました。 条件 1回の費用 (ラベルあり → 無し) 無しの方が安かった組 agent-device CLI $0.71 → $0.69 8/15 mobile-mcp CLI $0.71 → $0.69 8/15 mobile-mcp MCP $0.83 → $0.76 8/15 Argent CLI $1.01 → $0.82 11/15 agent-device MCP $0.94 → $0.97 7/15 Argent MCP $1.15 → $1.07 8/15 どの条件も、ラベル無しの方が安かった組は半分前後で、差は3回のばらつきの範囲に収まりました。Argent の CLI だけ2割安くなっていますが、ばらつきと区別しきれません。全条件を合わせた90組で見ても、トークンが少なかったのは41組、時間が短かったのは39組でした。 アイコンだけのリポストのボタンを長押しする #8502 でも、差は出ていません。エージェントは、名前の無いボタンをスクショや並び順から見つけていました。 なお、今回のお題はどれも、たどる画面が少ないものです。何画面もたどる操作では、結果が変わるかもしれません。また、Bluesky は testID とラベルが丁寧に付いたアプリで、ここで測ったのはそれを「外した」状態です。最初から付いていないアプリでは、画面の作りが違うかもしれません。 一番高い Argent の MCP が一番速い 作業時間は平均1分41秒で、6条件の中で一番短くなりました。同じお題どうしで並べると、30組中25組で agent-device の CLI より早く、平均で24秒の差です。 速さのわけは、やり取りの少なさです。タップのたびにスクショが返ってくるので、画面を見るためだけの呼び出しがほとんど要りません。やり取りは平均22回で、agent-device の CLI (26回) より4回少なく済みました。 その代わり、1回のやり取りの費用は agent-device の CLI の倍近く ($0.053 と $0.028) かかります。 まとめ 差が出たのは、バグを直せるかどうかではなく、画面をエージェントにどう渡すかでした。CLI で画面を短く読める agent-device と mobilecli は安く、操作のたびにスクショを返す Argent の MCP は高くつきました。新しいツールを入れるときも、CLI があるか、画面を何で返すか (文字の一覧か、スクショか) を見れば、費用の当たりはつけられます。testID やラベルは、少なくとも費用のためには足さなくて構いません。 まだエージェントの操作ツールを使ったことのない React Native の開発者は、まずは agent-device の CLI を試してみてください。 参考リンク callstack/agent-device (GitHub) software-mansion/argent (GitHub) mobile-next/mobile-mcp (GitHub) bluesky-social/social-app (GitHub)

  3. Social Media Character Limits From Each Platform's Docs X (Twitter) allows 280 characters per post and counts every link as 23 of them. LinkedIn allows 3,000. Bluesky allows 300, counted in graphemes, so an emoji is one. Each figure below comes from the platform's own documentation, linked in the table, and they are the same limits Skryvo writes to when it drafts a post for each channel. The short version: X 280, Bluesky 300, Threads 500, Mastodon 500 by default, Pinterest descriptions 800 with 100-character titles, Instagram captions 2,200, Discord 2,000, LinkedIn 3,000, Telegram 4,096 (captions 1,024). To check a post against all of them at once, paste it into our free post preview and thread maker. | Platform | Limit | How it counts | Source | |---|---|---|---| | X (Twitter) | 280 per post | Every link counts as 23 | X docs | | Bluesky | 300 per post | Graphemes, and at most 3,000 bytes | Post lexicon | | Threads | 500 per post | Up to 5 links | Threads API | | Mastodon | 500 by default | Characters | Mastodon docs | | Pinterest | 800 description, 100 title | Characters | Pinterest API spec | | Instagram | 2,200 caption | Also up to 5 hashtags (since December 2025) and 20 @ tags; see the hashtag limit | Instagram API | | Discord | 2,000 per message | Characters | Discord docs | | LinkedIn | 3,000 per post | Characters | LinkedIn Help | | Telegram | 4,096 per message | Captions on photos: 1,024 | Bot API | What is the character limit on X (Twitter)? 280 characters per post. X runs every link through its t.co shortener, so a link counts as 23 characters whether it is 20 characters long or 200. Emoji and Chinese, Japanese or Korean characters count as 2; our Twitter character counter applies X's rules as you type. Subscribers to X's paid tiers can post far longer; Twitter first raised that to 25,000 characters for subscribers in 2023. Does Twitter still have a 140 character limit? No. Twitter doubled the limit to 280 in November 2017, and 280 is still the limit for most accounts on X. How many characters can a LinkedIn post have? 3,000. LinkedIn's help page says that for anything longer you should write an article instead. In practice the opening lines carry the post, because long posts are folded in the feed until someone expands them. What is the character limit on Bluesky? 300 graphemes. A grapheme is what you see as one character, so an emoji with a skin tone, which is several code points under the hood, counts as one. The same post also has a hard ceiling of 3,000 bytes, which matters only for text heavy with emoji or non-Latin scripts. What is the character limit on Threads and Mastodon? Both default to 500. Threads also caps a post at 5 links; if you are choosing between the two short-post networks, Bluesky vs Threads compares them, and how to schedule Bluesky posts covers the 300-character side. On Mastodon, 500 is the default that the Mastodon software ships with; the server you are on decides, so check your server's composer. Why one post rarely fits everywhere A 600-character LinkedIn post is over the limit on X, Bluesky, Threads and Mastodon. You can cut it four times, split it into a thread, or write a version per network. We built Skryvo to do the last one: it writes a separate version of the post for each channel you publish to, within that channel's limit and in your brand's voice, then schedules them on one calendar. If you write the versions yourself, the post preview tool shows where each one breaks, our guide to scheduling X posts covers threads, and the best time to post on X compares three studies. Write for the shortest network first, then let the longer ones have the detail. Originally published at skryvo.ai.

  4. How to Schedule Bluesky Posts and Threads As of October 2026 the Bluesky app has no schedule button, so scheduling a Bluesky post means using a tool that publishes it for you at the time you pick. The tool connects to your account through Bluesky's own sign-in or an app password, never your main password. This guide covers both ways in, threads, and the limits a scheduled post must fit. The short version: connect a scheduler with Bluesky's sign-in (or an app password from Bluesky → Settings → App Passwords), write the post or thread within 300 characters per post and up to 4 images, and pick a time. Revoke the app password in Bluesky's settings whenever you stop using the tool. Can you schedule posts on Bluesky? Not inside the Bluesky app itself today. Bluesky publishes a post the moment you send it, so any scheduling happens in a separate tool that holds the post and sends it through Bluesky's API at the chosen time. Connecting a scheduler: sign-in or app password - Bluesky sign-in (OAuth). The tool sends you to Bluesky to approve access. You never type a password into the tool. - App password. In Bluesky, open Settings › App Passwords and create one for the tool. It is not your account password, it is shown once, and you can delete it any time to cut the tool off. Never give a scheduling tool your main Bluesky password. If a tool asks for it, use another tool. Bluesky post limits a scheduled post must fit | Limit | Value | |---|---| | Text per post | 300 characters (graphemes), and at most 3,000 bytes | | Images per post | Up to 4 | | Size per image | Up to 2,000,000 bytes | The text limits come from Bluesky's post lexicon; an emoji counts as one character. Paste a draft into our post preview tool to count it the way Bluesky does. How to schedule a Bluesky thread Write the whole thread first, with each part under 300 characters. A scheduler then posts the first part and replies to it with each following part, in order, so the thread appears at once at the time you chose. Our thread maker splits a long post into numbered parts that fit, keeping whole sentences together where it can. Scheduling Bluesky posts in Skryvo 1. In Skryvo, open Settings › Connected accounts and choose Bluesky. Sign in with Bluesky, or paste an app password. 2. Write the post or thread, or let Skryvo draft it in your brand's voice for Bluesky's length. 3. Pick a time on the calendar. Skryvo posts it on that quarter hour, reads it back from Bluesky to confirm it is live, and collects its results. The same idea can go to LinkedIn, X and Mastodon as their own versions, and an AI agent such as Claude can do the scheduling for you. Bluesky in Skryvo lists what it posts today. Is it safe to use a Bluesky scheduler? Yes, if it connects through Bluesky's sign-in or an app password. Both can be revoked without changing your main password, which is exactly why Bluesky offers them. Check that the tool shows you what went out and when, so a failed post does not go unnoticed. Schedule the posts you already know you will write, keep the replies live, and delete the app password the day you stop using the tool. Still choosing a network? Bluesky vs Threads compares the two on size, length and scheduling. Originally published at skryvo.ai.

  5. I ran a store rejection sweep on Bluesky's open source Expo app. One config plugin had written 5 iOS permission texts, and the app uses 1 A while back someone here got rejected because expo-audio turns on background playback by default, and a reply wished for "a build step somewhere to examine all the entitlements, default strings, and other bundled native configs". That's what I've been building, so I tried it on the biggest open source Expo app I know: Bluesky. Bluesky doesn't commit ios/ or android/, so app.config.js only shows half of it. What I did (no tool needed): 1. npx expo prebuild --no-install with their production env vars (it needed Node 24 and their committed google-services.json.example) 2. read ios/Bluesky/Info.plist 3. ./gradlew :app:processReleaseMainManifest, then read android/app/build/outputs/logs/manifest-merger-release-report.txt, which names the library behind every permission What came out: - 5 location and motion prompt texts, all expo-location's defaults ("Allow $(PRODUCT_NAME) to access your location"). The app only ever asks for when-in-use location; the "always", "temporary precise location" and motion ones are for things it never requests. It was 4 when I first ran this; their upgrade to SDK 58 last week added the precise location one, which is a new default in expo-location 58. The config is just ['expo-location'] with no options. Bluesky does show its own explanation screen first, and it has shipped like this since September 2025, so Apple clearly isn't rejecting it. But 5.1.1(ii) asks that purpose strings "clearly and completely describe your use of the data", and Expo's own docs say the defaults "will most likely need to be tailored". Fix (passing false removes the key, I checked the regenerated plist): ​ ['expo-location', { locationWhenInUsePermission: 'Bluesky uses your location to determine the content and features available in your region.', locationAlwaysAndWhenInUsePermission: false, locationAlwaysPermission: false, locationFullAccuracyPermission: false, // new in SDK 58 motionUsagePermission: false, }] - Precise location on Android from the same plugin, though the code only uses the country and region. Play's location policy says "coarse instead of fine". android.blockedPermissions: ['android.permission.ACCESS_FINE_LOCATION']. - READ_PHONE_STATE in the merged manifest. It's not in their config; it comes from the Bitdrift SDK's own manifest. The app never requests it, but it's still declared to Play. - Photo library permission asked before the avatar picker, which on Android 13+ uses the system photo picker and needs no permission. expo-media-library is what got my own app rejected by Play in May. Bluesky may well have the declaration that allows it. What they get right: account deletion in the app, report, block and mute everywhere, adult content can't be switched on from inside the iOS app (Apple's 1.2 rule), and the one "Google Account" string is already chosen per platform. Where my tool was wrong: it would have flagged that Google Account string under 2.3.10, because a per platform string still ships inside the iOS bundle. An earlier run also called the photo permission a blocker on an app that has shipped with it for over a year. Both fixed; it now checks git history for when each finding shipped, so "passed review for a year" reads as a risk, not a rejection. I opened an issue with the location fix: social-app#12118 Checked against their main branch at b2963d3 (26 Oct). The READ_PHONE_STATE line comes from the merged manifest of my first run on 21 Oct; I didn't rebuild Android since. The tool is a set of Claude Code skills (MIT): namedtoaster/the-last-mile. You don't need it for the steps above. What else have Expo plugins quietly added to your build that you only found out about from a rejection?

    3 points · 2 comments
  6. Hey, so what is this and why? Why do you hate the people that help build this site in its early days so much. Quickly becoming the not-so-open social restricting websites like this. github.com/bluesky-social/social-app/blob/main/sr…

    60 likes · 26 reposts
  7. Just an FYI on the bluesky profile links thing: They started just blocking onlyfans and fansly, then expanded to cover a bunch of link shorteners explicitly because adult content is linked to through them. Fuck you @bsky.app . Proof: github.com/bluesky-social/social-app/blob/f0b2edb…

    720 likes · 429 reposts
  8. that's right everyone, you guessed it. we're adding the long-awaited much-requested feature: chromebook support

    88 likes · 7 reposts
  9. If you are running the stock PDS distribution, it should auto-update in the next 24 hours with a mitigation for the eMudhra intermediate CA. Or you can also update manually (see below). The latest tagged version is 0.4.5043. bluesky-social/pds

    98 likes · 30 reposts
  10. bluesky recently broke the alt text editor. the issue below tracks the fix. this entire stack is a fucking shitshow.

    54 likes · 16 reposts
Trending awards, every completed day and week
Gold
01st place finishes
Silver
02nd place finishes
Bronze
13rd place finishes
Awarded repositories
1Owned by bluesky-social now

Repositories

Ordered by gold, then silver, then bronze.

  1. social-appBest: 3rd by stars, 1,007 stars001

Every award

Top-three finishes of these repositories in completed trending days and weeks, newest first.

  1. #3 by starsDaily trending
    1,007 stars
    social-app

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.