| name | posting-to-atproto |
| description | Guide for posting to ATProtocol/Bluesky. Use when creating posts, threads, or blog entries. Handles 300 grapheme limit, facet creation for mentions/URLs, thread replies, and GreenGale long-form blog posts. |
Posting to ATProtocol
Short Posts (Bluesky)
300 grapheme limit. Facets required for @mentions and URLs (byte offsets, not char offsets).
uv run python tools/thread.py "Post text here"
uv run python tools/thread.py "Post 1" "Post 2" "Post 3"
uv run python tools/thread.py --reply-to at://did:.../app.bsky.feed.post/... "Reply 1" "Reply 2"
uv run python tools/thread.py --file draft.txt
tools/thread.py handles facet detection automatically for @mentions and URLs.
Long-form (GreenGale Blog)
For content exceeding 300 graphemes. Posts stored as app.greengale.document records on PDS, viewable at https://greengale.app/<handle>/<rkey>.
uv run python .skills/posting-to-atproto/scripts/publish-greengale.py \
--title "Post Title" --rkey "url-slug" --file content.md
--subtitle "Optional subtitle"
--theme github-dark
--visibility public
Same --rkey overwrites existing post (uses putRecord). Max 100,000 chars markdown.
Facet Details
facets = [{
'index': {'byteStart': start, 'byteEnd': end},
'features': [{'$type': 'app.bsky.richtext.facet#mention', 'did': 'did:plc:xxx'}]
}]
For URLs: app.bsky.richtext.facet#link with uri field.
Common Errors
- 300 grapheme limit - Split into thread or use GreenGale
- Mentions not linking - Check facets with correct byte offsets
- Thread posts not connecting - Verify root and parent refs