自分の CLI を持ち込む: スマホからカスタム ACP セッションを監視する方法
ACP 互換の自作 CLI をコンピューターで動かしつつ、スマホから確認、承認、フォローアップができるワークフローを作る実践ガイドです。
- CLI
- 0.2.17
- プレビュー ref
- a2c45c8
「標準の」プロバイダー以外を使い始めた途端、よくある問題にぶつかります。
お気に入りの CLI はコンピューターで動かせます。
でも、スマホでのワークフローがなくなってしまいます。
このガイドは、そのスマホでのワークフローを取り戻すためのものです。
- ACP 互換の自作 CLI をローカルで動かす
- それでもスマホからセッションを監視する
- それでも承認やフォローアップに対応する
要点
- ローカルで動かしたい ACP 互換の CLI を選びます。
- それをカスタム ACP(Custom ACP)バックエンドとして定義します(コマンド、検出、認証確認)。
- ホストのコンピューターで挙動を確定させます:
- バイナリのパスを確認する
- 作業ディレクトリのルールを確認する
- 検出コマンドと認証コマンドを確認する
- 短いスマホループを使います: 確認 → 承認 → フォローアップを1つ → 離れる。
課題
カスタム連携は、実務的な理由で失敗します。
- バイナリのパスが違う
- 作業ディレクトリが違う
- 正しいコンピューターに認証情報がない
そのため、最初の目標は連携の挙動を確定させることです。
よくある方法とトレードオフ
- SSH/tmux: 使えますが、「スマホで本格的なターミナル作業をする」ことになります。
- リモートデスクトップ: 重くて扱いにくいです。
- 待つ: 安全ですが遅いです。
うまくいくのは、スマホ専用の操作画面です。
- Happier: カスタム ACP の CLI はコンピューターで動いたまま、確認、承認、フォローアップのためのスマホ UI が手に入ります。 トレードオフ: エージェントを実行するコンピューターがオンラインである必要があります。
Happier を初めて使う場合(概要と入手方法)
Happier を初めて見る方へ。Happier はコーディングセッション向けのオープンソースのコンパニオンアプリ(モバイル/Web/デスクトップ)です。
セットアップ:
- GitHub: https://github.com/happier-dev/happier
- インストール/ダウンロード: https://github.com/happier-dev/happier#how-it-works
- Discord: https://discord.gg/W6Pb8KuHfg
90秒でわかる ACP(このガイドの残りを理解するために)
ACP(Agent Client Protocol)は、次の2つの間のプロトコルです。
- クライアント(アプリ、IDE、ダッシュボード)
- エージェントプロセス(あなたの CLI)
デフォルトのトランスポートは stdio で、改行区切りの JSON-RPC メッセージです。
実務上の主な影響は次のとおりです。
- エージェントの stdout がプロトコルそのもの
- ログは stderr に出す必要がある
stdout にログが混ざると、クライアントはストリームを解析できず、すべてが「壊れている」ように見えます。
ACP と MCP(両方が出てくる理由)
- ACP は、クライアントがエージェントのセッションと話す方法です。
- MCP は、エージェントがツールサーバー(GitHub、ブラウザー自動化など)と話す方法です。
ACP セッションは mcpServers のリスト付きで開始できるので、次の組み合わせが可能です。
- 自作のエージェント CLI 1つ
- それに一貫したツール群
カスタム ACP の成否を分けるルール(stdio の約束事)
連携を壊す原因としてよくあるもの:
- stdout には ACP プロトコルのメッセージだけを出す
- ログは stderr に出す
- メッセージは改行区切りなので、1つの JSON メッセージの中に改行を入れない
- JSON を整形出力しない(
indent=2は動作を壊します)
「自分のエージェントは互換性があるか」を手早く確かめるなら:
- ACP モードで起動し、バナーを出さずに
initializeに応答できるか確認する
ステップ 1: カスタム ACP バックエンドを定義する
細かい設定作業なので、多くの人がここでつまずきます。
定義が必要なもの:
- 名前/ID(どう識別するか)
- コマンド(どう起動するか)
- 検出コマンド(「インストールされているか」を安全に確かめる)
- 認証確認(任意。安全な場合だけ)
- 作業ディレクトリの前提(リポジトリのルートを前提にしているか)
時間を節約するルール: まず検出だけで始め、認証確認は後から追加します。
機能のネゴシエーション(メソッドがあると決めつけない)
ACP は initialize から始まります。
エージェントは自分の機能を返します。
クライアントは、エージェントが対応を宣言していないメソッドを呼ぶべきではありません。
「再開/読み込み」に対応していない場合、次のような症状が出ます。
- 再開するつもりが新しいセッションが始まる
- 履歴がない
そのため、カスタム ACP では、まず最小限のエージェント(新規セッションとプロンプト)を出し、ライフサイクル系のメソッドは後から追加するのが普通です。
ステップ 2: まず1台のコンピューターで挙動を確定させる
複数のコンピューターでのワークフローを試す前に、1台で動かします。
ここで「自分のターミナルでは動く」と「クライアントから起動すると動く」の違いが出ます。
チェックリスト:
- 想定した作業ディレクトリからコマンドを実行できるか
- シェルの初期化ファイル(
.zshrc、nvm、asdf)に依存していないか - 環境変数やシークレットが必要か
- stdout にバナーや進捗バーを出していないか
CLI に認証情報が必要な場合、バックエンド定義に貼り付けないでください。環境変数か、保存済みシークレットの仕組みを使います。
よく見かける認証パターン
ほとんどの ACP エージェントは、次のどれかの認証パターンに当てはまります。
-
環境変数による認証
- クライアントが環境変数付きでエージェントを起動する
- シンプルで自動化しやすい
-
ターミナルでのログイン認証
- ターミナルで
<cli> loginを一度実行する - エージェントはマシンごとの認証状態を使う
- ターミナルで
-
UI での OAuth(CLI 中心のツールではあまり多くない)
ACP の認証設計は意図的に慎重です。エージェントがクライアントをだまして、認証のために任意のコマンドを実行させることはできないようになっています。
ステップ 3: スマホでのワークフロー
2分間のループ
- セッションを開く
- 承認を確認する
- フォローアップを1つ送る
- 離れる
コピーして使えるフォローアップ3つ
- チェックポイント
次のステップが終わったら止まって、次の内容をまとめてください:
- 変更した内容
- 変更していない内容
- 次にやりたいこと
- 制約
マイグレーションや認証には触れないでください。必要だと思ったら、止まって確認してください。
- 根拠
続ける前に、これから実行するコマンドをそのまま貼り付けて、理由を説明してください。
クライアント別の設定レシピ(コピー用)
エージェントが ACP として正しく動くようになると、次の悩みはクライアントの設定形式です。
よく出てくるもの:
acp.jsonを使う JetBrains のカスタムエージェント- Zed の設定 JSON
- Neovim の CodeCompanion ACP クライアント(制限が明記されています)
共通のファイル形式はありません。
ルールは、1つのクライアントを選んでそこで動かし、それから増やすことです。
デバッグの手順(エージェントを疑う前に)
1) エージェントの stdout がきれいなことを確かめる
解析エラーが出る場合、80%は stdout に JSON-RPC 以外のものが混ざっているのが原因です。
ログはすべて stderr に出してください。
2) メッセージ内の改行を避ける
JSON メッセージを整形出力しないでください。1メッセージは1行です。
3) 作業ディレクトリが想定どおりか確かめる
多くの自作エージェントは「動いて」いても、cwd が違うせいで別のリポジトリを操作しています。
トラブルシューティング
検出は通るのにセッションが開始しない
たいてい次のどれかです。
- 環境変数が足りない
- 作業ディレクトリが違う
- CLI が stdout にバナーやログを出している
- CLI が TTY を前提にしている(stdio の ACP と互換性がない)
エージェントは起動するのにツールが表示されない
MCP 設定の不一致であることが多いです。
- stdio と http/sse のフィールドの違い
- ヘッダーや環境変数の不足
認証が「不明(Unknown)」と表示される
認証確認が安全でない(または定義されていない)場合、不明(Unknown)になるのは想定どおりです。
「ログアウト」ではなく「わからない」と考えてください。
よくある質問
ACP の仕様をすべて実装する必要がありますか?
いいえ。
「最小限で動く」エージェントが対応すべきなのは:
- initialize
- session/new
- session/prompt
それ以外(読み込み/再開、リッチなツール、添付ファイル)は後からで構いません。
ターミナルでは動くのに IDE やアプリでは動かないのはなぜですか?
ほぼ必ず次のどれかです。
- PATH や環境変数の不一致
- 作業ディレクトリの違い
- stdout の汚染
エージェントに認証コマンドを操作させても安全ですか?
ACP はこれを防ぐように明確に設計されています。ターミナル認証のフローは同じバイナリを実行するべきで、エージェントが任意のコマンドを指定できないようになっています。
Happier を初めて使う場合
Happier は、信頼できるコンピューターでセッションを動かし、スマホから監視するためのコンパニオンアプリです。
セットアップ:
- GitHub: https://github.com/happier-dev/happier
- インストール/ダウンロード: https://github.com/happier-dev/happier#how-it-works
- Discord: https://discord.gg/W6Pb8KuHfg