> For the complete documentation index, see [llms.txt](https://weekly-essay.mikey.wang/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://weekly-essay.mikey.wang/ja/2026/w32-a-builders-mac-also-needs-a-sweeper.md).

# W32-BuilderのMacにもSweeperが必要だ

私はMacを3台持っている。今、主力として使っているのはデスクトップのMac Studioだ。M2 Maxチップ、12コアCPU、64GBメモリを搭載し、5KディスプレイとShure MV7+マイクを接続している。

ハードウェア資源には比較的余裕があり、日常の制約はむしろソフトウェア環境にある。Codex、Claude Code、ChatGPT、Antigravity、Multicaを常時並行して使い、その背後ではブラウザ、MCP Server、sidecar、サンドボックスの仮想マシン、各種子プロセスも動く。Node、Python、Rust、プロキシ、Skills、起動項目、キャッシュも変わり続けている。

最近の環境整理は、小さなエラーから始まった。毎日自動実行するSkill管理タスクが、`ModuleNotFoundError: No module named 'tomllib'` を返した。調べると、対話型ターミナルと定期タスクが別のPythonを呼び出していた。Macには、システムのPython、HomebrewのPython、python.orgから入れたPython、condaが共存していた。似た問題はNodeやRustにもあった。

局所的な問題が重なると、環境は徐々に説明できないものになる。コマンドが時々古いバージョンを指し、バックグラウンドプロセスの所属が分からず、同じタスクがターミナルでは成功して定期実行では失敗する。Agentが速く実行するほど、環境のドリフトも速まる。

私は今、MacをBuilderの生産システムとして見ている。継続した管理が必要だ。

### BuilderもSweeperを担う必要がある

Boris Chernyは最近、Claude Codeチームの仕事を、Prototyper、Builder、Sweeper、Grower、Maintainerの5つの役割に整理した。Builderは、試作品を本番で使える製品や基盤にする。Sweeperは、UIを整理し、システムを単純にし、価値を失った機能を取り除き、性能を改善する。[Borisの元の投稿](https://x.com/bcherny/status/2071379474277613732)には、製品の段階ごとの役割の組み合わせが示されており、Sweeperはすべての段階に登場する。

最近の私の実感によく合う。

Agentは、増やすことが得意だ。新しいツールを入れ、コードを生成し、設定を追加し、新しいSkillを作れる。追加の限界費用はすでに低いが、削除や整理には依然として判断が要る。何が価値を失ったのか、どのコピーを統合すべきか、どのランタイムが最終的な入口を持つべきか、どの自動操作が有効な状態を誤って消しうるか。これらはSweeperが必要な問題だ。

個人のBuilderにとって、Sweeperの対象にはローカル環境も含まれる。プロセス、キャッシュ、ランタイム、プロキシ設定、起動項目、Skill、Agentの設定は、すべて資源だ。依存関係があり、使い続けるうちに変質していく。

私にとって、整理された環境の条件は4つある。重要な入口の管理主体が明確であること、動いているものを説明できること、ドリフトを発見できること、既知の状態に戻せることだ。

### Macにはどのような資源があるか

私の主な作業環境は、Codex、Claude Code、ChatGPT、Antigravity、Multicaである。ターミナルではGhosttyとcmuxを使う。知識の管理には主にBasic MemoryとCraftを使っている。Craftには、人が読むのに適したノート、記事、整理した結果を保存する。Basic Memoryには、安定した結論、再利用できる手順、Agentが継続して検索できるコンテキストを保存する。

ブラウザと自動化の層では、Chrome、Playwright、MCP Serverが起動する。会社のセキュリティソフト、プロキシツール、入力メソッド、同期サービス、アプリの更新プログラムも常駐する。

1つのデスクトップアプリは、通常、複数のプロセスから成る。Claude Desktopは自身のサンドボックス仮想マシンを起動し、Codexはsidecarを起動する。ブラウザはRendererやGPUのプロセスに分かれ、AgentのツールはNode、Python、MCP、ブラウザの子プロセスを立ち上げる。アクティビティモニタで個々のプロセスを見るだけでは、実際の資源使用を理解しにくい。私は、アプリの系列ごとに主プロセスとHelperをまとめ、`memory_pressure`、swap、CPU使用量の増分、ネットワーク接続と合わせて異常かどうかを判断している。

これらの資源には、4種類のドリフトが起きる。

第一は、プロセスとストレージのドリフト。セッションが終わっても子プロセスが残る。ダウンロードのキャッシュ、ログ、ビルド生成物が増え続ける。親アプリが、回収したプロセスを何度も起動し直すこともある。

第二は、設定とネットワークのドリフト。システムプロキシ、shell環境、GUIの起動環境、アプリ独自のプロキシ設定、DNS、認証状態は、それぞれ変わりうる。

第三は、ランタイムのドリフト。Homebrew、公式インストーラ、バージョン管理ツール、古いプロジェクトが、それぞれNode、Python、Rustを入れ、最後にPATHがどれを使うかを決める。

第四は、Agentの能力資源のドリフト。さまざまなツールがSkillsを別々のディレクトリに入れ、実体のコピーが分岐し、シンボリックリンクが切れ、上流が更新され、frontmatterや固定のパスが機能しなくなる。

最初の3つは、プログラムが安定して動くかに関わる。第四は、Agentが正しい能力を呼び出せるかに関わる。同じ管理上の問題だ。

### プロキシ環境は多層になっている

プロキシは、最も長く苦労した層だ。

macOSには、互いに独立したプロキシ経路がいくつもある。システムのネットワークプロキシは、macOSの設定を読むアプリに影響する。`~/.zshrc` のプロキシ変数は、現在のshellとその子プロセスにしか効かない。Finder、Dock、デスクトップアプリから起動したプロセスは、通常ユーザーの `launchd` の環境を引き継ぐ。一部のブラウザやCLIは独自のプロキシ設定を持ち、TUN、DNS、認証状態はさらに別の層にある。

典型的な問題を経験した。ターミナルのAntigravity CLIは正常に呼び出せるのに、Multicaの同じruntimeは地域で利用できないと返した。最初の修正は `.zshrc` の関数に書いたため、対話型ターミナルだけに有効だった。Multica DesktopはGUIからdaemonを起動し、`.zshrc` を読まないので、通信は結局直接接続になっていた。

有効な証拠は、実行中のプロセスから得られた。Multica daemonの環境にはプロキシ変数がなかった。直接リクエストとローカルプロキシ経由のリクエストでは、出口の地域も違った。最後に、実行ファイルの入口に置いたwrapperへプロキシ処理を移し、クリーンな環境で非対話型の起動を模擬して、実際の呼び出し経路で効いていることを確認した。

この調査から、安定したルールができた。確認すべきは対象プロセスであり、自分が設定したはずだという印象ではない。

同じツールでも、ターミナル、デスクトップアプリ、定期タスク、MCP、別のAgentから起動されうる。名前が同じでも、実行環境はまったく違うかもしれない。

### 1つのランタイムには、1つの管理主体だけを置く

`tomllib` のエラーから、最終的に4系統のPythonが見つかった。condaは `base` を自動で有効化し、ユーザーが気づかないままAgentがグローバル環境にパッケージを入れていた。python.orgのインストーラは `.zprofile` に自身のPATHを書き、Homebrewには別のPythonが残り、非対話型タスクではmacOS付属版が先に見つかることもあった。

Rustも2系統あった。Homebrewで入れたRustがPATHの先頭にあり、rustup管理のバージョンは長く更新されていなかった。Nodeの問題はnpm global prefixにあった。fnmでNodeのバージョンを切り替えると、npmのグローバルインストール先も変わる。だが古いClaude Codeのwrapperには、Homebrewのパスが固定されていた。実行の入口と更新の入口が別の場所を指し、コマンドは動くが正しい更新が届かない状態だった。

整理後、3つの主要ランタイムに、それぞれ唯一の管理主体を定めた。

| ランタイム  | 管理主体                                                   | 主な役割                                      |
| ------ | ------------------------------------------------------ | ----------------------------------------- |
| Node   | [fnm](https://github.com/Schniz/fnm)                   | Nodeのバージョン管理とプロジェクトごとの切り替え                |
| Python | [uv](https://docs.astral.sh/uv/guides/install-python/) | Pythonのインストール、プロジェクトのバージョン固定、環境作成、依存関係の管理 |
| Rust   | [rustup](https://rust-lang.github.io/rustup/)          | stable、beta、nightly、指定バージョン、コンポーネントの管理    |

システム付属のランタイムは残す。macOSに属するもので、普段のPATHには入れず、個人プロジェクトの依存関係を載せない。ほかのformulaの依存先としてHomebrewが入れた言語ランタイムも、内部依存として残してよい。ただし、ユーザーの入口を奪ってはならない。

Homebrewは、システムレベルのパッケージ、安定したCLI、GUIアプリ、下位の依存関係の管理に向いている。たとえば `ripgrep`、`jq`、`ffmpeg`、そしてfnmやuvといったバージョン管理ツール自体だ。現在の安定版だけでよく、プロジェクトごとの切り替えが不要なツールなら、Homebrewに任せるのが適している。

次の場面では、fnm、uv、rustupを直接使うべきだ。

1. 複数のプロジェクトで、異なるmajorまたはminorバージョンが必要。
2. バージョン指定ファイルで実行環境を固定する必要がある。
3. Rustでstable、beta、nightly、または特定の日付のツールチェーンが必要。
4. Nodeのグローバルパッケージのprefixが、バージョンによって変わる。
5. Pythonで、システムやグローバル環境を汚さず、プロジェクトの依存関係を分離したい。
6. Agent、定期タスク、非対話型shellが、同じ検証可能な入口を見つけなければならない。

ルールは単純だ。Homebrewはソフトウェアパッケージ、バージョン管理ツールは言語、プロジェクトのファイルはバージョンを管理する。PATHに出す標準の入口は1つだけにする。

古いランタイムを整理する前に、新しい管理主体を更新し、検証する。Rustでは、移行先でコンパイルテストを済ませてからHomebrewのRustを削除した。Pythonでは、uvの標準の入口がクリーンな環境で動くことを確かめてから、conda、python.org、Homebrewの重複を処理した。この順番にすれば、管理作業で現在の作業能力を壊さずに済む。

### 継続して管理する2つのroutines

Borisは、長時間動くAgentには自分の仕事を検証する能力が必要だと、繰り返し強調している。長いタスクなら、バックグラウンドのAgentに検証させてもよいし、Stop hookで決定的なチェックを行い、失敗した結果をAgentへ返して処理を続けさせてもよい。検証のフィードバックを結果の質を高める最も重要な手段の1つと捉え、経験上は2〜3倍の改善があるとしている。[元の投稿](https://x.com/bcherny/status/2007179861115511237)

その後、彼は働き方の変化を、ソースコードからAgentへ、Agentから継続して動くloopへと整理した。人の仕事も、毎回promptを書くことから、自力で前進する循環の設計へ変わる。[Meta @ScaleでのBorisとの対談](https://www.youtube.com/watch?v=Z47vatpsGPI)では、loopsも同じくらい重要な転換だと述べている。

有効なloopには、少なくとも明確な目標、現在の状態、検証のフィードバック、停止条件が要る。Agentは各回の実行後に結果を読み、検証に失敗すれば続け、目標達成か予算・リスクの境界に達したら止まる。Sweeperは継続して減らす方向を与え、Loop Engineeringはそれを繰り返し起こす。

私はClaudeに2つのroutinesを作り、これまでの管理原則を日常運用に落とし込んだ。

第一は、毎日のSkills管理だ。再利用可能なSkillはすべて、Git管理する同じ正本に置き、Claude CodeとCodexからシンボリックリンクで参照する。routineは切れたリンク、空のディレクトリ、不要なキャッシュ、欠けたリンクを自動修復する。実体のコピー、参照されないSkill、frontmatterのエラー、上流の更新、認証情報のリスクに出会ったら、分析と報告だけを行い、最終判断は私に残す。

第二は、毎週のMacの基礎資源管理だ。まずメモリ、CPU、swap、プロセスの状態を収集し、アプリの系列ごとに資源を集計し、確認済みの残留パターンを特定する。プロセス回収には、存続時間が閾値を超え、CPUがアイドルで、ネットワークソケットがないという3条件を同時に求める。キャッシュ整理は再構築できる内容だけを対象とし、アプリ固有のデータや所属不明の資源は測定と報告にとどめる。

両routinesは同じ境界を守る。情報を失わない確定的な操作はスクリプトが行い、判断が必要な項目はモデルが分析し、削除、上書き、権限拡大は人が担う。

各回の新しい発見は、Skill、reference、Basic Memoryへ書き戻す。次回は更新された正本を読むため、管理能力が蓄積されていく。

### 整理された状態を保つことは、エンジニアリングの能力である

以前、Macの環境設定は一度きりの仕事だと思っていた。ソフトを入れ、shellとプロキシを設定したら、使い始める。

今は変化の頻度がはるかに高い。Agentは依存関係を入れ、サービスを起動し、キャッシュを作り、Skillを生成し、設定を変える。Node、Python、Rustは更新され続け、デスクトップアプリとCLIには別々の更新経路があり、プロキシと認証も異なる起動経路を伝わる。

Macには、自身の制御系が必要だ。現在どんな重要資源があり、誰が管理し、目標状態は何か。ドリフトをどう見つけ、どの操作を自動化し、どの判断で止まるべきかを把握しなければならない。

Sweeperは、減らすことを担う。Loopは、減らすことを続けさせる。

短期的には新機能を生まない仕事だが、将来の実行ごとの不確実性を下げる。Agentが偶然古いバージョンを拾わなくなり、定期タスクとターミナルで同じ結果を得やすくなる。障害を具体的な環境の層へ素早く絞り込め、新しいツールも、どの入口につなぐべきか分かる。

Builderにとって、これは複利で効く基盤への投資だ。環境が安定するほど、Agent loopは長く動ける。管理主体が明確なほど、自動化に渡せる権限が増える。管理記録が充実するほど、次の調査で発見し直すことが減る。

これからの生産性は、より強いモデル、よりよいツール、そして長期にわたって説明でき、既知の状態へ戻せ、管理できるローカル環境から生まれる。

Builderは創造を担う。

Sweeperは、その創造が自身の残したものに足を取られないようにする。

### 参考資料

* [Claude Codeチームの5つの役割に関するBoris Chernyの元の投稿](https://x.com/bcherny/status/2071379474277613732)
* [長時間タスクと検証のフィードバックに関するBoris Chernyの元の投稿](https://x.com/bcherny/status/2007179861115511237)
* [Fireside Chat with Boris Cherny, Head of Claude Code](https://www.youtube.com/watch?v=Z47vatpsGPI)
* [Homebrew Formulae Versions](https://docs.brew.sh/Versions)
* [fnm（Fast Node Manager）](https://github.com/Schniz/fnm)
* [uvのPythonインストール・管理ドキュメント](https://docs.astral.sh/uv/guides/install-python/)
* [uvのPythonバージョンに関するドキュメント](https://docs.astral.sh/uv/concepts/python-versions/)
* [The rustup book](https://rust-lang.github.io/rustup/)
* [rustupのToolchainsドキュメント](https://rust-lang.github.io/rustup/concepts/toolchains.html)
