2016judea/sms-native-product

テキストメッセージをインターフェースとするプロダクトを構築するスキル — 「アプリもウェブサイトも不要」、ユーザーは番号にテキストを送るだけ。SMSボット、Telegramボット、グループチャット、最小摩擦のUXを実現する。

sms-native-product とは?

このスキルは、テキストメッセージ(SMS、Telegram、WhatsAppなど)を唯一のユーザーインターフェースとするプロダクトを設計・構築するための包括的なガイドです。従来のアプリやウェブサイトを排除し、ユーザーが番号にテキストを送るだけで操作できる「ネイティブテキスト体験」を提供します。中核的な課題は、キャリア(特に米国A2P 10DLC)によるコンテンツ規制と承認プロセスであり、このスキルでは設計の前にこの「ゲート」を通過する方法を詳細に解説します。SHAFT(Sex, Hate, Alcohol, Firearms, Tobacco)ルールによる永久拒否コード、グループMMSの技術的制約、チャネル喪失に耐えるアーキテクチャ、モデルによるユーザーコンテンツ書き換えのガードなど、実践的なルールとコード構造(machine.js, effects.js, シミュレータ)を提供します。Twilio Conversations、Telegram Bot API、WhatsApp Cloud APIなど複数のチャネルをサポートし、シミュレータによる時間ジャンプテストや、プロダクションと同じパスを実行する駆動テストによって、シーケンスバグを早期に発見する方法も含まれています。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/2016judea/brick-mortar-skills/tree/HEAD/skills/sms-native-product

Installed? Explore more 生産性&コラボレーション skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

インターフェースがテキストメッセージであるプロダクト

アプリをインストールしたりウェブサイトを訪問したりするのは面倒ですが、誰でもテキストは送れます。そこに魅力があります。ただし、チャネルを自分で所有しているわけではありません。米国のキャリアが所有しており、コンテンツポリシーと承認プロセスがあり、永久に拒否される可能性があります。そのゲートがプロダクトの許容範囲を決定するため、最初に取り組む必要があります。


ステップ0 — ゲート。設計の後ではなく、前に行うこと

2025年2月以降、米国のキャリアは未登録のA2Pトラフィックを完全にブロックするため、1件のメッセージを送信する前にブランドとキャンペーンの承認が必要です。毎回、最新のエラードキュメントを読み直してください。キャリアポリシーは変更されます。

コードトリガー再申請?
30953露骨/性的示唆のある文言、または「ポルノ、エスコート、デート、アダルトエンターテイメントコンテンツ」をホストするリンク先サイト不可
30885「高リスク」 — 欺瞞的なマーケティング、またはトラフィックを偽って報告する登録不可
308981つのEINに多すぎるブランド、または重複とみなされる登録理由があれば可

ルール:最初の返信でプロダクトのコンテンツカテゴリを声に出して述べ、それがそのリストに載っているかどうかを言う。 カテゴリ(例:デート)が拒否ルールのキーワードそのものである場合、それを5分目で見つけると、アーキテクチャ、ランディングコピー、フォールバック計画が変わります。SHAFTは略語です:Sex(性)、Hate(憎悪)、Alcohol(アルコール)、Firearms(銃器)、Tobacco(タバコ) — さらにCannabis(大麻)、デートもこれに準じます。

ルール:サイドプロジェクトは、既存の会社のEINではなく、個人事業主(Sole Proprietor)ブランドとして登録する。 リスクパターンは税ID(30898)に従うため、サイドプロジェクトでの拒否がメインビジネスの送信能力に影響してはいけません。個人事業主は税IDのない個人を対象としており、スループットは低いですが、ベータ版には十分です。

ルール:キャンペーン承認を得るために偽のランディングページを作成してはいけない。 実際のトラフィックを隠すページはまさに30885のパターンであり、1つの番号のリスクを、今後登録するすべての番号のリスクに変えます。確率を率直に述べ、オーナーに決定を委ねてください。

サービスを、それが機械的に何をするかによって説明する。 そしてそれが真実である場合に限ります(例:ジャーナリングと小グループの説明責任、それがメッセージの内容である場合)。真実の説明がゲートを通らない場合、答えはより良い婉曲表現ではなく、異なるチャネルです。

審査では、指摘できる事実が報われます:受信のみのオプトイン、会話量、繰り返しメッセージ内のリンクなし、すべてに先立つSTOP処理、入り口での露骨なコンテンツ拒否。

ステップ0.5 — ブリーフを意図ではなく「数字」と「オブジェクト」として読む

創業者のブリーフをそのままREADME.mdとして保持し、CLAUDE.mdにそれがすべてのエンジニアリングドキュメントよりも優先されると記載する。

ルール:ステートマシンを書く前に、ブリーフ内のすべての期間と、それが作用するすべての名詞をリストアップする。2つの期間が存在する場合、それらは2つの機能である。 「友達の返信が作者に届くまでの1週間の遅延」と「作者自身の更新に関する2週間のロック」というブリーフは、「エントリ」に対する1つの7日間保留に簡単に統合できます — どちらの遅延も対象としていなかった1つのオブジェクト — そして、その統合からすべての下流のエラーが発生します。

ルール:すべての遅延のオブジェクトに名前を付ける — 「誰から保留されているか」。 友達から保留されているのと、作者から保留されているのは、正反対のプロダクトです。

ルール:ブリーフの文字通りの設計をチャネルで強制できない場合、その旨を述べ、代替案を示す。強制できる方を黙って選んではいけない。 (グループチャットの作成者はそのメンバーでもあるため、どのコードもグループの返信を彼らから差し控えることはできません。)これは前提の決定であり、前提の決定はオーナーのものです。

一貫性のある誤読は、誤読のように感じられない。 置き換えられた設計段落を取り消し線付きでそのまま残し、削除しない。後のセッションに、ブリーフがどのように誤読されたかを示します。

ステップ1 — チャネルでできることとできないこと

  • コードからのグループテキストは機能します。 Twilio Conversationsは、+1ロングコードのみでグループMMSをサポートします — フリーダイヤルやショートコードは不可 — 最大自分自身の番号を含む10人の参加者まで。記憶に基づいて別の主張をしないでください。
  • グループMMS SMS参加者はAddressを持ち、ProxyAddressはありません。そのため、1つの番号ですべてのルームにサービスを提供できますが、参加者/プロキシの一意性ルール(50425)には、プロキシなしの参加者に対する文書化された動作がありません。1つの番号と1つの参加者セットを共有する多数の同時ルームを決して設計しないでください。 1人につき1つの永続的なルームは、安定した参加者セットを持ちます。
  • WebページはiPhoneのアドレス帳を読めません。 Contact Picker APIはChrome on Androidのみです。「連絡先を同期」は機能しません。代わりに、ユーザーが転送する行を用意します — 受信者の受信テキストが、キャリアが求める同意記録になります。
  • Telegramボットはグループを作成したり、誰かをグループに追加したりできません。 また、プライバシーモードがオンの場合、自分宛てのコマンドのみを認識します。どちらも役に立ちます:作成者はすでに存在するチャットにボットを追加し、一般的な雑談が入力と誤認されることはありません。ボットの作成には@BotFatherで人間の操作が必要です(APIはありません)。トークンを要求してください。
  • WhatsApp Cloud APIにはグループメッセージング機能はありません。
  • iMessage API(Sendblue、LoopMessage)は青いバブルと実際のグループチャットを提供しますが、回線あたり月額約100ドルと初期費用がかかります。

ステップ2 — チャネル喪失に耐えるアーキテクチャ

チャネルは拒否される可能性があるため、トランスポートは1つのファイルでなければなりません:

machine.js   純粋関数: (context, event) -> {replies, effects}   I/Oなし、クロックなし
engine.js    コンテキストのアセンブリ -> machine -> effects    パス全体
effects.js   createEffects({db, channel})                     決定を実行
twilio.js  / telegram.js                                      交換可能
api/*.js     engine.js へのシンラッパー                        約10行
sim/         インメモリDB + コンソールチャネル
  • 決定コアはnowを引数として受け取り、ネットワークに触れない。 このクラスのプロダクトのバグはすべてシーケンスバグです(2回起動するリマインダー、空のルームへのメッセージ、届かない保留アイテム)。そして、それらはライブネットワークと7日間のタイマーに対してテストできません。
  • アダプターはエフェクトレイヤーでインポートではなく引数として渡される。 これはシミュレーターとフォールバックチャネルの両方に必要なリファクタリングです。
  • HTTPハンドラー内にロジックを書かない。 api/telegram.js内にチャネル固有のオンボーディングを書くとテスト不可能です。抽出してください。

ステップ3 — テストするだけでなく、駆動する

node sim/drive.js          スクリプト駆動:完全なループ、時間ジャンプ、ガード
node sim/drive.js --repl   任意の番号として入力;/as <n>  /jump <days>  /state
  • シミュレーターはプロダクションパスを実行しなければならない。 並列コピーではダメです。
  • 最初の駆動では、単体テストでは到達できないいくつかの実際の欠陥が明らかになることを想定してください:誰もいないのに自分自身にあいさつするルーム、1週間後の日付の裸の曜日、どのアイテムのことか言わないリマインダー、全員が退出したルーム。
  • テストがレッドになったら、まずテストを確認する。 (Sun, Aug 30のカンマを許可しない日付正規表現、別の正当なメッセージで発動するdoesNotMatchなど)。
  • ストアがスタンプしたタイムスタンプから判断したり表示したりしない。 ストアはcreated_atを実際のクロックから書き込みます。エンジンの注入されたnowからではありません。そのため、時間ジャンプ下では嘘をつき(過去の日付を表示します)。マシンが書き込んだカラムからのみ判断し、関連する日付は1つの保存アンカーにぶら下げてください。

ステップ4 — ロック画面のためのコピー

1つのファイルにすべての送信文字列を保持します。

  • 絵文字なし、感嘆符なし、マーケティングなし。
  • 1〜2日以上先の日付には、決して裸の曜日を使わない。 Sun Aug 30。
  • すべてのキーワードで句読点と大文字小文字を許容する — Wait. と Yes! が機能しなければならない。
  • キーワードを含む散文は依然として散文です:「we should wait and see」はWAITではありません。正規化されたメッセージ全体をマッチさせ、部分文字列ではマッチさせない。
  • STOP / HELP / START は、すべてのアプリケーション状態とすべてのモデル呼び出しの前に解析される。 そのため、オプトアウトが他の場所のバグやAPI障害によって壊れることはありません。
  • モデルがコンテンツをガードする場合、フェイルクローズする:チェックを実行できない場合、何も送信せず、その旨を伝える。

ステップ5 — モデルがユーザーコンテンツを書き換える場合、信頼する前に実行する

ユーザーエントリから第三者名を除去するガードは、完全に読めても次のことを行う可能性があります:

  1. 事実を作り出す — 「Jane Doe」を「自然なハンドル」に置き換えるよう指示されたとき、アプリについて何も言及されていないのに「the girl from the app」と書きました。受信者は作り話を事実として読みます。
  2. 過剰修正して実際の詳細を削除する — 「Jane from the run club」が「her」になりました。

ルール:指示は、モデルが何を発明してはいけないか、何を削除してはいけないかを述べなければならない。 機能する形式:置換をソースに基づかせ、フレーズ全体ではなくトークンを置換し、文がすでに述べている詳細を再利用するよりも中立的なフォールバックを優先する。

ルール:各ライブモデルの欠陥をオプトインテストとして固定し、APIキーなしではスキップする。 これにより、プロンプト編集がすべてのテスト実行でコストを増大させることなく、黙って後退することを防ぎます。ガード呼び出しごとに2〜5秒を見積もってください。

コスト(桁は概算。ライブで確認すること)

+1ロングコードは月額1〜2ドル。SMSは1セグメントあたり1セント未満(双方向)。MMSは数セント。個人事業主登録は数ドルの初期費用と少額の月額キャンペーン料金。Telegramは無料。

質問する vs. 決定する

  • 質問する: 永久拒否される可能性があることを承知で正直な登録を提出するか、Telegramで始めるか(費用と不可逆的な結果)。プロダクトの本質を変えるものすべて。
  • 決定する: アーキテクチャ、コピーの声、ステートマシン、テストカバレッジ、最初にどのアダプターを使うか、日付形式、ガードの動作。

何かがブロックされていると報告する前に、すべての候補となる認証情報を列挙してください。 (ディスクに1つの使い果たされたAPIキーがあるからといって、別の動作するキーがないとは限りません。)

関連項目: build-remote-mcp-server(別の「ネイティブサーフェス」パターン)。

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

2016judea/ascii-charts

Build charts as plain Unicode-block text — bar, range, bullet, gap-bracket, star-histogram, heatmap, line, Venn, pie, donut and scatter — with a dependency-free Python script, for anywhere only monospace text survives (newsletter code blocks, Markdown, terminals, plain-text email, chat). Use when a chart has to embed as literal text instead of an image or a third-party chart service, or when you want a hand-made terminal look with no branding footer.

2016judea/buffett-checklist

Apply Warren Buffett's investment framework as a discipline lens when weighing a buy, hold, or sell decision — circle of competence, economic moat, owner earnings & intrinsic value, margin of safety, management/capital-allocation quality, and market psychology (Mr. Market, fear vs greed, temperament). Use when asked to "run this through Buffett", "what would Buffett say", "does this pass the moat test", "is this cheap enough", or for a second, more skeptical read on a name being evaluated or already held. This is a discipline overlay, not a replacement for a strategy — it applies the Buffett lens to how someone actually invests, rather than issuing generic advice.

2016judea/image-riff

Turn one or more reference images into original art in that reference's own visual language, then cut it to whatever surface it's for. Use when you paste or point at art and say "use this as the base image", "generate art from this", "riff on this", "some creative ideation with these images", "make me a channel banner / avatar / cover / plate", "wilder version of this", or want a spread of options off one piece of reference. This is the TASK skill; the engine is the `make-art` tool skill.

2016judea/leonardo

Draw the way Leonardo da Vinci drew — a study sheet, a notebook folio, a red-chalk or silverpoint study, a machine cutaway, a storm of vortices — in his real materials and page-logic, generated with the make-art engine and anchored on fifteen of his actual (public-domain) sheets. Use when you say "Leonardo", "da Vinci", "like his notebooks", "a codex page of X", "draw this as one of his study sheets", "sanguine", "silverpoint", or wants a design, diagram, or illustration in that hand. Also a reading guide to his notebooks (Richter's 1883 public-domain translation) for "what did Leonardo say about shadow / trees / water". This is a TASK skill; the engine is `make-art`.

2016judea/mcp-stack

Which free MCP server or framework to reach for, and its traps — finance/gov data (SEC EDGAR, Yahoo, SAM.gov, USAspending), web research (Exa, Firecrawl, Crawl4AI, Jina reader), design/art/brand (Canva, Inkscape, Penpot, Figma, Orshot, Hugging Face image gen, vectorizing, charts), data/spatial (DuckDB spatial, live ArcGIS layers, OpenStreetMap/Overpass, Census, MapLibre), and ops (PostHog, iMessage, context7 docs). Use when making a social post, OG card, poster, logo/vector, chart, map, or brand asset; when querying parquet/geojson/duckdb or a city's open-data layer; when an MCP "needs authentication" or fails; or when asked "what tools do we have", "is there an MCP for X", "should we add X".

2016judea/records-request

Get a specific record out of a US government office by public-records request — "request the assessor's model", "file a data practices request", "FOIA this", "open records request", "can we just ask the county for it", "who do I write to at <county>", "chase that request", "did they ever answer". Covers checking the website first, finding the right office and statute, the carve-out paragraph that makes a request answerable instead of refused, web-form traps (hidden character caps, WAFs that reject apostrophes), chasing (there is usually no deadline), whether what comes back may be republished, and parsing multi-year tables without silent errors.

2016judea/vertical-market-agent

Build a chat agent that knows one industry in one metro better than any general model because it carries a precomputed digest of real public records (or a mined review corpus) and can pull live records mid-conversation — finding the moat, building a byte-stable substrate, enumerating what the records can't, the data traps that produce plausible wrong numbers, deterministic math in tools, measured prompt cost and cache TTL, shipping as an ad destination, an off-sector ending, and a precomputed spatial "what is this next to" layer. Use when building a vertical AI agent grounded in records rather than general knowledge.

関連スキル