tag:github.com,2008:https://github.com/ArchiveBox/abxpkg/releasesRelease notes from abxpkg2026-04-14T23:46:02Ztag:github.com,2008:Repository/802422164/v1.10.52026-04-14T23:47:15Zv1.10.5<h2>Highlights</h2>
<ul>
<li>Fixed provider cache ownership so dependency cache entries no longer masquerade as installed binaries. This makes <code>update</code> / <code>upgrade</code> pick real owning providers again, e.g. <code>brew</code> can upgrade <code>node</code> even when other providers cache <code>node</code> as an upstream dependency.</li>
<li>Added shared <code>BinProvider.depends_on_binaries()</code> and <code>BinProvider.installed_binaries()</code> APIs and switched provider sections in <code>abxpkg version</code> to use them directly.</li>
<li>Tightened update verification so normal post-update checks reuse cached installer dependencies when appropriate, while explicit <code>--no-cache</code> still forces a fully fresh path.</li>
<li>Cleaned up CLI output: provider binary rows in <code>abxpkg version</code> now use a fixed-width version column, non-debug progress logs no longer inherit misleading deep indentation, and shared subprocess stderr/stdout formatting is more consistent.</li>
</ul>
<h2>Docs</h2>
<ul>
<li>Updated the README and generated docs to match current defaults and flag behavior, especially around <code>None</code> handling for <code>postinstall_scripts</code> / <code>min_release_age</code>, managed <code>ABXPKG_LIB_DIR</code> install roots, and the current visible CLI surface.</li>
</ul>piratetag:github.com,2008:Repository/802422164/v1.10.42026-04-14T22:53:05Zv1.10.4<h1>abxpkg v1.10.4</h1>
<h2>✨ Highlights</h2>
<ul>
<li>Added richer CLI inspection commands with <code>abxpkg version</code> and <code>abxpkg list</code>, including per-provider runtime state, installer provenance, dependency binaries, and installed binary caches.</li>
<li>Tightened provider dependency provenance so wrapper providers now record the upstream runtimes they actually depend on (<code>node</code>, <code>python</code>, <code>ruby</code>, installer binaries) instead of flattening everything into the active provider.</li>
<li>Improved <code>run --script</code> option merging so same-name script dependencies now contribute defaults to the final run binary without overriding an explicit <code>--binproviders</code> / <code>ABXPKG_BINPROVIDERS</code> selection.</li>
<li>Hardened the base provider action flow so nullable security options are resolved to real provider/action defaults before handlers run, instead of leaking <code>None</code> into provider-specific install/update code.</li>
</ul>
<h2>🧭 Quick Examples</h2>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="abxpkg version
abxpkg version yt-dlp
abxpkg list
abxpkg list env playwright chromium"><pre>abxpkg version
abxpkg version yt-dlp
abxpkg list
abxpkg list env playwright chromium</pre></div>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="abxpkg --binproviders=env,uv,pip run yt-dlp --version
abx --global yt-dlp --version"><pre>abxpkg --binproviders=env,uv,pip run yt-dlp --version
abx --global yt-dlp --version</pre></div>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="#!/usr/bin/env -S abxpkg run --script node
// /// script
// dependencies = [
// {name = "node", binproviders = ["env", "brew"], min_version = "22.0.0"},
// {name = "playwright", binproviders = ["playwright", "pnpm", "npm", "yarn"]},
// ]
// ///"><pre>#!/usr/bin/env -S abxpkg run --script node
<span class="pl-c">// /// script</span>
<span class="pl-c">// dependencies = [</span>
<span class="pl-c">// {name = "node", binproviders = ["env", "brew"], min_version = "22.0.0"},</span>
<span class="pl-c">// {name = "playwright", binproviders = ["playwright", "pnpm", "npm", "yarn"]},</span>
<span class="pl-c">// ]</span>
<span class="pl-c">// ///</span></pre></div>
<h2>🛠 What Changed</h2>
<ul>
<li>Added documented <code>abxpkg version</code> / <code>abxpkg list</code> flows and refreshed the generated docs/site output to match the current provider/runtime model.</li>
<li>Refined cache handling so provider-local <code>derived.env</code> entries preserve stable absolute paths, create missing cache directories lazily, and de-duplicate repeated installer/binary lines in global listings.</li>
<li>Fixed <code>Binary._binprovider_order()</code> so cached providers are preferred without dropping uncached fallback providers during update/uninstall flows.</li>
<li>Made no-op providers like <code>env</code> and <code>bash</code> still resolve and validate binaries during <code>install()</code> / <code>update()</code>, including enforcing <code>min_version</code> on the final loaded binary instead of silently accepting a mismatch.</li>
<li>Resolved nullable <code>postinstall_scripts</code> / <code>min_release_age</code> in the base <code>BinProvider.install()</code> / <code>update()</code> / <code>uninstall()</code> path using provider/action defaults, while preserving warnings for unsupported strict values.</li>
<li>Tightened installer provenance so <code>INSTALLER_BINARY()</code> now preserves the real upstream provider that loaded the installer binary, instead of re-wrapping everything as if it came from the active provider.</li>
<li>Ensured explicit <code>--binproviders</code> / <code>ABXPKG_BINPROVIDERS</code> remain an exact provider allowlist/order during installer and dependency resolution, instead of silently widening back to defaults.</li>
<li>Added explicit upstream dependency tracking for wrapper providers that really depend on another runtime binary:
<ul>
<li><code>npm</code>, <code>pnpm</code>, <code>yarn</code>, <code>playwright</code>, and <code>puppeteer</code> now cache <code>node</code></li>
<li><code>pip</code>, <code>ansible</code>, and <code>pyinfra</code> now cache <code>python</code></li>
<li><code>gem</code> now caches <code>ruby</code></li>
</ul>
</li>
<li>Fixed <code>GoGetProvider</code> installer resolution so <code>go</code> is loaded through a proper <code>go version</code> override instead of relying on generic <code>--version</code> probing.</li>
<li>Tightened <code>BrewProvider</code> behavior so <code>postinstall_scripts=False</code> is only claimed for <code>brew install</code>, not <code>brew upgrade</code>, which has no equivalent <code>--skip-post-install</code> flag.</li>
<li>Improved script-mode dependency merging so same-name dependencies (for example <code>node</code> in <code>run --script node</code>) merge their defaults into the final run binary generically instead of only special-casing <code>min_version</code>.</li>
<li>Updated provider summaries and list/version output so installer binaries, upstream dependency binaries, and installed binaries are reported more accurately and with less duplication.</li>
</ul>
<h2><g-emoji class="g-emoji" alias="warning">⚠️</g-emoji> Behavioral Changes</h2>
<ul>
<li>Explicit provider selection now stays explicit. If you pass <code>--binproviders=...</code> or set <code>ABXPKG_BINPROVIDERS</code>, dependency and installer resolution no longer silently re-add default providers behind your back.</li>
<li><code>install()</code> / <code>update()</code> on read-only/no-op providers still behave as no-ops for mutation, but they now validate the resolved binary and enforce <code>min_version</code> on the result.</li>
<li>Passing nullable security fields through provider instances or provider overrides is safer now: <code>None</code> means “use the provider/action default”, not “let a provider handler crash on an assertion”.</li>
</ul>piratetag:github.com,2008:Repository/802422164/v1.10.22026-04-13T11:06:33Zv1.10.2<h1>abxpkg v1.10.2</h1>
<h2>✨ Highlights</h2>
<ul>
<li>Renamed the project from <code>abx-pkg</code> / <code>abx_pkg</code> to <code>abxpkg</code>, including the Python package name, docs, examples, and release surface.</li>
<li>Added a much richer CLI runtime model around <code>abxpkg run</code>, <code>abx</code>, and <code>abxpkg run --script</code>, with consistent provider ENV/PATH merging for real subprocess execution.</li>
<li>Added provider-local <code>derived.env</code> caches for resolved binaries and installer binaries, including <code>version</code>, <code>sha256</code>, <code>mtime</code>, and <code>euid</code> tracking.</li>
<li>Tightened provider ownership and provenance reporting so installer binaries, upstream dependency binaries, and installed binaries are surfaced more explicitly.</li>
<li>Simplified provider state: much more work now happens lazily at <code>setup()</code> / first-use time instead of during import or construction.</li>
</ul>
<h2>🧭 Quick Examples</h2>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="pip install abxpkg
abxpkg --global install yt-dlp
abx --binproviders=env,uv,pip,brew yt-dlp --version"><pre>pip install abxpkg
abxpkg --global install yt-dlp
abx --binproviders=env,uv,pip,brew yt-dlp --version</pre></div>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="abxpkg --min-version=1.2.3 --min-release-age=7 install yt-dlp
abxpkg --overrides='{"pip":{"install_args":["yt-dlp[default]"]}}' install yt-dlp
abxpkg --install-args='["black==24.2.0"]' install black"><pre>abxpkg --min-version=1.2.3 --min-release-age=7 install yt-dlp
abxpkg --overrides=<span class="pl-s"><span class="pl-pds">'</span>{"pip":{"install_args":["yt-dlp[default]"]}}<span class="pl-pds">'</span></span> install yt-dlp
abxpkg --install-args=<span class="pl-s"><span class="pl-pds">'</span>["black==24.2.0"]<span class="pl-pds">'</span></span> install black</pre></div>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="#!/usr/bin/env -S abxpkg run --script node
// /// script
// dependencies = [
// {name = "node", binproviders = ["env", "apt", "brew"], min_version = "22.0.0"},
// {name = "playwright", binproviders = ["pnpm", "npm"]},
// ]
// ///"><pre>#!/usr/bin/env -S abxpkg run --script node
<span class="pl-c">// /// script</span>
<span class="pl-c">// dependencies = [</span>
<span class="pl-c">// {name = "node", binproviders = ["env", "apt", "brew"], min_version = "22.0.0"},</span>
<span class="pl-c">// {name = "playwright", binproviders = ["pnpm", "npm"]},</span>
<span class="pl-c">// ]</span>
<span class="pl-c">// ///</span></pre></div>
<h2>🛠 What Changed</h2>
<ul>
<li>Reworked the core provider engine around the new <code>abxpkg/</code> package layout and a much larger <code>BinProvider</code> / <code>Binary</code> runtime surface.</li>
<li>Added <code>loaded_mtime</code> and <code>loaded_euid</code> alongside <code>loaded_abspath</code>, <code>loaded_version</code>, and <code>loaded_sha256</code>, and threaded them through provider caches, summaries, and binary models.</li>
<li>Added provider-local <code>derived.env</code> metadata caching, installer caching, and dependency caching so repeated loads can skip expensive version probes when the fingerprint still matches.</li>
<li>Standardized <code>pip</code> and <code>uv</code> install-root layouts so hermetic environments live at <code><install_root>/venv</code> while provider metadata stays at <code><install_root></code>.</li>
<li>Hardened install semantics so package-manager success only counts if a runnable binary is actually produced; failed installs now roll back generically in the base provider flow.</li>
<li>Split runtime dependency reporting into clearer concepts like <code>INSTALLER_BINARY</code>, <code>depends_on_binaries</code>, and <code>installed_binaries</code>.</li>
<li>Extended the CLI with <code>--global</code> as a thin alias for <code>--lib=None</code>, hidden <code>upgrade</code> aliases, richer provider/version reporting, and direct handler-style override flags such as <code>--install-args</code>, <code>--version</code>, <code>--abspath</code>, and <code>--packages</code>.</li>
<li>Improved <code>abx</code> so it stays a very thin wrapper over <code>abxpkg run --install ...</code> while still forwarding the expanded CLI surface correctly.</li>
<li>Added inline <code>/// script</code> dependency parsing for <code>abxpkg run --script</code>, including <code>[tool.abxpkg]</code> env injection and dependency provider ENV/PATH merging before script execution.</li>
<li>Reworked logging output and CLI rendering substantially: quieter non-debug failures, better subprocess output formatting, better method highlighting, and richer provider/version summaries.</li>
</ul>
<h2><g-emoji class="g-emoji" alias="warning">⚠️</g-emoji> Behavioral Changes</h2>
<ul>
<li>The package/import surface is now <code>abxpkg</code>, not <code>abx-pkg</code> / <code>abx_pkg</code>.</li>
<li>CLI managed mode is now the default; use <code>--global</code> or <code>--lib=None</code> to force provider global mode.</li>
<li><code>load()</code> / <code>install()</code> correctness is stricter: providers no longer get to report success unless they can resolve a runnable binary afterward.</li>
<li>Provider ownership/provenance is less hand-wavy now: upstream installer/dependency binaries are tracked separately from installed binaries.</li>
</ul>piratetag:github.com,2008:Repository/802422164/v1.9.302026-04-12T19:39:52Zv1.9.30<h1>abx-pkg v1.9.30</h1>
<h2>✨ Highlights</h2>
<ul>
<li>Added <code>abx-pkg run --script</code>, which reads inline <code>/// script</code> metadata blocks so scripts can declare binary dependencies and <code>tool.abx-pkg</code> settings right at the top of the file.</li>
<li>Unified managed providers around shared <code>install_root</code> / <code>bin_dir</code> behavior, and made <code>ABX_PKG_LIB_DIR</code> resolve from the live environment so CLI <code>--lib</code> overrides behave consistently.</li>
<li>Added first-class <code>--no-cache</code> and <code>--debug</code> CLI controls, and tightened the shared binary lifecycle so <code>load()</code> / <code>install()</code> / <code>update()</code> / <code>uninstall()</code> all speak the same cache semantics.</li>
<li>Fixed several installer-resolution and recursion edge cases, while making the real Playwright and Puppeteer test paths much faster instead of faking them.</li>
</ul>
<h2>🧭 Quick Examples</h2>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="abx-pkg --lib=/tmp/abx --no-cache install yt-dlp
abx-pkg --debug --binproviders=env,npm,playwright run --script node ./capture.js"><pre>abx-pkg --lib=/tmp/abx --no-cache install yt-dlp
abx-pkg --debug --binproviders=env,npm,playwright run --script node ./capture.js</pre></div>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="#!/usr/bin/env -S abx-pkg run --script node
// /// script
// dependencies = [
// {name = "playwright", binproviders = ["npm", "pnpm"]},
// {name = "chromium", binproviders = ["playwright", "puppeteer", "apt"], min_version = "131.0.0"},
// ]
// [tool.abx-pkg]
// ABX_PKG_POSTINSTALL_SCRIPTS = true
// ///"><pre>#!/usr/bin/env -S abx-pkg run --script node
<span class="pl-c">// /// script</span>
<span class="pl-c">// dependencies = [</span>
<span class="pl-c">// {name = "playwright", binproviders = ["npm", "pnpm"]},</span>
<span class="pl-c">// {name = "chromium", binproviders = ["playwright", "puppeteer", "apt"], min_version = "131.0.0"},</span>
<span class="pl-c">// ]</span>
<span class="pl-c">// [tool.abx-pkg]</span>
<span class="pl-c">// ABX_PKG_POSTINSTALL_SCRIPTS = true</span>
<span class="pl-c">// ///</span></pre></div>
<h2>🛠 What Changed</h2>
<ul>
<li><code>parse_script_metadata()</code> and <code>run --script</code> now parse comment-prefix-agnostic <code>/// script</code> blocks, resolve declared dependencies before execution, merge <code>[tool.abx-pkg]</code> settings, and preserve child exit codes/stdout/stderr cleanly.</li>
<li>The provider constructor surface now consistently prefers <code>install_root</code> and <code>bin_dir</code>, while legacy provider-specific root aliases are still accepted through validation aliases.</li>
<li><code>abx_pkg_install_root_default()</code> now reads <code>ABX_PKG_LIB_DIR</code> from the live environment instead of a module-import snapshot, so CLI <code>--lib</code> and runtime env overrides propagate correctly across providers.</li>
<li>Removed <code>load_or_install</code> from the public API / CLI in favor of <code>install()</code>, and promoted <code>no_cache</code> into the shared lifecycle surface for <code>Binary</code> and <code>BinProvider</code>.</li>
<li>Hardened installer resolution across providers: fixed <code>detect_euid()</code> recursion, fixed dry-run version probing, corrected Go <code>PATH</code> / env handling, restored Yarn Berry <code>--force</code> behavior for <code>no_cache</code>, and normalized installer-binary abspath handling.</li>
<li>Playwright and Puppeteer now share the cleaned <code>install_root</code> / <code>bin_dir</code> model, bootstrap their installer binaries more predictably, and reuse seeded real browser installs in tests to cut redundant downloads.</li>
<li>CI now provisions both Yarn classic and Yarn Berry explicitly, pins pnpm to <code>10.19.0</code>, and uses workflow concurrency cancellation plus job timeouts to prevent stale runs from piling up.</li>
<li>README and generated docs were refreshed to match the new CLI, lifecycle, and managed-root behavior.</li>
</ul>
<h2><g-emoji class="g-emoji" alias="warning">⚠️</g-emoji> Behavioral Changes</h2>
<ul>
<li>Use <code>Binary.install()</code> / <code>abx-pkg install</code> instead of <code>load_or_install</code>.</li>
<li>CLI logging now defaults to <code>INFO</code>; enable debug output explicitly with <code>--debug</code> or <code>ABX_PKG_DEBUG=1</code>.</li>
<li><code>--no-cache</code> / <code>ABX_PKG_NO_CACHE=1</code> now apply consistently across <code>load()</code>, <code>install()</code>, <code>update()</code>, <code>uninstall()</code>, and <code>run</code>.</li>
</ul>
<h2>🧪 Verification</h2>
<ul>
<li><code>uv run prek run --all-files</code> passed on the release commit.</li>
<li>Focused real-provider coverage was exercised for Playwright, Puppeteer, Bun, pnpm, Yarn classic, Yarn Berry, and GoGet lifecycle paths.</li>
</ul>
<p>Thanks to everyone pushing on the install-root cleanup, browser provider edge cases, and CLI ergonomics. 🛠️</p>piratetag:github.com,2008:Repository/802422164/v1.9.292026-04-10T06:31:12Zv1.9.29<h1>abx-pkg v1.9.29</h1>
<h2>✨ Highlights</h2>
<ul>
<li>Added <code>abx-pkg run</code>, a direct exec path that resolves a binary through the configured providers and then hands off execution cleanly.</li>
<li>Added <code>abx</code>, a thin <code>abx-pkg --install run ...</code> alias that behaves like a cross-provider <code>npx</code> / <code>uvx</code> / <code>pipx run</code>.</li>
<li>Unified provider install-root defaults around <code>ABX_PKG_LIB_DIR</code>, provider-specific <code>ABX_PKG_<NAME>_ROOT</code> overrides, and a platform-aware default lib dir.</li>
<li>Added a generated GitHub Pages landing page with a docs build pipeline and a much more structured README.</li>
<li>Made provider behavior more explicit by removing silent <code>uv</code> / <code>pnpm</code> auto-switching from <code>PipProvider</code> and <code>NpmProvider</code>.</li>
</ul>
<h2>🧭 Quick Examples</h2>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="abx yt-dlp --help
abx --binproviders=env,uv,pip,brew yt-dlp --version
abx-pkg --binproviders=pip --install run black --version"><pre>abx yt-dlp --help
abx --binproviders=env,uv,pip,brew yt-dlp --version
abx-pkg --binproviders=pip --install run black --version</pre></div>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="export ABX_PKG_LIB_DIR=~/.config/abx/lib
export ABX_PKG_PIP_ROOT=~/.cache/abx/pip
abx-pkg --binproviders=pip,uv install black
abx-pkg --postinstall-scripts=False --min-release-age=7 install yt-dlp"><pre><span class="pl-k">export</span> ABX_PKG_LIB_DIR=<span class="pl-k">~</span>/.config/abx/lib
<span class="pl-k">export</span> ABX_PKG_PIP_ROOT=<span class="pl-k">~</span>/.cache/abx/pip
abx-pkg --binproviders=pip,uv install black
abx-pkg --postinstall-scripts=False --min-release-age=7 install yt-dlp</pre></div>
<h2>🛠 What Changed</h2>
<ul>
<li>Exposed the full <code>Binary</code> / <code>BinProvider</code> configuration surface on the CLI, including install roots, timeouts, release-age controls, postinstall-script policy, and overrides.</li>
<li>Hardened the new <code>run</code> / <code>abx</code> command path for macOS, <code>--</code> handling, bare boolean flags, and child-arg forwarding.</li>
<li>Switched the centralized default lib dir to <code>platformdirs</code>, while keeping explicit kwargs and provider-specific env vars highest priority.</li>
<li>Landed a GitHub Pages deployment workflow, docs renderer, and generated landing page for the provider matrix and API surface.</li>
<li>Propagated security flags to Playwright bootstrap installs and tightened several provider-specific install-root edge cases.</li>
<li>Expanded test coverage heavily, especially around the CLI, install-root precedence, and real subprocess execution.</li>
</ul>
<h2><g-emoji class="g-emoji" alias="warning">⚠️</g-emoji> Behavioral Changes</h2>
<ul>
<li><code>PipProvider</code> no longer silently falls through to <code>uv</code>; choose <code>UvProvider</code> explicitly when you want <code>uv</code> semantics.</li>
<li><code>NpmProvider</code> no longer silently falls through to <code>pnpm</code>; choose <code>PnpmProvider</code> explicitly when you want <code>pnpm</code> semantics.</li>
<li>Providers with isolated install roots now follow one clear precedence order: explicit kwargs > <code>ABX_PKG_<NAME>_ROOT</code> > <code>ABX_PKG_LIB_DIR/<name></code> > provider default.</li>
</ul>
<h2>🧪 Verification</h2>
<ul>
<li>GitHub Actions passed on <code>main</code> for the release line before the version bump.</li>
<li>Local checks passed with <code>uv run pyright</code> and focused <code>uv run pytest</code> slices covering the new CLI/install-root work.</li>
</ul>
<p>Thanks to everyone pushing on the provider edge cases and CLI ergonomics. 🚀</p>piratetag:github.com,2008:Repository/802422164/v1.9.282026-04-09T09:52:34Zv1.9.28<h1>abx-pkg v1.9.28</h1>
<h2>✨ Highlights</h2>
<ul>
<li>Added dedicated providers for <code>uv</code>, <code>pnpm</code>, <code>yarn</code>, <code>bun</code>, <code>deno</code>, and Playwright browser installs, and exported them from the public <code>abx_pkg</code> API.</li>
<li>Added a real <code>abx-pkg</code> CLI built with <code>rich-click</code>, including <code>version</code>, <code>install</code>, <code>update</code>, <code>uninstall</code>, <code>load</code>, and <code>load_or_install</code>, plus <code>--lib</code>, <code>--binproviders</code>, and <code>--dry-run</code>.</li>
<li>Added centralized install-root defaults via <code>ABX_PKG_LIB_DIR</code>, with per-provider <code>ABX_PKG_<NAME>_ROOT</code> overrides across providers that manage their own install roots.</li>
</ul>
<h2>🧰 What Changed</h2>
<ul>
<li><code>UvProvider</code> now stands on its own instead of piggybacking on <code>PipProvider</code>, with support for both hermetic venv installs and <code>uv tool</code> mode.</li>
<li><code>PnpmProvider</code>, <code>YarnProvider</code>, <code>BunProvider</code>, and <code>DenoProvider</code> each got dedicated implementations with their own install/update/uninstall logic, managed prefixes, and provider-specific security flag handling.</li>
<li>Added <code>PlaywrightProvider</code> for browser artifact installs, alongside follow-up improvements to browser-provider path handling and install/load coverage.</li>
<li>Provider defaults now honor <code>ABX_PKG_LIB_DIR</code> and provider-specific root env vars consistently, and the repo now includes end-to-end tests covering precedence and on-disk install locations.</li>
<li>The generic version probe now skips non-zero <code>--version</code> exits instead of misreading their stderr, and <code>PipProvider</code> now falls back to package metadata when a console script refuses version flags.</li>
<li>Ansible and Pyinfra package-install paths were hardened for real-world privilege boundaries, including better interpreter selection for apt-backed Ansible runs and safer brew drop-privilege handling.</li>
<li>Packaging metadata was refreshed to ship the console script cleanly and include the new CLI dependency and build layout changes.</li>
</ul>
<h2>🧪 Quality & Docs</h2>
<ul>
<li>CI now provisions Yarn 4 via corepack, Bun, Deno, Go, and richer environment diagnostics so the expanded provider matrix is exercised more realistically.</li>
<li>Added broad new provider and CLI test coverage, including dedicated suites for <code>uv</code>, <code>pnpm</code>, <code>yarn</code>, <code>bun</code>, <code>deno</code>, <code>playwright</code>, and <code>ABX_PKG_LIB_DIR</code>.</li>
<li>README docs were expanded to cover the new providers, environment-variable install-root behavior, and the new CLI, with the Django-specific guidance folded into a single collapsible section.</li>
</ul>
<p>Thanks to everyone stress-testing the edge cases that made this release sharper. 🛠️</p>piratetag:github.com,2008:Repository/802422164/v1.9.252026-04-03T06:58:41Zv1.9.25: Rename CustomProvider to BashProvider<p>Highlights</p>
<ul>
<li>Renamed the shell-command provider from <code>CustomProvider</code> / <code>custom</code> to <code>BashProvider</code> / <code>bash</code>.</li>
<li>Renamed the provider module to <code>abx_pkg.binprovider_bash</code>, updated lazy exports/imports, and switched the managed-root config from <code>ABX_PKG_CUSTOM_ROOT</code> to <code>ABX_PKG_BASH_ROOT</code>.</li>
<li>Renamed provider-specific fields and exported shell env vars to <code>bash_root</code>, <code>bash_bin_dir</code>, <code>BASH_INSTALL_ROOT</code>, and <code>BASH_BIN_DIR</code>.</li>
</ul>
<p>Behavior</p>
<ul>
<li>Preserved the existing shell-command install/update/uninstall model while keeping <code>install_root</code> and <code>bin_dir</code> aliases working for the renamed provider.</li>
<li>Updated the provider lifecycle and security-control tests to exercise the renamed <code>bash</code> provider end to end.</li>
<li>Fixed Puppeteer's internal installer binary naming to <code>puppeteer-browsers</code> so the documented/provider-facing name matches the actual binary being bootstrapped.</li>
</ul>
<p>Documentation</p>
<ul>
<li>Refreshed the README provider list and binprovider sections so the security-option docs match the current implementation.</li>
<li>Added and corrected documentation for <code>bash</code>, <code>chromewebstore</code>, and <code>puppeteer</code>, including provider defaults, env-backed security controls, and unsupported-option warning behavior.</li>
</ul>
<p>Upgrade notes</p>
<ul>
<li>Replace <code>CustomProvider</code> imports with <code>BashProvider</code>.</li>
<li>Replace provider name <code>custom</code> with <code>bash</code> in <code>Binary.overrides</code> and any serialized config.</li>
<li>Replace <code>custom_root</code> / <code>custom_bin_dir</code> with <code>bash_root</code> / <code>bash_bin_dir</code>.</li>
<li>Replace <code>ABX_PKG_CUSTOM_ROOT</code> with <code>ABX_PKG_BASH_ROOT</code>.</li>
</ul>piratetag:github.com,2008:Repository/802422164/v1.9.242026-04-03T06:43:17Zv1.9.24<h2>Highlights</h2>
<ul>
<li>Added three new first-class providers: <code>ChromeWebstoreProvider</code>, <code>PuppeteerProvider</code>, and <code>CustomProvider</code>.</li>
<li>Packaged the Chrome/extension JS runtime directly inside <code>abx-pkg</code>, so Chrome Web Store installs now work without depending on a sibling <code>abx-plugins</code> checkout.</li>
<li>Reworked provider option precedence so per-call args override <code>Binary(...)</code>, and <code>Binary(...)</code> overrides provider defaults, with cleaner handling for <code>dry_run</code>, <code>postinstall_scripts</code>, and <code>min_release_age</code>.</li>
<li>Improved privilege escalation and subprocess error reporting across providers, including preserving failed <code>sudo</code> output when a fallback attempt also fails.</li>
<li>Parallelized CI to run one test file per job with auto-discovered live lifecycle coverage.</li>
</ul>
<h2>New Providers</h2>
<h3><code>ChromeWebstoreProvider</code></h3>
<ul>
<li>Added a dedicated Chrome Web Store provider in <code>abx_pkg/binprovider_chromewebstore.py</code>.</li>
<li>Supports <code>install_root</code> / <code>bin_dir</code> via <code>extensions_root</code> / <code>extensions_dir</code>.</li>
<li>Installs extensions into a managed cache and resolves the installed binary to the unpacked <code>manifest.json</code>.</li>
<li>Ships the required JS runtime and config files inside the package:
<ul>
<li><code>abx_pkg/js/base/config.json</code></li>
<li><code>abx_pkg/js/base/utils.js</code></li>
<li><code>abx_pkg/js/chrome/config.json</code></li>
<li><code>abx_pkg/js/chrome/chrome_utils.js</code></li>
</ul>
</li>
<li>Includes real lifecycle tests covering provider and <code>Binary(...)</code> flows.</li>
</ul>
<h3><code>PuppeteerProvider</code></h3>
<ul>
<li>Added a dedicated Puppeteer/browser provider in <code>abx_pkg/binprovider_puppeteer.py</code>.</li>
<li>Supports provider-managed install roots and bin dirs for <code>@puppeteer/browsers</code> installs.</li>
<li>Handles generic browser install args instead of forcing a Chrome-only abstraction.</li>
<li>Fixed installed-browser resolution to use semantic version ordering rather than lexicographic string sorting.</li>
<li>Includes real lifecycle tests plus regression coverage for version ordering.</li>
</ul>
<h3><code>CustomProvider</code></h3>
<ul>
<li>Added a dedicated <code>CustomProvider</code> built on top of <code>EnvProvider</code> for shell-command installs.</li>
<li>Supports <code>install_root</code> / <code>bin_dir</code> via <code>custom_root</code> / <code>custom_bin_dir</code>.</li>
<li>Uses literal per-binary shell overrides for install/update/uninstall while still participating in the standard <code>Binary</code>/<code>BinProvider</code> lifecycle.</li>
<li>Includes real lifecycle coverage for direct provider and <code>Binary(...)</code> usage.</li>
</ul>
<h2>Core Behavior Changes</h2>
<h3>Provider and Binary option precedence</h3>
<ul>
<li>Added consistent per-call <code>dry_run</code> support to <code>install()</code>, <code>update()</code>, <code>uninstall()</code>, and <code>load_or_install()</code>.</li>
<li>Standardized precedence so:
<ul>
<li>explicit action args win</li>
<li><code>Binary(...)</code> defaults come next</li>
<li>provider defaults come last</li>
</ul>
</li>
<li>Exposed env-backed defaults for:
<ul>
<li><code>ABX_PKG_INSTALL_TIMEOUT</code></li>
<li><code>ABX_PKG_VERSION_TIMEOUT</code></li>
<li><code>ABX_PKG_DRY_RUN</code> (preferred over <code>DRY_RUN</code> when both are set)</li>
</ul>
</li>
</ul>
<h3>Security controls</h3>
<ul>
<li>Provider-wide defaults for <code>min_release_age</code> / <code>postinstall_scripts</code> now only hydrate from env vars on providers that actually support those controls.</li>
<li>Unsupported providers no longer fail closed by default when these options are present.</li>
<li>Instead, unsupported explicit values now warn and continue.</li>
<li><code>EnvProvider</code> no longer claims support for install-only security controls it cannot enforce.</li>
<li><code>pip</code> and <code>npm</code> install-arg merging now preserves explicitly supplied conflicting flags instead of blindly overriding them.</li>
</ul>
<h3>API cleanup</h3>
<ul>
<li><code>binproviders</code> is now the canonical field name used throughout docs/examples instead of <code>binproviders_supported</code>.</li>
<li>Module API normalization now handles both provider classes and provider instances consistently.</li>
<li>Unavailable-provider errors now use the generic wording:
<ul>
<li><code>XProvider is disabled because <installer> is not available on this host</code></li>
</ul>
</li>
</ul>
<h2>Subprocess and Privilege Handling</h2>
<ul>
<li>Centralized subprocess error logging in the shared <code>_raise_proc_error(...)</code> path.</li>
<li>Reworked older providers to use shared subprocess error handling instead of open-coded log+raise branches.</li>
<li>Updated shared <code>exec()</code> behavior to attempt privilege escalation when the provider needs a different EUID, while still falling back to the unprivileged path when escalation is unavailable.</li>
<li>When both a <code>sudo</code> attempt and a fallback attempt fail, the final error now includes both outputs.</li>
<li>Fixed ansible/pyinfra tempdir cleanup when privileged subprocesses leave root-owned files behind.</li>
</ul>
<h2>Provider-specific Improvements</h2>
<ul>
<li><code>AptProvider</code>, <code>BrewProvider</code>, <code>CargoProvider</code>, <code>GemProvider</code>, <code>GoGetProvider</code>, <code>NixProvider</code>, <code>PipProvider</code>, <code>NpmProvider</code>, <code>PyinfraProvider</code>, <code>AnsibleProvider</code>, and <code>DockerProvider</code> now rely more consistently on shared subprocess/error handling.</li>
<li><code>PipProvider</code> and <code>NpmProvider</code> now merge security controls with explicit install args more rigorously.</li>
<li><code>BrewProvider</code> respects explicit <code>--skip-post-install</code> args when present.</li>
<li><code>PipProvider</code> and <code>NpmProvider</code> gained stronger tests around provider defaults vs per-call overrides.</li>
</ul>
<h2>Packaging and Tooling</h2>
<ul>
<li>Added wheel/sdist inclusion rules for packaged JS assets in <code>pyproject.toml</code>.</li>
<li>Added <code>bin/setup_monorepo.sh</code> for local monorepo setup.</li>
<li>Updated the README to document the new providers, env vars, canonical <code>binproviders</code> field name, and current provider behavior.</li>
</ul>
<h2>CI and Test Coverage</h2>
<ul>
<li>Switched the main test workflow to one-job-per-file parallelization.</li>
<li>Live lifecycle tests are now auto-discovered from the actual test files instead of being hard-coded.</li>
<li>Reduced the standard matrix to:
<ul>
<li>Linux: Python 3.11, 3.14</li>
<li>macOS: Python 3.13</li>
</ul>
</li>
<li>Added new provider integration suites for:
<ul>
<li><code>chromewebstore</code></li>
<li><code>custom</code></li>
<li><code>puppeteer</code></li>
</ul>
</li>
<li>Expanded coverage for:
<ul>
<li>module API normalization</li>
<li>env-backed security defaults</li>
<li>unsupported security option warning behavior</li>
<li>provider-vs-action override precedence</li>
</ul>
</li>
</ul>piratetag:github.com,2008:Repository/802422164/v1.9.232026-04-02T16:38:18Zv1.9.23<h1>abx-pkg v1.9.23</h1>
<h2>Highlights</h2>
<ul>
<li>🧪 Replaced the old single-file <code>tests.py</code> runner with a real <code>pytest</code> suite under <code>tests/</code>, with live lifecycle coverage across <code>apt</code>, <code>brew</code>, <code>pip</code>, <code>npm</code>, <code>cargo</code>, <code>gem</code>, <code>goget</code>, <code>nix</code>, <code>docker</code>, <code>pyinfra</code>, and <code>ansible</code>.</li>
</ul>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="uv run pytest -m "not root_required and not docker_required""><pre>uv run pytest -m <span class="pl-s"><span class="pl-pds">"</span>not root_required and not docker_required<span class="pl-pds">"</span></span></pre></div>
<ul>
<li>🧭 Standardized isolated install layout across providers with shared <code>install_root</code> / <code>bin_dir</code> aliases, while still supporting provider-specific knobs like <code>pip_venv</code>, <code>npm_prefix</code>, <code>cargo_root</code>, <code>gem_home</code>, <code>gopath</code>, <code>nix_profile</code>, and <code>docker_shim_dir</code>.</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="from pathlib import Path
from abx_pkg import PipProvider
provider = PipProvider(install_root=Path("/tmp/venv"))
print(provider.install_root, provider.bin_dir)"><pre><span class="pl-k">from</span> <span class="pl-s1">pathlib</span> <span class="pl-k">import</span> <span class="pl-v">Path</span>
<span class="pl-k">from</span> <span class="pl-s1">abx_pkg</span> <span class="pl-k">import</span> <span class="pl-v">PipProvider</span>
<span class="pl-s1">provider</span> <span class="pl-c1">=</span> <span class="pl-en">PipProvider</span>(<span class="pl-s1">install_root</span><span class="pl-c1">=</span><span class="pl-en">Path</span>(<span class="pl-s">"/tmp/venv"</span>))
<span class="pl-en">print</span>(<span class="pl-s1">provider</span>.<span class="pl-c1">install_root</span>, <span class="pl-s1">provider</span>.<span class="pl-c1">bin_dir</span>)</pre></div>
<ul>
<li>⏱️ Centralized shared provider runtime behavior in <code>BinProvider</code>, including <code>install_timeout</code>, <code>version_timeout</code>, PATH propagation into subprocesses, deep-copy override handling, and safer cache-dir setup.</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="from abx_pkg import NpmProvider
provider = NpmProvider(install_timeout=120, version_timeout=10)
binary = provider.install("zx")"><pre><span class="pl-k">from</span> <span class="pl-s1">abx_pkg</span> <span class="pl-k">import</span> <span class="pl-v">NpmProvider</span>
<span class="pl-s1">provider</span> <span class="pl-c1">=</span> <span class="pl-en">NpmProvider</span>(<span class="pl-s1">install_timeout</span><span class="pl-c1">=</span><span class="pl-c1">120</span>, <span class="pl-s1">version_timeout</span><span class="pl-c1">=</span><span class="pl-c1">10</span>)
<span class="pl-s1">binary</span> <span class="pl-c1">=</span> <span class="pl-s1">provider</span>.<span class="pl-c1">install</span>(<span class="pl-s">"zx"</span>)</pre></div>
<h2>Provider Fixes</h2>
<ul>
<li>🔒 Fixed security override precedence so explicit <code>install_args</code> can adjust effective security behavior before fail-closed checks run, especially for npm <code>--ignore-scripts</code> and <code>--min-release-age=...</code>.</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="from abx_pkg import NpmProvider
provider = NpmProvider(min_release_age=36500).get_provider_with_overrides(
overrides={"zx": {"install_args": ["zx", "--min-release-age=0"]}},
)"><pre><span class="pl-k">from</span> <span class="pl-s1">abx_pkg</span> <span class="pl-k">import</span> <span class="pl-v">NpmProvider</span>
<span class="pl-s1">provider</span> <span class="pl-c1">=</span> <span class="pl-en">NpmProvider</span>(<span class="pl-s1">min_release_age</span><span class="pl-c1">=</span><span class="pl-c1">36500</span>).<span class="pl-c1">get_provider_with_overrides</span>(
<span class="pl-s1">overrides</span><span class="pl-c1">=</span>{<span class="pl-s">"zx"</span>: {<span class="pl-s">"install_args"</span>: [<span class="pl-s">"zx"</span>, <span class="pl-s">"--min-release-age=0"</span>]}},
)</pre></div>
<ul>
<li>🐳 Improved version detection for multiline banners by teaching <code>SemVer.parse(...)</code> to scan up to 5 lines. This fixes wrappers and tools whose version appears after a heading line, including Docker-backed command shims.</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="from abx_pkg import SemVer
SemVer.parse(
"ShellCheck - shell script analysis tool\nversion: v0.11.0-65-gcd41f79"
)
# -> SemVer("0.11.0")"><pre><span class="pl-k">from</span> <span class="pl-s1">abx_pkg</span> <span class="pl-k">import</span> <span class="pl-v">SemVer</span>
<span class="pl-v">SemVer</span>.<span class="pl-c1">parse</span>(
<span class="pl-s">"ShellCheck - shell script analysis tool<span class="pl-cce">\n</span>version: v0.11.0-65-gcd41f79"</span>
)
<span class="pl-c"># -> SemVer("0.11.0")</span></pre></div>
<ul>
<li>🧰 Tightened provider-specific behavior across the built-ins:
<ul>
<li><code>apt</code> / <code>brew</code> helper backends now use resolved <code>install_args</code></li>
<li><code>cargo uninstall</code> no longer reuses incompatible version-pinned install flags</li>
<li><code>nix uninstall</code> preserves other entries in the same profile</li>
<li><code>goget</code> is now the canonical provider name throughout the package and docs</li>
<li><code>Binary.abspaths</code> is available as a backward-compatible read alias for <code>loaded_abspaths</code></li>
</ul>
</li>
</ul>
<h2>Docs And DX</h2>
<ul>
<li>📚 Refreshed the README API reference with verified provider defaults, install roots, security controls, timeout behavior, override support, and direct source/test links.</li>
<li>🛠️ Updated the development workflow docs to match the current toolchain and test layout.</li>
</ul>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="uv sync --all-extras --all-groups
uv run prek run --all-files
uv run pytest -sx tests/"><pre>uv sync --all-extras --all-groups
uv run prek run --all-files
uv run pytest -sx tests/</pre></div>piratetag:github.com,2008:Repository/802422164/v1.9.222026-04-02T07:34:44Zv1.9.22<h2>✨ Highlights</h2>
<ul>
<li>
<p>🔒 <strong>Security defaults now propagate consistently across binaries and providers.</strong></p>
<ul>
<li><code>BinProvider</code> now owns default <code>postinstall_scripts</code> and <code>min_release_age</code> values, and <code>Binary</code> inherits them automatically when you don't override them explicitly.</li>
<li>Unsupported providers now fail closed instead of silently ignoring security constraints.</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="provider = EnvProvider(postinstall_scripts=True, min_release_age=4)
binary = Binary(name="python", binproviders=[provider])
assert binary.postinstall_scripts is True
assert binary.min_release_age == 4"><pre><span class="pl-s1">provider</span> <span class="pl-c1">=</span> <span class="pl-en">EnvProvider</span>(<span class="pl-s1">postinstall_scripts</span><span class="pl-c1">=</span><span class="pl-c1">True</span>, <span class="pl-s1">min_release_age</span><span class="pl-c1">=</span><span class="pl-c1">4</span>)
<span class="pl-s1">binary</span> <span class="pl-c1">=</span> <span class="pl-en">Binary</span>(<span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s">"python"</span>, <span class="pl-s1">binproviders</span><span class="pl-c1">=</span>[<span class="pl-s1">provider</span>])
<span class="pl-k">assert</span> <span class="pl-s1">binary</span>.<span class="pl-c1">postinstall_scripts</span> <span class="pl-c1">is</span> <span class="pl-c1">True</span>
<span class="pl-k">assert</span> <span class="pl-s1">binary</span>.<span class="pl-c1">min_release_age</span> <span class="pl-c1">==</span> <span class="pl-c1">4</span></pre></div>
</li>
<li>
<p>⬆️ <strong><code>min_version</code> is enforced end-to-end instead of only being advisory.</strong></p>
<ul>
<li><code>install()</code> and <code>update()</code> now validate the resolved version after the package manager runs.</li>
<li><code>load_or_install()</code> will upgrade an already-installed binary when it exists but does not satisfy the requested minimum version.</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="binary = provider.load_or_install("black", min_version=SemVer("24.0.0"))"><pre><span class="pl-s1">binary</span> <span class="pl-c1">=</span> <span class="pl-s1">provider</span>.<span class="pl-c1">load_or_install</span>(<span class="pl-s">"black"</span>, <span class="pl-s1">min_version</span><span class="pl-c1">=</span><span class="pl-en">SemVer</span>(<span class="pl-s">"24.0.0"</span>))</pre></div>
</li>
<li>
<p>📦 <strong>Provider install/update plumbing is more explicit and consistent.</strong></p>
<ul>
<li>Core handler signatures now thread <code>postinstall_scripts</code>, <code>min_release_age</code>, and <code>min_version</code> through setup/install/update paths.</li>
<li><code>pip</code> and <code>npm</code> explicitly declare support for release-age and postinstall controls.</li>
<li><code>brew</code> only uses Pyinfra/Ansible helper paths when postinstall scripts are allowed, and otherwise falls back to direct CLI invocations with the right flags.</li>
<li>Timeout settings are preserved through provider copies via model fields instead of hidden underscored state.</li>
</ul>
</li>
<li>
<p>🧪 <strong>Tests were expanded around the new behavior and cleaned up for strict type-checking.</strong></p>
<ul>
<li>Added fail-closed coverage for providers that cannot honor <code>min_release_age</code> or disabled postinstall scripts.</li>
<li>Added live tests for <code>pip</code> minimum-version upgrades and <code>npm</code> postinstall-script overrides.</li>
<li>Tightened the test helper typing so <code>ty-check</code> and <code>pyright</code> pass without <code>cast</code>, <code>Any</code>, or <code>type: ignore</code> shortcuts.</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="def is_install_args_sequence(value: object) -> TypeGuard[InstallArgs]:
return isinstance(value, (tuple, list)) and all(isinstance(item, str) for item in value)"><pre><span class="pl-k">def</span> <span class="pl-en">is_install_args_sequence</span>(<span class="pl-s1">value</span>: <span class="pl-smi">object</span>) <span class="pl-c1">-></span> <span class="pl-v">TypeGuard</span>[<span class="pl-smi">InstallArgs</span>]:
<span class="pl-k">return</span> <span class="pl-en">isinstance</span>(<span class="pl-s1">value</span>, (<span class="pl-s1">tuple</span>, <span class="pl-s1">list</span>)) <span class="pl-c1">and</span> <span class="pl-en">all</span>(<span class="pl-en">isinstance</span>(<span class="pl-s1">item</span>, <span class="pl-s1">str</span>) <span class="pl-k">for</span> <span class="pl-s1">item</span> <span class="pl-c1">in</span> <span class="pl-s1">value</span>)</pre></div>
</li>
<li>
<p>🏷️ <strong>Release metadata</strong></p>
<ul>
<li>Version bumped to <code>1.9.22</code>.</li>
<li><code>uv.lock</code> refreshed to match the new package version.</li>
</ul>
</li>
</ul>pirate