Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .beads/issues.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{"id":"ai-959","title":"analyze fit of spec-workflow-mcp","description":"https://github.com/Pimzino/spec-workflow-mcp\nalso 'claude-code-spec-workflow'\n","status":"open","priority":2,"issue_type":"task","owner":"36318507+aRustyDev@users.noreply.github.com","created_at":"2026-01-30T02:53:07.086543-05:00","created_by":"aRustyDev","updated_at":"2026-01-30T02:53:46.93047-05:00"}
{"id":"ai-aem","title":"add frontmatter scopes","description":"add scopes (user/project/component/etc) to each context file","status":"open","priority":2,"issue_type":"task","owner":"36318507+aRustyDev@users.noreply.github.com","created_at":"2026-01-30T02:16:52.824174-05:00","created_by":"aRustyDev","updated_at":"2026-01-30T02:16:52.824174-05:00"}
{"id":"ai-bt2","title":"add command namespacing in frontmatter","description":"use build time logic to remove illegal frontmatter keys\n\nOrganize commands in subdirectories. The subdirectories are used for organization and appear in the command description, but they do not affect the command name itself. The description will show whether the command comes from the project directory (`.claude/commands`) or the user-level directory (`~/.claude/commands`), along with the subdirectory name.\n\nConflicts between user and project level commands are not supported. Otherwise, multiple commands with the same base file name can coexist.\n\nFor example, a file at `.claude/commands/frontend/component.md` creates the command `/component` with description showing \"(project:frontend)\".\nMeanwhile, a file at `~/.claude/commands/component.md` creates the command `/component` with description showing \"(user)\".\n\n```yaml\n---\nallowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*)\nargument-hint: [message]\ndescription: Create a git commit\nmodel: claude-3-5-haiku-20241022\n---\n```\n","status":"open","priority":2,"issue_type":"task","owner":"36318507+aRustyDev@users.noreply.github.com","created_at":"2026-01-30T02:18:13.280099-05:00","created_by":"aRustyDev","updated_at":"2026-01-30T02:24:12.262077-05:00"}
{"id":"ai-exp","title":"question: is it a good pattern to use progressive disclosure in sub-agents?","status":"open","priority":2,"issue_type":"task","owner":"36318507+aRustyDev@users.noreply.github.com","created_at":"2026-01-30T02:31:30.657878-05:00","created_by":"aRustyDev","updated_at":"2026-01-30T02:31:30.657878-05:00"}
1 change: 1 addition & 0 deletions context/skills/pkgmgr-homebrew-formula-dev/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
18 changes: 18 additions & 0 deletions context/skills/pkgmgr-homebrew-formula-dev/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!--https://github.com/GongRzhe/JSON-MCP-Server-->
<!--https://lobehub.com/mcp/kehvinbehvin-json-mcp-filter-->
<!--https://lobehub.com/mcp/kehvinbehvin-json-mcp-->
<!--https://lobehub.com/mcp/buzdolapci-json-validate-->
<!--https://lobehub.com/mcp/gage-russell-jsonresume-mcp-->
<!--https://lobehub.com/mcp/buzdolapci-json-validate-->
<!--https://lobehub.com/mcp/gszecsenyi-schemavault-->
<!--https://lobehub.com/mcp/bablu-singh-json-mapping-and-context-mcp-server-->
<!--https://lobehub.com/mcp/semanticintent-semantic-context-mcp-->
<!--https://lobehub.com/mcp/5queezer-mcp-json-->
<!--https://lobehub.com/mcp/berrydev-ai-json-mcp-server-->
<!--https://lobehub.com/mcp/berrydev-ai-jq-mcp-server-->
<!--https://github.com/mgraczyk/json-query-mcp-->
<!--https://github.com/vadimnastoyashchy/json-mcp-->
<!--https://github.com/gongrzhe/json-mcp-server-->
<!--https://www.pulsemcp.com/servers/jeannier-homebrew-->
<!--https://www.pulsemcp.com/servers/tatn-unified-diff-generator-->
<!--https://www.pulsemcp.com/servers/benjamine-jsondiffpatch-->
172 changes: 172 additions & 0 deletions context/skills/pkgmgr-homebrew-formula-dev/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
name: pkgmgr-homebrew-formula-dev
description: Create, test, and maintain Homebrew formulas. Use when adding packages to a Homebrew tap, debugging formula issues, running brew audit/test, or automating version updates with livecheck. Use when creating a new Homebrew formula for a project.
---

# Homebrew Formula Development

Guide for researching, creating, testing, and maintaining Homebrew formulas in a custom tap.

## When to Use This Skill

- Creating a new Homebrew formula for a project
- Debugging formula build or test failures
- Running local validation before CI
- Understanding Homebrew's Ruby DSL
- Setting up livecheck for automatic version detection

## Template Pipeline

This skill includes a **JSON Schema → Mustache template** pipeline for generating formulas from structured data.

### Workflow

1. Create a JSON file conforming to `scripts/formula.schema.ts`
2. Run `just javascript-recipe <path-to-json>` to validate and render
3. The pipeline validates with AJV, preprocesses (PascalCase, language dispatch, license rendering), then renders via Mustache

### Key Files

| File | Purpose |
|------|---------|
| `scripts/formula.schema.ts` | JSON Schema (draft-2020-12) defining formula structure |
| `scripts/formula.helper.ts` | Preprocessing: PascalCase, license rendering, install flattening, partials loading |
| `reference/templates/main.mustache` | Main template — renders all shared fields, dispatches to language partials |
| `reference/templates/langs/*.mustache` | Language-specific install partials (go, rust, python, zig, cmake, autotools, meson) |
| `test/data/*.json` | Test fixtures covering each scenario |
| `test/cases/*.sh` | Test cases that validate rendered output |

### Running

```bash
# Render a formula from JSON
just javascript-recipe path/to/formula.json

# Run all tests
just test
```

### Adding a New Language

1. Add `install-<lang>` definition to `scripts/formula.schema.ts`
2. Add language dispatch `allOf` entry in the `formula` definition
3. Create `reference/templates/langs/<lang>.mustache` partial
4. Add `"<lang>"` to the `language` enum
5. Add a test fixture in `test/data/` and test case in `test/cases/`

## Research Phase

Before creating a formula, gather this information:

| Field | How to Find |
|-------|-------------|
| Latest version | `gh api repos/owner/repo/releases/latest --jq '.tag_name'` (404 → HEAD-only) |
| License | Check LICENSE file or repo metadata (use SPDX identifier) |
| Build system | Look at Makefile, go.mod, Cargo.toml, pyproject.toml, etc. |
| Dependencies | Check build docs, CI files, or dependency manifests |
| Default branch | Check repo settings — may be `main` or `master` |
| Binary name | May differ from formula name — check Cargo.toml `[[bin]]`, Go `cmd/`, or pyproject.toml `[project.scripts]` |

### Determine Formula Type

| Scenario | Type | Has `url`/`sha256`? | Has `livecheck`? |
|----------|------|---------------------|------------------|
| Tagged releases | Standard | Yes | Yes |
| No releases | HEAD-only | No | No |
| Monorepo subdirectory | Standard | Yes | Yes |

### Calculate SHA256

```bash
curl -sL "https://github.com/owner/repo/archive/refs/tags/vX.Y.Z.tar.gz" | shasum -a 256
```

### Formula Naming

- Formula name: **kebab-case** (`hex-patch`, `jwt-ui`)
- Class name: **PascalCase** (`HexPatch`, `JwtUi`)

## Formula Structure

### File Location

Formulas are organized alphabetically: `Formula/<first-letter>/<name>.rb`

### Key Elements

| Element | Purpose |
|---------|---------|
| `desc` | Short description (~80 chars) for `brew info` |
| `homepage` | Project homepage URL |
| `url` | Source tarball URL (omit for HEAD-only) |
| `sha256` | Checksum (omit for HEAD-only) |
| `license` | SPDX identifier |
| `head` | Git URL for `--HEAD` installs |
| `livecheck` | Auto-detect new versions (omit for HEAD-only) |
| `depends_on` | Build or runtime dependencies |
| `test` | Verification block |

### SPDX License Identifiers

| License | SPDX |
|---------|------|
| MIT | `"MIT"` |
| Apache 2.0 | `"Apache-2.0"` |
| GPL 3.0 (only) | `"GPL-3.0-only"` |
| GPL 3.0 (or later) | `"GPL-3.0-or-later"` |
| BSD 2-Clause | `"BSD-2-Clause"` |
| BSD 3-Clause | `"BSD-3-Clause"` |

Always specify `-only` or `-or-later` for GPL/LGPL/AGPL.

## Language-Specific Patterns

Each language has a reference doc with install patterns, schema fields, and common issues:

- **Go:** `reference/langs/go.md`
- **Rust:** `reference/langs/rust.md`
- **Python:** `reference/langs/python.md`

Additional languages supported by the template pipeline (cmake, autotools, meson, zig) — see their Mustache partials in `reference/templates/langs/`.

## Reference Materials

| Topic | Location |
|-------|----------|
| Local validation steps | `reference/checklists/local-validation.md` |
| Common issues & FAQ | `reference/faq/common.md` |
| Test block patterns | `reference/testing/patterns.md` |
| Generated formula examples | `reference/templates/formulas/*.rb` |
| JSON Schema definition | `scripts/formula.schema.ts` |
| Bottle attestation & provenance | `reference/security/attestation.md` |

## Batch Formula Creation

When creating many formulas at once:

1. **Compute SHA256 hashes in parallel** — launch multiple `curl | shasum` calls concurrently
2. **Research build details in parallel** — check build manifests concurrently
3. **Write all formula files** — no dependencies between them
4. **Create branches/PRs sequentially** — one branch per formula, each from main
5. **Use `ruby -c *.rb`** to syntax-check all formulas before pushing

## Checklist

- [ ] Research complete (version, license, build system, deps, binary name, default branch)
- [ ] Formula type determined (standard vs HEAD-only)
- [ ] SHA256 calculated (if not HEAD-only)
- [ ] Formula file created at `Formula/<letter>/<name>.rb`
- [ ] `ruby -c` passes
- [ ] `brew audit --new` passes
- [ ] `brew style arustydev/tap` passes
- [ ] `brew install --build-from-source` succeeds
- [ ] `brew test` passes
- [ ] Binary executes correctly
- [ ] PR created with CI passing

## References

- [Homebrew Formula Cookbook](https://docs.brew.sh/Formula-Cookbook)
- [SPDX License List](https://spdx.org/licenses/)
- [Homebrew Ruby Style Guide](https://docs.brew.sh/Ruby-Style-Guide)
- [Homebrew Python Guidelines](https://docs.brew.sh/Python-for-Formula-Authors)
33 changes: 33 additions & 0 deletions context/skills/pkgmgr-homebrew-formula-dev/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
- [ ] Zig support
- [ ] C/C++ support
- [ ] Java support
- [ ] Roc support
- [ ] Rust support
- [ ] Go support
- [ ] Python support
- [ ] TypeScript support
- [ ] Swift support
- [ ] Kotlin support
- [ ] Scala support
- [ ] Haskell support
- [ ] Lua support
- [ ] JavaScript support
- [ ] PHP support
- [ ] Ruby support
- [ ] Erlang support
- [ ] Elixir support
- [ ] Clojure support
- [ ] CSharp support
- [ ] Objective-C support
- [ ] FSharp support
- [ ] Fortran support
- [ ] Dart support
- [ ] Erlang support
- [ ] Gleam support
- [ ] Groovy support
- [ ] Scheme support
- [ ] OCaml support
- [ ] Perl support
- [ ] Nim support
- [ ] Julia support
- [ ] R support
58 changes: 58 additions & 0 deletions context/skills/pkgmgr-homebrew-formula-dev/justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
data := '{"formulas":[{"name":"Chris","role":"Developer"},{"name":"Anna","role":"Designer"}]}'

add-formula name:
echo "{{ kebabcase(name) }}"
echo "{{ uppercamelcase(name) }}"

[macos]
_deps:
brew bundle -f "{{ justfile_directory() }}/reference/Brewfile"
npm install


export PATH := "./node_modules/.bin:" + env('PATH')
export NODE_PATH := justfile_directory() + "/node_modules"

javascript-recipe json=data:
#!/usr/bin/env node
const Mustache = require('mustache');
const fs = require('fs');
const path = require('path');
const Ajv = require('ajv/dist/2020');

Mustache.escape = (text) => text;
const { SCHEMA } = require('{{ justfile_directory() }}/scripts/formula.schema.ts');
const { preprocessFormulas, loadPartials, parseInput } = require('{{ justfile_directory() }}/scripts/formula.helper.ts');
const baseDir = '{{ justfile_directory() }}/reference/templates';

const jsObject = JSON.parse(parseInput(`{{json}}`));
const ajv = new Ajv();
const validate = ajv.compile(SCHEMA);
if (!validate(jsObject)) {
console.error(JSON.stringify(validate.errors, null, 2));
process.exit(1);
}

const partials = loadPartials(path.join(baseDir, 'langs'));
preprocessFormulas(jsObject.formulas);

const main = fs.readFileSync(path.join(baseDir, 'main.mustache'), 'utf8');
console.log(Mustache.render(main, jsObject, partials));

test:
#!/usr/bin/env bash
set -euo pipefail
cd "{{ justfile_directory() }}"
passed=0
failed=0
for t in test/cases/test-*.sh; do
echo "--- Running $(basename "$t") ---"
if bash "$t"; then
passed=$((passed + 1))
else
failed=$((failed + 1))
fi
done
echo ""
echo "Results: $passed passed, $failed failed"
[ "$failed" -eq 0 ]
99 changes: 99 additions & 0 deletions context/skills/pkgmgr-homebrew-formula-dev/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading