Agent skill
sms
Send, read, listen, respond, and manage SMS conversations via Telnyx and Twilio. Supports 8 phone numbers across both providers with auto-detection, conversation threading, MMS, real-time inbound listening, background watcher, batch reply processor, and soul-aware auto-reply. 10 Python scripts for SMS operations.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/sms
SKILL.md
SMS Skill
Send SMS/MMS, read inboxes, auto-reply as Claudius, and view conversation threads via Telnyx (2 numbers) and Twilio (6 numbers).
When to Use This Skill
- Sending a text message to any phone number
- Reading recent SMS messages (inbox)
- Listening for real-time inbound messages (two-way SMS)
- Auto-replying to inbound SMS as Claudius (soul-aware responses)
- Viewing a conversation thread with a specific number
- Listing available phone numbers across providers
- Sending MMS with image attachments
Prerequisites
Requires requests (uv pip install --system requests).
Credentials are loaded automatically:
- Telnyx:
TELNYX_API_KEYenv var, or falls back to~/.claude.json(already configured) - Twilio:
TWILIO_ACCOUNT_SID+TWILIO_AUTH_TOKENenv vars, or falls back to hardcoded defaults
Quick Start
# Send a text
python3 ~/.claude/skills/sms/scripts/sms_send.py "+19175551234" "Hello from Claude"
# Read recent messages
python3 ~/.claude/skills/sms/scripts/sms_read.py -n 10
# View conversation with someone
python3 ~/.claude/skills/sms/scripts/sms_conversation.py "+19175551234"
# List all available numbers
python3 ~/.claude/skills/sms/scripts/sms_numbers.py
# Start real-time listener (background)
python3 ~/.claude/skills/sms/scripts/sms_listen.py --bg
# Check inbound messages
python3 ~/.claude/skills/sms/scripts/sms_inbox.py
Available Scripts
1. sms_send.py — Send SMS/MMS
python3 ~/.claude/skills/sms/scripts/sms_send.py TO "MESSAGE" [OPTIONS]
| Flag | Description |
|---|---|
--from NUMBER |
Send from a specific number (auto-detects provider) |
--provider telnyx|twilio |
Force a specific provider |
--media URL |
Attach media for MMS |
Examples:
# Send via Telnyx (default)
python3 ~/.claude/skills/sms/scripts/sms_send.py "+19175551234" "Meeting at 3pm"
# Send from a Twilio number
python3 ~/.claude/skills/sms/scripts/sms_send.py "+19175551234" "Hello" --from "+18508058037"
# Send MMS with image
python3 ~/.claude/skills/sms/scripts/sms_send.py "+19175551234" "Check this" --media "https://example.com/photo.jpg"
2. sms_read.py — Read Inbox
python3 ~/.claude/skills/sms/scripts/sms_read.py [OPTIONS]
| Flag | Description |
|---|---|
--to NUMBER |
Messages to a specific number |
--from-number NUMBER |
Messages from a specific sender |
--direction inbound|outbound |
Filter by direction |
-n/--limit NUM |
Number of messages (default: 10) |
--provider telnyx|twilio |
Query specific provider |
--all-providers |
Query both providers |
Examples:
# Read last 10 messages (Twilio recommended for reads)
python3 ~/.claude/skills/sms/scripts/sms_read.py -n 10 --provider twilio
# Messages to a specific number
python3 ~/.claude/skills/sms/scripts/sms_read.py --to "+18508058037" --provider twilio
# Only inbound messages
python3 ~/.claude/skills/sms/scripts/sms_read.py --direction inbound --provider twilio
# Query both providers
python3 ~/.claude/skills/sms/scripts/sms_read.py --all-providers -n 20
3. sms_conversation.py — View Conversation Thread
python3 ~/.claude/skills/sms/scripts/sms_conversation.py NUMBER [OPTIONS]
| Flag | Description |
|---|---|
-n/--limit NUM |
Max messages per direction (default: 20) |
--our-number NUMBER |
Filter to a specific one of our numbers |
--provider telnyx|twilio |
Query specific provider |
--all-providers |
Query both providers |
Examples:
# View conversation with a number
python3 ~/.claude/skills/sms/scripts/sms_conversation.py "+19175551234" --provider twilio
# Limit to last 10 messages per direction
python3 ~/.claude/skills/sms/scripts/sms_conversation.py "+19175551234" -n 10 --provider twilio
# Filter to a specific one of our numbers
python3 ~/.claude/skills/sms/scripts/sms_conversation.py "+19175551234" --our-number "+18508058037"
4. sms_numbers.py — List Available Numbers
python3 ~/.claude/skills/sms/scripts/sms_numbers.py [OPTIONS]
| Flag | Description |
|---|---|
--provider telnyx|twilio |
Filter by provider |
--live |
Query APIs for live status (slower) |
Examples:
# List all 8 numbers
python3 ~/.claude/skills/sms/scripts/sms_numbers.py
# Twilio numbers only
python3 ~/.claude/skills/sms/scripts/sms_numbers.py --provider twilio
# Live API status check
python3 ~/.claude/skills/sms/scripts/sms_numbers.py --live
5. sms_listen.py — Real-Time Inbound Listener
Background daemon that polls Twilio for new inbound messages and runs a webhook server for Telnyx inbound. Messages are written to data/inbox.jsonl.
python3 ~/.claude/skills/sms/scripts/sms_listen.py [OPTIONS]
| Flag | Description |
|---|---|
--bg |
Run in background (daemonize) |
--stop |
Stop running listener |
--status |
Check if listener is running |
--interval N |
Twilio poll interval in seconds (default: 10) |
--numbers +1... +1... |
Twilio numbers to monitor (default: all 6) |
--webhook-port N |
Telnyx webhook port (default: 9147) |
--no-telnyx |
Disable Telnyx webhook server |
--no-twilio |
Disable Twilio polling |
Examples:
# Start listener in background
python3 ~/.claude/skills/sms/scripts/sms_listen.py --bg
# Check status
python3 ~/.claude/skills/sms/scripts/sms_listen.py --status
# Stop listener
python3 ~/.claude/skills/sms/scripts/sms_listen.py --stop
# Monitor only the Aldea production number, poll every 5s
python3 ~/.claude/skills/sms/scripts/sms_listen.py --bg --numbers +18557066006 --interval 5
# Telnyx webhook only (no Twilio polling)
python3 ~/.claude/skills/sms/scripts/sms_listen.py --bg --no-twilio
Telnyx webhook setup: Point your Telnyx Messaging Profile webhook URL to http://localhost:9147/telnyx. For remote access, use ngrok or similar tunnel.
6. Auto-Reply — Two Modes
Mode A: /sms-respond Slash Command (Interactive)
Process unhandled SMS using the current Claude Code session as the LLM. No subprocess needed—follows the same pattern as /slack-respond.
/sms-respond # Process all unhandled messages
/sms-respond 2 # Process only message #2 from inbox
The slash command loads inbox, soul.md, and memory context dynamically, then walks through a 6-step cognitive pipeline (internal monologue → external dialogue → user model check → user model update → soul state check → soul state update). Replies are sent via sms_send.py and all memory layers are updated.
The command also starts a background watcher (sms_watch.py) after processing, which polls for new inbound messages every 5 seconds and notifies the session when one arrives—creating a continuous two-way SMS loop.
Use this when: You're in an active Claude Code session and want to reply to SMS.
Mode B: sms_respond.py Daemon (Standalone)
Standalone daemon for Mac Mini or headless deployment. Uses claude -p subprocess to generate responses. Does not work from within a running Claude Code session (subprocess nesting conflict).
python3 ~/.claude/skills/sms/scripts/sms_respond.py [OPTIONS]
| Flag | Description |
|---|---|
--daemon |
Loop continuously, polling inbox |
--bg |
Run daemon in background (requires --daemon) |
--status |
Check if responder daemon is running |
--stop |
Stop running responder daemon |
--interval N |
Poll interval in seconds (default: 5) |
--model MODEL |
Override LLM model (default: claude-sonnet-4-5-20250514) |
--no-soul |
Disable soul context (plain responses) |
--dry-run |
Process messages without sending replies |
Examples:
# Start auto-reply daemon in background (Mac Mini)
python3 ~/.claude/skills/sms/scripts/sms_respond.py --daemon --bg
# Check daemon status
python3 ~/.claude/skills/sms/scripts/sms_respond.py --status
# Stop daemon
python3 ~/.claude/skills/sms/scripts/sms_respond.py --stop
Use this when: Running headless on Mac Mini or outside Claude Code.
Shared Infrastructure
Both modes require sms_listen.py running to feed inbox.jsonl.
Memory: 3-tier SQLite at data/sms_memory.db:
- Working memory — per-conversation message history + cognitive outputs
- User models — per-phone-number personality profiles
- Soul memory — cross-conversation soul state
7. sms_watch.py — Background Watcher for Claude Code
Polls inbox.jsonl for new unhandled messages. Designed as a run_in_background bash task—exits when a new message is detected, printing a structured line for Claude Code to parse.
python3 ~/.claude/skills/sms/scripts/sms_watch.py [OPTIONS]
| Flag | Description |
|---|---|
--interval N |
Poll interval in seconds (default: 5) |
--enrich |
On detect, also print sender's memory context (user model, soul state, recent conversation) |
Output on detect: {"event": "NEW_SMS", "id": "...", "from": "...", "to": "...", "body": "..."}
Output on detect with --enrich: Same JSON line, followed by ---MEMORY_CONTEXT--- and the sender's user model, soul state, and recent conversation history.
Output on timeout/kill: NO_NEW_SMS
Examples:
# Start watcher (run as background task in Claude Code)
python3 ~/.claude/skills/sms/scripts/sms_watch.py
# Enriched mode — pre-loads memory context for faster processing
python3 ~/.claude/skills/sms/scripts/sms_watch.py --enrich
# Faster polling
python3 ~/.claude/skills/sms/scripts/sms_watch.py --interval 3
8. sms_process_reply.py — Batch Reply Processor
Sends SMS reply and performs all 9 memory operations in a single call. Replaces the 9 separate python3 -c invocations from the /sms-respond pipeline.
python3 ~/.claude/skills/sms/scripts/sms_process_reply.py [OPTIONS]
| Flag | Description |
|---|---|
--phone NUMBER |
Sender's E.164 number (required) |
--our-number NUMBER |
Our number they texted (required) |
--message-id ID |
Inbox message ID (required) |
--message-text TEXT |
Original inbound message text (required) |
--reply-text TEXT |
External dialogue text to send (required) |
--monologue-text TEXT |
Internal monologue text (required) |
--monologue-verb VERB |
Monologue verb (default: thought) |
--dialogue-verb VERB |
Dialogue verb (default: said) |
--user-model-check BOOL |
Whether user model was updated (default: false) |
--user-model-md MD |
Updated user model markdown (if check was true) |
--soul-updates JSON |
JSON dict of soul state updates |
--stdin-json |
Read all args from stdin as JSON (avoids shell quoting) |
--dry-run |
Skip sending SMS, do memory operations only |
Examples:
# Basic reply with memory update
python3 ~/.claude/skills/sms/scripts/sms_process_reply.py \
--phone "+17327595647" \
--our-number "+18557066006" \
--message-id "SM0334c637c6017dbf84eae2a7fd824abd" \
--message-text "Hello there" \
--reply-text "Hello! Good to hear from you." \
--monologue-text "A friendly greeting." \
--monologue-verb "noticed" \
--dialogue-verb "replied" \
--user-model-check false
# With soul state update
python3 ~/.claude/skills/sms/scripts/sms_process_reply.py \
--phone "+17327595647" \
--our-number "+18557066006" \
--message-id "SM..." \
--message-text "text" \
--reply-text "reply" \
--monologue-text "monologue" \
--dialogue-verb "said" \
--user-model-check true \
--user-model-md "# Updated model" \
--soul-updates '{"currentTopic": "testing", "emotionalState": "engaged"}'
9. sms_inbox.py — Read Inbound Inbox
Read messages collected by sms_listen.py.
python3 ~/.claude/skills/sms/scripts/sms_inbox.py [OPTIONS]
| Flag | Description |
|---|---|
--all |
Show all messages (including handled) |
-n/--limit NUM |
Number of messages to show |
--from NUMBER |
Filter by sender number |
--provider telnyx|twilio |
Filter by provider |
--mark-read ID |
Mark a specific message as handled |
--mark-all-read |
Mark all messages as handled |
Examples:
# Show unhandled messages
python3 ~/.claude/skills/sms/scripts/sms_inbox.py
# Show last 5 messages from a specific sender
python3 ~/.claude/skills/sms/scripts/sms_inbox.py --from "+17327595647" -n 5
# Mark all as read
python3 ~/.claude/skills/sms/scripts/sms_inbox.py --mark-all-read
Configuration
Provider Auto-Detection
When you use --from, the skill detects the provider by matching against known numbers:
- Telnyx numbers:
+18628026208,+18334843851 - Twilio numbers:
+13205950420,+18557066006,+18559149834,+18776882519,+18665517616,+18778377603,+18665650327,+18667056747,+18445491928
Defaults
| Setting | Value |
|---|---|
| Default provider | Telnyx |
| Default Telnyx from | +18628026208 |
| Default Twilio from | +18557066006 (Claudius 855) |
Edit _sms_utils.py to change defaults.
Local Message Log
All sent messages are automatically logged to ~/.claude/skills/sms/data/messages.jsonl (JSONL format). This enables:
- Telnyx conversation history: Since Telnyx is send-only (no REST API for reading messages), the local log provides the only record of Telnyx messages.
- Offline message browsing: Read/conversation scripts automatically fall back to the local log when Telnyx API returns 404.
- Per-number history: Filter by any phone number to see all correspondences.
The log grows with each sent message. To reset, delete data/messages.jsonl.
Known Limitations
- Telnyx is send-only: Telnyx has no
GET /v2/messagesendpoint — message receiving is webhook-based only. Sent messages are tracked via the local log. For full read/conversation capability, use--provider twilioor--all-providers.
Phone Number Reference
Telnyx
| Number | Type | Label | Reserved |
|---|---|---|---|
+18628026208 |
Longcode | Primary (default) | Aldea / Dr. Shefali |
+18334843851 |
Toll-free | Secondary | Aldea (dev/backup) |
Twilio (9 numbers — verified live 2026-03-03)
| Number | Type | Label | Reserved |
|---|---|---|---|
+13205950420 |
Local | Claudius 320 | Claudius (broken—needs 10DLC registration) |
+18557066006 |
Toll-free | Claudius 855 | Claudius (2-way) |
+18559149834 |
Toll-free | 855 number | Available |
+18776882519 |
Local | 877 number | Available |
+18665517616 |
Local | 866 number | Available |
+18778377603 |
Local | 877-837 number | Available |
+18665650327 |
Local | 866-565 number | Available |
+18667056747 |
Local | 866-705 number | Available |
+18445491928 |
Local | 844 number | Available |
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?