@@ -69,6 +69,10 @@ token count, plus overall metadata usage. I've used and tested them most with
with restricted tool access for parallel tasks across repositories. Requires
[synu] and the `claude` CLI. Useful for summarizing git history or processing
large diffs without filling the main context window.
+- [maintaining-aur-packages](skills/maintaining-aur-packages/SKILL.md): Creates
+ and updates AUR packages following Arch packaging standards. Covers PKGBUILDs
+ for source, `-bin`, and `-git` package types, checksums with `updpkgsums`,
+ linting with `namcap`, and `.SRCINFO` generation.
- [managing-and-navigating-worktrees](skills/managing-and-navigating-worktrees/SKILL.md):
Manages git worktrees using [wt] with a bare repository structure. Each branch
lives in its own sibling directory. Requires [wt], git, and [gum].
@@ -389,6 +393,17 @@ Token breakdown:
βββββββββββββββββββββββββββββββββββββββββββββββ
Total: 277 tokens
+=== maintaining-aur-packages ===
+
+Token breakdown:
+ Name: 9 tokens
+ Description: 58 tokens
+ Body: 1439 tokens (103 lines)
+ References:
+ build-patterns.md 1120 tokens
+ βββββββββββββββββββββββββββββββββββββββββββββββ
+ Total: 2626 tokens
+
=== managing-and-navigating-worktrees ===
Token breakdown:
@@ -550,10 +565,10 @@ Token breakdown:
SUMMARY
============================================================
-Skills: 29
-Metadata: 1770 tokens
-Combined bodies: 30123 tokens
-Overall: 84275 tokens
+Skills: 30
+Metadata: 1837 tokens
+Combined bodies: 31562 tokens
+Overall: 86901 tokens
Validation errors: 0
Largest skills (by total tokens):
@@ -0,0 +1,108 @@
+---
+name: maintaining-aur-packages
+description: Creates and updates AUR packages following Arch packaging standards. Use when creating new AUR packages, updating existing AUR PKGBUILDs, bumping package versions, or when the user mentions AUR, PKGBUILD, makepkg, pacman packaging, or Arch Linux packages.
+---
+
+## Code style
+
+- PKGBUILD is bash; `.install` files are POSIX-shβcompatible functions
+- Indent 2 spaces; UTF-8; LF endings; no trailing whitespace
+- Single quotes for literals; double quotes when expanding variables
+- Quote variables: `"$pkgdir"`, `"$srcdir"`, and all paths
+- Prefix custom PKGBUILD variables with `_` to avoid collisions with makepkg internals
+- Arrays: `arch`, `license`, `provides`, `conflicts` use `( ... )` syntax
+- `arch=('x86_64')` for compiled packages; `arch=('any')` for arch-independent ones
+- `license=()` must use [SPDX identifiers](https://spdx.org/licenses/)
+- Functions: `prepare()`, `build()`, `check()`, `package()`; only define the ones needed
+- No `sudo`, networking, or user config in `build`/`package` functions
+- Use `install -Dm755` for binaries; set exact modes explicitly
+- Keep checksums in sync with sources
+- Keep `.SRCINFO` in lockstep with PKGBUILD; never commit build artifacts
+
+## Package types
+
+When the working directory contains subdirectories with these suffixes, we're maintaining multiple packages for the same software:
+
+- **suffix-less**: Downloads a release archive, builds, and installs from source
+- **`-bin`**: Downloads the project's pre-built binary and installs it
+- **`-git`**: Clones the primary branch and builds from source; version is determined by `updpkgsums`, not specified manually
+
+If no subdirectories exist, we're maintaining a single package. The current directory name indicates which type.
+
+## Constraints
+
+- The agent **cannot run `makepkg`**. Always give the user a copyable code block of `makepkg` commands instead.
+- Same applies to `makepkg --printsrcinfo > .SRCINFO`.
+- Use `updpkgsums` for checksums (agent can run this).
+- Use `namcap` to lint built `.pkg.tar.zst` files (agent can run this).
+- Use `b2sums` for all packages.
+
+## Creating packages
+
+Follow this strict workflow. If a planning or todo tool is available, fill it
+out in detail; the session might get interrupted and need to resume.
+
+1. List the contents of the current working directory.
+ - Read any text files present.
+ - List subdirectory contents (ignore what looks like the upstream project repo).
+ - Subdirectories with `-bin` or `-git` suffixes mean multiple packages for the same software.
+
+2. Ask for: package name (`provides=`), description (`pkgdesc=`), license (`license=()`), and the license path inside the project repo (for `install`ing). For each non-`-git` package, ask for the current version and source URL.
+ - **`-git` packages**: Use `"$pkgname::git+https://...#branch=BRANCH"` as the source entry (the `$pkgname::` prefix ensures makepkg clones into a directory matching `$pkgname`; the `#branch=` fragment selects the branch). Add `git` to `makedepends`. Use `b2sums=('SKIP')` β VCS sources have no static content to checksum. Include this versioning function:
+ ```bash
+ pkgver() {
+ cd "$pkgname" || exit
+ ( set -o pipefail
+ git describe --long --abbrev=7 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g' ||
+ printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short=7 HEAD)"
+ )
+ }
+ ```
+ - **`-bin` packages**: Use `bin-name-$pkgver::https://...` in `source`, then `install` `bin-name-$pkgver` as `bin-name`. Obtain the license from the original repo. For GitHub sources, the raw URL is `https://raw.githubusercontent.com/USER/REPO/refs/tags/{TAG}/LICENSE`. For non-GitHub sources, ask for the raw tagged LICENSE URL.
+
+3. Write a `PKGBUILD` for each package. `Maintainer` comment: `Amolith <amolith@secluded.site>`. If multiple packages, include `conflicts=()` so they can't coexist. Packages with `-git` or `-bin` suffixes use versioned provides: `provides=("pkgname=${pkgver}")`. Use `b2sums` (except `-git` sources, which use `'SKIP'`).
+
+4. Ask to find and relay the build system/installation methods recommended by the project (e.g. `cargo` for Rust, `go` for Go).
+
+5. Adapt those instructions for each package's `build()`, `check()`, `package()`, etc. See [build-patterns.md](references/build-patterns.md) for language-specific templates.
+
+6. Present **all** diagnostics, whether seemingly relevant or not, with reasoning for each. Resolve genuine issues before proceeding.
+
+7. Update checksums with `updpkgsums` in each package directory.
+
+8. Give the user a copyable code block of `makepkg -Ccsi` commands. Include `cd` if multiple packages. Work through any build issues.
+
+9. After the user builds, run `namcap` on `./package-name-*.pkg.tar.zst`. Report all issues with reasoning.
+
+10. Give the user `makepkg --printsrcinfo > .SRCINFO` commands (with `cd` if multiple packages).
+
+11. If only PKGBUILDs and `.SRCINFO`s were created, enter each package directory and `git add` + `git commit` them. If other tracked files were modified, show the diff and ask which to commit. Create a `.gitignore` in each repo listing everything not committed, using appropriate globs.
+
+12. Clean all artifacts with `git clean -fdx`.
+
+## Updating packages
+
+Follow this strict workflow.
+
+1. List the contents of the current working directory.
+ - Read any text files present.
+ - List subdirectory contents (ignore what looks like the upstream project repo).
+ - Subdirectories with `-bin` or `-git` suffixes mean multiple packages.
+
+2. We're upgrading to version `$VERSION`. Read the PKGBUILD(s), then edit the version number for non-`-git` packages.
+
+3. Update checksums with `updpkgsums`.
+
+4. Present **all** diagnostics with reasoning. Resolve genuine issues before proceeding.
+
+5. Give the user a copyable code block of `makepkg -Ccsi` commands. Include `cd` if multiple packages. Work through any build issues.
+
+6. After the user builds, run `namcap` on `./package-name-*.pkg.tar.zst`. Report all issues with reasoning.
+
+7. Give the user `makepkg --printsrcinfo > .SRCINFO` commands.
+
+8. If only `PKGBUILD` and `.SRCINFO` were modified, `git add` and `git commit` them. If other tracked files were modified, show the diff and ask which to commit.
+
+9. Clean all artifacts with `git clean -fdx`.
+
+If anything other than `pkgver` is edited during the update, re-run `shellcheck` and `namcap` as appropriate.
@@ -0,0 +1,186 @@
+# Build Patterns
+
+Language-specific templates for AUR packages. These templates use
+`cd "${pkgname}-${pkgver}"`, which suits suffix-less and `-bin` packages. For
+`-git` packages, use `cd "$pkgname"` instead (the source entry
+`"$pkgname::git+..."` clones into `$pkgname`).
+
+Based on the Arch Wiki's
+[Go](https://wiki.archlinux.org/title/Go_package_guidelines) and
+[Rust](https://wiki.archlinux.org/title/Rust_package_guidelines) package
+guidelines.
+
+## Go
+
+`makedepends=('go')`
+
+### Module caching
+
+Keep Go modules in the build environment rather than polluting `~/go`:
+
+```bash
+prepare() {
+ cd "${pkgname}-${pkgver}"
+ mkdir -p build/
+ export GOPATH="${srcdir}"
+ go mod download -modcacherw
+}
+```
+
+If upstream lacks `go.mod`, initialise it before downloading (file an issue upstream):
+
+```bash
+prepare() {
+ cd "$pkgname-$pkgver"
+ go mod init "${url#https://}"
+ go mod tidy
+}
+```
+
+### Building
+
+The standard approach exports CGO flags and uses `GOFLAGS`:
+
+```bash
+build() {
+ cd "${pkgname}-${pkgver}"
+ export CGO_CPPFLAGS="${CPPFLAGS}"
+ export CGO_CFLAGS="${CFLAGS}"
+ export CGO_CXXFLAGS="${CXXFLAGS}"
+ export CGO_LDFLAGS="${LDFLAGS}"
+ export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"
+ go build -o build .
+}
+```
+
+When upstream embeds version info via `-ldflags`, pass flags explicitly instead:
+
+```bash
+build() {
+ cd "${pkgname}-${pkgver}"
+ export CGO_CPPFLAGS="${CPPFLAGS}"
+ export CGO_CFLAGS="${CFLAGS}"
+ export CGO_CXXFLAGS="${CXXFLAGS}"
+ export CGO_LDFLAGS="${LDFLAGS}"
+ go build \
+ -trimpath \
+ -buildmode=pie \
+ -mod=readonly \
+ -modcacherw \
+ -o build/"$pkgname" \
+ -ldflags "-linkmode external -extldflags \"${LDFLAGS}\"" \
+ .
+}
+```
+
+Use `-o build` with a `mkdir -p build/` in `prepare()` to control output
+location. For projects with multiple binaries: `go build -o build ./cmd/...`
+
+If upstream uses a Makefile, verify it passes hardening flags β many overwrite
+`GOFLAGS`. Bypass the Makefile if needed and invoke `go build` directly.
+
+### Testing and packaging
+
+```bash
+check() {
+ cd "${pkgname}-${pkgver}"
+ go test ./...
+}
+
+package() {
+ cd "${pkgname}-${pkgver}"
+ install -Dm755 build/"$pkgname" "$pkgdir"/usr/bin/"$pkgname"
+}
+```
+
+### FULL RELRO
+
+If `namcap` reports `ELF file lacks FULL RELRO`, add `-bindnow` to ldflags
+(requires Go β₯ 1.23):
+
+```bash
+-ldflags "-linkmode external -extldflags \"${LDFLAGS}\" -bindnow"
+```
+
+Or in the `GOFLAGS` style:
+
+```bash
+export GOFLAGS="-buildmode=pie -trimpath -ldflags='-linkmode=external -bindnow' -mod=readonly -modcacherw"
+```
+
+### Vendored dependencies
+
+If upstream ships a `vendor/` directory with `modules.txt`, change
+`-mod=readonly` to `-mod=vendor`.
+
+## Rust
+
+`makedepends=('cargo')`
+
+### Source
+
+Prefer source tarballs or GitHub release archives. When unavailable, use
+crates.io:
+
+```bash
+source=("$pkgname-$pkgver.tar.gz::https://static.crates.io/crates/$pkgname/$pkgname-$pkgver.crate")
+```
+
+Note: crates.io archives often lack test files, license files, and other assets.
+
+### Prepare, build, check
+
+```bash
+prepare() {
+ cd "$pkgname-$pkgver"
+ export RUSTUP_TOOLCHAIN=stable
+ cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')"
+}
+
+build() {
+ cd "$pkgname-$pkgver"
+ export RUSTUP_TOOLCHAIN=stable
+ export CARGO_TARGET_DIR=target
+ cargo build --frozen --release --all-features
+}
+
+check() {
+ cd "$pkgname-$pkgver"
+ export RUSTUP_TOOLCHAIN=stable
+ export CARGO_TARGET_DIR=target
+ cargo test --frozen --all-features
+}
+```
+
+- `--locked` / `--frozen`: Respect `Cargo.lock` exactly for reproducible builds.
+- `CARGO_TARGET_DIR=target`: Avoids user-preference side effects outside chroots.
+- `RUSTUP_TOOLCHAIN=stable`: Ensures default toolchain (unnecessary if upstream has `rust-toolchain.toml`).
+- Do **not** use `--release` for `check()` β it enables optimisations that hide bugs.
+- For cargo workspaces (check for `[workspace]` in `Cargo.toml`), add `--workspace` to `cargo test`.
+
+### Packaging
+
+```bash
+package() {
+ cd "$pkgname-$pkgver"
+ install -Dm0755 -t "$pkgdir/usr/bin/" "target/release/$pkgname"
+}
+```
+
+For multiple binaries:
+
+```bash
+package() {
+ cd "$pkgname-$pkgver"
+ find target/release \
+ -maxdepth 1 \
+ -executable \
+ -type f \
+ -exec install -Dm0755 -t "$pkgdir/usr/bin/" {} +
+}
+```
+
+### VCS packages
+
+For `-git` packages where upstream doesn't keep `Cargo.lock` in sync between
+releases, add `cargo update` before `cargo fetch` in `prepare()`.