「外出先でPCが開けない」問題
自分は会社で働きながら、個人のAIエージェント(Claude Code)を使って、いろいろなことを自動化してきた。
具体的にはこういうもの:
- 業界ニュースの自動配信 — 毎朝、AI・マーケティング関連のニュースを自動収集して要約を生成し、チームのチャットに投稿する
- 業務レポートの自動生成 — クライアントのKPIデータを取得して、前日比・前週比の分析レポートを自動作成する
- 案件の自動ソーシング — 複数のプラットフォームから自分に合う案件を自動検索して、提案ドラフトまで生成する
- 競合調査の自動化 — Webから競合の情報を収集して、差別化ポイントと自社への示唆をまとめる
- タスク管理・進捗追跡 — GitHubのIssue管理、コード修正、デプロイまで一気通貫で実行
全部で50以上のスキル(自動化された機能)がある。ニュース配信、レポート生成、リサーチ、コード修正、データ分析——あらゆる「PCでやっていた作業」を自動化してきた。これらは全て、VPS(仮想サーバー)上で動くClaude Code(AnthropicのAIエージェントCLI)が実行する。
問題は、それが全部PCでしか操作できないこと。
Claude Codeはターミナル(コマンドライン)で動く。PCを開いて、ターミナルを立ち上げて、コマンドを打つ。あるいはSSHでVPSに接続して操作する。
外出先ではPCを開けない。でも「あのデータ、今すぐ確認したい」「朝のルーティン実行し忘れた」「移動中にあの提案書のドラフトを作りたい」みたいな瞬間は毎日のようにある。
つまり欲しかったのは、スマホからAIエージェントに指示を出して、結果を受け取る仕組みだった。
そもそもClaude Codeとは何か
Claude Codeは、Anthropic社が提供するAIエージェントのCLI(コマンドラインインターフェース)。ChatGPTのようなチャットAIとは根本的に違う。
普通のチャットAI:
- テキストで質問して、テキストで答えが返ってくる
- ファイルを読んだり、コマンドを実行したりはできない
Claude Code:
- テキストで指示を出すと、実際にコンピュータを操作する
- ファイルの読み書き、コードの編集、Bashコマンドの実行、Git操作、外部APIの呼び出し、Webスクレイピング…全部できる
- 要するに「AIがPCの前に座って作業している」状態
だから単なるチャットBotをスマホに入れても意味がない。Claude Codeのツール実行能力ごとスマホから使えるようにしないと、価値がない。
最初のアプローチ:SSH(Termius)
最初は力技だった。
スマホにTermius(SSHクライアントアプリ)を入れて、VPS(仮想サーバー)にSSH接続する。VPSにはClaude Codeがインストールしてあるから、ターミナルでそのまま操作できる。
[スマホ] → Termius(SSH) → VPS → Claude Code
技術的にはこれで「スマホからClaude Codeを使える」状態になった。実際に試してみた。
結論:実用的じゃなかった。
- スマホの小さいキーボードでターミナルコマンドを打つのがとにかく辛い。
cd /root/ops && claudeみたいなコマンドを、フリック入力で打つ苦行 - タイプミスが多い。ターミナルはスマホUIに最適化されていない
- Claude Codeの出力は長い。マークダウン形式のレポートがターミナルの小さい画面に流れてきても読めない
- SSHが不安定。電車で移動中にWi-Fiが切れると接続が落ちる。再接続するとセッションが消えていて最初からやり直し
「動く」と「使える」の間には大きな溝がある。技術的に可能なことと、毎日使いたいと思えることは全然違う。
第2のアプローチ:Discord Botを自作する
1週間ほどSSHで我慢した後、もっといい方法を考えた。
スマホで毎日使っていて、UIが快適で、プッシュ通知があるアプリ。Discordだ。
自分は既にDiscordサーバーを持っていて、自動化ツールの通知先にしていた。ここにもう一つチャンネルを作って、チャットで指示を出す → 結果がチャットで返ってくる仕組みを作ればいい。
やることは明確だった:
- VPS上でDiscord Botを常駐させる
#claude-cmdという専用チャンネルでメッセージを監視する- メッセージが来たら、VPS上で
claude -p "メッセージ内容"を実行する - 実行結果をDiscordに返信する
claude -p というのは、Claude Codeの「非対話モード」。通常のClaude Codeはターミナルで対話的に使うが、-pオプションを付けると、一発のコマンドとして実行して結果を返してくれる。パイプやスクリプトから呼び出すための機能だ。
[スマホ] → Discord → Bot(VPS) → claude -p "指示" → 結果 → Discord返信
Claudecordとの違い
「Claudecord」という既存のDiscord Botがある。Claude APIをDiscord上で使えるようにしたもので、要はDiscordの画面でClaude(チャットAI)と会話できる。
でもこれでは足りなかった。
ClaudecordはClaude API(チャット機能)だけを使う。「この文章を要約して」みたいなテキストのやりとりはできるが、ファイルを操作したり、コマンドを実行したり、外部サービスと連携したりはできない。
自分が欲しいのは、Claude Codeのフル機能をDiscordから使えること。ファイル読み書き、コマンド実行、Git操作、50以上の自作スキル——全部使えないと意味がない。Claudecordの上位互換を作る。
1日目:Botは起動した。でも動かない。
discord.js(Node.jsのDiscordライブラリ)でBotを書いた。170行程度のシンプルなコード。
VPSにデプロイして、systemd(Linuxのサービス管理)で常駐化。起動ログを確認。
[discord-cmd] Bot ready as opsclaude#0242
Botは起動した。Discordを開いて #claude-cmd チャンネルに「テスト」と送る。
反応なし。
ログを確認する。メッセージの受信すら記録されていない。Botは起動しているのにメッセージを検知していない。
デバッグログの追加
コードにデバッグログを追加して、メッセージ受信のフィルタリングの各段階でログを出すようにした。
VPSに再デプロイ。もう一度「テスト」を送る。
今度はログが出た:
msg received: author=1478001975931961374 channel=claude-cmd
accepted: "<@&1480936114746429443> test"
メッセージは受信していた。 しかも正しくフィルタを通過して、claude -p の実行まで進んでいた。
Discordには processing... という表示も出ている。つまりBotはメッセージを受け取り、「処理中」の表示を返し、Claude Codeの実行を開始している。
でも、そこから先が返ってこない。5分後にタイムアウト。
直接実行すると動く
VPSにSSHで入って、直接 claude -p "say hi" を実行してみる。
$ time claude -p "say hi" --output-format json
{"type":"result","result":"Hi!","session_id":"...","duration_ms":2180}
real 0m30.190s
普通に動く。 API自体は2秒、プロセス起動を含めて30秒で結果が返ってくる。
つまり、Claude Code自体は正常に動いている。Node.jsのBotから呼び出したときだけ、結果が返ってこない。
この日はここで行き詰まった。
2日目:5つの方式を検討し、全部却下する
execFile の罠
最初のコードでは execFile というNode.jsの関数を使っていた。外部コマンドを実行してコールバックで結果を受け取る、最もシンプルな方法だ。
execFile("claude", ["-p", prompt], (error, stdout) => {
// ここが永遠に呼ばれない
});
このコールバックが永遠に呼ばれない。claude プロセスは起動していて、ログにはPIDも見えている。しかしプロセスが終了せず、コールバックも呼ばれない。
速度問題にも気づく
並行して、「仮にバグが直っても30秒はかかる」という問題にも気づいていた。claude -p は呼び出すたびにプロセスを新規起動する。プロセス起動だけで28秒。スマホからサッと使いたいのに、毎回30秒待つのは厳しい。
ここで一度立ち止まって、取りうる全ての方式を整理した。
方式A: claude -p を毎回起動(現状) — 遅い(30秒)が全機能使える。バグ修正のみ。
方式B: Claude APIを直接叩く — 速い(2-3秒)がチャットのみ。ファイル操作もコマンド実行もできない。
方式C: 常駐プロセス方式(stream-json) — Claude CLIにはstream-json入出力モードがある。プロセスを1つ立ち上げっぱなしにすれば起動コストはゼロ。最有力候補。
方式D: Agent SDKで自作 — ツールを全部自前で実装。工数が膨大。
方式E: ハイブリッド(B + A) — 会話はAPI直接、スキルは claude -p。2系統のメンテが必要。
方式Cに賭ける → 撃沈
最も有望に見えた方式C(常駐プロセス)を調査した。VPSで実際にstream-jsonモードを試す。
出力なし。
stdinを開いたままにしてみる。環境変数を変えてみる。フォーマットを変えてみる。全部ダメ。
Claude Codeの内部仕様を調査した結果:stream-jsonは常駐デーモン設計ではない。 Claude CLIは1回の呼び出しで完結する設計。stdinから継続的にメッセージを受け取る機能は存在しなかった。
方式Cは不可能。B(API直接)は機能不足。D(SDK自作)は工数過大。E(ハイブリッド)はメンテが複雑。
残ったのは方式A。バグを直して、30秒の遅延を受け入れる。
3日目:発想の転換と解決
「30秒」は本当に致命的か?
ここで発想を変えた。自分がスマホからClaude Codeを使いたいシーンを具体的にリストアップした:
- 「実行して」(朝のルーティン全実行)→ そもそも完了まで数分かかる
- 「この競合を調査して」→ 調査自体が3-5分かかる
- 「Issue確認して」→ 30秒でも十分実用的
ほとんどのユースケースで、30秒は問題にならなかった。
しかもスマホ経由なら「投げて放置 → 通知で結果確認」が自然なフロー。PCの前で30秒じっと待つのとは体験が違う。
認識を改めた:速度ではなく「手軽さ」が本質だった。
根本原因の修正
claude -p は stdinの終了を待ってからプロセスを完了する仕様 だった。一方、Node.jsの execFile はデフォルトでstdinをパイプとして開いたままにする。
つまり:
- Botが
execFile("claude", ...)を実行 - Claude Codeが起動し、処理を完了する
- しかしstdinがまだ開いているので、「まだ入力があるかもしれない」と待ち続ける
- プロセスが終了しないので、コールバックも永遠に呼ばれない
修正は2つ:
execFile→spawnに変更proc.stdin.end()を追加(「もう入力はない」と伝える)
3日間悩んだ問題の原因が、stdinを閉じる1行だった。
テスト成功
修正をVPSにデプロイして、Discordに「テスト」と送る。8秒後——結果が返ってきた。
「Issue確認して」を送る。16秒後、15件のIssue一覧が返ってきた。テーブルがDiscordのマークダウンで崩れたので、コードブロックに自動変換する処理も追加した。
翌日、スレッド内の返信が動かないバグも見つけて修正(Discordのスレッドは channel.name がスレッド名になるため、親チャンネル名のチェックが必要だった)。
自作Botが完成した。
完成した翌日に知ったこと
自作Botが動いて喜んでいた翌日、あることを知った。
Claude Code v2.1.80で、「Claude Code Channels」という公式機能がリリースされていた。
Claude Code Channelsは、DiscordやTelegramなどのメッセージングアプリからClaude Codeのセッションに直接メッセージを送れる仕組みだ。VPS上でClaude Codeを常駐させておけば、スマホのDiscordからDMを送るだけで、ファイル操作もBash実行もスキル呼び出しも全部できる。まさに自分が3日間かけて自作しようとしていたもの——それが公式機能として、コマンド3つで実現できる。
# プラグインのインストール
claude plugins install discord@claude-plugins-official
# Botトークンの設定
# ~/.claude/channels/discord/.env にトークンを書く
# 起動
claude --channels plugin:discord@claude-plugins-official
しかもClaude Code Channelsには、自作Botにはなかった利点がある:
自作Bot → Claude Code Channels で何が変わったか:
- 起動方式: 毎回プロセス起動 → 常駐セッション(起動コストゼロ)
- 速度: 8〜30秒 → 数秒
- 通信方式: チャンネル+スレッド → DM(よりシンプル)
- 実装: 200行のbot.js → コマンド3つ
- メンテ: 自分で保守 → Anthropicが保守
- コンテキスト:
--resumeで手動復元 → 自然に維持される
特に「常駐セッション」は大きい。自分が方式Cとして調査して「不可能」と結論したもの—— Anthropicが「Claude Code Channels」として公式に実装していた。 当然、内部の仕組みを知っている開発元だからこそできること。
Claude Code Channelsに移行
迷わず移行を決めた。
自作Botを停止し、Claude Code Channelsをセットアップした。手順はシンプルだった:
- プラグインインストール —
claude plugins install discord@claude-plugins-official - Botトークン設定 —
~/.claude/channels/discord/.envにトークンを書く - 起動 —
claude --channels plugin:discord@claude-plugins-official - ペアリング — DiscordでBotにDMを送ると、認証コードが返ってくる。VPS側でそれを承認すると、自分のDiscordアカウントが許可リストに登録される
- 権限設定 —
settings.jsonにBashやDiscord返信の権限を事前登録して、承認プロンプトなしで動くように設定
VPS上ではtmuxで常駐セッションとして走らせている。一度起動すれば、スマホからDMを送るたびにそのセッションが反応して結果を返す。
DiscordでBotにDM:「イシュー確認して」
数秒後、Issue一覧が返ってきた。承認なし、起動コストなし。
何ができるようになったか
スマホのDiscordでopsclaudeにDMを送る。それだけで:
VPS上のClaude Codeがフル機能で起動する。
- ファイルの読み書き、コードの修正、git commit & pushができる
gh issue listのようなGitHub CLI操作ができる- 50以上の自作スキル(競合調査、レポート生成、案件ソーシング、データ分析等)が全部使える
- コンテキストが自然に維持される(前の文脈を覚えている)
- 自分以外のメッセージは完全に無視するセキュリティ制限付き
具体的な使用例:
朝の通勤電車で: 「実行して」→ ニュース配信、未読メッセージのダイジェスト、カレンダー取得が一括実行される
外出先で: 「今週のKPI確認して」→ スプレッドシートからデータを読み取り、前日比・前週比の分析結果が返ってくる
打ち合わせ前に: 「競合の最新動向を調べて」→ Webから情報を収集し、差別化ポイントと示唆のサマリーが返ってくる
帰宅後のソファで: 「Issue確認して」→ 今のタスク一覧が返ってくる。「この提案書のドラフト作って」→ その場で生成される
PCでの作業の体感8割がスマホで完結する。
3日間で学んだこと
1. 「動く」と「使える」は別物
SSHは「動く」。でもスマホで毎日使いたいかと聞かれたらNo。UIが用途に合っていなかった。
技術的に実現可能なことと、ユーザー(今回は自分)が実際に使い続けるものの間には、大きなギャップがある。「動く」で止まらず、「使える」まで持っていくことが大事。
2. 原因の小ささと被害の大きさは比例しない
3日間悩んだバグの原因が proc.stdin.end() の1行だった。
execFile がデフォルトでstdinを開いたままにすること、claude -p がstdinの終了を待つこと。この2つの仕様の組み合わせが、プロセスの永久ハングを引き起こしていた。
どちらの仕様も単体では問題ない。組み合わせたときに初めてバグになる。こういう「仕様の隙間」に落ちるバグは、ドキュメントにも書いていないし、ググっても出てこない。
3. 全部の要件を満たそうとすると何もできない
「速度もフル機能もUIも全部完璧に」と考えると、永遠に完成しない。
5つの方式を検討して全部不十分だった。30秒の起動コストを受け入れた瞬間に、最もシンプルな方式A(バグを直すだけ)が正解だとわかった。
完璧を目指すより、「80点でいいから今日使えるもの」を作る方が価値がある。
4. ユースケースの解像度を上げると、必要な性能が変わる
最初の要件は「スマホからClaude Codeを使いたい」だった。これだと「速くないとダメ」「全機能使えないとダメ」と、全てが要件に見える。
「外出先でPCを開けないから、スマホで診断やルーティンを発火して、結果をプッシュ通知で受け取りたい」まで解像度を上げると、30秒の遅延は問題にならないことがわかった。
要件が曖昧なまま技術検討を始めると、必要以上に難しい問題を解こうとしてしまう。
5. 完成した後にもバグは出る
完成して喜んだ翌日、スレッド内の返信が動かないことに気づいた。Discordのスレッドでは channel.name がスレッド名になり、チャンネル名のチェックに引っかかって無視されていた。
リリースしてユーザー(自分)が使って初めて見つかるバグは必ずある。 完璧にしてからリリースするのではなく、早くリリースして早く直す方が速い。
6. 自分で作ったからこそ、公式の価値がわかる
3日間かけて自作したBotが、公式プラグインの3コマンドで実現できた。
「最初から公式を待てばよかった」と思うかもしれない。でも自分はそう思わない。
自作Botを作る過程で、以下を深く理解した:
claude -pの起動コストとその回避策- stdinの管理とプロセスライフサイクル
- Discordのスレッド・チャンネル・DM の仕様
- 常駐セッション方式が「速い理由」
公式プラグインがなぜ「常駐セッション」を採用しているのか、なぜ「DM」を使うのか、なぜ「MCP統合」なのか——全部、自分で失敗したから理解できる。
遠回りは、無駄じゃなかった。
7. 調査して却下したプロセスにも価値がある
方式C(常駐プロセス)の調査に半日かけた。結果は「不可能」だった。方式B、方式D、方式Eも検討して全部却下した。
一見、無駄に見える。でもこの調査があったから、「方式Aが最善である」と自信を持って判断できた。選択肢を全て検討した上での判断と、最初から1つしか知らない状態での判断は、たとえ結論が同じでも質が違う。
※ この記事のDiscord Bot(200行)もNote記事自体も、全てAI(Claude Code)が生成した。自分が書いたのは日本語の指示だけ。
筆者: コンサル・事業会社を経て中小企業の経営に参画。コードは1行も書けないが、Claude Codeで66個の業務スキルを構築し、経営業務の8割を自動化。日々の実験はXで発信中。