X投稿をSlack確認付きで半自動化した話(ラズパイ常駐 + Claude Code)
X(旧Twitter)の投稿を完全自動化するのではなく、Slackで確認してから投稿する半自動構成を作りました。
完全自動はリスクが高いので、AIが下書きを作って人間が最終判断する形にしています。
全体像
┌──────────────┐ ┌───────────────┐ ┌─────────────┐
│ RSSフィード │────▶│ 記事キャッシュ │────▶│ Claude Code │
│ (15ソース) │ │ (Markdown) │ │ (下書き3候補) │
└──────────────┘ └───────────────┘ └──────┬──────┘
│
▼
┌──────────────┐ ┌───────────────┐ ┌─────────────┐
│ X API │◀────│ 下書きJSON │◀────│ Slack │
│ (投稿実行) │ │ │ │ (確認・修正) │
└──────┬───────┘ └───────────────┘ └─────────────┘
│
▼
┌──────────────┐
│ 投稿済み履歴 │────▶ 次の下書きプロンプトに注入
│ + メトリクス │ (テーマ被り防止・改善)
└──────────────┘
常駐デーモンが以下のスケジュールで動きます。
| タイミング | 処理 |
|---|---|
| 6時間おき | RSSフィード再取得 |
| 8時 / 13時 / 19時 | 下書き3候補を生成 → Slack通知 |
| 5分おき | Slackのポーリング(返信・リアクション監視) |
前提・必要なもの
| 要素 | 内容 |
|---|---|
| X API | Developer Portal でアプリ作成、OAuth 1.0a キー4つ |
| Slack Bot | Bot Token、操作用チャンネル |
| Claude Code | CLI をインストール・ログイン済み(Max または Pro プラン) |
| 常駐環境 | ラズパイ・VPS・Mac など何でも可 |
X API のコスト
X API は現在 Pay-Per-Use(従量課金) です。月額サブスクではなくクレジットを事前購入して消費します。
| 操作 | 単価 |
|---|---|
| 投稿(POST /2/tweets) | $0.01 / 投稿 |
| メトリクス取得(GET /2/tweets) | $0.005 / 件 |
1日3投稿のペースで月の X API コストは $0.90 程度です。
Claude は後述するように Claude Code CLI をヘッドレス実行するため Anthropic API は使いません。Claude Max / Pro プランのセッションをそのまま利用します。月$3〜5程度です。
| 項目 | 月額 |
|---|---|
| X API | ~$1 |
| Claude(Max/Proプラン按分) | ~$3〜5 |
| 合計 | $4〜6 |
Claude Code をヘッドレス実行する
このシステムの肝は Anthropic API キーを使わないことです。
claude -p "プロンプト" でCLIをヘッドレス実行すると、ログイン済みのMax/Proプランのセッションでそのままテキストが返ってきます。
// Dart から Claude Code CLI をヘッドレス実行
final result = await Process.run(
Config.claudePath, // 'claude' or フルパス
['-p', prompt],
environment: {'HOME': Platform.environment['HOME'] ?? ''},
);
final output = result.stdout as String;
API キーの管理が不要で、Max プランのレート制限の範囲内で動きます。月$20のMaxプランをすでに使っている場合、追加コストゼロでAI生成が使えます。
トークン最適化
下書き生成のプロンプトには以下を含めます。
[投稿ルール] CLAUDE.md の内容
[最新記事] knowledge/ の直近記事(カテゴリ別)
[投稿履歴] posted/ の直近10件(テーマ被り防止)
[パフォーマンス] analytics/ の高ER投稿パターン
全部渡すとトークンが膨らむので、記事は カテゴリ別にキャッシュしておき、必要なカテゴリだけ渡す設計にしています。
knowledge/
├── flutter/ ← Flutter関連のフィード記事
├── ai-dev/ ← AI開発関連
└── my-apps/ ← 自分のアプリ情報
投稿ルール(トーン・テーマ・NG事項)は CLAUDE.md に書いておき、プロジェクトルートに置くだけで Claude Code が自動で読み込みます。プロンプトに毎回書く必要がなく、トークンの節約と管理のしやすさ両方に効きます。
# CLAUDE.md(抜粋)
## 投稿しないテーマ(厳守)
- × プログラミング・開発ツールの話
- × ニュースの要約だけで終わる投稿
## トーン
- 「こうするといいよ」くらいのカジュアルさ
- 読んだ直後に試せる内容にする
Slack を操作パネルにする
専用のUIを作る代わりに Slack をコントロールパネルにしています。スマホからでも操作できます。
ボットが3候補をSlackに投稿し、スレッドで返信して操作します。
Bot: 下書き候補です。
[1] ChatGPTに「表にして」と一言添えるだけで...
[2] Googleフォトで「犬」と検索すると...
[3] Gmailの返信、AIが下書き作ってくれるの...
| 入力 | 動作 |
|---|---|
1 / 2 / 3 | その候補をXに投稿 |
1 もっとカジュアルに | Claude Code で修正 → 修正版を表示 |
ok | 修正版で投稿 |
そのまま書いたテキスト | Bot が添削提案 → ok で投稿 |
report | X API からメトリクス取得してレポート表示 |
Slack の Bot Token を取得して、チャンネルの投稿をポーリング(5分おき)するだけで実現しています。WebSocketではなくポーリングにすることで、常時接続が不要になり安定します。
ラズパイで常駐させる
Dart でコンパイルした実行ファイルを systemd で常駐させます。
デプロイ手順
# 1. Mac からソースをラズパイに転送
tar czf - -C ./app --exclude='.dart_tool' --exclude='bin/x-posting' \
--exclude='logs' --exclude='.env' . \
| ssh [email protected] "tar xzf - -C ~/bots/x-auto-posting"
# 2. ラズパイ上でコンパイル & 再起動
ssh [email protected] '
export PATH=/opt/dart-sdk/bin:$PATH
cd ~/bots/x-auto-posting
dart pub get
dart compile exe bin/main.dart -o bin/x-posting
sudo systemctl restart x-auto-posting
'
systemd サービス設定
# /etc/systemd/system/x-auto-posting.service
[Unit]
Description=X Auto Posting Bot
After=network.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/bots/x-auto-posting
ExecStart=/home/pi/bots/x-auto-posting/bin/x-posting daemon
Restart=always
RestartSec=10
EnvironmentFile=/home/pi/bots/x-auto-posting/.env
[Install]
WantedBy=multi-user.target
sudo systemctl enable x-auto-posting # 自動起動
sudo systemctl start x-auto-posting
tail -f ~/bots/x-auto-posting/logs/daemon.log # ログ確認
Dart を AOT コンパイルした実行ファイルは ARM64(ラズパイ4)でもそのまま動きます。ただし Mac 側でクロスコンパイルはできないので、コンパイルはラズパイ上で行います。
Claude Code の再ログイン問題
ラズパイ上の Claude Code は Max プランのブラウザ認証が必要です。セッションが切れた場合は SSH でログインして再認証します。
ssh -t [email protected]
claude # 対話モードで起動
# /login でブラウザ認証
まとめ
| ポイント | 内容 |
|---|---|
| 完全自動にしない | Slackで確認してから投稿。品質を担保 |
| X API コスト | 1日3投稿で月$1未満 |
| Anthropic API 不要 | claude -p でMax/Proプランを再利用 |
| トークン節約 | カテゴリ別キャッシュ + CLAUDE.md でルールを外出し |
| 操作UI | Slackだけ。専用UIなし |
| 常駐 | Dart AOTコンパイル + systemd |
「完全自動にしない」設計にしたことで、AIが変な投稿を出力しても人間が止められます。Slackで確認するひと手間が、アカウントの信頼性を守る保険になっています。