bluesky
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEverything runs through the shipped CLI
— self-contained ( + , both preinstalled in the sandbox). One
call creates the session, auto-computes clickable facets (links, #hashtags,
@mentions with correct UTF-8 byte offsets), and for image posts downloads the
file, resizes/recompresses it to Bluesky's ~1 MB blob limit, s it
and builds the embed — so there's no fragile
to hand-assemble (the old inline recipe kept breaking on
shell quoting, especially once an image + facets were involved).
scripts/bluesky.pyrequestsPillowuploadBlobapp.bsky.embed.imagescurl + jq + heredocThree connector credentials are injected:
(e.g. ), (an App Password from Bluesky
Settings → Privacy and Security → App Passwords, NOT the login password) and
(PDS base URL, default ). The CLI reads
them from the env — never echo them.
$BLUESKY_HANDLEname.bsky.social$BLUESKY_APP_PASSWORD$BLUESKY_SERVICEhttps://bsky.socialsh
BSKY="$SKILL_DIR/scripts/bluesky.py"
python3 "$BSKY" whoami # verify the session → {did, handle, service}If fails with / , the
identifier or App Password is wrong. The #1 cause is a bare handle — the CLI
auto-appends to a bare username on the default PDS, but if it
still fails the user must reconnect the connector with their full handle
(, a custom domain, a DID, or the account email) and a valid
App Password.
whoamisession_failedAuthenticationRequired.bsky.socialname.bsky.social所有操作都通过内置的CLI脚本完成
—— 该脚本独立运行(依赖和,二者已预安装在沙箱环境中)。单次调用即可创建会话,自动生成可点击的facets(链接、#话题标签、@提及,并计算正确的UTF-8字节偏移量);对于带图帖子,会自动下载图片、调整大小/压缩至Bluesky约1MB的blob限制、调用上传,并构建嵌入内容——无需手动编写脆弱的组合(旧版内联方案经常因shell引号问题失效,尤其是涉及图片和facets时)。
scripts/bluesky.pyrequestsPillowuploadBlobapp.bsky.embed.imagescurl + jq + heredoc注入了三个连接器凭据:(例如 )、(来自Bluesky的设置→隐私与安全→应用密码,并非登录密码)以及(PDS基础URL,默认值为)。CLI会从环境变量中读取这些凭据——切勿回显它们。
$BLUESKY_HANDLEname.bsky.social$BLUESKY_APP_PASSWORD$BLUESKY_SERVICEhttps://bsky.socialsh
BSKY="$SKILL_DIR/scripts/bluesky.py"
python3 "$BSKY" whoami # 验证会话 → {did, handle, service}如果返回 / 错误,说明标识符或应用密码有误。最常见的原因是使用了不完整的handle——在默认PDS环境下,CLI会自动为纯用户名追加,但如果仍失败,用户必须重新配置连接器,提供完整的handle(、自定义域名、DID或账户邮箱)以及有效的应用密码。
whoamisession_failedAuthenticationRequired.bsky.socialname.bsky.socialPost — text, images and links in one call
发布帖子——文本、图片和链接一键完成
Confirm the text with the user before posting (it publishes as their real
account). Text ≤ 300 graphemes. Clickable links / #hashtags / @mentions are
turned into facets automatically — just write them in the text, no byte-offset
math needed.
sh
undefined发布前请与用户确认文本内容(帖子将以用户真实账号发布)。文本长度≤300个字符(按用户感知的字符数计算,表情符号算1个)。可点击的链接/#话题标签/@提及会自动转换为facets——只需在文本中正常书写,无需计算字节偏移量。
sh
undefinedplain text post
纯文本帖子
python3 "$BSKY" post --text "Hello Bluesky 👋 shipping with the AT Protocol"
python3 "$BSKY" post --text "Hello Bluesky 👋 shipping with the AT Protocol"
带图发送 / post WITH an image (URL or local path) — the image is downloaded,
带图发布(支持URL或本地路径)——图片会自动下载、调整大小以符合blob限制、上传并嵌入:
resized to fit the blob limit, uploaded and embedded automatically:
—
python3 "$BSKY" post
--text "Stop wiring 3 image APIs. One endpoint → posters, cards, mockups. https://platform.acedata.cloud/documents/openai-images-generations-integration #AI #API"
--image "https://cdn.acedata.cloud/xxxx.png" --alt "AI image API hero"
--text "Stop wiring 3 image APIs. One endpoint → posters, cards, mockups. https://platform.acedata.cloud/documents/openai-images-generations-integration #AI #API"
--image "https://cdn.acedata.cloud/xxxx.png" --alt "AI image API hero"
python3 "$BSKY" post
--text "Stop wiring 3 image APIs. One endpoint → posters, cards, mockups. https://platform.acedata.cloud/documents/openai-images-generations-integration #AI #API"
--image "https://cdn.acedata.cloud/xxxx.png" --alt "AI image API hero"
--text "Stop wiring 3 image APIs. One endpoint → posters, cards, mockups. https://platform.acedata.cloud/documents/openai-images-generations-integration #AI #API"
--image "https://cdn.acedata.cloud/xxxx.png" --alt "AI image API hero"
up to 4 images, each with its own --alt (paired by order)
最多支持4张图片,每张图片需对应一个--alt参数(按顺序配对)
python3 "$BSKY" post --text "gallery" --image a.png --alt "one" --image b.png --alt "two"
Multi-line text or lots of emoji? Skip shell-quoting headaches by writing the
text to a file and using `--text-file` (or pipe via `--text -`):
```sh
cat > /tmp/post.txt <<'EOF'
Line one 🎨
Line two with a link https://platform.acedata.cloud #AI
EOF
python3 "$BSKY" post --text-file /tmp/post.txt --image "https://cdn.acedata.cloud/xxxx.png"Success prints
.
The is the public, shareable link — hand it to the user verbatim.
{"posted":true,"uri":"at://…","url":"https://bsky.app/profile/<handle>/post/<rkey>", ...}urlpython3 "$BSKY" post --text "gallery" --image a.png --alt "one" --image b.png --alt "two"
如果需要发布多行文本或大量表情符号?为避免shell引号问题,可将文本写入文件并使用`--text-file`参数(或通过管道符`--text -`传入):
```sh
cat > /tmp/post.txt <<'EOF'
Line one 🎨
Line two with a link https://platform.acedata.cloud #AI
EOF
python3 "$BSKY" post --text-file /tmp/post.txt --image "https://cdn.acedata.cloud/xxxx.png"发布成功后会输出
。其中是公开可分享的链接——直接将其提供给用户即可。
{"posted":true,"uri":"at://…","url":"https://bsky.app/profile/<handle>/post/<rkey>", ...}urlList my recent posts + engagement
查看我的近期帖子及互动数据
sh
python3 "$BSKY" list --limit 20 # default filter: posts_no_replies
python3 "$BSKY" list --limit 50 --filter posts_with_media--filterposts_no_repliesposts_with_repliesposts_with_mediaposts_and_author_threads--limitsh
python3 "$BSKY" list --limit 20 # 默认筛选条件:posts_no_replies
python3 "$BSKY" list --limit 50 --filter posts_with_media--filterposts_no_repliesposts_with_repliesposts_with_mediaposts_and_author_threads--limitDelete a post
删除帖子
sh
python3 "$BSKY" delete --uri "at://did:plc:xxxx/app.bsky.feed.post/3kabc123xyz"Pass the full post (from or a prior ); the CLI
extracts the . An empty result / is success.
at://…urilistpostrkeydeleted:truesh
python3 "$BSKY" delete --uri "at://did:plc:xxxx/app.bsky.feed.post/3kabc123xyz"传入完整的格式帖子(来自命令或之前发布帖子的返回结果);CLI会自动提取。返回空结果或即为删除成功。
at://…urilistrkeydeleted:trueGotchas
注意事项
- App Password, not account password: creating a session with the real login password may be rejected or trip 2FA. Always the App Password from Settings → App Passwords.
- Facets & image resizing are automatic — the CLI computes link/#tag/@mention byte offsets and shrinks oversized images to the ~1 MB blob limit for you.
- 300 graphemes, counted as user-perceived characters (emoji = 1).
- Rate limits: the PDS rate-limits writes per account; space out bulk posts
or you'll get .
429 {"error":"RateLimitExceeded"} - Self-hosted PDS: if the user runs their own PDS, points there; all XRPC calls target that host, not
$BLUESKY_SERVICE.bsky.social - The CLI creates a fresh short-lived session on every invocation, so an
expiring is never a concern — just run the command again.
accessJwt
- 使用应用密码而非账户密码: 使用真实登录密码创建会话可能会被拒绝或触发二次验证。务必使用来自「设置→应用密码」的应用密码。
- Facets与图片调整自动完成——CLI会自动计算链接/#话题标签/@提及的字节偏移量,并将过大的图片压缩至约1MB的blob限制。
- 文本限制300个字符,按用户感知的字符数计算(表情符号算1个)。
- 速率限制: PDS对每个账号的写入操作有速率限制;批量发布时需间隔一段时间,否则会返回错误。
429 {"error":"RateLimitExceeded"} - 自托管PDS: 如果用户运行自己的PDS,需指向该PDS地址;所有XRPC调用都会针对该主机,而非
$BLUESKY_SERVICE。bsky.social - CLI每次调用都会创建一个新的短期会话,因此无需担心过期——只需重新运行命令即可。
accessJwt
Record the output
记录输出结果
After you successfully publish and obtain the live result URL, call the built-in
tool ONCE so the user can track this deliverable in My Outputs:
publish_artifactpublish_artifact(kind="message", channel="bluesky", title="<title>", url="<the REAL returned URL>", status="delivered")Use the real returned URL — never fabricate one. Call it once per published item,
only after delivery is confirmed; skip it (or use ) if publishing failed.
See .
status="failed"_shared/artifacts.md成功发布并获取到实时结果URL后,调用内置的工具一次,以便用户在「我的输出」中跟踪该交付物:
publish_artifactpublish_artifact(kind="message", channel="bluesky", title="<title>", url="<the REAL returned URL>", status="delivered")请使用真实返回的URL——切勿伪造。每个发布的内容仅调用一次该工具,且仅在确认交付成功后调用;如果发布失败,请跳过调用(或使用)。详情请查看。
status="failed"_shared/artifacts.md