ケーススタディ · Shelly
事例:Shelly ― AI を率いてつくった Android のターミナルと AI エージェント基盤
コードは書かない。AI を率いて、実機で動くまで完了と呼ばない。
公開 2026-11-04 · 数字は 2026-11-04 時点
要約。 私は RYO ITABASHI、Creative Director です。8 か月かけて、AI コーディングエージェントを指揮して、Android 向けのオープンソースの AI ターミナル兼エージェント実行環境 Shelly を作りました。何を作り、何を捨てるかを決めるのは私で、実機で動くまでは完了と呼びませんでした。
| 期間 | コミット | リリース | 検証端末 |
|---|---|---|---|
| 2026-03-04 → 2026-11-04 | 2,830 | バージョン付き 21 件 | 1 台(Galaxy Z Fold6、N=1) |
GitHub の Shelly · デモ動画(Shelly の README)
課題
スマホは常に電源が入っていて、いつも手元にあり、ファイルもアカウントも文脈もすでに入っています。それでも、そこで開発ツールや無人で動く AI エージェントを使おうとすると、Termux を入れて手で設定するか、別の場所にサーバーを置くことになります。そこで、bash・Node.js・Python・git と、それを使うターミナル、さらにスケジュールで動くエージェントを一つの Android アプリに収められるかを試しました。動かすのに PC・Termux・クラウドランナーが要らないこと。これはアプリの動作条件の話で、開発のしかたの話ではありません。
制約
- 端末は 1 台。 Samsung Galaxy Z Fold6 一台を前提に設計し、その実機で検証しています。結果には N=1 と明記します。
- 出荷状態の Android セキュリティ。 Shelly は Samsung Knox の SELinux ポリシーの下で動く普通のアプリです。root も proot も使いません。
- 実装は AI に任せる。 製品のコードを私が手で書くことはなく、実装は私のディレクションで AI コーディングエージェントに任せています。git では 2,830 コミット中およそ 2,200 に AI の作者・共著者の印があります。残りにはどちらの印もないため、すべての行の出どころを git で証明することはできません。
- 他社の利用規約。 技術的には動いても、規約を理由に使わなかったルートがあります。
決める・実装する・確かめる
- 決める — 私。 Shelly が何のためにあるか、画面に何を置き何を置かないか、どの機能を捨てるか、どのリスクを許すか、何をもって完了とするか。
- 実装する — AI コーディングエージェント(Claude Code、Codex)。 Kotlin と C のネイティブモジュール、TypeScript のアプリ、bash のランタイム、テスト、調査、一次レビュー。リスクの高い場面では、Claude Code と Codex が互いの成果をレビューし、どの指摘を採るかは私が決めました。
- 確かめる — Fold6。 製品判断の主な場は Fold6 で、実機検証の対象も Fold6 だけです。実機での確認は、PC から adb 経由で AI エージェントが行うことも多くありました。合格かどうかを決めるのは私です。
プロジェクトの記憶は誰かの頭の中にはなく、docs/superpowers/DEFERRED.md にあります。後回し・対象外にした作業と既知の限界をまとめた唯一の台帳で、各項目に理由と優先度が付いています。CLAUDE.md には「口頭の『あとでね』禁止、すべて DEFERRED.md に追加する」というルールがあります。製品判断も私の言葉のまま残していて、たとえばある機能は「無くしちゃおうぜ」の一言で削除しました。
3 つの転機
1. Knox が shebang スクリプトと am start を止める
初期の設計では、PATH 上に小さな #! シェルスクリプトを置き、シェルからアプリへ URL を渡すのに am start を使っていました。Fold6 では、どちらも動きませんでした。カーネルのスクリプトローダーに必要な読み取り権限を、Knox のポリシーがアプリ自身のデータファイルに対して拒否するため、#!/system/bin/sh でも $HOME の bash でも linker64 でも同じエラーになりました。アプリの uid からの am start は Activity Manager に拒否されました。対処は構造の変更でした。PATH から見えるコマンドはすべて APK 同梱のネイティブバイナリにし、$HOME/bin からシンボリックリンクを張る。シェルからアプリへの連絡はファイルキューにし、アプリが 250ms ごとに読む。./script.sh の直接実行はこの端末では今も失敗するので、ドキュメントにも「bash script.sh で呼ぶ」と書いてあります。
2. app.act — 実験として出して、2 日後に撤去
app.act は、Android のユーザー補助サービスと記録したレシピを使って、エージェントに他のアプリを操作させる機能でした(LINE の送信、X への投稿など)。実験版の Phase 1 は 2026-08-29 に有効にしました。一度の実機テストで、別々の構造的なバグが 3 つ見つかりました。コールドスタート時のタイミングのずれ、画面上の複数の要素に一致しうるマッチャー、そして直せないと判断したレシピ記録 UI のフォーカス奪取です。画面を読む自動操作は、対象を 2 アプリに絞っても、相手のアプリの画面が変わるたびに壊れました。2026-08-31、Kotlin のサービス、TypeScript、テスト、ドキュメント、i18n キー約 25 個まで、機能を丸ごと削除しました。投稿は API コネクタに移しました。他アプリの操作はのちに、別アプリ(ClosePaw)に任せ、承認はスマホで行う形で戻ってきました。
3. ゲートを試して見つけた抜け道
最も強い権限レベル「すべて承認なしで実行」は、ファイル操作を確認なしで許可します。発端は使い勝手の不満で、grep のパターンのクォート内にある \| がパイプとして読まれていました。これを直す途中で、main にある既存の判定に攻撃的な入力を直接与えたところ、いくつかが誤って許可されました。クォートした "<<EOF" を heredoc と誤認し、後の cp evil ~/bin/git を本文として読み飛ばす。ブレース展開の中に .. を隠す。失敗するかもしれない cd の後の作業ディレクトリを確定扱いする。2026-11-02、判定を、クォート・エスケープ・コメント・heredoc をシェルと同じ規則で読む字句解析器に置き換えました。翌日には cu''rl・"c"url・$'\x63'url のようにクォートで隠したネットワークコマンドも検出するようにし、こちらは実機で確認しました(build 2821)。字句解析器への置き換え自体はテストを通っていますが、実機ではまだ確かめていません。
そのほかの判断
- CLI の約束を絞る。 v5.3.1(2026-05-14)では、ターミナルで Claude Code と Codex を正式対応にしていました。その後、スマホ上の Claude Code の経路は 5 月中旬に修正を重ねても安定せず、2026-05-29 に Claude Code / Gemini CLI の統合を撤去しました。それから 2026 年 10 月下旬まで、ターミナルの CLI は Codex で、ほかのプロバイダは明示的な API として使っていました。Claude Code は 2026-10-31 に、手動でステージングした公式バイナリとして戻ってきました。
- 動いていたルートを凍結。 2026-08-31、Claude Code の配布形式である Bun の単一実行ファイルを解析して JavaScript を取り出し、Node で動かす PoC を作りました。
--versionは動きました。ところが、コーディングツールの安全分類器がこの種の操作を繰り返しブロックしました。理由を検討した結果、このルートはベンダーの規約に触れる可能性が高いと判断し、凍結しました。法的な結論ではなく、プロジェクトとしてのリスク判断です。Claude Code はのちに、Anthropic 公式の linux-arm64 glibc ビルドを改変せずに起動する形で戻ってきました。教訓は、他社の独自バイナリに手を付ける前に規約を確かめることです。 - 27B のローカルモデルは却下。 スマホで読み込めましたが、会話に使える速度に届きませんでした(2026-07-15)。
- 確認カードではなくチャットの平文。 エージェント登録の確認に構造化されたカードを何度か試したうえで、チャットの平文を選びました。
セキュリティ境界(承認ゲート)
AI がコードを書き、エージェントが無人で動くなら、境界を信頼に頼ることはできません。仕組みとして作り込む必要があります。Shelly では、エージェントの CLI ワーカー(Codex / Claude Code)が出すコマンドは、すべて一つのドライバ(shelly-agent-driver.js)と一つのゲートを通ります。ゲートは、コマンドの危険度・ワークスペースの境界・ポリシーを判定します。危険度 CRITICAL のコマンドやポリシー自体への書き込みのように、人に聞く前に拒否されるものもあります。
- 無人実行では、人の判断が要る要求はその場で断ります。
- 有人実行では、スマホに通知でエスカレーションします。承認は Android Keystore の鍵で署名した返信で戻ります。
- ChatGPT → スマホアプリ操作(ClosePaw)の流れでは、ChatGPT はスマホ操作を頼めても、承認はできません。承認はスマホ側でしか行えません。実験的な Codex リモートコントロールのホスト(
shelly codex pair)は別の経路で、この説明の対象外です。 - **「承認なしで実行」**は既定 OFF で、エージェントごとに設定します。「標準」は軽い理由で止まったものだけを許可します。「すべて」は有人実行に限られ、Web 調査・URL・通知など信頼できない入力を読むエージェントには適用されません。自動で許可するのは、アプリのホーム内でのファイル操作(作成・編集・移動・削除。ドットディレクトリや
~/bin・~/modelsなどのランタイム領域は除く)、/tmpと$TMPDIRでのファイル操作、ワークスペース内ファイルの読み取り専用の構文チェック(node --check・python3 -m py_compile・bash -n)です。スクリプトやプログラムの実行、ネットワーク、秘密情報に触れるもの、リンクを作るコマンド、システムコマンドは引き続き人に聞きます。フラグは、実行中に書き換えられうるエージェントのファイルではなく、Keystore で裏付けた保存先に置いています。 - 未解決の問題。 Codex が MCP サーバーや ChatGPT アプリ経由で行うツール呼び出しがゲートを素通りするかどうかは、まだ確認できていません。2026-11-04 の実機テストでは、インストール済みの ChatGPT アプリを使った検索が承認なしで動き、コードレビューも同じ方向を示しています。P1 として記録しており、まだ直していません。
実機検証の方法(N=1、Galaxy Z Fold6)
テスト端末は Galaxy Z Fold6 一台(N=1)です。その端末で動くのを確かめるまで、完了とは呼びません。README は結果に「実機検証済み(Galaxy Z Fold6、N=1)」と書き、DEFERRED.md には「実装済み・実機未検証」という状態を別に残しています。この状態のままの項目も多くあります。端末の確認は adb で行い、PC から AI エージェントが動かすことも多くありました(UI の自動操作、Shelly 独自のログタグで絞った logcat、dumpsys で見るアラームの状態)。エージェント実行パイプラインの回帰テストは、手で写した再実装ではなく、実際に生成されたスクリプトを本物のプロセスで動かします。ネイティブ・OAuth・IPC・セキュリティ境界のようなリスクの高い変更は、取り込む前に別のエージェントがレビューします。ほかの端末の利用者には shelly doctor --report の提出をお願いしています。
結果(2026-11-04 時点)
mainに 2,830 コミット(2026-03-04 〜 2026-11-04)- バージョン付きリリース 21 件(v4.2.0 2026-04-01 〜 v8.2.0 2026-11-03)
- GitHub 68 stars / 12 forks
- 自然言語で登録 → 画面オフでスケジュール起動 → 結果を通知、という無人の一連のサイクルを Fold6 の実機で端から端まで確認(N=1)
規模の目安として、この AI に指揮する開発のしかたで作られたコードは、アプリ本体が約 22.5 万行(空行・コメントを含む物理行。テスト・生成物・取り込んだ Termux のコードを除く)、テストが約 10.1 万行(443 ファイル、テストケースは grep で数えた概算で約 6,150。通過数ではありません)です。これは規模を示すだけで、品質の指標でも、誰が書いたかの証明でもありません。
残る限界
- 端末は 1 台。 別のスマホや別メーカーの Android では、何も確かめていません。
- 修正済みだが実機未確認。 「すべて」レベルの字句解析器への置き換えと、実機のエージェント実行で見つかったバグ 4 件の修正(「OK」の後の結果の表示順、Codex ステップが黙ってローカルモデルに切り替わる件、MONITOR の表示名、スキップのあった実行の後のスキル保存の提案)。どちらもテストは通っていますが、実機ではまだ確かめていません。
- MCP の問題。 Codex の MCP / ChatGPT アプリのツール呼び出しがゲートを素通りするかどうかは未解決です(上記)。
- 判定は字句的。 ゲートはコマンドの文字列を読むだけで、ファイル操作の結果が後で何に使われるかまでは追いません。これは受け入れた制約として明記してあります。
- 自前の検証。 テストもレビューも実機確認も、プロジェクト自身が行っています。外部のセキュリティ監査は受けていません。
- Codex は公式版ではない。 Codex はオープンソースの Termux 向けフォークで、OpenAI 公式のバイナリではありません。
- 配布。 GitHub Releases のみ(Play Store / F-Droid は未対応)で、APK は約 700MB です。
- スマホだけの開発ではない。 AI エージェントはスマホと Windows PC で動かしました。スマホが担ったのは、製品の判断と実機での検証です。
次にやること
まず MCP の問題を片付けます。Codex のワーカーには MCP サーバーやアプリを渡さないか、読み取り専用の許可リストだけを渡し、MCP のツール呼び出しは別のゲートで判定します。そのうえで「すべて」レベルと実機バグ 4 件の修正を実機で確かめ、2 台目の端末での結果と外部のセキュリティレビューを得たいと考えています。
登壇やプロジェクトのご相談は、お問い合わせフォームからどうぞ。
根拠
各節の出典です。ファイルは GitHub の Shelly リポジトリ(main)にリンクしています。公開クレーム台帳と開発記の目次は非公開の作業文書のため、リンクしていません。
-
プロジェクトの公開クレーム台帳(非公開の作業文書。2026-11-04 に
git rev-list --count HEAD・gh release list・GitHub API で計測)の「1. 計測値」、README「About the Creator」。commit history (main) GitHub Releases README — About the Creator ↩
-
README 冒頭(README.ja.md)、CLAUDE.md「プロジェクト概要」(バンドルツール)。
-
公開クレーム台帳(非公開)「1.3」「1.4」: AI の作者・共著者の印の和集合 2,204 / 2,830 コミット(
git logを 1 コミットずつ判定)。 -
CLAUDE.md「セッション開始時に必ず読むもの」のルール、DEFERRED.md の app.act 廃止の記録、公開クレーム台帳(非公開)「1.3」。
-
CLAUDE.md Architecture Decisions「PATH-visible shim は native binary 必須」「shell→RN bridge は file-queue (am start 不可)」、CLAUDE.md「bash wrapper」、commit ba177fea7。
-
CHANGELOG.md「[8.0.0] - 2026-08-31」Removed、DEFERRED.md の app.act 廃止の記録、commit bde82f4e6・325e9d702、README Status「ChatGPT → phone-app task」。
CHANGELOG.md docs/superpowers/DEFERRED.md bde82f4e6 325e9d702 README.md ↩
-
DEFERRED.md「「承認なしで実行(すべて)」で定型コマンドが人に回る(build 2790、Claude Code ワーカー)— 修正済み・実機未検証」の「同時に塞いだ既存の穴」、「gate の NETWORK_RE が生のコマンド文字列で判定される … 実機 VERIFIED(build 2821)」、CHANGELOG.md「[8.2.0]」Security、commit c8ab23f34・5f7216503・35829696c・e1e10329d。
docs/superpowers/DEFERRED.md CHANGELOG.md c8ab23f34 5f7216503 35829696c e1e10329d ↩
-
CHANGELOG.md「[5.3.1] - 2026-05-14」、commit 3095aa479(2026-05-29)、commit a51b7c577…31c941c4a(2026-05-18〜05-21 の Claude Bash ツール修正群)、DEFERRED.md「2026-08-31 復活検討 → Bun SEA 逆解析ルートは ToS 懸念で打ち切り」、CLAUDE.md「AI CLIs」2026-10-31 追記(S1–S4)、CLAUDE.md「Local LLM」、開発記の目次(非公開)第24話・第26話。
CHANGELOG.md 3095aa479 a51b7c577^…31c941c4a docs/superpowers/DEFERRED.md CLAUDE.md ↩
-
CLAUDE.md Architecture Decisions「CLI ワーカーは共通ゲート経由(Codex / Claude Code)」(2026-10-31 / 11-01 / 11-02 追記)、lib/agent-run-without-approval.ts(ALL_LEVEL_SOFT_REASONS のコメント、ALL_LEVEL_TOOLS)、README Status「ChatGPT → phone-app task」「Codex remote control host」(Experimental)、DEFERRED.md「Codex ワーカーの ChatGPT アプリ(MCP)ツール呼び出しがゲートを通るか未確認 — 未調査 (P1)」。
CLAUDE.md lib/agent-run-without-approval.ts README.md docs/superpowers/DEFERRED.md ↩
-
README「The Story」(README.ja.md の相当節)、CLAUDE.md「デバッグログタグ」、README の device report の案内。
-
公開クレーム台帳(非公開)「1」「1.1」「1.2」「3」、README 冒頭の unattended cycle の記述。
-
DEFERRED.md「「承認なしで実行(すべて)」で定型コマンドが人に回る … 修正済み・実機未検証」、「S4 エージェント実行の実機バグ 4 件 … 修正済み・実機未検証」、「Codex ワーカーの ChatGPT アプリ(MCP)ツール呼び出しがゲートを通るか未確認」、「依頼文のパスから CLI の作業フォルダを決める /「承認なしで実行」の「すべて」レベル」の「残り(受け入れた制約)」、README Status「Distribution」、公開クレーム台帳(非公開)A1–A3。
-
DEFERRED.md「Codex ワーカーの ChatGPT アプリ(MCP)ツール呼び出しがゲートを通るか未確認」の修正案。