Multi-Formula Coordinator
Coordinate releases across multiple Homebrew formulas, respecting dependency order and handling batch updates.
Surface scope: Homebrew installs plugins to the Claude Code CLI surface (
~/.claude/). Claude Desktop (DXT/MCPB extensions — a different, MCP-server format) and Cowork are separate surfaces; seedist-extrasandcommands/dist/surfaces.mdfor the full model.
Use Cases
- Monorepo Releases - Multiple packages from one repository
- Ecosystem Releases - Related packages with dependencies (e.g., rforge ecosystem)
- Batch Updates - Update multiple formulas in one PR
- Dependency Chains - Release in correct order when packages depend on each other
Dependency Detection
Formula Dependencies
# In myapp-cli.rb
depends_on "myapp-core" # Runtime dependency
# In myapp-plugin.rb
depends_on "myapp-cli" # Also depends on cli
Build Order
myapp-core → myapp-cli → myapp-plugin
↓ ↓
└──────────────┴──────→ (can release in parallel after core)
Workflow: Batch Release
Input Manifest
Create .homebrew-batch.yml:
# Batch release configuration
tap: data-wise/tap
auto_merge: true
formulas:
- name: myapp-core
version: "2.0.0"
source: github
- name: myapp-cli
version: "2.0.0"
source: github
depends_on:
- myapp-core
- name: myapp-plugin
version: "1.5.0"
source: pypi
depends_on:
- myapp-cli
Execution Order
Step 1: Build dependency graph
────────────────────────────────
myapp-core (no deps) → Level 0
myapp-cli (deps: core) → Level 1
myapp-plugin (deps: cli) → Level 2
Step 2: Release in waves
────────────────────────────────
Wave 0: myapp-core
✓ Updated formula
✓ PR created: #42
✓ Auto-merged
Wave 1: myapp-cli
⏳ Waiting for Wave 0...
✓ Updated formula
✓ PR created: #43
✓ Auto-merged
Wave 2: myapp-plugin
⏳ Waiting for Wave 1...
✓ Updated formula
✓ PR created: #44
✓ Auto-merged
Step 3: Summary
────────────────────────────────
✓ 3 formulas updated
✓ 3 PRs merged
⏱ Total time: 4m 23s
GitHub Actions Workflow
Reusable Batch Workflow
Note — illustrative pattern, not yet in the tap.
batch-update.ymland the./.github/actions/update-formulacomposite action below are a design sketch for coordinated multi-formula releases; they do not currently exist inData-Wise/homebrew-tap. What the tap actually ships today is.github/workflows/update-formula.yml— a single-formula reusable workflow (seehomebrew-workflow-expert). To release several formulas now, call that single-formula workflow once per formula. Build the batch workflow below only if/when true batch orchestration is needed.
# homebrew-tap/.github/workflows/batch-update.yml (illustrative — not present in tap)
name: Batch Formula Update
on:
workflow_call:
inputs:
formulas:
required: true
type: string
description: 'JSON array of {name, version, sha256, source_type}'
auto_merge:
required: false
type: boolean
default: true
secrets:
tap_token:
required: true
jobs:
parse:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.parse.outputs.matrix }}
order: ${{ steps.parse.outputs.order }}
steps:
- name: Parse formulas and build order
id: parse
run: |
echo '${{ inputs.formulas }}' | jq -r '
# Build dependency graph
def toposort:
# ... topological sort implementation
;
toposort | @json
' > order.json
echo "order=$(cat order.json)" >> $GITHUB_OUTPUT
update:
needs: parse
runs-on: ubuntu-latest
strategy:
max-parallel: 1 # Sequential for dependency order
matrix:
formula: ${{ fromJson(needs.parse.outputs.order) }}
steps:
- name: Wait for dependencies
if: matrix.formula.depends_on
run: |
for dep in ${{ join(matrix.formula.depends_on, ' ') }}; do
echo "Waiting for $dep to complete..."
# Poll for PR merge status
done
- name: Update formula
uses: ./.github/actions/update-formula
with:
formula_name: ${{ matrix.formula.name }}
version: ${{ matrix.formula.version }}
sha256: ${{ matrix.formula.sha256 }}
source_type: ${{ matrix.formula.source_type }}
auto_merge: ${{ inputs.auto_merge }}
Caller Workflow
# In project repo
name: Release Ecosystem
on:
workflow_dispatch:
inputs:
core_version:
description: 'Core version'
required: true
cli_version:
description: 'CLI version'
required: true
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
formulas: ${{ steps.build.outputs.formulas }}
steps:
- name: Calculate SHA256s
id: sha
run: |
CORE_SHA=$(curl -sL "https://github.com/.../v${{ inputs.core_version }}.tar.gz" | shasum -a 256 | cut -d' ' -f1)
CLI_SHA=$(curl -sL "https://github.com/.../v${{ inputs.cli_version }}.tar.gz" | shasum -a 256 | cut -d' ' -f1)
echo "core_sha=$CORE_SHA" >> $GITHUB_OUTPUT
echo "cli_sha=$CLI_SHA" >> $GITHUB_OUTPUT
- name: Build formula list
id: build
run: |
echo 'formulas=[
{"name":"myapp-core","version":"${{ inputs.core_version }}","sha256":"${{ steps.sha.outputs.core_sha }}","source_type":"github"},
{"name":"myapp-cli","version":"${{ inputs.cli_version }}","sha256":"${{ steps.sha.outputs.cli_sha }}","source_type":"github","depends_on":["myapp-core"]}
]' >> $GITHUB_OUTPUT
release:
needs: prepare
uses: data-wise/homebrew-tap/.github/workflows/batch-update.yml@main
with:
formulas: ${{ needs.prepare.outputs.formulas }}
auto_merge: true
secrets:
# Preferred: GitHub App token (see homebrew-workflow-expert). PAT is a fallback.
app_id: ${{ secrets.APP_ID }}
app_private_key: ${{ secrets.APP_PRIVATE_KEY }}
CLI Command
Usage
# Multi-formula coordination workflow:
/craft:dist:homebrew deps # Show dependency order
/craft:dist:homebrew audit --all # Validate all formulas
# Then release in dependency order using /release per-project
Interactive Flow
╔═══════════════════════════════════════════════════════════════╗
║ MULTI-FORMULA RELEASE ║
╠═══════════════════════════════════════════════════════════════╣
║ ║
║ Detected formulas in Data-Wise/homebrew-tap: ║
║ ║
║ [ ] aiterm (v0.3.8) ║
║ [ ] atlas (v1.2.0) ║
║ [x] flow-cli (v2.1.0) → v2.2.0 ║
║ [x] nexus-cli (v0.5.0) → v0.6.0 ║
║ [ ] mcp-bridge (v0.1.0) ║
║ [ ] scribe-cli (v1.0.0) ║
║ ║
║ Selected: 2 formulas ║
║ Dependencies: None detected ║
║ ║
║ Release order: ║
║ 1. flow-cli ║
║ 2. nexus-cli (parallel OK) ║
║ ║
║ [Continue] [Edit Selection] [Cancel] ║
║ ║
╚═══════════════════════════════════════════════════════════════╝
Dependency Graph Visualization
Generate Mermaid diagram of formula dependencies:
/craft:dist:homebrew deps --mermaid
Output:
flowchart LR
subgraph "Data-Wise Tap"
aiterm
atlas
flow-cli
nexus-cli
mcp-bridge
scribe-cli
end
subgraph "System Dependencies"
python@3.12
node
rust
end
aiterm --> python@3.12
atlas --> python@3.12
nexus-cli --> python@3.12
mcp-bridge --> node
scribe-cli --> rust
Error Handling
Dependency Failure
Error: myapp-cli release failed
Dependency chain affected:
✗ myapp-cli (failed)
⏸ myapp-plugin (skipped - depends on cli)
Options:
1. Retry myapp-cli release
2. Skip myapp-cli, continue with others
3. Abort batch release
Choice: _
Version Conflict
Warning: Version mismatch detected
myapp-cli v2.0.0 depends on myapp-core >= 2.0.0
But myapp-core in batch is v1.9.0
Options:
1. Update myapp-core version to 2.0.0
2. Lower myapp-cli dependency requirement
3. Abort
Choice: _
Integration
| Command | Purpose |
|---|---|
/craft:dist:homebrew deps |
Show dependency graph |
/craft:dist:homebrew audit --all |
Validate all formulas |
Best Practices
- Test Dependencies First - Run
brew install --build-from-sourcefor base packages - Use Semantic Versioning - Makes dependency resolution predictable
- Pin Major Versions -
depends_on "myapp-core" => "~> 2.0" - Batch Related Releases - Release ecosystem packages together
- Auto-merge for Speed - Safe for personal taps with CI validation