Read from and post to Bluesky social network using the AT Protocol. Use this skill when the user wants to interact with Bluesky including posting text/images/links, replying to posts, reading their timeline, searching posts, viewing profiles, following/unfollowing users, checking notifications, or viewing reply threads. All scripts use PEP 723 inline metadata for dependencies and run via `uv run`. Requires BLUESKY_HANDLE and BLUESKY_PASSWORD environment variables.
This skill provides access to the Bluesky social network via a set of Python scripts.
When posting to BlueSky, always start the post with a brief statement saying who you are and that you are using the user's BlueSky account. Something short like: `This is [AI name] posting using [user name]'s account.` is good, but feel free to vary it. Replace `[AI name]` with your name and `[user name]` with the user's BlueSky full name or first name for brevity.
**Tool Dependency**:
**Environment Variables** (must be set before running any script):
**Important**: The user should configure a BlueSky App Password (create in Settings > App Passwords) instead of using their main account password. App Passwords can be revoked individually if compromised.
**Important**: The scripts in this skill require network access to the following domains:
If you (the AI agent) have network restrictions, the user may need to whitelist the above domains in the agent's settings for this skill to function. This is known to be necessary with Claude, and may be necessary with others.
All scripts include PEP 723 inline metadata declaring their dependencies. Just run with `uv run` — no manual dependency installation or `--with` flags needed.
Create posts with text, images, or link cards. URLs in the text are automatically detected and made clickable (supports `https://...`, `http://...`, `www....`, and bare domain URLs like `github.com/user/repo`).
```bash
uv run scripts/post.py --text "Hello, Bluesky!"
uv run scripts/post.py --text "Check this out" --image photo.jpg
uv run scripts/post.py --text "Photos" --image a.jpg --image b.jpg
uv run scripts/post.py --text "My cat" --image cat.jpg --alt "Orange cat sleeping"
uv run scripts/post.py --text "Read this" \
--link-url "https://example.com" \
--link-title "Article Title" \
--link-description "Description text"
```
Fetch and display the reply thread for a specific post.
```bash
uv run scripts/replies.py https://bsky.app/profile/someone.bsky.social/post/abc123
uv run scripts/replies.py "at://did:plc:xxx/app.bsky.feed.post/abc123"
uv run scripts/replies.py --depth 1 https://bsky.app/profile/someone/post/abc123
uv run scripts/replies.py --json https://bsky.app/profile/someone/post/abc123
uv run scripts/replies.py --no-parents https://bsky.app/profile/someone/post/abc123
```
**Arguments:**
| Argument | Description |
|----------|-------------|
| `post` | Post identifier: either a `bsky.app` URL or an AT Protocol URI (required) |
| `--depth`, `-d` | Maximum depth of replies to fetch (default: no limit) |
| `--json`, `-j` | Output as JSON instead of human-readable format |
| `--no-parents` | Don't show parent posts (only target post and replies) |
Reply to an existing Bluesky post. The script automatically handles AT Protocol threading (root and parent references). URLs in the reply text are automatically detected and made clickable.
```bash
uv run scripts/reply.py --to https://bsky.app/profile/someone.bsky.social/post/abc123 \
--text "Great post!"
uv run scripts/reply.py --to "at://did:plc:xxx/app.bsky.feed.post/abc123" \
--text "I agree with this!"
uv run scripts/reply.py -p https://bsky.app/profile/someone/post/abc123 -t "Thanks!"
```
**Arguments:**
| Argument | Description |
|----------|-------------|
| `--to`, `-p` | Post to reply to: either a `bsky.app` URL or an AT Protocol URI (required) |
| `--text`, `-t` | The reply text content, max 300 characters (required) |
**How it works:** The script fetches the target post's thread to determine:
1. The **parent** (the post you're replying to)
2. The **root** (the original post that started the thread)
Both references are required by AT Protocol to maintain proper thread structure.
View posts from accounts the user follows.
```bash
uv run scripts/read_timeline.py
uv run scripts/read_timeline.py --limit 50
uv run scripts/read_timeline.py --json
uv run scripts/read_timeline.py --cursor "cursor_string"
```
Find posts by keywords or hashtags.
```bash
uv run scripts/search.py "python programming"
uv run scripts/search.py "#machinelearning"
uv run scripts/search.py "topic" --limit 100 --all
uv run scripts/search.py "query" --json
```
View profile information for any user.
```bash
uv run scripts/profile.py
uv run scripts/profile.py someone.bsky.social
uv run scripts/profile.py --json
```
Manage the user's social connections.
```bash
uv run scripts/follow.py someone.bsky.social
uv run scripts/follow.py --unfollow someone.bsky.social
uv run scripts/follow.py --list
uv run scripts/follow.py --list --followers
uv run scripts/follow.py --list someone.bsky.social
```
View and manage the user's notifications.
```bash
uv run scripts/notifications.py
uv run scripts/notifications.py --limit 50
uv run scripts/notifications.py --count
uv run scripts/notifications.py --mark-read
uv run scripts/notifications.py --json
```
```bash
export BLUESKY_HANDLE="username.bsky.social"
export BLUESKY_PASSWORD="app-password"
BLUESKY_HANDLE="username.bsky.social" BLUESKY_PASSWORD="pass" uv run scripts/post.py --text "Hello"
```
All scripts support `--json` for machine-readable output:
```bash
uv run scripts/read_timeline.py --json | jq '.posts[0]'
uv run scripts/search.py "topic" --json | jq '.count'
```
Scripts that return lists support cursor-based pagination. Use this to scroll through the user's
timeline and other sequences of posts:
```bash
uv run scripts/read_timeline.py --json > page1.json
CURSOR=$(jq -r '.cursor' page1.json)
uv run scripts/read_timeline.py --cursor "$CURSOR" --json > page2.json
```
Scripts exit with non-zero status on errors. Common issues:
Leave a review
No reviews yet. Be the first to review this skill!