9 ポイント 投稿者 GN⁺ 2025-09-18 | 2件のコメント | WhatsAppで共有
  • HomebrewはmacOSでCLIツールを簡単にインストール・管理できるパッケージマネージャーであり、開発者がよく使うツールを通じてシステム環境を効率よく構成できる
  • このガイドではHomebrewを使って個人のCLIスクリプトを配布する流れを説明し、GitHub連携と自動化ワークフローによって保守を簡素化する方法を示す
  • 配布プロセスはCLIの作成 → GitHubリリース → Tap作成 → Formula作成と更新という流れで進み、最終的にはbrew tapbrew installコマンドだけでインストールできる
  • Homebrewの用語体系ベストプラクティスを理解すれば、再現性とサプライチェーンセキュリティを強化した安定的な配布が可能になる
  • GitHub Actionsワークフローで自動化でき、一度設定すればその後ほかのCLIの配布も非常に簡単になる利点がある

背景と動機

  • HomebrewはCLIツールのインストール時に好まれるパッケージマネージャーで、多くの開発者に使われている
  • しかし、自作CLIはnpmやRubyGemで配布されることが多く、Homebrewでの配布方式は手順がなじみにくく感じられることがある
  • Homebrewの公式coreリポジトリでは自作ツールの登録にHomebrewチームが消極的な方針のため、一般開発者は別個のtapとformulaで配布する
  • 本ガイドはシンプルなRubyベースCLIの配布経験をもとに説明する

用語説明

  • Homebrewはビール醸造テーマを反映した独特の用語を使うため、これを理解するとシステム構造を把握しやすい
    • Formulaはパッケージ定義ファイルで、ソースコードやバイナリをインストールするための手順を含む
    • TapはFormula群のGitリポジトリで、ユーザー単位または組織単位でカスタムパッケージを管理する
    • CaskはGUIアプリや大型バイナリをインストールするためのマニフェストで、Formulaと似ているが事前ビルド済みファイルを扱う
    • Bottleはソースからビルドせず事前ビルド済みバイナリパッケージをコピーする形で、インストール速度を高める
    • Cellarはインストール済みFormulaが置かれるディレクトリで、たとえば/opt/homebrew/Cellarというパスを持つ
    • Kegは特定Formulaのインストールインスタンス用ディレクトリで、Cellar内にバージョンごとに配置される

概要

  • Homebrewのコアリポジトリはニッチなものや個人提出のコンテンツを受け付けないため、ユーザーは別途tapリポジトリを作ってCLIを配布する必要がある
    • 1. CLIを作成してGitHubに置き、タグ付きリリースを作る
    • 2. brew tap-newでTapを作成してGitHubにpushする
    • 3. brew createでFormulaを作成する(tarball URLとSHA256を含む)
    • 4. 新バージョンをリリースするたびにFormulaを更新し、ユーザーがbrew installコマンドで簡単にインストールできるようにする
  • 配布完了後、ユーザーは2つのコマンドでCLIをインストールできる: brew tap your_github_handle/tapbrew install your_cool_cli
    • このガイドではCLI開発そのものは省略し、tap作成、Formula作成、更新手順に焦点を当てる
    • 例として、iMessageデータベースからインタラクティブなWebアーカイブを作るimsg CLIを使う
    広告

tapの作成

  • Homebrewのtap作成ガイドに従い、GitHubのユーザー名や組織名に置き換えて設定する
    • 今後すべてのCLIツールを1つのtapにまとめるため、名前はhomebrew-tapを推奨する。homebrew接頭辞はCLIで特別扱いされ、tap接頭辞は慣習的である
  • tap作成コマンドを実行: brew tap-new searlsco/homebrew-tap
    • これにより/opt/homebrew/Library/Taps/searlsco/homebrew-tapにスキャフォールドが生成される
    • 対応するGitHubリポジトリを作成し、生成された内容をpushする: cd /opt/homebrew/Library/Taps/searlsco/homebrew-tap, git remote add origin git@github.com:searlsco/homebrew-tap.git, git push -u origin main
  • tapを所有した後は、ほかのユーザーがbrew tap searlsco/tapコマンドでそのリポジトリをクローンし、/opt/homebrew/Library/Tapsに配置できる
    • 初期状態では有用な内容はないが、基本動作は確認できる

Formulaの作成

  • HomebrewはGitHubリポジトリを直接参照できるが、バージョン付きtarballとチェックサムの使用を推奨しており、再現性とオープンソースのサプライチェーンセキュリティを強化できる
    広告
  • Formula作成コマンド: brew create https://github.com/searlsco/imsg/archive/refs/tags/v0.0.5.tar.gz --tap searlsco/homebrew-tap --set-name imsg --ruby
    • --tapフラグはカスタムtapを指定し、Formulaを/opt/homebrew/Library/Taps/searlsco/homebrew-tap/Formulaに配置する
    • --set-name imsgはFormula名を明示的に設定するもので、名前の重複を避けるためユニークに選ぶべきである(例: 既存のTLDRやstandard CLIとの衝突に注意)
    • --rubyはRuby CLI向けのテンプレートプリセットで、カスタマイズを簡素化する複数オプションの1つである
  • 生成されたFormulaは最初は動かないことがあるため、LLMを活用して修正する: brew install --verbose imsgを実行し、エラーをChatGPTに入力してFormula更新を繰り返す
    • 最終的なFormula/imsg.rbファイルは、Ruby CLI配布の出発点としてコピー可能
    • 言語固有のパッケージマネージャーではなくHomebrew経由で配布すれば、実装言語を変更してもユーザーのアップグレードは円滑に行える

Formulaの主なポイント

  • すべてのFormulaはRubyで書かれている。これはJavaScriptやAI以前に人気だった開発ツールの多くがRubyベースだったためである
    • headメソッドでGitリポジトリを指定できるが、実際の効果は不明
    • livecheckを追加するとFormulaのバージョン更新が容易になり、価値がある
    • バイナリ実行テストはヘルプ出力の確認で簡単に実装でき、生成されたコメントに気後れする必要はない
    • brew style searlsco/tapコマンドでスタイルエラーを確認できる
    • --rubyテンプレートのデフォルトであるuses_from_macos "ruby"は2.6.10版(COVID以前のリリースで、3年前にEOL)を使うため、depends_on "ruby@3"で最新のruby Formulaへの依存を推奨する
  • Formulaに満足できたらgit pushで本番配布し、ユーザーはbrew tap searlsco/tapbrew install imsgでインストールできる
広告

各CLIリリースごとのFormula更新

  • Formula先頭のurlsha256ハッシュをリリースごとに手動更新するのは面倒で、タグのpushやGitHubリリース作成ですら負担だと指摘している
    • Homebrewのbump-formula-prコマンドやGitHub ActionsでPRを作ることもできるが、forkとPRのプロセスは不必要に複雑
    • tapの所有者であれば、mainブランチへ直接コミットする簡単な方法が望ましい
  • これを避けるため、FormulaリポジトリにGitHubワークフローを追加し、リリース時にtapを自動更新することを推奨する
    • ワークフロー例をコピーして使える
    • 設定が必要: GitHub個人アクセストークン(PAT)を作成する際、homebrew-tapリポジトリにContentWrite権限を付与し、FormulaリポジトリのSecretsにHOMEBREW_TAP_TOKENとして保存する
    • 環境変数でtapとFormulaを指定する(例: 13〜15行目)
    • GitHubボットアカウントでの更新を推奨: GH_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com, GH_NAME: github-actions[bot]
  • リリース作成後にgit push --tagsを実行すれば、数秒以内に自動更新され、ユーザーはbrew updatebrew upgrade imsgでアップグレードできる

いちばん良い点

  • このプロセスは複雑だが、tapの設定と1つのFormula例が完成すれば、追加のCLI配布はほぼ些細な作業になる
    • 数分で新しいFormulaを公開できて便利
  • Homebrewの公式プロセスはやや複雑だが、自動化によって楽になる
    • 各ツールのリリースから配布までの煩雑さを減らし、さまざまな言語のCLIにも拡張して対応できる
  • 実際に別のFormulaを公開するかは未定だが、その可能性が開けたことに満足している

2件のコメント

 
lamanus 2025-09-18

Homebrew の bump-formula-pr コマンドや GitHub Actions で PR を作成できますが、fork と PR のプロセスが不必要に複雑です。

--no-fork オプションがあるため、ブランチを直接 push してマージでき、自動更新機能も提供しています。

 
GN⁺ 2025-09-18
Hacker Newsのコメント
  • Homebrewの命名規則は時々ややこしく感じることもあるが、全体として本当に便利なツールだと改めて感じている。
    また、自分のtapを作ってツールを配布する手順が、こんなに簡単だとは思わなかった。
    言語ごとのパッケージマネージャー(例: uv)と比べて、どんな点が優れているのか気になる。
    特に、特定のエコシステムに属していない人にとってより簡単なのか、つまり汎用性の面で優位があるのか知りたい。

    • 感謝を伝えるとともに、パッケージレジストリを使う他のツールはたいていアカウント作成、2段階認証、署名プロセスなどが必要になる。
      HomebrewではGitHubの利用規約(ToS)が信頼の基盤として機能するため、全体的にずっと簡素化されている。
      Homebrewチームもこの方式のおかげで多くの複雑さを減らせている。

    • Pythonパッケージの観点で言うと、uvのようにすべてを一度にパッケージ化しようとする試みは、現実的には難しい。
      そのため、一般的にはvenv環境に固定された依存関係だけをインストールする方式が使われる。
      具体例としてはこのformulaを参照できる。
      uvについては、公式ツール(brew update-python-resources, homebrew-pypi-poet)でプライベートパッケージをサポートしようとしたがうまくいかなかったため、
      自分でuvbrewを作ってリソース生成を支援するようにした。
      HomebrewでPython formulaを書く際の参考として公式ドキュメントがある。

  • Go開発者ならGoreleaserというツールをおすすめする。
    個人tap内でバイナリ配布をとても簡単にしてくれる(公式coreでは禁止されている方式)。

    • 最近知ったのだが、Goreleaserは今ではGoだけでなくRust、TypeScript、Python、Zigなど複数の言語をサポートしている。
      各言語のプロジェクト管理で活用しやすい。
  • 個人的には、tap側で直接アップデートを管理するほうがより理想的だと思う。
    一般的なupstreamでの更新方式に近い。
    このワークフローを参考にすれば、自分が所有していないformula/caskも簡単に更新できる。
    brew bumpコマンドですべてをスキャンし、PRを作成しつつbrew test-botでテストまで自動化できる。
    実際のPR例はこちらで確認できる。

    • いいアイデアだと思う。
      普段はGitHub Actionsの利用時間が気になってなかなか手が出なかったが、オープンソースなら無料なので、こういう使い方も良さそうだ。
  • 自分のHomebrew tap向けのバージョン自動bumpワークフローとして、homebrew-bump-revisionを自作してみた。
    複数の個人プロジェクトでうまく使っている。

    • すごく良さそうだと思う。
      自分は面倒で試していないが、いいツールだ。
  • Ruby Roguesポッドキャストで、HomebrewでCLIを配布するときのさまざまなコツを扱ったエピソードがあった。
    関連エピソードのリンクでさらに詳しく聞ける。

  • Pythonツールのパッケージングについて興味深い点を見つけた。
    一部のPythonパッケージはビルド過程で依存関係ループが発生し、Homebrewと互換性がない場合がある。
    pipはバイナリリリースをダウンロードするので問題ないが、Homebrewは依存関係まですべて自前でビルドするため、この工程にはずっと時間がかかる。
    そのため、中規模のPythonプロジェクトでも"bottle"ビルドに1時間以上かかることがある。

  • システム管理のためにnixを使い始めて以来、一度も後悔したことはない。
    唯一惜しいのは、マルチプレイヤーゲームのためにWindowsへ依存しなければならない点だけだ。