ケーススタディ · 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)

根拠 1

課題

スマホは常に電源が入っていて、いつも手元にあり、ファイルもアカウントも文脈もすでに入っています。それでも、そこで開発ツールや無人で動く AI エージェントを使おうとすると、Termux を入れて手で設定するか、別の場所にサーバーを置くことになります。そこで、bash・Node.js・Python・git と、それを使うターミナル、さらにスケジュールで動くエージェントを一つの Android アプリに収められるかを試しました。動かすのに PC・Termux・クラウドランナーが要らないこと。これはアプリの動作条件の話で、開発のしかたの話ではありません。

根拠 2

制約

  • 端末は 1 台。 Samsung Galaxy Z Fold6 一台を前提に設計し、その実機で検証しています。結果には N=1 と明記します。
  • 出荷状態の Android セキュリティ。 Shelly は Samsung Knox の SELinux ポリシーの下で動く普通のアプリです。root も proot も使いません。
  • 実装は AI に任せる。 製品のコードを私が手で書くことはなく、実装は私のディレクションで AI コーディングエージェントに任せています。git では 2,830 コミット中およそ 2,200 に AI の作者・共著者の印があります。残りにはどちらの印もないため、すべての行の出どころを git で証明することはできません。
  • 他社の利用規約。 技術的には動いても、規約を理由に使わなかったルートがあります。

根拠 3

決める・実装する・確かめる

  • 決める — 私。 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 に追加する」というルールがあります。製品判断も私の言葉のまま残していて、たとえばある機能は「無くしちゃおうぜ」の一言で削除しました。

根拠 4

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 で呼ぶ」と書いてあります。

根拠 5

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)に任せ、承認はスマホで行う形で戻ってきました。

根拠 6

3. ゲートを試して見つけた抜け道

最も強い権限レベル「すべて承認なしで実行」は、ファイル操作を確認なしで許可します。発端は使い勝手の不満で、grep のパターンのクォート内にある \| がパイプとして読まれていました。これを直す途中で、main にある既存の判定に攻撃的な入力を直接与えたところ、いくつかが誤って許可されました。クォートした "<<EOF" を heredoc と誤認し、後の cp evil ~/bin/git を本文として読み飛ばす。ブレース展開の中に .. を隠す。失敗するかもしれない cd の後の作業ディレクトリを確定扱いする。2026-11-02、判定を、クォート・エスケープ・コメント・heredoc をシェルと同じ規則で読む字句解析器に置き換えました。翌日には cu''rl・"c"url・$'\x63'url のようにクォートで隠したネットワークコマンドも検出するようにし、こちらは実機で確認しました(build 2821)。字句解析器への置き換え自体はテストを通っていますが、実機ではまだ確かめていません。

根拠 7

そのほかの判断

  • 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)。
  • 確認カードではなくチャットの平文。 エージェント登録の確認に構造化されたカードを何度か試したうえで、チャットの平文を選びました。

根拠 8

セキュリティ境界(承認ゲート)

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 として記録しており、まだ直していません。

根拠 9

実機検証の方法(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 の提出をお願いしています。

根拠 10

結果(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。通過数ではありません)です。これは規模を示すだけで、品質の指標でも、誰が書いたかの証明でもありません。

根拠 11

残る限界

  • 端末は 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 で動かしました。スマホが担ったのは、製品の判断と実機での検証です。

根拠 12

次にやること

まず MCP の問題を片付けます。Codex のワーカーには MCP サーバーやアプリを渡さないか、読み取り専用の許可リストだけを渡し、MCP のツール呼び出しは別のゲートで判定します。そのうえで「すべて」レベルと実機バグ 4 件の修正を実機で確かめ、2 台目の端末での結果と外部のセキュリティレビューを得たいと考えています。

根拠 13

登壇やプロジェクトのご相談は、お問い合わせフォームからどうぞ。

根拠

各節の出典です。ファイルは GitHub の Shelly リポジトリ(main)にリンクしています。公開クレーム台帳と開発記の目次は非公開の作業文書のため、リンクしていません。

  1. プロジェクトの公開クレーム台帳(非公開の作業文書。2026-11-04 に git rev-list --count HEAD・gh release list・GitHub API で計測)の「1. 計測値」、README「About the Creator」。

  2. README 冒頭(README.ja.md)、CLAUDE.md「プロジェクト概要」(バンドルツール)。

  3. 公開クレーム台帳(非公開)「1.3」「1.4」: AI の作者・共著者の印の和集合 2,204 / 2,830 コミット(git log を 1 コミットずつ判定)。

  4. CLAUDE.md「セッション開始時に必ず読むもの」のルール、DEFERRED.md の app.act 廃止の記録、公開クレーム台帳(非公開)「1.3」。

  5. CLAUDE.md Architecture Decisions「PATH-visible shim は native binary 必須」「shell→RN bridge は file-queue (am start 不可)」、CLAUDE.md「bash wrapper」、commit ba177fea7。

  6. CHANGELOG.md「[8.0.0] - 2026-08-31」Removed、DEFERRED.md の app.act 廃止の記録、commit bde82f4e6・325e9d702、README Status「ChatGPT → phone-app task」。

  7. DEFERRED.md「「承認なしで実行(すべて)」で定型コマンドが人に回る(build 2790、Claude Code ワーカー)— 修正済み・実機未検証」の「同時に塞いだ既存の穴」、「gate の NETWORK_RE が生のコマンド文字列で判定される … 実機 VERIFIED(build 2821)」、CHANGELOG.md「[8.2.0]」Security、commit c8ab23f34・5f7216503・35829696c・e1e10329d。

  8. 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話。

  9. 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)」。

  10. README「The Story」(README.ja.md の相当節)、CLAUDE.md「デバッグログタグ」、README の device report の案内。

  11. 公開クレーム台帳(非公開)「1」「1.1」「1.2」「3」、README 冒頭の unattended cycle の記述。

  12. DEFERRED.md「「承認なしで実行(すべて)」で定型コマンドが人に回る … 修正済み・実機未検証」、「S4 エージェント実行の実機バグ 4 件 … 修正済み・実機未検証」、「Codex ワーカーの ChatGPT アプリ(MCP)ツール呼び出しがゲートを通るか未確認」、「依頼文のパスから CLI の作業フォルダを決める /「承認なしで実行」の「すべて」レベル」の「残り(受け入れた制約)」、README Status「Distribution」、公開クレーム台帳(非公開)A1–A3。

  13. DEFERRED.md「Codex ワーカーの ChatGPT アプリ(MCP)ツール呼び出しがゲートを通るか未確認」の修正案。