Installation
Precompiled releases
Each Forgejo release provides standalone binaries for Linux, macOS, and Windows on AMD64 and ARM64. Builds are statically linked with CGO_ENABLED=0; no Go installation is required.
| Platform | AMD64 asset | ARM64 asset |
|---|---|---|
| Linux | wraptool_VERSION_linux_amd64 |
wraptool_VERSION_linux_arm64 |
| macOS | wraptool_VERSION_darwin_amd64 |
wraptool_VERSION_darwin_arm64 |
| Windows | wraptool_VERSION_windows_amd64.exe |
wraptool_VERSION_windows_arm64.exe |
Homebrew tracks releases for you. The two scripts further down resolve the newest release themselves, and each shows how to pin a version instead.
Homebrew (macOS and Linux)
Homebrew is the shortest path on macOS, and the only one that handles upgrades for you. The formula lives in a wraptool-owned tap rather than homebrew-core, so tap it once with its full clone URL:
brew tap pti/wraptool https://forge.snamellit.com/pti/homebrew-wraptool.git
brew trust pti/wraptool
brew install pti/wraptool/wraptool
wraptool versionThe brew trust step is not optional, and skipping it fails quietly rather than loudly — see Trusting the tap below.
Upgrade with the rest of your Homebrew packages:
brew update && brew upgrade pti/wraptool/wraptoolThe formula installs the same release binary documented below and verifies the same SHA-256 checksum, so it needs no compiler and no Go toolchain. It covers macOS and Linux on both AMD64 and ARM64.
Homebrew installs only wraptool itself. The harnesses (claude, agy, and friends) still come from wraptool’s own harness pool — see Harness pool — and never from brew.
The formula pulls no dependencies on either platform: it places one static binary, about 20 MB, and compiles nothing.
Trusting the tap
Homebrew treats a third-party tap as untrusted until you say otherwise, because brew install executes the Ruby in that repository on your machine as your user. Formulae in homebrew-core are reviewed by Homebrew maintainers; this tap is not — it is reviewed by whoever controls forge.snamellit.com/pti/homebrew-wraptool.
Until the tap is trusted, brew update skips it:
Warning: Skipping pti/wraptool because it is not trusted.
Run `brew trust pti/wraptool` to trust it.
That is the failure mode worth knowing about: it is a warning, not an error, so an untrusted tap does not break anything visibly — it just never delivers a new version. Trusting the formula alone is not enough; trust the tap, or upgrades stay silently stale. Homebrew records this in ${XDG_CONFIG_HOME}/homebrew/trust.json, or ~/.homebrew/trust.json, and brew untrust pti/wraptool reverses it.
If you would rather check before trusting, the formula is small, generated, and verifiable in three steps:
brew tap pti/wraptool https://forge.snamellit.com/pti/homebrew-wraptool.git
# 1. read it — it declares four URLs, four checksums, and one install line
less "$(brew --repository pti/wraptool)/Formula/wraptool.rb"
# 2. compare its sha256 values against the checksums published with the release
# it pins — read the version out of the formula rather than assuming latest
formula="$(brew --repository pti/wraptool)/Formula/wraptool.rb"
version=$(awk -F'"' '/^ version /{print $2}' "$formula")
curl -fL "https://forge.snamellit.com/pti/wraptool/releases/download/wraptool-v$version/checksums.txt"
brew trust pti/wraptoolThose checksums are not independent of each other by accident: the formula is generated by wraptool’s release workflow from that very checksums.txt, in the same job that built the binaries, so a mismatch between the two means something went wrong after the build. The release tag itself is PGP-signed — see Releases and changes for the fingerprint and the trust model.
Nothing about this is specific to wraptool: it is the standard trade-off of any third-party tap. Installing via the script below instead of the tap swaps trust-the-repository for verify-the-checksum-yourself, at the cost of manual upgrades.
A brew-installed binary is not subject to the quarantine attribute that Gatekeeper applies to browser downloads, so the unnotarized macOS binary runs without a security prompt. Homebrew also replaces the file rather than writing over it, which avoids the stale code-signature failure described below.
Linux or macOS
The following commands detect the platform and architecture, download the matching binary, verify its SHA-256 checksum, and install it under ~/.local/bin:
# Resolve the newest release. To pin one instead, replace this command with
# e.g. version=X.Y.Z
version=$(curl -fsSL https://forge.snamellit.com/api/v1/repos/pti/wraptool/releases/latest \
| sed -n 's/.*"tag_name":"wraptool-v\([^"]*\)".*/\1/p')
test -n "$version" || { echo "cannot resolve the latest version" >&2; exit 1; }
case "$(uname -s)" in
Linux) os=linux ;;
Darwin) os=darwin ;;
*) echo "unsupported operating system: $(uname -s)" >&2; exit 1 ;;
esac
case "$(uname -m)" in
x86_64) arch=amd64 ;;
arm64|aarch64) arch=arm64 ;;
*) echo "unsupported architecture: $(uname -m)" >&2; exit 1 ;;
esac
asset="wraptool_${version}_${os}_${arch}"
release="https://forge.snamellit.com/pti/wraptool/releases/download/wraptool-v${version}"
curl -fLO "$release/$asset"
curl -fLO "$release/checksums.txt"
if command -v sha256sum >/dev/null 2>&1; then
grep " $asset$" checksums.txt | sha256sum -c -
else
grep " $asset$" checksums.txt | shasum -a 256 -c -
fi
mkdir -p "$HOME/.local/bin"
install -m 0755 "$asset" "$HOME/.local/bin/wraptool"
export PATH="$HOME/.local/bin:$PATH"
wraptool versionAdd $HOME/.local/bin to your shell’s PATH configuration if it is not already present. macOS release binaries are not currently notarized by Apple; use the source-build path below if local policy requires notarized software.
cp over the old binary
On Apple silicon, overwriting an executable in place (cp new wraptool) leaves the kernel’s code-signing cache holding the old file’s signature for that inode; the next run is refused with Killed: 9 even though the bytes are fine. The script above is safe — install(1) unlinks the destination first — as is rm followed by cp, or any write-to-temp-then-mv. If a binary is already in that state, re-sign it in place: codesign -s - -f ~/.local/bin/wraptool.
Windows PowerShell
This example detects AMD64 versus ARM64, verifies the downloaded executable, and installs it under %USERPROFILE%\bin:
# Resolve the newest release. To pin one instead, replace these two lines with
# e.g. $Version = "X.Y.Z"
$Latest = Invoke-RestMethod "https://forge.snamellit.com/api/v1/repos/pti/wraptool/releases/latest"
$Version = $Latest.tag_name -replace '^wraptool-v', ''
$Arch = switch ([Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString()) {
"X64" { "amd64" }
"Arm64" { "arm64" }
default { throw "Unsupported architecture: $_" }
}
$Asset = "wraptool_${Version}_windows_${Arch}.exe"
$Release = "https://forge.snamellit.com/pti/wraptool/releases/download/wraptool-v${Version}"
Invoke-WebRequest "$Release/$Asset" -OutFile $Asset
Invoke-WebRequest "$Release/checksums.txt" -OutFile checksums.txt
$ChecksumLine = Get-Content checksums.txt | Where-Object { $_.EndsWith($Asset) }
if (-not $ChecksumLine) { throw "Checksum for $Asset not found" }
$Expected = ($ChecksumLine -split '\s+')[0]
$Actual = (Get-FileHash $Asset -Algorithm SHA256).Hash
if ($Actual -ne $Expected) { throw "SHA-256 checksum mismatch" }
$InstallDir = Join-Path $HOME "bin"
New-Item -ItemType Directory -Force $InstallDir | Out-Null
Move-Item -Force $Asset (Join-Path $InstallDir "wraptool.exe")
$env:Path = "$InstallDir;$env:Path"
wraptool versionAdd %USERPROFILE%\bin to the user PATH to make wraptool available in future PowerShell sessions. Windows binaries are not currently Authenticode-signed.
checksums.txt verifies the downloaded bytes against the release manifest. build-info.txt records the source commit, Go version, and hashes of the pinned Guix inputs. Release tags are PGP-signed; see Releases and changes for the signing fingerprint and trust model.
Build with Go
Clone the repository, then build the main package with Go 1.26.0 or newer (the version declared by go.mod):
git clone https://forge.snamellit.com/pti/wraptool.git
cd wraptool
go build -o wraptool .
./wraptool versionMove the resulting binary to a directory on your PATH using the installation conventions for your system. Using GOTOOLCHAIN=local makes a version mismatch fail rather than downloading a toolchain implicitly.
GOTOOLCHAIN=local go build -o wraptool .Build with Guix
The repository’s flat manifest.scm supplies Go, Git, Quarto, Node, the linter, and shell utilities used by development and containers. Quarto comes from the configured Snamguix channel:
guix time-machine -C channels.scm -- shell -m manifest.scm -- go build -o wraptool .
guix time-machine -C channels.scm -- shell -m manifest.scm -- ./wraptool versionchannels.scm pins Snamguix and brings in its declared Nonguix dependency so a clean checkout can resolve quarto-bin. Review changes to both Scheme files before evaluating them.
Verify the checkout
go test ./...
go vet ./...
go build -o wraptool .
./wraptool --helpThe full contributor checks, including formatting and golangci-lint, are in Contributing.
Runtime dependencies
Wraptool itself is a Go binary. Individual features need additional host tools:
| Feature | Host dependency |
|---|---|
| Wrapped CLI | The configured absolute binary and any helpers it launches |
up --runtime=guix |
guix, plus manifest.scm in the worktree |
up --runtime=devcontainer |
devcontainer and its container runtime |
| Harness installation | Guix for automated pool installers; otherwise use the Dev Container feature |
Proceed to Getting started to create a policy and launch the server.