はじめに
Claude Code や Codex のようなコーディングエージェントは、ターミナルの中ではとても有能です。では、その「手」をスマホの画面まで伸ばしたらどうなるか。そう考えて、Android アプリ Buddy を作りました。
- リポジトリ: https://github.com/ghorbelhamdi/buddy-android
- ライセンス: Apache 2.0
- 対応: Android 11 以上、64 ビット。root も PC も不要です
画面に浮かぶチャットの吹き出しに、やってほしいことを文字か声で伝えます。するとエージェントが画面を読み、タップや入力をしてアプリを操作します。
この記事では、どういう仕組みで動いているかを中心に紹介します。
できること
- インストール済みのアプリを使う(設定の変更、フォームの入力、複数のショッピングアプリでの価格比較など)
- 通知をきっかけに動く(「この相手からメッセージが来たら、営業時間を返信する」のようなルール)
- 決まった時刻にタスクを実行する
- 画面を使わないバックグラウンドのブラウザで Web を調べる
- 内蔵の Linux 環境でコマンドを実行し、小さなアプリをビルドする
- 自分の MCP サーバーをつないで、ツールを追加する
対応エージェントは Claude Code、Codex、OpenCode、Antigravity、Grok の 5 つです。自分のサブスクリプション、API キー、ローカルモデルのいずれでも使えます。OpenCode の無料モデルならアカウントも要りません。
仕組み
大きく 3 つの部品でできています。
Buddy アプリ(画面・UI・鍵の管理)
│ 127.0.0.1 の MCP サーバー(トークン付き)
▼
アプリ内の Linux(proot 上の Alpine): claude / codex / opencode …
1. 画面の読み取りと操作: AccessibilityService
Android のユーザー補助サービスを使って、画面上の要素(テキスト、ボタン、入力欄)を一覧として取得し、タップ・入力・スクロールを行います。スクリーンショットを毎回モデルに送るのではなく、基本は要素の一覧をテキストで渡します。地図やゲームのように要素が取れない画面だけ、スクリーンショットを使います。
2. エージェントの実行環境: proot 上の Alpine Linux
エージェントの CLI はスマホの中で動きます。Buddy は小さな Alpine Linux をアプリ専用の領域に展開し、proot で実行します。Claude Code などは公式のインストーラーでそこに入れます。root 化は不要です。
3. 両者をつなぐ: localhost の MCP サーバー
アプリは 127.0.0.1 で MCP サーバーを立て、read_screen、tap、type_text、open_app、confirm などのツールを提供します。エージェントから見ると、スマホは「MCP のツールがたくさん付いた環境」です。エージェントごとに出力形式が違うので、シェルスクリプトのヘルパーが 5 種類の出力を 1 つのイベント形式にそろえています。
依存ライブラリはほぼなく、Java と Bash で書いています。
安全のための設計
エージェントにスマホを触らせる以上、ここが一番大事だと考えています。
- 承認カード: 送信、投稿、購入、削除にあたる操作の前に、Buddy 自身がカードを出して確認します。これはプロンプトでのお願いではなく、タップの直前にアプリ側で止める仕組みです。
- アプリごとのモード: メッセージ、SNS、メール、通話、買い物、お金に関わるアプリは、最初から厳しいモード(Hard)です。
- 自分自身は触らせない: エージェントは Buddy の吹き出しや承認カードをタップできません。つまり、自分で自分を承認することはできません。
- API キーは Linux 側に渡さない: キーは Android の Keystore で暗号化して保存し、アプリ内のリレーがリクエストに付け足します。エージェントからは見えません。
- 画面の文字は「内容」であって「指示」ではない: 通知や Web ページの文章に指示が書かれていても従わないよう、ツールの結果としてだけ渡します。
バックグラウンドモード
2.3 で追加した機能です。エージェントが自分専用の見えない画面でアプリを操作し、その間もユーザーは普段どおりスマホを使えます。画面をロックしていても動き続け、承認が必要になるとロック画面の通知に「承認」「拒否」が出ます。
実現方法は少し変わっています。
- Buddy が内蔵 Linux の中の adb を、スマホ自身の「ワイヤレス デバッグ」とペアリングします(PC は使いません。設定アプリの操作も Buddy が自分で行います)。
- その adb 経由で、
app_processを使って小さなヘルパーを shell ユーザーとして起動します。 - ヘルパーが仮想ディスプレイを作り、アプリの起動、タッチの注入、画面の取得を担当します。
他のアプリが動く仮想ディスプレイを作れるのは shell ユーザーだけなので、この経路になりました。
機種ごとの差にはかなり苦労しました。たとえば Samsung では、フレームワークがヘルパーに設定オブジェクトを要求してきてクラッシュしました。Android 17 の Pixel では、開発者向けオプションが有効かどうかをアプリから読めなくなっており、ペア設定のダイアログからポート番号も消えていました。どれも利用者からの Issue のおかげで直せました。
ローカルモデル(Ollama など)
自分の PC で Ollama、LM Studio、llama.cpp のサーバーを動かせば、AI 企業に何も送らずに使えます。設定 → API キー → Ollama を選び、PC のアドレスを入れるだけです。
正直なところ、小さなモデルには限界があります。RTX 2060 Super(8 GB)で試したところ、Qwen3 の 4B や 8B は「バッテリー残量を教えて」のような 1 ステップの依頼はこなせますが、画面を何度も操作するタスクでは失敗が目立ちました。実用には、ツール呼び出しが得意な大きめのモデルが必要です。
できないこと
- 銀行アプリやパスワード管理アプリなど、画面の取得を禁止しているアプリの中身は見えません。
- ゲームのように要素のない画面は、位置を指定したタップしかできず、失敗しやすいです。
- パスワード、ワンタイムコード、支払い情報の入力はユーザーに任せます。
インストール
APK は GitHub の Releases にあります。
インストール後、ユーザー補助サービスを有効にし、使いたいエージェントをアプリ内でインストールしてサインインすれば使えます。
おわりに
「エージェントに PC を操作させる」話はよく見かけますが、毎日持ち歩くスマホでも同じことができると、使い道がかなり広がると感じています。コードはすべて公開しているので、仕組みに興味のある方はぜひ読んでみてください。不具合や要望は Issue で受け付けています。