wa — safe WhatsApp automation について
waは、常駐デーモン、CLI、MCPサーバーを備えた個人向けWhatsApp自動化ツールで、スクリプトやAIエージェントから利用できます。送信は既定で人の確認を待つ下書きとなり、デーモンが許可リスト、レート制限、追記専用監査ログを適用します。
主な機能
- 01常駐デーモンによるWhatsAppセッション管理
- 02メッセージやメディアの送信・予約
- 03確認後に送信する下書き機能
- 04強制適用される許可リストとレート制限
- 05メッセージ検索とチャット情報の確認
活用シーン
- 01スクリプトやcronからのメッセージ送信
- 02AIエージェントによる確認用メッセージの作成
- 03同期済みメッセージの検索とスレッド確認
- 04仕事用と個人用プロフィールの分離管理
MCP 対応
`wa mcp serve`はstdio経由で、メッセージ、チャット、連絡先などのツールとリソース、プロンプトをMCPクライアントに提供します。すべての呼び出しがデーモンの安全機構を通り、送信は既定で下書きとなり、人の承認後に送信されます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
wa
Go で記述された、個人向け WhatsApp 自動化 CLI + デーモンです。
WhatsApp Multi-Device セッションを管理するヘキサゴナルアーキテクチャの Go デーモンと、デーモンと通信する薄い JSON-RPC クライアントです。言語モデルに代わりにメッセージを送信させても安全で、移行中の停電にも耐えられるほどクラッシュに強く、想定される破壊的なフラグをすべて拒否するほど用心深く設計されています。
クイックスタート · インストール · マニュアル · アーキテクチャ · セキュリティ · コントリビューション · Português (BR)
機能
パターン。 Unix ソケット経由の永続的な WhatsApp デーモンです。1 つの wad プロセスが Multi-Device セッション、ラチェットストア、WebSocket を保持し、薄い wa JSON-RPC クライアントが呼び出します。
トレードオフ。 プロファイルごとに約 30 MB の RSS と、コールド接続に 5~8 秒を要する代わりに、その後の wa send は毎回、ウォーム状態なら 1 秒未満のレイテンシーで呼び出せます。呼び出しごとのセッション再アタッチは完全に回避されます。
用途。 シェルパイプライン、cron ジョブ、または Claude Code プラグインから、予測可能なレイテンシーで WhatsApp メッセージを送信する必要がある場合に適しています。すべての RPC 経路の下に、上書きできない安全パイプライン(デフォルト拒否の許可リスト + レートリミッター + ウォームアップランプ + 追記専用監査ログ)を備えています。
brew install yolo-labz/tap/wa
wad & # daemon, single instance per profile
wa pair # QR-code pairing on first run
wa allow add [email protected] --actions send
wa send --to [email protected] --body "hello"
デモ

すべてのフレームは、このリポジトリ内のバイナリからの実際の出力です。
非公開の一時ディレクトリに用意した、ペアリングされていない使い捨てデーモンを
相手に記録しています。doctor はデバイスがペアリングされていないことを正直に警告し
(新しいサンドボックスでバックアップの不足も指摘する場合があります)。
実際のアカウントデータは使用していません。取り消しコマンドは変更を行わず、
ヘルプのみを表示します。
録画は生成されたもので、手作業で編集されたものではありません。正本は
プレーンテキストの docs/assets/wa-demo.tape です。
次の 1 つのコマンドで、GIF、MP4、WebM、静止 PNG、キャプチャしたテキストを再生成できます。
nix develop -c ./scripts/record-demo.sh
再生コントロールやモーション低減を使いたい場合は、MP4、 WebM、静止フレーム、 またはテキスト版をご利用ください。 録画に関するメモでは、分離、安全制御、 バイト数の上限、チェックについて説明しています。再生速度は 1 倍で、音声はありません。 ライブ送信のデモは行っていません。
wa の比較
リバースエンジニアリングされた WhatsApp エコシステムにおける、最も近い競合との比較です。
| 機能 | wa(このリポジトリ) | whatsmeow 直接利用 | whatsapp-web-cli |
|---|---|---|---|
| 永続デーモン(ウォーム呼び出しはサブ秒) | はい | いいえ(呼び出しごとにセッションを接続) | いいえ(ブラウザー駆動) |
| Unix ソケット経由の JSON-RPC | はい | 該当なし(デーモンではなくライブラリ) | いいえ(Chrome ブリッジ) |
| デフォルト拒否の許可リスト(アクションごと) | はい | 手動で実装 | いいえ |
| オーバーライド不可能なレート制限(2回/秒+30回/分) | はい | 手動で実装 | いいえ |
| 新規セッション向けウォームアップランプ | はい | 手動で実装 | いいえ |
| 追記専用 JSON-Lines 監査ログ | はい | 手動で実装 | いいえ |
| SLSA L2+Sigstore 署名付きリリース | はい | 該当なし | いいえ |
| デュアル SBOM(CycloneDX 1.6+SPDX 2.3) | はい | 該当なし | いいえ |
CGO_ENABLED=0 の静的バイナリ | はい | 利用者に依存 | いいえ(ブラウザー駆動) |
| 受信プロンプトインジェクションファイアウォール | はい | 該当なし | いいえ |
マルチテナント REST ゲートウェイについては、EvolutionAPI または WAHA をご覧ください。これらは課題の性質が異なり、このプロジェクトが対象としないものに記載しています。
このプロジェクトについて
1 つのリポジトリに 2 つのバイナリがあります。
wad— WhatsApp セッション、SQLite ラチェットストア、web.whatsapp.comへの WebSocket 接続を管理する、長時間稼働するデーモンです。systemd(Linux)、launchd(macOS)、または NixOS モジュールで実行します。プロファイルごとに単一インスタンスで動作し、root では絶対に実行しません。wa— Unix ソケット経由でwadと通信する、軽量な JSON-RPC クライアントです。シェルスクリプト、cron ジョブ、Claude Code プラグインが実際に呼び出すのはこちらです。
本プロジェクトは go.mau.fi/whatsmeow を基盤にしています。これは、本番環境で mautrix-whatsapp を支えるライブラリであり、2026 年時点で積極的にメンテナンスされている唯一のリバースエンジニアリングされた WhatsApp ライブラリです。また、安全性を最優先した MCP サーバー(wa mcp serve)も提供しており、AI エージェントは回避不可能な同一の安全性パイプラインを通じて WhatsApp を操作できます。デフォルトでは下書きの承認が必要です。MCP サーバーをご覧ください。
このプロジェクトが対象としないもの
- 一括メッセージ送信ツールではありません。 レート制限はオーバーライドできず、
--forceフラグもありません。 - マルチテナント SaaS ではありません。 各
waインストールは 1 人の利用者を対象とし、仕事用と個人用に分ける場合は、任意で複数プロファイルに分離できます。 - Matrix ブリッジではありません。 それをお求めの場合は、
mautrix-whatsappをご利用ください。 - REST ゲートウェイではありません。 それをお求めの場合は、
EvolutionAPIまたはWAHAをご利用ください。 - 公式 WhatsApp Cloud API ではありません。 このプロジェクトは
whatsmeowを通じて、リバースエンジニアリングされた Multi-Device プロトコルを使用します。
クイックスタート
# Install (Homebrew — macOS + Linuxbrew)
brew install yolo-labz/tap/wa
# Or via Nix (recommended for NixOS/nix-darwin users)
nix profile install github:yolo-labz/wa
# Or the checksum-verified installer (80 lines — inspect first if you like)
curl -fsSL https://raw.githubusercontent.com/yolo-labz/wa/main/install.sh | bash
# Or Docker — single distroless container (~12 MB); /data holds the session
docker compose up -d # see docker-compose.yaml; pair via `docker compose exec`
# Start the daemon (default profile)
wad &
# Pair your phone — QR code in terminal
wa pair
# Allowlist yourself (default-deny policy)
wa allow add [email protected] --actions send
# Send a message
wa send --to [email protected] --body "hello from wa"
# Install as a persistent system service
wad install-service --profile default
# Hand it to an AI agent — MCP over stdio, draft-gated sends by default:
# the agent PROPOSES messages into a human-review queue; nothing leaves
# until you run `wa draft approve`. Add to Claude Desktop/Code, Cursor:
# {"mcpServers": {"wa": {"command": "wa", "args": ["mcp", "serve"]}}}
wa mcp serve --help
宛先を指定するフラグはコマンドによって --to、--jid、または --group です。どのコマンドでも、共通の別名として --chat <jid> を使用できます(元のフラグも引き続き使用できます)。
複数プロファイルの設定、シェル補完、移行、監査ログを含む詳細なガイドについては、docs/manual.md をご覧ください。
MCP サーバー
wa mcp serve は、Model Context Protocol(stdio トランスポート)を介してデーモンを AI エージェントに公開します。すべてのツール呼び出しは、CLI と同じ、バイパス不可能な安全性パイプラインを通ります。具体的には、デフォルト拒否の許可リスト、ウォームアップ付きの短時間枠の上限(毎秒 2 件、バースト 2 件、毎分 30 件、バースト 30 件。通常の送信に1日あたりの上限はありません)、追記専用の監査ログが適用されます。送信はデフォルトで下書きモードです。モデルは人間のレビュー待ちキューにメッセージを提案し、wa draft approve を実行するまで何も送信されません。この下書きゲートが重要です。これにより、自律型エージェントに WhatsApp を任せても安全になります。
公式の MCP Registry に io.github.yolo-labz/wa として登録されています。各 リリースにある署名済み .mcpb バンドルからワンクリックでインストールするか、Claude Desktop/Code または Cursor に手動で設定できます。
{ "mcpServers": { "wa": { "command": "wa", "args": ["mcp", "serve"] } } }
ツール(12 個):
| ツール | 用途 |
|---|---|
wa_send_message | 安全性パイプラインを通じてメッセージを送信(または下書き) |
wa_send_media | メディアファイルを送信(または下書き) |
wa_schedule_message | 後で送信するようスケジュール設定(下書きにも対応) |
wa_draft_review | 人間の承認待ちの下書きを一覧表示 |
wa_search_messages | 同期済みメッセージを全文検索 |
wa_get_thread | 1 つのチャットの最近のメッセージを取得 |
wa_list_chats | 最近アクティビティのあったチャットを一覧表示 |
wa_resolve_contact | 名前または電話番号を JID に解決 |
wa_group_info | グループのメタデータと参加者 |
wa_wait_for_reply | 条件に一致する受信イベントが届くまで待機 |
wa_transcribe_voice | 音声メモを文字起こし |
wa_status | デーモンの接続状態とセッション状態 |
MCP 仕様に従って、リソース(読み取り専用のコンテキスト情報)とプロンプト(事前構築済みのワークフロー)も提供します。--toolsets で公開範囲を設定できます。送信モードは draft(デフォルト)、direct、deny から選択でき、read-only セットでは変更を伴うすべてのツールが非表示になります。
レジストリへの公開手順とバンドルの内部構造については、docs/mcp-registry.md を参照してください。
インストール
Homebrew(macOS + Linux)
brew install yolo-labz/tap/wa
Nix flake
# One-shot
nix run github:yolo-labz/wa -- profile list
# Install to profile
nix profile install github:yolo-labz/wa
# Dev shell (go + gopls + golangci-lint + goreleaser + sqlite + jq)
nix develop github:yolo-labz/wa
NixOS モジュール — システムモジュールをインポートして有効にします:
{
inputs.wa.url = "github:yolo-labz/wa";
outputs = { self, nixpkgs, wa, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [
wa.nixosModules.default
{ services.wa.enable = true; services.wa.profile = "default"; }
];
};
};
}
home-manager モジュール — ユーザーごとのインストール用にインポートします:
{
imports = [ wa.homeManagerModules.default ];
services.wa = {
enable = true;
profile = "default";
autoStart = true;
};
}
GoReleaser tarball + サプライチェーンの検証
VERSION=v2.0.5 # pin to a known tag
ARCH=linux_amd64 # or darwin_arm64 / linux_arm64
BASE="https://github.com/yolo-labz/wa/releases/download/$VERSION"
# 1. Download the tarball + checksums
curl -LO "$BASE/wa_${VERSION#v}_${ARCH}.tar.gz"
curl -LO "$BASE/checksums.txt"
# 2. Verify the SHA256 (defends against accidental corruption)
sha256sum -c checksums.txt --ignore-missing
# 3. Verify the SLSA-L2 attestation against THIS tarball (not just the
# manifest) via GitHub's native attestation store. From v2.0.5 onward
# every artifact (.tar.gz / .deb / .rpm / .apk) is registered as its
# own attestation subject — earlier releases (≤ v2.0.4) only attested
# `checksums.txt` and would 404 on per-artifact verify. Requires
# `gh` CLI ≥ 2.50 (Sigstore bundle v0.3.1 support). The verify step
# transparently checks Rekor v2 transparency-log inclusion proof on
# the Sigstore bundle — no separate `rekor-cli` invocation needed.
gh attestation verify "wa_${VERSION#v}_${ARCH}.tar.gz" --repo yolo-labz/wa
# 4. Install
tar xzf "wa_${VERSION#v}_${ARCH}.tar.gz"
install -m 0755 wa wad ~/.local/bin/
gh attestation verify のステップでは、この tarball が、タグが指す正確なコミット SHA における yolo-labz/wa の GoReleaser ジョブによって生成されたことを証明します。各リリースには以下が含まれます。
wa_<version>_<os>_<arch>.tar.gz— プラットフォーム用 tarballchecksums.txt— 各アーティファクトの SHA256checksums.txt.sigstore.json—checksums.txt用の Cosign 署名付き Sigstore バンドル(従来の任意の検証方法。上記のアーティファクトに対してgh attestation verifyを使用する場合は不要です)sbom.cdx.json— CycloneDX 1.6 SBOM(リポジトリ全体、syft)sbom.spdx.json— SPDX 2.3 SBOM(リポジトリ全体、syft)sbom.gomod.{wa,wad}.cdx.json— Go ネイティブの CycloneDX SBOM(cyclonedx-gomod、バイナリごと、標準ライブラリとライセンス情報を含む)openvex.json— OpenVEX 0.2 のステートメントファイル。VEX 対応スキャナー(Trivy、Grype)はこれを利用して、「この CVE は実際にwaで悪用可能か」を絞り込みます。depguardによって適用されるポート境界により、依存関係由来の CVE の大半は実行時の経路に入らないため、not_affectedとなります。検出結果が明らかになるにつれてステートメントは増えていきます。現在のベースラインは、CVE ごとのトリアージ待ちのため空です。CHANGELOG.md— git-cliff で生成された変更履歴
darwin ユーザー — 署名なしのリリース: Apple Developer アカウントなしで作成されたリリースには、署名も公証もされていない darwin-arm64 バイナリが含まれます。初回起動時に Gatekeeper によって隔離されます。実行前に隔離フラグを削除してください。
xattr -cr ~/.local/bin/wa ~/.local/bin/wadまたは、Homebrew tap(
brew install yolo-labz/tap/wa)経由でインストールしてください。brew はローカルでソースから再ビルドするため、隔離を完全に回避できます。APPLE_DEVELOPER_ID_APPLICATION_{CERT,KEY}シークレットが設定された後、次回の GA タグ作成時に、署名と公証済みの darwin バイナリが復活します。
go install
モジュールパスには、v2+ リリースに関する Go のセマンティックインポートバージョニングルールに従い、/v2 サフィックスが含まれます。
# Pin to a tag (recommended — reproducible builds need a known revision):
go install github.com/yolo-labz/wa/v2/cmd/[email protected]
go install github.com/yolo-labz/wa/v2/cmd/[email protected]
# Or follow main:
go install github.com/yolo-labz/wa/v2/cmd/wa@latest
go install github.com/yolo-labz/wa/v2/cmd/wad@latest
タグに対する go install では、GoReleaser のビルドフラグ(-trimpath、-buildvcs=true、ldflag によるバージョンの埋め込み)は引き継がれません。生成されたバイナリは実行できますが、wa --version は (devel) と表示します。バージョンが埋め込まれた再現可能なバイナリが必要な場合は、GoReleaser tarball または Homebrew tap を使用してください。
複数プロファイル
2 つの WhatsApp アカウントを、個人用と仕事用、またはクライアントごとに 1 つずつ、プロセスを完全に分離して並行して実行できます。各プロファイルには、それぞれ独自の session.db、allowlist.toml、audit.log、レートリミッター、unix ソケット、ウォームアップ時刻があります。
wa profile create work
wad --profile work &
wa --profile work pair
wa --profile work status
wa profile list
# PROFILE ACTIVE STATUS JID LAST_SEEN
# default * connected [email protected] 2026-04-11T17:00:00Z
# work connected [email protected] 2026-04-11T17:00:00Z
プロファイルの選択優先順位(上位ほど優先されます):
--profile <name>フラグWA_PROFILE環境変数(空の場合は未設定)$XDG_CONFIG_HOME/wa/active-profileポインター- シングルトン(プロファイルが 1 つだけ存在する場合)
- リテラルの
default
docs/manual.md §4 を参照してください。
安全性
wa は、言語モデルがあなたに代わって呼び出しても安全です。安全性パイプラインは上書きできないもので、デーモン内のすべての RPC 経路より下位にあります。
- 許可リスト。デフォルトではすべて拒否します。アクション単位(
read/send/group.add/group.create)で設定します。SIGHUP でホットリロードされます。wa allow add/removeで変更します。 - レート制限。通常の送信は、2 件/秒(バースト 2 件)および 30 件/分(バースト 30 件)に制限されます。通常送信の日次上限はありません。
--forceフラグはありません。今後も追加されません。 - ウォームアップランプ。新しいセッションは、経過日数が 7 日未満の場合は上限の 25%、7 日以上 14 日未満の場合は 50%、14 日以上の場合は 100%で動作します。タイムスタンプはセッションストアから取得するため、デーモンを再起動しても期間はリセットされません。
- 監査ログ。
$XDG_STATE_HOME/wa/<profile>/audit.logに追記専用の JSON Lines 形式で記録します。すべての送信、許可リストの判定、マイグレーションが記録されます。自動ローテーションは行われないため、ご自身でバックアップしてください。 - 受信メッセージのプロンプトインジェクション防御。受信メッセージの本文は、Claude Code に渡す前に
<channel source="wa" ...>…</channel>タグで囲まれます。これにより、モデルは「ユーザーがターミナルに入力した内容」と「不明な連絡先から送られた内容」を構造的に区別できます。 - クラッシュセーフなマイグレーション。007→008 のマイグレーションでは、先行書き込みマーカー、単一の
os.Renameによる切り替え、fsync バリアを使用します。各ステップの間でプロセスを強制終了させ、復旧時にデータが失われないことを検証するサブプロセスのSIGKILL注入テストで実証済みです。 - ソケットの強化。Unix ソケットと隣接するロックファイルを
O_NOFOLLOWで開き(CVE-2025-68146)、親ディレクトリのモードが0700で実効ユーザーが所有していることを検証します。接続を受け入れるたびにSO_PEERCREDを確認し、umask を制限してバインドします。
脅威モデルの全文は、SECURITY.md を参照してください。
アーキテクチャ
┌──────────────────────────┐
│ cmd/wa │ thin JSON-RPC client
│ (cobra, no business │ (stateless, re-invokable,
│ logic, no state) │ what scripts actually call)
└─────────────┬────────────┘
│ JSON-RPC 2.0 over
│ $XDG_RUNTIME_DIR/wa/<profile>.sock
▼
┌──────────────────────────────────────────────────────────────┐
│ cmd/wad │ composition root
│ │ (one process per profile)
│ ┌─────────────────────────┐ ┌────────────────────────┐ │
│ │ internal/app/dispatcher │◄──►│ Safety pipeline: │ │
│ │ (use cases, port-only) │ │ allowlist + rate lim │ │
│ │ │ │ + warmup + audit │ │
│ └───────────┬─────────────┘ └────────────────────────┘ │
│ │ │
│ ▼ 9 port interfaces │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ internal/adapters/secondary │ │
│ │ whatsmeow | sqlitestore | sqlitehistory | memory │ │
│ │ slogaudit | … │ │
│ └───────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
│
│ Signal Protocol ratchets +
│ WhatsApp Multi-Device websocket
▼
web.whatsapp.com
- ヘキサゴナルコア(
internal/domain/、internal/app/)は、internal/app/ports.goにある 9 つのポートインターフェースのみに依存します。アダプター以外でgo.mau.fi/whatsmeowをインポートしていないことを、CI でビルドを失敗させるgolangci-lint depguardルールで強制しています。 - ポート境界のフェイク:すべてのセカンダリアダプターには、テスト用のインメモリ版が付属します。コントラクトテストスイート(
internal/app/porttest/)は、どのアダプターに対しても実行できます。実際の WebSocket に到達するテストはありません。 - プロファイルごとに 1 つのデーモン。機能 008 により影響範囲を限定します。あるプロファイルのデーモンがクラッシュしても、別のプロファイルには影響しません。トレードオフとして、プロファイルごとに RSS を約 30 MB 使用します。
- CGO なし。今後も使用しません。SQLite の経路には
modernc.org/sqliteのみを使用します。Nix flake(env.CGO_ENABLED = "0")、GoReleaser、およびgo.modのツールチェーンフラグで強制しています。
設計と信頼性の原則について詳しくは、docs/manual.md を参照してください。
コマンドリファレンス(概要)
クライアント(wa):
| コマンド | 目的 |
|---|---|
wa pair | QR コードをスキャンするか、--phone を使って電話番号コードでペアリングします |
wa status | ブロックせずに接続状態を確認します |
wa send --to <jid> --body <text> | テキストメッセージを送信します(許可リストとレート制限が適用されます) |
wa sendMedia --to <jid> --path <file> | 画像/動画/音声/ドキュメントを送信します(--remote 経由の場合、クライアント側のローカルファイルが自動でアップロードされ、sha256 で送信されます) |
wa reply --to <jid> --quoted-id <id> --body <text> | メッセージに紐付く引用返信を送信します |
wa markRead --chat <jid> --messageId <id> | メッセージを既読にします |
wa react --chat <jid> --messageId <id> --emoji 👍 | リアクションを追加/削除します |
wa msg revoke|edit|forward|star|disappearing | 送信済みメッセージを管理します |
wa poll create --chat <jid> --question <text> --option <text> --option <text> | 投票を送信します(選択肢は 2~12 個、複数選択には --selectable を指定します) |
wa poll vote --chat <jid> --poll-id <id> --option <n> | 投票に回答します(複数選択の場合は --option を繰り返し指定できます) |
wa presence composing|recording start|stop --chat <jid> | 入力中/録音中のインジケーターを送信します |
wa groups | 参加中のグループを一覧表示します |
wa group create|leave|add|remove|promote|demote|edit|invite | グループを管理します(管理者操作) |
wa chat list / wa chat last-active | チャットを最終アクティブ日時の新しい順に一覧表示します(読み取り専用) |
wa chat archive|pin|mute|mark-unread --chat <jid> | チャット単位の状態を変更します |
wa history --chat <jid> [--before <id>] | 1 つのチャットの履歴を表示します(ページネーション対応) |
wa messages list --chat <jid> --media-type audio | チャット、メディアの種類、方向、期間でメッセージを絞り込みます |
wa search --query <fts5> | すべてのメッセージを全文検索(FTS5)します |
wa thread get --chat <jid> [--cursor <c>] | カーソルによるページネーションに対応したメッセージ範囲を取得します |
wa export --chat <jid> [--since <ts>] | チャットを古い順に NDJSON としてエクスポートします |
wa contacts list / wa contacts search --query <q> | ローカルの連絡先ディレクトリを一覧表示するか、トライグラム検索します |
wa contact block|unblock|blocklist|lid|pn | サーバー側のブロックリスト管理と PN↔LID の解決を行います |
wa privacy get [--key <k>] | アカウントの現在のプライバシー設定を読み取ります |
wa privacy set --key <k> --value <v> | プライバシー設定を 1 つ変更します(例:lastSeen → contacts) |
wa media list --chat <jid> [--sender <jid>] [--caption <text>] [--since/--until <rfc3339>] | キャッシュ状態(sha256、サイズ、再生時間)とともにメディアを一覧表示します。取得前に絞り込めます |
wa media resolve|download|fetch | コンテンツアドレス指定されたメディアを解決/遅延取得します |
wa media gc --dry-run | GC 候補を NDJSON としてプレビューし、回収可能なバイト数の概要を表示します |
wa --remote <url> push <file> | クライアント側のローカルファイルをリモートデーモンのメディアストアにアップロードします。sendMedia --sha256 で再利用するための sha256 を出力します |
wa schedule send|list|cancel|update | 予約送信を管理します(保留中 → 発火済み|キャンセル済み|失敗) |
wa draft list|get|approve|reject | 人によるレビュー用の下書きキュー |
wa labels list|create|delete|assign|unassign | WhatsApp Business のラベル(labels フラグが有効な場合) |
wa session logout-all | アカウントからすべてのデバイスのリンクを解除します |
wa allow add <jid> --actions send,read | 操作を許可します |
wa allow remove <jid> | すべての操作を取り消します |
wa allow list | 許可リストを出力します |
wa wait --events message --timeout 30s | イベントが届くまでブロックします |
wa subscribe --events <types> [--since <seq>] | フィルターされたイベントを NDJSON としてストリーミングします(カーソルから再開可能) |
wa stream [--chat <jid>] | 受信メッセージを NDJSON としてライブ表示します(wa subscribe --events message をラップします) |
wa sync force [--chat <jid>] [--count N] | DB の履歴が電話の履歴より遅れている場合に、即時の履歴取得を強制します |
wa sync status | オンデマンド同期エンジンの状態(進行中の取得、キューの深さ)を表示します |
wa embeddings status / wa embeddings purge --yes | ベクトルインデックスを確認/削除します(embeddings フラグが有効な場合) |
wa health | ブロックしない稼働確認プローブ(ペアリング済み/接続済み/最終イベント) |
wa doctor | ローカルインストールに対して 11 項目の自己診断チェックを実行します |
wa debug pprof [cpu|heap|goroutine|block|mutex] | wad からランタイムプロファイルを取得します |
wa audit verify [--path <log>] [--key <keyfile>] | 監査ログの HMAC チェーンを検証します |
wa config features | 解決済みの機能フラグ(embeddings、scheduled_sends、labels)を表示します |
wa profile list/use/create/rm/show | 複数プロファイルのライフサイクルを管理します |
wa migrate [--dry-run|--rollback] | 007→008 の明示的なマイグレーション |
wa panic | デバイスのリンクを解除し、ローカルセッションを消去します |
wa version | バージョン、コミット、ビルド日を表示します |
wa upgrade | インストール方法に応じたアップグレードコマンドを出力します |
wa completion bash|zsh|fish|powershell | シェル補完スクリプト |
デーモン(wad): |
| コマンド | 目的 |
|---|---|
wad [--profile <name>] [--log-level <lvl>] | デーモンをフォアグラウンドで実行します |
wad install-service --profile <name> | プロファイル用の systemd/launchd ユニットをインストールします |
wad uninstall-service --profile <name> | 指定したプロファイルのユニットのみを削除します |
wad migrate [--dry-run|--rollback] | wa migrate の内部ターゲットです |
フラグの全リファレンスについては、docs/manual.md §6を参照してください。
デーモンの調査(CLI の「嘘」を見抜く)
SQLite の実データを管理しているのはデーモンであり、CLI はその上にある薄いクライアントです。コマンドの出力がおかしく見える場合(あるはずのチャットが見当たらない、メッセージ数が古いように見えるなど)は、次の手順を上から順に確認してください。最初の手順で、ほとんどのケースはデータベースに触れずに解決できます。
1. 標準の検出コマンド(サポートされている方法)
これらのコマンドはデーモンから直接読み取り、SQL は不要です。以前のように docker cp messages.db と手書きの SELECT を組み合わせる回避策に代わるものです。
| 質問 | コマンド |
|---|---|
| どのチャットがありますか。新しいものから表示できますか。 | wa chat list(または wa chat last-active) |
| 特定のチャットの内容を絞り込んで表示できますか。 | wa messages list --chat <jid> --media-type audio --since 2026-01-01T00:00:00Z |
| 連絡先ディレクトリには誰がいますか。 | wa contacts list / wa contacts search --query <name> |
| ディスク上にどのメディアがキャッシュされていますか。 | wa media list --chat <jid>(SIZE / CACHED / SHA256 列) |
| 添付ファイルのうち、実際に必要なものはどれですか。 | wa media list --chat <jid> --sender <jid> --caption <text> — まず絞り込んでください。タイムスタンプの近さでまとめて取得すると、他の人のプライベートなファイルまでダウンロードされます |
| GC によって何が回収されますか。 | wa media gc --dry-run(回収候補を NDJSON で出力し、回収可能なバイト数を stderr に表示します) |
| スマートフォンにはあるのに、こちらにはないメッセージはありますか。 | wa sync force(全体)、または wa sync force --chat <jid>(そのチャットの取得が完了するまでブロックします)を実行してから、クエリを再実行します |
| 現在、同期が進行中ですか。 | wa sync status(syncing、進行中の強制取得、ワーカーキューの深さ) |
| 新しいメッセージが届くのをリアルタイムで監視できますか。 | wa stream(または wa stream --chat <jid>) |
これらのコマンドには --json を追加すると、jq に渡せる NDJSON が出力されます。Dokku にデプロイしている場合は、コンテナ内で同じコマンドを実行します — dokku enter <app> -- /usr/local/bin/wa chat list — または、SSH で転送したソケット経由で scripts/wa-remote chat list を実行します。
2. wa doctor
検出コマンド自体があり得ない結果に見える場合(例:ペアリング済みアカウントなのにチャットが 0 件)、wa doctor を実行してください。ソケットの権限、ペアリング状態、ディスク上のレイアウトバージョン、監査ログのサイズなど、11 項目をチェックし、WARN/FAIL ごとに hint: 行を表示します。schema_version の WARN は、ディスク上のレイアウトが domain.LayoutSchemaVersion と一致しなくなっていることを意味します。前方移行するには wa migrate を実行してください。
3. SQLite を直接確認する(最終手段)
本番イメージは gcr.io/distroless/static-debian12:nonroot です。シェル、sqlite3、ls/find はありません。そのため、dokku enter <app> -- sqlite3 … は実行できず、また、攻撃対象領域を広げることになるため(distroless ベースイメージはそれを縮小するためにあります)、意図的に wa-debug サイドカーイメージもありません。代わりに、独自の sqlite3 がインストールされている Dokku ホスト から、WAL セーフなスナップショットを照会してください。
# messages.db lives under XDG_DATA_HOME → on the host storage mount:
DB=/var/lib/dokku/data/storage/<app>/data/wa/<profile>/messages.db # <profile> defaults to "default"
# Snapshot via the online-backup API (WAL-safe; never `cp` a live WAL DB):
ssh dokku.example.com sudo -u dokku-65532 \
sqlite3 "$DB" ".backup '/tmp/messages-snapshot.db'"
# Inspect the snapshot, not the live file:
ssh dokku.example.com sqlite3 /tmp/messages-snapshot.db \
"SELECT chat_jid, push_name, COUNT(*) AS msgs, MAX(ts) AS last
FROM messages
WHERE chat_jid LIKE '%@s.whatsapp.net'
GROUP BY chat_jid ORDER BY last DESC LIMIT 20;"
ディスク上のレイアウト(コンテナ内のパス → /var/lib/dokku/data/storage/<app> 配下の Dokku ホスト上のパス):
| ファイル | コンテナ内のパス | 目的 |
|---|---|---|
messages.db | /data/data/wa/<profile>/messages.db | 履歴 + FTS5 |
session.db | /data/data/wa/<profile>/session.db | Signal セッション(稼働中のものは決してコピーしないでください) |
contacts.db | /data/data/wa/<profile>/contacts.db | 連絡先ミラー |
| メディア blob | /data/cache/wa/media/sha256/ | コンテンツアドレス可能なキャッシュ |
.schema-version | /data/config/wa/.schema-version | ディスク上のレイアウトバージョン |
WAL モードの DB を稼働中に cp でコピーすると、ファイルが破損する可能性があります。必ず .backup を使用してください。詳しくは、docs/deploy/dokku.mdのバックアップのセクションを参照してください。
開発
# Clone
git clone [email protected]:yolo-labz/wa.git
cd wa
# Devshell (Nix users)
nix develop
# Or use your own Go toolchain (1.26+, matching go.mod)
go version
# Build
go build ./cmd/wa ./cmd/wad
# Test (race detector on by default; ~20s wall clock)
go test -race ./...
# Lint
golangci-lint run
# Format
gofumpt -w .
# Nix build + smoke test
nix build .#default && ./result/bin/wa version
# Snapshot release (local only, no publish)
goreleaser release --snapshot --clean --skip=publish
ワークフロー:すべての変更は、main に対する PR を通じて取り込まれ、コミットの件名には Conventional Commits の規約に従います。詳しくは CONTRIBUTING.md をご覧ください。
CI/CD はセルフホストの GitHub Actions ランナープール(ラベルセット [self-hosted, dokku]。そのうち wa-sonar-runner には追加で sonar ラベルが付いています)で実行されます。必須チェックのジョブは、detect、lint(golangci-lint)、test(競合検出+シャッフル+カバレッジ)、sonar(SonarQube スキャン。cover.out アーティファクトを使用)、nix(nix flake check+nix build .#default+スモークテスト)、commitlint(PR タイトル)、Reproducibility(2 回のビルド結果のバイト単位での一致)、OSV-Scanner(脆弱性データベース+内部 govulncheck による Go コールグラフ到達可能性解析)、gitleaks(シークレットスキャン)、CodeQL(Go+actions)です。ホスト型ランナーは、最新イメージの保証が必要な OpenSSF Scorecard 用に確保されています。リリースワークフローは v* タグで実行され、GoReleaser の tarball、デュアル SBOM(CycloneDX 1.6+SPDX 2.3+バイナリごとの Go ネイティブ SBOM)、Cosign Sigstore バンドル、GitHub ネイティブのアテステーションを GitHub Releases に公開します。Apple の公証と Homebrew tap の公開は、シークレットがない場合はそれぞれ適切にスキップされます。
プロジェクトの状況
| バージョン | 主な変更点 |
|---|---|
| v2.0.2 | system.hello のハンドシェイク回帰(issue #41)をホットフィックスし、すべての CLI コマンドが v2 デーモンで動作するようにします。 |
| v2.0.1 | リリースパイプラインのホットフィックス:cyclonedx-gomod のパス、syft の CycloneDX 1.6 上限、gomod プロキシの無効化、rc7 後の Apple GA ゲート修正。不具合:CLI ハンドシェイク — v2.0.2 に置き換えられました。 |
| v2.0.0 | パリティの強化 — 7 つの新しいポート+20 の P0 メソッド+冪等性+チャット状態+ブロッカー+プライバシー+プロフィールエディター+グループ管理+投票管理。OTel ランタイムメトリクス、ファジング、doctor。JSON-RPC は protoVersion: 2 で凍結されています。 |
| v1.2.x | エージェント体験のティア 3 リリース — 埋め込みサイドカー、スケジュール済み下書き、FTS5 trigram による連絡先検索、オブザーバビリティ用リングバッファー。 |
| v1.0.x – v1.1.x | 最初の本番リリース — サプライチェーンアテステーション、OSV-Scanner V2、OpenSSF Scorecard、Cosign 署名、デュアル SBOM。 |
| v0.x | 1.0 以前 — マルチプロフィール、クラッシュセーフな移行、強化された systemd+launchd、ベンチマーク対象の SC はすべて 7.6×~870×の余裕をもって合格。 |
進行中のバックログ(プロフィールのピン留め、または外部アクションが可能になるまで保留):homebrew_casks: への移行(brews: を置き換えますが、darwin 専用 cask では Linuxbrew が formula のパスを失います。まず Linux の代替手段として nFPM 経由の apt/rpm が必要です)、domain.JID の LID/BSUID デュアルキー対応(Meta の 2026 年 6 月のユーザー名展開)、default.pgo の PGO プロファイル(取得パイプライン+コミット)、attest-build-provenance@v4 ラッパーからの actions/attest への移行。
対象ユーザー
対象はメンテナー 1 人です。マルチテナント、ホスト型 SaaS、グループへの一括メッセージ送信は明示的に対象外です。安全性に関する設計全体は、FileVault/LUKS を暗号化の境界とし、wa panic を復旧ボタンとする単一ユーザーの脅威モデルを前提としています。それが要件に合わない場合は、対象外の用途 に記載されている代替手段をお使いください。
ライセンス
Apache-2.0。上流の go.mau.fi/whatsmeow は MPL-2.0 です。これはファイル単位のコピーレフトであり、利用者には適用されません(Mozilla MPL FAQ Q9–Q11)。Apache を選んだのは、Anthropic の公式 Telegram チャンネルプラグインの先例に倣い、明示的な特許許諾を付与するためです。
謝辞
tulir/whatsmeow— 2026年に使う価値のある唯一のWhatsAppライブラリを提供してくれた、Tulir Asokanとmautrixプロジェクトに感謝します。AsamK/signal-cli— エンドツーエンド暗号化メッセンジャー向けのデーモンと薄型CLIを組み合わせたアーキテクチャが、単一のバイナリで実現可能であることを証明してくれました。aldinokemal/go-whatsapp-web-multidevice— 最も近い先行事例です。異なる形の課題(RESTゲートウェイとCLIデーモン)を解決しています。spf13/cobra+creachadair/jrpc2+modernc.org/sqlite— このプロジェクトをCGO不要で、テスト可能かつ保守しやすくしている、基盤となる3つのGoライブラリです。rogpeppe/go-internal— プロジェクトで大いに活用しているlockedfileとtestscriptを提供してくれました。
関連項目(yolo-labz エコシステム)
- yolo-labz/claude-mac-chrome — アプリをまたいだパイプラインのためのChrome自動化機能です(例:LinkedInのDM → トリアージ → このデーモン経由のWhatsAppフォローアップ)。
- yolo-labz/linkedin-chrome-copilot — チャネルをまたぐ自動化のために
waと連携するLinkedInワークフロープラグインです。 - yolo-labz/kokoro-speakd — 長時間実行される送信バッチの進行状況を音声で知らせるTTSデーモンです。
- アーキテクチャの詳細解説とWhatsAppデーモンの設計上の背景:blog.home301server.com.br。
- 作者のポートフォリオ:portfolio.home301server.com.br。
サービス
規制対象のワークロード向けのコンプライアンス水準のAIアーキテクチャです。非同期優先、米ドル建て、ラテンアメリカ拠点/英語対応です。blog.home301server.com.br/servicesをご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。