ravn
Claude skill

Check numbers are real mobiles before texting

Before a text campaign, confirm each number is valid, put it in E.164 format, and check it is a real mobile line rather than a landline or VoIP number. It runs in two passes: a cheap number-plan check for everyone, then a live carrier check only where it matters.

Download SKILL.md Start free

Install

One command.

Installs into ~/.claude/skills for Claude Code. In Claude, upload the downloaded file under Settings → Capabilities → Skills.

npx ravn skill install check-mobile-before-sms

When to use

  • The user is about to send SMS and wants to avoid texting landlines, toll-free or VoIP numbers.
  • Phone numbers came in mixed formats from forms or imports.
  • "Which of these numbers can actually receive a text?"

Before you start

  1. Check the connection: npx ravn whoami (free).
  2. phone_to_carrier needs your own provider key connected — run ravn keys add twilio first; this tool runs on your own provider account. If it returns 403 provider_key_required, stop and tell the human to add their key. validate_phone is ours and needs no key; it uses the number plan only (carrier_checked: false). Every call is one lookup; misses are free.
  3. Ask which country most numbers are from. National numbers without a + need a country (ISO 2-letter code); the default is US.
  4. Confirm the user has consent to text these people. This skill checks numbers, not permission.

Steps

  1. Pass 1, format and line type from the number plan, for everyone:
npx ravn enrich contacts.csv --tool validate_phone --map phone=Phone,country=Country --dry-run
npx ravn enrich contacts.csv --tool validate_phone --map phone=Phone,country=Country --limit 10 --out sample.csv
npx ravn enrich contacts.csv --tool validate_phone --map phone=Phone,country=Country --out pass1.csv

If there is no country column, use --column Phone and numbers default to US. Fill empty country cells (for example with US) first, or those rows come back as error with invalid_input. Single number over MCP:

{ "phone": "(415) 555-0134", "country": "US" }
  1. Sort pass 1 results: - rw_valid false or rw_status not_found: remove. - rw_line_type landline or toll_free: remove from the SMS list. - mobile, voip or unclear: keep for pass 2.

Write the kept rows to keep.csv, renaming rw_phone to phone_e164 and rw_line_type to plan_line_type, and dropping the other pass 1 rw_* columns, so pass 2 does not produce clashing column names. 3. Pass 2, live carrier check, only on the kept rows. Number-plan line type can be wrong when numbers have been ported, so this is the real answer.

npx ravn enrich keep.csv --tool phone_to_carrier --column phone_e164 --dry-run
npx ravn enrich keep.csv --tool phone_to_carrier --column phone_e164 --out pass2.csv

The input is the E.164 number from pass 1. The dry run shows how many lookups the pass will use. 4. If phone_to_carrier returns 403 provider_key_required, the account has no carrier provider key connected. Tell the human to add one with ravn keys add twilio, and in the meantime send them the pass 1 result with a clear note that line types are from the number plan only. 5. Keep only rows where the live line_type is mobile. Flag non-fixed VoIP separately; whether to text those is the user's call.

Output

sms-ready.csv with original columns plus:

  • From pass 1: phone_e164 and plan_line_type (the number-plan guess).
  • From pass 2: rw_status (ok, not_found, error, dropped), rw_phone, rw_line_type (live), the carrier name, and rw_carrier_checked true.
  • sms_ok: yes or no, with sms_reason (invalid, landline, toll_free, voip, mobile).

Also removed.csv and a count per reason.

Rules

  • Never text anyone who opted out or replied STOP. Remove them before you start. See /privacy#optout.
  • A valid mobile is not consent. Remind the user that texting rules in their country still apply.
  • No FCRA uses: do not check numbers to screen people for credit, employment, insurance or housing.
  • On a 429 fair_use_exhausted or a 403 provider_key_required, stop and tell the human.

Example prompt

We're texting 2,000 customers a delivery update next week. Phone numbers are all over the place. Make sure we only text real mobiles and fix the formatting.