tools/social-cli/SKILL.md
Agent-optimized CLI for Bluesky (ATProto) and X (Twitter). YAML in, YAML out, exit codes for automation. Use when the task involves posting, replying, reading feeds, searching, annotating URLs, or running a sync/check/dispatch agent loop across social platforms.
npx skillsauth add letta-ai/skills social-cliInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Agent-optimized social CLI. Bluesky + X. YAML in, YAML out, exit codes for automation.
Repo: https://github.com/letta-ai/social-cli
git clone https://github.com/letta-ai/social-cli.git
cd social-cli
pnpm install
pnpm build
Link the binary globally or invoke via node dist/cli.js / pnpm start from the repo directory.
Create a .env in the working directory where you run social-cli:
# Bluesky / ATProto
ATPROTO_HANDLE=you.bsky.social
ATPROTO_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx
ATPROTO_PDS=https://bsky.social # optional, defaults to bsky.social
# X / Twitter (OAuth 1.0a)
X_API_KEY=...
X_API_SECRET=...
X_ACCESS_TOKEN=...
X_ACCESS_TOKEN_SECRET=...
X_BEARER_TOKEN=... # optional, for app-only endpoints
Only credentials for platforms you actually use are required.
social-cli whoami
social-cli rate-limits
The canonical automation workflow. Each phase reads/writes YAML files in the working directory.
social-cli sync # pull notifications → inbox-{platform}.yaml
social-cli check || exit 0 # anything actionable? exit 1 = nothing to do
# read inbox, decide, write outbox-{platform}.yaml
social-cli dispatch # execute outbox, archive results
sync: deduplicates against sent_ledger-{platform}.yaml and caps inbox size.check: exits 0 if inbox has actionable items, 1 otherwise. Wrap with || exit 0 in cron loops.dispatch: executes the outbox atomically. Writes dispatch_result-{platform}.yaml and appends to sent_ledger-{platform}.yaml for replay protection.# Post / reply / thread
social-cli post "Hello world" -p bsky
social-cli reply "Thanks" --id "at://did:plc:.../app.bsky.feed.post/abc" -p bsky
social-cli thread "p1" "p2" "p3" -p bsky
# Engagement
social-cli like "at://..." -p bsky
social-cli delete "at://..." -p bsky
social-cli follow "handle.bsky.social" -p bsky
# Reading
social-cli search "query" -p bsky -n 10 # → stdout YAML
social-cli feed -p bsky -n 20 # → feed.yaml (or -o - for stdout)
social-cli feed --feed "at://did:.../app.bsky.feed.generator/name" -n 10 # custom feed
social-cli profile "handle.bsky.social" -p bsky
social-cli whoami
social-cli rate-limits
Uses the at.margin.note lexicon (W3C Web Annotation model). Annotations work on any URL, not just ATProto posts. They appear in margin.at and Semble.
# Annotate a web page
social-cli annotate "Note about this article" --target https://example.com
# Anchor to an exact passage
social-cli annotate "Key insight" --target https://example.com \
--quote "exact passage from the page" --motivation highlighting
Motivations: commenting, highlighting, questioning, describing, linking.
inbox-{platform}.yaml)notifications:
- id: "at://did:plc:xxx/app.bsky.feed.post/abc"
platform: bsky
type: mention # mention, reply, like, follow, repost, quote
author: someone.bsky.social
authorId: "did:plc:xxx"
postId: "at://..."
text: "Hey, what do you think?"
timestamp: "2026-03-25T12:00:00Z"
parentPostId: "at://..." # for replies
parentPostText: "..." # context
rootPostId: "at://..." # thread root
rootPostText: "..."
outbox-{platform}.yaml)Write decisions as a dispatch list. Each entry is a single action.
dispatch:
- reply:
platform: bsky
id: "at://did:plc:xxx/app.bsky.feed.post/abc"
text: "Thanks for the mention"
- post:
text: "Hello from my agent"
platforms: [bsky, x] # post to both
- thread:
platform: bsky
posts:
- "Thread post 1"
- "Thread post 2"
- like:
platform: bsky
id: "at://..."
- annotate:
platform: bsky
id: "https://example.com/article"
text: "Key observation"
motivation: commenting
quote: "exact text to anchor to"
- ignore:
id: "notif_003"
reason: "spam"
dispatch_result-{platform}.yaml is written after every dispatch. Exit codes:
| Code | Meaning | |------|---------| | 0 | All actions succeeded | | 1 | Invalid outbox (schema error, missing creds) | | 2 | Partial failure (some succeeded, some failed) |
Thread failures include a resumeFrom field with the index and remaining posts so you can retry just the tail.
| Platform | Limit | |----------|-------| | Bluesky | 300 chars | | X | 280 chars |
The CLI rejects over-limit posts before hitting the API.
| Feature | Bluesky | X |
|---------|---------|---|
| Annotations (at.margin.note) | Yes | No |
| Search | Yes | Yes |
| Feed | Yes (custom feeds) | Yes (home/user) |
| Threads | Yes | Yes |
| Notifications | mention, reply, like, follow, repost, quote | mentions only |
| Quote post context | Yes | Yes |
Retry-After.resumeFrom.sent_ledger-{platform}.yaml prevents duplicate dispatch across runs.Everything is scoped to your current working directory, so you can run multiple agents with isolated state:
./
├── .env
├── inbox-bsky.yaml # sync output
├── inbox-x.yaml
├── outbox-bsky.yaml # your decisions
├── outbox-x.yaml
├── dispatch_result-bsky.yaml # last dispatch outcome
├── dispatch_result-x.yaml
├── sent_ledger-bsky.yaml # replay protection
├── sent_ledger-x.yaml
└── feed.yaml # optional feed snapshots
references/commands.md: full command map with all flagsreferences/outbox-schema.md: complete outbox YAML schemareferences/agent-loop.md: patterns for cron/systemd automation loopstesting
Navigates archived ChatGPT or Claude-style conversation exports and a MemFS reference archive on demand. Use when recalling what a past assistant knew, searching old conversations, rendering specific chats, seeding reference memory from export sidecars, or mining historical context without doing a full import.
testing
Migrates deprecated Letta Filesystem folders/files to MemFS using markdown document corpora, chunking, local lexical search, and QMD semantic search via the memfs-search skill. Use when replacing folders.files.upload, working with PDFs or document QA, or emulating open_file, grep_file, and search_file behavior.
data-ai
Configures Letta agent compaction settings and custom summarization prompts. Use when a user asks to change an agent's compaction prompt, improve summaries after context eviction, tune sliding-window or all-message compaction, or design companion/coding-agent continuity summaries.
development
Semantic search over agent memory files. Use when you need to find conceptually related memory blocks, discover forgotten reference files, check what you already know before creating new memory, or search beyond exact keyword matching. Currently supports QMD (local, no API keys).