Claude-code-minoan 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
source · Clone the upstream repo
git clone https://github.com/tdimino/claude-code-minoan
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/tdimino/claude-code-minoan "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/integration-automation/sms" ~/.claude/skills/tdimino-claude-code-minoan-sms && rm -rf "$T"
manifest: skills/integration-automation/sms/SKILL.md
source content

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_KEY
    env var, or falls back to
    ~/.claude.json
    (already configured)
  • Twilio:
    TWILIO_ACCOUNT_SID
    +
    TWILIO_AUTH_TOKEN
    env 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]
FlagDescription
--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]
FlagDescription
--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]
FlagDescription
-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]
FlagDescription
--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]
FlagDescription
--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]
FlagDescription
--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]
FlagDescription
--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]
FlagDescription
--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]
FlagDescription
--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

SettingValue
Default providerTelnyx
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/messages
    endpoint — message receiving is webhook-based only. Sent messages are tracked via the local log. For full read/conversation capability, use
    --provider twilio
    or
    --all-providers
    .

Phone Number Reference

Telnyx

NumberTypeLabelReserved
+18628026208
LongcodePrimary (default)Aldea / Dr. Shefali
+18334843851
Toll-freeSecondaryAldea (dev/backup)

Twilio (9 numbers — verified live 2026-03-03)

NumberTypeLabelReserved
+13205950420
LocalClaudius 320Claudius (broken—needs 10DLC registration)
+18557066006
Toll-freeClaudius 855Claudius (2-way)
+18559149834
Toll-free855 numberAvailable
+18776882519
Local877 numberAvailable
+18665517616
Local866 numberAvailable
+18778377603
Local877-837 numberAvailable
+18665650327
Local866-565 numberAvailable
+18667056747
Local866-705 numberAvailable
+18445491928
Local844 numberAvailable