You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2026/09/17 07:35:49 UTC
(skywalking-ai-sessionizer) 01/02: Write a Homebrew formula for each install: asz and asz-claude-code
This is an automated email from the ASF dual-hosted git repository.
wu-sheng pushed a commit to branch homebrew-two-formulae
in repository https://gitbox.apache.org/repos/asf/skywalking-ai-sessionizer.git
commit bcaf902938d8c87d1fec3e00aace74d70de1d0d5
Author: Wu Sheng <wu...@foxmail.com>
AuthorDate: Thu Sep 17 14:59:46 2026 +0800
Write a Homebrew formula for each install: asz and asz-claude-code
The install pages have two installs, asz and the Claude Code plugin, and
the release wrote one formula, skywalking-ai-sessionizer, with both
binaries. It now writes asz.rb, which installs asz, and
asz-claude-code.rb, which installs asz-claude-plugin and whose caveats give
the two commands that install the plugin into Claude Code. From a tap,
that is brew install asz and brew install asz-claude-code.
Neither name is taken in homebrew-core or its casks, read on 2026-09-17.
Both formulae download the same package, which Homebrew caches once. In a
local tap they pass brew style and brew audit --strict.
---
docs/en/changes/changes.md | 5 +-
docs/en/guides/how-to-release.md | 20 +++---
docs/en/setup/install.md | 46 +++++++-------
tools/install-manifests.sh | 130 ++++++++++++++++++++++++++-------------
4 files changed, 126 insertions(+), 75 deletions(-)
diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index e0b2638..de25342 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -92,8 +92,9 @@
- **Each binary package holds `asz` and `asz-claude-plugin` side by side**, with `LICENSE`, `NOTICE`
and `licenses/`, and no `claude-code-plugin/` directory. `make build` writes both to `bin/`. The
package smoke test finds the plugin's binary by name on `PATH`. The candidate check in
- `tools/release.sh`, the Homebrew formula, and the Scoop and winget manifests follow the new
- layout, and put both binaries on the path.
+ `tools/release.sh`, and the Scoop and winget manifests follow the new layout, and put both
+ binaries on the path. The Homebrew formula becomes two, one for each install: `asz` and
+ `asz-claude-code`, so a tap gives `brew install asz` and `brew install asz-claude-code`.
- **Two install scripts, one for each install.** asz, the collector, and the Claude Code plugin are
installed apart. `install/asz.sh` and `install/asz.ps1` install `asz`, and
[Install](../setup/install.md#quick-install) runs them from the version's tag in one command. The
diff --git a/docs/en/guides/how-to-release.md b/docs/en/guides/how-to-release.md
index d66b0fe..1a9c648 100644
--- a/docs/en/guides/how-to-release.md
+++ b/docs/en/guides/how-to-release.md
@@ -917,23 +917,23 @@ are conveniences.
| File | Where it goes | What it downloads |
| --- | --- | --- |
-| `homebrew/skywalking-ai-sessionizer.rb` | a Homebrew tap | the macOS or Linux binary package, from the GitHub release, with archive.apache.org as its mirror |
+| `homebrew/asz.rb`, `homebrew/asz-claude-code.rb` | a Homebrew tap | the macOS or Linux binary package, from the GitHub release, with archive.apache.org as its mirror |
| `scoop/skywalking-ai-sessionizer.json` | a Scoop bucket | the Windows packages, from dlcdn.apache.org |
| `winget/manifests/a/Apache/SkyWalkingAISessionizer/$VERSION/` | microsoft/winget-pkgs | the Windows packages, from the GitHub release |
-The Homebrew formula installs the voted binary package for the machine: macOS or Linux, on ARM 64
-or x86-64. It names a URL, a mirror and a sha256 for each of the four packages. It builds nothing,
-so it needs no Go. It installs `asz` and `asz-claude-plugin` on the path, and `LICENSE`, `NOTICE`
-and `licenses/`, and its test runs both binaries. Its caveats give the two commands that install
-the plugin from the marketplace at the version's tag. It goes to a tap only.
-Homebrew/homebrew-core takes a formula only when it builds from source or installs output that is
-the same on every platform, and this formula installs a binary built for each platform.
+The two Homebrew formulae install from the voted binary package for the machine: macOS or Linux, on
+ARM 64 or x86-64. Each names a URL, a mirror and a sha256 for each of the four packages. They build
+nothing, so they need no Go. `asz` installs `asz`, and `asz-claude-code` installs
+`asz-claude-plugin`, whose caveats give the two commands that install the plugin into Claude Code.
+Each installs `LICENSE`, `NOTICE` and `licenses/`, and its test runs its binary. They go to a tap
+only. Homebrew/homebrew-core takes a formula only when it builds from source, and these install a
+binary built for each platform.
-Submit each file only after the version is on the download site. The Homebrew formula and the
+Submit each file only after the version is on the download site. The Homebrew formulae and the
winget files download from the GitHub release, which [Publish](#3-publish) promotes.
That URL keeps working after a newer version replaces this one on the download site.
archive.apache.org keeps every version too, but it slows down and then bans heavy use, and winget
-runs in scripts and on shared CI machines. The Homebrew formula names the archive as its mirror,
+runs in scripts and on shared CI machines. The Homebrew formulae name the archive as their mirror,
which Homebrew tries only when the GitHub URL fails. The archive can show a version later than the
download site does. A manifest that names a file that is not there yet fails its review.
`dist/$VERSION/install/README.md` checks every URL against its expected hash, and says how to test
diff --git a/docs/en/setup/install.md b/docs/en/setup/install.md
index 4e6cca8..389c2ce 100644
--- a/docs/en/setup/install.md
+++ b/docs/en/setup/install.md
@@ -178,34 +178,38 @@ KEYS, then run the same two `gpg` commands.
## Homebrew, on macOS and Linux
-**Available only once its formula is published after a release.** Until then, Homebrew does not
-know the package.
+**Available only once its formulae are published after a release.** Until then, Homebrew does not
+know them.
-Each release writes a formula from the voted binary packages, for macOS and Linux on ARM 64 and
-x86-64. The release manager submits it to a Homebrew tap, and this section will name the tap once
-the formula is published there. It does not go to homebrew-core, which takes only formulae that
-build from source or install output that is the same on every platform. This formula installs a
-binary built for each platform.
+Each release writes two formulae from the voted binary packages, for macOS and Linux on ARM 64 and
+x86-64, one for each install: `asz`, and `asz-claude-code`, the binary of the
+[Claude Code plugin](claude-code-plugin.md). The release manager submits them to a Homebrew tap,
+and this section will name the tap once they are published there. Once it is named:
-The formula downloads the binary package for your machine from the GitHub release of the version.
+```sh
+brew tap <owner>/<name>
+brew install asz
+brew install asz-claude-code
+```
+
+They do not go to homebrew-core, which takes only formulae that build from source, and which asks
+for more public interest than a new project has. These formulae install a binary built for each
+platform.
+
+Each formula downloads the binary package for your machine from the GitHub release of the version.
That release carries the voted packages, and its URL keeps working after a newer version comes
out. When GitHub fails, Homebrew takes the same package from archive.apache.org, which keeps every
version. Either way, Homebrew checks the download against the sha256 of the voted package. The
-formula builds nothing, so it needs no Go. It installs `asz` and `asz-claude-plugin` on your
-`PATH`, and `LICENSE`, `NOTICE` and `licenses/` at the root of the formula's prefix. Because it installs the binary package, `asz view` draws the page with the
+formulae build nothing, so they need no Go. `asz` installs `asz`, and `asz-claude-code` installs
+`asz-claude-plugin`, each on your `PATH`, with `LICENSE`, `NOTICE` and `licenses/` at the root of
+the formula's prefix. Because they install the binary package, `asz view` draws the page with the
renderer's fonts.
-Once the tap is named here, install by the formula's full name:
-
-```sh
-brew install <owner>/<tap>/skywalking-ai-sessionizer
-```
-
-Since Homebrew 6.0.0, a formula from a tap that is not Homebrew's own must be trusted before it is
-loaded. Installing by the full name trusts that one formula only. The formula's caveats, which
-`brew info skywalking-ai-sessionizer` prints again, give the two commands that install the plugin
-into Claude Code at the formula's version. [Claude Code Plugin](claude-code-plugin.md#install)
-gives the same commands.
+Homebrew asks you to trust a tap that is not its own before it loads its formulae. A formula
+cannot change your Claude Code configuration, so `asz-claude-code` does not install the plugin
+into Claude Code. Its caveats, which `brew info asz-claude-code` prints again, give the two commands
+that do, at the formula's version. [Claude Code Plugin](claude-code-plugin.md#by-hand) gives the
+same commands.
## Scoop, on Windows
diff --git a/tools/install-manifests.sh b/tools/install-manifests.sh
index dbced84..39ff00d 100755
--- a/tools/install-manifests.sh
+++ b/tools/install-manifests.sh
@@ -30,7 +30,8 @@
# match its .sha512.
# It writes into OUT_DIR:
#
-# homebrew/skywalking-ai-sessionizer.rb a formula that installs the macOS and Linux packages
+# homebrew/asz.rb a formula that installs asz from the macOS and Linux packages
+# homebrew/asz-claude-code.rb a formula that installs the Claude Code plugin's binary
# scoop/skywalking-ai-sessionizer.json a Scoop manifest for the Windows packages
# winget/manifests/a/Apache/SkyWalkingAISessionizer/VERSION/
# the three winget manifests
@@ -220,14 +221,12 @@ winget_dir=winget/manifests/a/Apache/SkyWalkingAISessionizer/$version
mkdir -p "$out_dir/homebrew" "$out_dir/scoop" "$out_dir/$winget_dir"
# ------------------------------------------------------------------ Homebrew
-fill > "$out_dir/homebrew/skywalking-ai-sessionizer.rb" <<'EOF'
-# Written by tools/install-manifests.sh in apache/skywalking-ai-sessionizer
-# from the voted binary packages of @VERSION@.
-class SkywalkingAiSessionizer < Formula
- desc "Conversation-level observability for long-lived AI agents"
- homepage "https://github.com/apache/skywalking-ai-sessionizer"
- license "Apache-2.0"
-
+# Two formulae, as the install pages have two installs: asz, the collector,
+# and asz-claude-code, the binary of the Claude Code plugin. A person who
+# runs only one of them installs only its binary. Both download the same
+# package, which Homebrew keeps once in its cache.
+homebrew_urls() {
+ cat <<'EOF'
# Each package comes from the GitHub release of v@VERSION@, which carries
# the voted files. Its URL keeps working after a newer version replaces
# this one on the download site. The mirror, archive.apache.org, keeps
@@ -258,11 +257,24 @@ class SkywalkingAiSessionizer < Formula
sha256 "@LINUX_AMD64_SHA256@"
end
end
+EOF
+}
+
+{
+ cat <<'EOF'
+# Written by tools/install-manifests.sh in apache/skywalking-ai-sessionizer
+# from the voted binary packages of @VERSION@.
+class Asz < Formula
+ desc "Conversation-level observability for long-lived AI agents"
+ homepage "https://github.com/apache/skywalking-ai-sessionizer"
+ license "Apache-2.0"
+
+EOF
+ homebrew_urls
+ cat <<'EOF'
def install
- # The Claude Code plugin's hooks run asz-claude-plugin by name, so it
- # goes on PATH beside asz.
- bin.install "asz", "asz-claude-plugin"
+ bin.install "asz"
# Homebrew keeps a formula's license files at the root of its prefix. It
# moves LICENSE and NOTICE there by itself, but not a directory, so
# licenses/ goes with them here. It holds the license of every module
@@ -270,27 +282,53 @@ class SkywalkingAiSessionizer < Formula
prefix.install "LICENSE", "NOTICE", "licenses"
end
+ test do
+ assert_match version.to_s, shell_output("#{bin}/asz version")
+ # glossary needs no configuration and no input, and its table names
+ # agent.call, so the program does real work, not only print its version.
+ assert_match "agent.call", shell_output("#{bin}/asz glossary")
+ end
+end
+EOF
+} | fill > "$out_dir/homebrew/asz.rb"
+
+{
+ cat <<'EOF'
+# Written by tools/install-manifests.sh in apache/skywalking-ai-sessionizer
+# from the voted binary packages of @VERSION@.
+class AszClaudeCode < Formula
+ desc "Claude Code plugin that records which files each tool call changed"
+ homepage "https://github.com/apache/skywalking-ai-sessionizer"
+ license "Apache-2.0"
+
+EOF
+ homebrew_urls
+ cat <<'EOF'
+
+ def install
+ # The plugin's hooks run asz-claude-plugin by name, so it goes on PATH.
+ bin.install "asz-claude-plugin"
+ prefix.install "LICENSE", "NOTICE", "licenses"
+ end
+
def caveats
- # The plugin comes from the marketplace at the tag of this version, so
- # its hooks are the ones this binary was released with.
+ # A formula cannot change the user's Claude Code configuration, so the
+ # plugin itself is installed by these commands. They add the marketplace
+ # at the tag of this version, so its hooks are the ones this binary was
+ # released with.
<<~EOS
- asz-claude-plugin, the binary of the Claude Code plugin that records
- which files each tool call changed, is on your PATH. To install the
- plugin itself into Claude Code:
+ asz-claude-plugin, the binary of the Claude Code plugin, is on your
+ PATH. To install the plugin itself into Claude Code:
claude plugin marketplace add "https://github.com/apache/skywalking-ai-sessionizer.git#v#{version}" --sparse .claude-plugin plugins/claude-code/plugin
claude plugin install asz-changes@skywalking-ai-sessionizer
- See:
- https://github.com/apache/skywalking-ai-sessionizer/blob/v#{version}/docs/en/setup/claude-code-plugin.md
+ To move an installed plugin to this version without losing the records
+ asz has not collected, see:
+ https://github.com/apache/skywalking-ai-sessionizer/blob/v#{version}/docs/en/setup/claude-code-plugin.md#upgrade
EOS
end
test do
- assert_match version.to_s, shell_output("#{bin}/asz version")
- # glossary needs no configuration and no input, and its table names
- # agent.call, so the program does real work, not only print its version.
- assert_match "agent.call", shell_output("#{bin}/asz glossary")
-
assert_match version.to_s, shell_output("#{bin}/asz-claude-plugin version")
# Claude Code names the plugin's data directory in CLAUDE_PLUGIN_DATA.
# status reads the settings there and compiles the exclusion rules. With
@@ -300,6 +338,7 @@ class SkywalkingAiSessionizer < Formula
end
end
EOF
+} | fill > "$out_dir/homebrew/asz-claude-code.rb"
# --------------------------------------------------------------------- Scoop
# The notes name the plugin's tag as VERSION for the reader to fill in. Scoop
@@ -448,14 +487,15 @@ create.
<https://downloads.apache.org/skywalking/ai-sessionizer/@VERSION@/>. The Homebrew formula and the
winget files also wait for the GitHub release of v@VERSION@, which `tools/release.sh publish`
promotes: <https://github.com/apache/skywalking-ai-sessionizer/releases/tag/v@VERSION@>.
-The Homebrew formula names the archive,
+The Homebrew formulae name the archive,
<https://archive.apache.org/dist/skywalking/ai-sessionizer/@VERSION@/>, as its mirror, and the
archive can show a new version later than the download site does. A manifest that names a file
that is not there yet fails its review, and it fails for everyone who installs it.
| File | Where it goes | What it downloads |
| --- | --- | --- |
-| `homebrew/skywalking-ai-sessionizer.rb` | `Formula/` in a tap | the macOS or Linux package, from the GitHub release, or else from archive.apache.org |
+| `homebrew/asz.rb` | `Formula/` in a tap | the macOS or Linux package, from the GitHub release, or else from archive.apache.org; installs `asz` |
+| `homebrew/asz-claude-code.rb` | `Formula/` in the same tap | the same package; installs `asz-claude-plugin`, and its caveats give the commands that install the plugin into Claude Code |
| `scoop/skywalking-ai-sessionizer.json` | `bucket/` in a Scoop bucket | the Windows package, from dlcdn.apache.org |
| `winget/manifests/a/Apache/SkyWalkingAISessionizer/@VERSION@/` | the same path in microsoft/winget-pkgs | the Windows package, from the GitHub release |
@@ -526,29 +566,35 @@ curl -fsSL https://github.com/apache/skywalking-ai-sessionizer/releases/download
## Homebrew
-Test the formula in a local tap. It downloads the package for your machine from the GitHub
+Test both formulae in a local tap. Each downloads the package for your machine from the GitHub
release, so this also checks that URL and its hash. The commands above check all four. `brew test`
-runs `asz version`, `asz glossary`, and the plugin's `version` and `status`.
+runs `asz version` and `asz glossary`, and the plugin's `version` and `status`.
```sh
brew tap-new --no-git "$USER/asz-test"
-cp homebrew/skywalking-ai-sessionizer.rb "$(brew --repository "$USER/asz-test")/Formula/"
-brew install "$USER/asz-test/skywalking-ai-sessionizer"
-brew test "$USER/asz-test/skywalking-ai-sessionizer"
-brew audit --strict --online --formula "$USER/asz-test/skywalking-ai-sessionizer"
-brew uninstall skywalking-ai-sessionizer
+cp homebrew/asz.rb homebrew/asz-claude-code.rb "$(brew --repository "$USER/asz-test")/Formula/"
+for f in asz asz-claude-code; do
+ brew install "$USER/asz-test/$f"
+ brew test "$USER/asz-test/$f"
+ brew audit --strict --online --formula "$USER/asz-test/$f"
+ brew uninstall "$f"
+done
brew untap "$USER/asz-test"
```
-Submit it by committing the file under `Formula/` in a tap, a GitHub repository named
-`homebrew-<name>`. People then run `brew install <owner>/<name>/skywalking-ai-sessionizer`.
-Homebrew asks people to trust a formula from a tap that is not its own, and installing by that
-full name trusts this one formula only.
+Submit them by committing both files under `Formula/` in a tap, a GitHub repository named
+`homebrew-<name>`. People then run `brew tap <owner>/<name>` once, and after it
+`brew install asz` and `brew install asz-claude-code`. Homebrew asks people to trust a tap that is
+not its own.
-Homebrew/homebrew-core does not take this formula. A formula there must build from source, or
-install output that runs on every platform, and this one installs a binary built for each
-platform. For a later version, run the script again on that version's voted packages and replace
-the file.
+Homebrew/homebrew-core does not take these formulae. A formula there must build from source, or
+install output that runs on every platform, and these install a binary built for each platform.
+Core also asks for public interest before it takes a new project. On 2026-09-17 its policy asked a
+GitHub project for 30 forks, 30 watchers or 75 stars, or three times that when the project submits
+itself, and for a repository at least 30 days old. Formulae of the same names that build from the
+source release could go there once the project qualifies, and the two commands would stay the
+same. For a later version, run the script again on that version's voted packages and replace the
+files.
## Scoop
@@ -605,7 +651,7 @@ if grep -rn '@[A-Z0-9_]*@' "$out_dir" >&2; then fail "a placeholder above was no
cat <<DONE
wrote the manifests for $version into $out_dir:
- homebrew/skywalking-ai-sessionizer.rb darwin and linux, arm64 and amd64, sha256
+ homebrew/asz.rb, asz-claude-code.rb darwin and linux, arm64 and amd64, sha256
scoop/skywalking-ai-sessionizer.json windows-amd64 and windows-arm64, sha512
$winget_dir/ schema $winget_schema, sha256
README.md