← すべての記事

Mac App Store はウィンドウマネージャーの存在を許さない。それでも私は出荷した。

Apple のデベロッパテクニカルサポート(DTS)のエンジニアから、私のアプリは不可能だと告げられました。「サンドボックス化されたアプリから Accessibility API を使うことはできません……ここから先の唯一の道は、アプリを直接配布することです」1 そのアプリはウィンドウタイラーで、Accessibility API はあらゆるウィンドウマネージャーの土台であり、Mac App Store のアプリはすべて、それを禁じるサンドボックスの中で動きます。それでも先週、941 Tiles は Mac App Store で公開されました。メニューバーで 1 回クリックすれば、アプリの散らばったウィンドウがすべて均等なグリッドに収まります。サンドボックスの規則は一度も曲げていません。鍵になったのは、macOS には Apple の完全な承認を得た特権的なウィンドウ移動役がすでに存在し、しかもそれが JSON を受け取る、と気づいたことでした。

TL;DR

  • App Sandbox は、アプリをまたぐ Accessibility の呼び出しを一律にブロックします。これを解除する entitlement は存在せず、Mac App Store のアプリはすべてサンドボックス化が必須です。ウィンドウマネージャーというカテゴリは、2012 年 6 月以降、新規参入者に対して事実上閉ざされてきました。今もストアに残るタイラーは義務化より前から存在し、永久にサンドボックスなしで動きます。134
  • 認められた扉。サンドボックス化されたアプリでも、Apple events 経由で Apple の Shortcuts エンジンを動かすことはできます。そして Shortcuts には、他のアプリのウィンドウを Apple 自身の権限で動かす Find Windows / Move Window / Resize Window のアクションが用意されています。25 私のアプリは、どのウィンドウをどこへ置くべきかを計算するだけ。実際に動かすのは付属のショートカットです。許可ではなく、委譲というわけです。
  • これを現実にしたエンジニアリング。付属の .shortcut を WFWorkflowActions のバイナリ plist としてプログラムから生成すること、ウィンドウの z オーダーに紐づく JSON フレームペイロードの取り決め、幻のウィンドウやインデックス超過に対するガードレール、そして Developer ID ビルドでは直接 Accessibility を、ストアビルドでは Shortcuts への委譲を使うデュアルエンジンのコードベースです。
  • 5 本のストアビルドが失敗したマシンでの初回成功実行。散らばった 4 つのターミナルウィンドウが、0.6 秒で正確な四分割のフレームに収まりました。
  • 功績は然るべき相手に。この仕組みは snApp(オープンソース、2023 年)と Align(2024 年)によって実地で実証されています。「不可能」を実装計画に変えたのは、snApp のソースを読んだことでした。2

壁

941 Tiles の最初のバージョンは、ごく普通のメニューバー型タイラーでした。macOS には Accessibility という仕組みがあり、ユーザーの許可があれば、あるアプリが別のアプリのウィンドウを列挙して動かせます(ウィンドウの位置とサイズの属性に対する AXUIElementSetAttributeValue)。それを土台にしたアプリは、数週間の開発を通じて完璧に動いていました。App Store Connect のリスティングも一通り整えました。17 言語のメタデータ、スクリーンショット、価格、アップロード済みの 21 本のビルド。

そこで TestFlight のビルドを 2 台目の Mac に入れてみました。Accessibility の許可は付与済み、アプリもアクセスは有効だと報告している。それでも読み取れたウィンドウは 0 個でした。

バグではありません。Mac App Store のアプリはすべて Apple の App Sandbox の中で動きます。これは、アプリが自分のものにしか触れないようにする封じ込めの規則で、まさに Mac の他の部分を覗いたり干渉したりできないようにするためのものです。4 別のアプリのウィンドウに手を伸ばす行為こそ、サンドボックスが止めるために存在する対象です。開発ビルドはサンドボックスなしで動くため、数週間は何もかもうまくいっていました。ストアビルドは、私が無視してきた規則をそのまま適用したのです。許可ダイアログも entitlement も設定も、これを解除しません。Apple に直接尋ねたときの DTS の回答が、この記事の冒頭にあるものでした。ストアの外で配布しなさい、と。1

2012 年から閉ざされたカテゴリ

この壁が興味深いのは、その向こう側に誰が立っているかという点です。Magnet、Moom、BetterSnapTool。今日でも Mac App Store で買えるウィンドウ操作ツールです。これらのリスティングは 2012 年 6 月のサンドボックス義務化より前から存在するため、他の誰にも引き継がれない祖父条項のもとでサンドボックスなしに動いています。2012 年より後に生まれたウィンドウマネージャー(Rectangle、Swish、Loop、BetterTouchTool、Amethyst)は、いずれもストアの外で配布されています。Apple はこの線引きを逆方向にも適用してきました。13 年近くストアにあった PopClip は、Accessibility を用いた新機能はサンドボックス化されたアップデートでは出せないと審査から告げられ、2024 年 3 月にストアを去りました。3

私の見方をはっきり書いておきます。サンドボックスの規則は妥当です。画面上のあらゆるウィンドウを黙って読み、動かせるアプリは、あなたを監視できるアプリでもあります。「私を信じて」はセキュリティモデルではありません。ストアの約束は、そこからインストールしたものにそんなことはできない、というものです。不公平さはごく狭く、具体的です。既存の事業者は、新規参入者がどれだけユーザーの同意を得ても手に入らない能力を保持し続けます。カテゴリは禁止されたのではなく、化石になったのです。

転回

DTS の判断には、ひとつだけ穴がありました。ストアにはすでに反例が存在していたのです。Align(2024 年)と snApp(2023 年)はどちらもウィンドウをタイル配置し、どちらも Mac App Store にあり、どちらも 2012 年よりずっと後に生まれています。snApp はオープンソースなので、この仕組みは秘密ではありません。リポジトリとして公開されています。2

サンドボックス化されたアプリは、別のアプリのウィンドウには一切触れません。動かすのは Shortcuts、つまり Apple 自身の自動化アプリで、宣言した 2 つの entitlement を通じてそれを行います。

<key>com.apple.security.automation.apple-events</key>
<true/>
<key>com.apple.security.temporary-exception.apple-events</key>
<array>
  <string>com.apple.shortcuts.events</string>
</array>

Shortcuts には macOS 12 以降、Find Windows、Move Window、Resize Window という名前のアクションが用意されています。5 Shortcuts がウィンドウを動かせるのは、それが Apple のものだからです。そこでアプリは、どのウィンドウをどこへ置くべきかを計算し、その計画をユーザーがインストールした付属のショートカットに渡し、Apple 自身のエンジンが移動を行います。サンドボックスが破られることはありません。サンドボックス化されたプロセスは、特権的な行為を一度も実行しないからです。許可ではなく、委譲です。

この形には、どこか建築的なところがあります。セキュリティの境界は Apple が引いたその場所に留まったまま、能力のほうが、システム上で正当にそれを持つ唯一のプロセスを経由して境界を越えていくのです。

作り込み

仕組みを知ることと、それを出荷することは別の週の話です。これを本番レベルにした要素を挙げます。

ショートカットをプログラムから生成する。 ユーザーに 12 個のアクションからなるワークフローを手で組ませるべきではありません。付属の .shortcut ファイルは WFWorkflowActions のバイナリ plist で、アプリがビルド時に生成し、shortcuts sign -m anyone で署名します。そのためインストールは Shortcuts アプリへの 1 クリックで済みます。実行時の取り決めは、ScriptingBridge の shortcut.run(withInput:) を通して渡す JSON ペイロードです。

{"app": "Ghostty", "frames": [{"x": 0, "y": 38, "w": 1280, "h": 771}, ...]}

ウィンドウの同一性は z オーダー。 ショートカットの Find Windows アクションはウィンドウを手前から奥へと並べ、CGWindowList も同じ順序で列挙します。したがってペイロードのスロット i は、そのままウィンドウ i のフレームを運びます。位置の順位どおりにセルを割り当てれば、グリッドは「ウィンドウは元あった場所の近くに留まる」を再現します。ウィンドウ ID が境界を越えることはありません。向こう側にはそもそも存在しないからです。

ガードレール。 Count で上限を取った Items in Range のクランプにより、古いペイロードが現在のウィンドウリストの範囲外を参照することを防ぎます。最小サイズのフィルター(120×80)は、CGWindowList が報告し、以前は Accessibility のロール判定で隠していた幻の待機パネルを除外します。そして驚いた事実がひとつ。ウィンドウの列挙には許可が一切要りません。CGWindowList はサンドボックスの上で合法です。禁じられていたのは移動だけだったのです。

ひとつのコードベース、2 つのエンジン。 アプリは起動時に APP_SANDBOX_CONTAINER_ID 環境変数でサンドボックスを検出します。ストアビルドは Shortcuts 経由でタイル配置し、Developer ID ビルドと開発ビルドは直接 Accessibility の経路を使います。同じ UI、同じ計算、違う運び手です。

通知なしのウォッチモード。 オプトイン式の自動再タイル機能は、通常なら Accessibility のウィンドウ通知を購読しますが、これもサンドボックスが取り上げます。代わりにウィンドウサーバーのポーリングとして生き延びました。安価な CGWindowList の差分を取り、変化があれば再タイルします。

代償を正直に述べる

ユーザーは一度きりのセットアップという税を払います。付属のショートカットをインストールし(1 クリック)、自動化の同意ダイアログを 1 回承認する(「941 Tiles が Shortcuts を制御しようとしています」という標準のプロンプトで、InfoPlist.xcstrings により 17 言語すべてにローカライズ済み)。それが済めば、体験は直接 API を使うタイラーと変わりません。グリッドのアイコンをクリックし、アプリをクリックすれば、ウィンドウが収まります。Shortcuts の実行は目に見えず、1 秒を大きく下回ります。

この税がゼロだとは言いません。Magnet より画面が 1 つ多いのは事実です。同時にこれは、まだ信頼する理由のない公証済みダウンロードのためにユーザーへ Gatekeeper の回避を求めるのではなく、サンドボックスの中に存在するための代金のすべてでもあります。

見返り

5 本のストアビルドが失敗したのと同じ Intel Mac で、インストール、ショートカットの設定、同意を経て、散らばった 4 つの Ghostty のウィンドウが、初回の実行で 0.6 秒のうちに正確な四分割のフレームに収まりました。その後は国際化の作業(String Catalogs、アラビア語の 6 つのカテゴリすべてを含む CLDR の複数形規則)、ローカライズしたリスティング、そして申請です。1 回の審査リジェクトと約 30 分の再審査を経て、941 Tiles は公開されました。買い切り 4.99 ドル、macOS 15 以降、17 言語、データ収集ゼロ、ネットワークアクセスなし。

一般化できること

このパターンは、ウィンドウのタイル配置より大きな話です。プラットフォームがある能力を境界の向こうに閉じ込めたとき、答えは境界と戦うことではめったにありません。その能力をすでに持っているファーストパーティのプロセスを洗い出し、そこへの公認のインターフェースを見つけることです。macOS では、その棚卸しの先はますますひとつの場所を指しています。Shortcuts です。これは静かにシステムの特権的な自動化の仲介役となり、設計上サンドボックスの内側から到達できます。私の Shortcuts ガイドではその領域を詳しく扱っており、941 Tiles のケーススタディでは同じ話をアーキテクチャ図とともにたどっています。

サンドボックスは仕事を果たしました。それでもアプリは出荷されました。どちらの文も真であり、その間にあった扉は Apple 自身のものでした。

よくある質問

サンドボックス化された Mac アプリは Accessibility API を使えますか?

いいえ。App Sandbox はアプリをまたぐ Accessibility の呼び出しを一律にブロックし、entitlement も許可ダイアログも設定も、これを解除しません。私に対する Apple 自身の DTS の回答はこうでした。「サンドボックス化されたアプリから Accessibility API を使うことはできません……ここから先の唯一の道は、アプリを直接配布することです」。開発ビルドはサンドボックスなしで動きます。だからこそ、タイラーが数週間動いたあと、ストアビルドではウィンドウを 0 個しか読めない、ということが起こるのです。14

ウィンドウマネージャーはどうすれば Mac App Store で出荷できますか?

特権的な行為を委譲することによってです。サンドボックス化されたアプリでも Apple events を通じて Apple の Shortcuts エンジンを動かせますし、Shortcuts は macOS 12 以降 Find Windows、Move Window、Resize Window のアクションを提供しています。私のアプリはどのウィンドウをどこへ置くべきかを計算し、その計画をユーザーがインストールした付属のショートカットに渡します。移動を行うのは、Apple 自身の権限を持つそのショートカットです。サンドボックスが破られることはありません。サンドボックス化されたプロセスが特権的な行為を実行しないからです。25

ウィンドウマネージャーが不可能なら、なぜ Magnet や Moom はストアにあるのですか?

それらのリスティングは 2012 年 6 月のサンドボックス義務化より前から存在するため、他の誰にも引き継がれない祖父条項のもとでサンドボックスなしに動いています。Rectangle、Swish、Loop、BetterTouchTool、Amethyst を含め、2012 年より後に生まれたウィンドウマネージャーはすべてストアの外で配布されています。PopClip は、Accessibility の新機能はサンドボックス化されたアップデートでは出せないと審査から告げられ、2024 年 3 月にストアを去りました。カテゴリは禁止されたのではなく、化石になったのです。34

Shortcuts への委譲はユーザーに何を強いますか?

一度きりのセットアップという税です。付属のショートカットを 1 クリックでインストールし、自動化の同意ダイアログを 1 回承認します。その後の体験は直接 API を使うタイラーと変わりません。グリッドのアイコンをクリックし、アプリをクリックすれば、ウィンドウが収まりますし、Shortcuts の実行は目に見えず 1 秒を大きく下回ります。Magnet より画面が 1 つ多いこと、それがサンドボックスの中に存在するための代金のすべてです。

ひとつのコードベースで、サンドボックス版と直接版の両方をどう支えているのですか?

アプリは起動時に APP_SANDBOX_CONTAINER_ID 環境変数でサンドボックスを検出します。ストアビルドは Shortcuts 経由でタイル配置し、Developer ID ビルドと開発ビルドは直接 Accessibility の経路を使います。同じ UI、同じ計算、違う運び手です。ウォッチモードも同様に適応します。サンドボックスは Accessibility のウィンドウ通知を取り上げるため、オプトイン式の自動再タイルは、差分を取って変化があれば再タイルする安価な CGWindowList のポーリングとして生き延びています。

参考文献


  1. Apple Developer Forums、スレッド 805556(2025 年 10 月)、Apple DTS の回答。「サンドボックス化されたアプリから Accessibility API を使うことはできません……ここから先の唯一の道は、Developer ID 署名を使ってアプリを直接配布することです」 ↩↩↩↩

  2. Om Chachad、GitHub の snApp(2023 年)。Mac App Store で公開されているオープンソースのウィンドウタイラーで、そのソースが Shortcuts への委譲という仕組みを記録しています。com.apple.security.automation.apple-events のスクリプティング対象 entitlement と、Apple のウィンドウアクションから組み立てた付属のショートカットです。 ↩↩↩↩

  3. Michael Tsai、「PopClip Leaving the Mac App Store」(2024 年 3 月 21 日)。13 年近くストアにあったアプリに対し、Apple の審査がサンドボックス化されたアップデートから Accessibility を用いた新機能の削除を求めた件について。 ↩↩↩

  4. Apple、App Sandbox のドキュメント。2012 年 6 月以降、Mac App Store のすべてのアプリに採用が義務づけられている封じ込めモデル。 ↩↩↩↩

  5. Apple、Mac 用 Shortcuts ユーザガイド。macOS 12 以降で利用できる Find Windows、Move Window、Resize Window の各アクションを記載しています。 ↩↩↩

関連記事

The Shader Gallery That Lied: Debugging 216 WebGL Presets

A user said the shader playground looked broken. Pixel-readback testing found 30 dead presets, 11 that never compiled, a…

13 分で読める

MacPaintをブラウザで再現する——1984年のソースコードこそが仕様書

MacPaint 1.3をブラウザ上に再構築し、公開されたBill AtkinsonのPascalソースとすべてのツールの動作を照合しました。忠実なソフトウェア再現には何が必要かを綴ります。

13 分で読める

エンジニアリング哲学:ワーナー・ヴォゲルス

Amazonの CTO ワーナー・ヴォゲルスは、ある一つの前提の上にクラウドを築きました。あらゆるものは常に壊れる、というものです。故障を前提に設計し、影響範囲を最小化し、その間も可用性を保ち続けるのです。

23 分で読める