Skip to content

Add search() method to query package indexes across all providers#35

Merged
pirate merged 1 commit intomainfrom
claude/add-binprovider-search-6UP5g
May 3, 2026
Merged

Add search() method to query package indexes across all providers#35
pirate merged 1 commit intomainfrom
claude/add-binprovider-search-6UP5g

Conversation

@pirate
Copy link
Copy Markdown
Member

@pirate pirate commented May 1, 2026

Summary

This PR adds a new search() method to the BinProvider base class and implements provider-specific search handlers across all package manager integrations. The feature enables users to search package indexes in parallel and discover available binaries before installation.

Key Changes

Core Infrastructure

  • Added search() method to BinProvider base class that queries a provider's package index and returns a list of Binary objects with pre-configured install arguments
  • Added default_search_handler() to base class returning empty list for providers without search backends
  • Added "search" action to handler configuration in all provider classes
  • Added deadlock prevention logic in INSTALLER_BINARY() to avoid circular cross-provider dependencies during search operations
  • Added search CLI command that queries all selected providers in parallel and displays results

Provider-Specific Implementations

  • GoGetProvider: Uses go list -m -versions to resolve exact Go module paths
  • AptProvider: Uses apt-cache search for substring matching against Debian packages
  • NixProvider: Uses nix search with regex matching against nixpkgs attributes
  • ChromeWebstoreProvider: Scrapes Chrome Web Store detail pages to resolve 32-char extension IDs
  • DockerProvider: Uses docker search to query Docker Hub
  • CargoProvider: Uses cargo search to query crates.io
  • GemProvider: Uses gem search to query rubygems.org
  • NpmProvider: Uses npm search with JSON output
  • PnpmProvider: Uses pnpm search with JSON output
  • YarnProvider: Queries npm registry HTTP API directly (yarn 4+ removed search command)
  • BunProvider: Queries npm registry HTTP API directly
  • DenoProvider: Queries npm registry HTTP API directly
  • PipProvider: Uses pip index versions for exact PyPI package name lookup
  • UvProvider: Queries PyPI JSON API directly
  • BrewProvider: Uses brew search to query homebrew formulae
  • PlaywrightProvider: Returns hardcoded list of supported browsers with substring matching
  • PuppeteerProvider: Returns hardcoded list of supported browsers with substring matching

Implementation Details

  • Search handlers avoid triggering heavy cross-provider bootstrap chains by loading tool binaries directly from PATH via EnvProvider
  • Results are returned as non-loaded Binary objects with binproviders=[self] and pre-configured install overrides
  • Search respects min_version, min_release_age, and timeout parameters where applicable
  • Parallel search execution via ThreadPoolExecutor in CLI command
  • Comprehensive test coverage added for all provider search implementations

https://claude.ai/code/session_019dF435Q88rW5oCbjYwAQU3


Summary by cubic

Adds a cross‑provider search() API and abxpkg search CLI to query package indexes in parallel and install a match in one call. Also tightens load behavior and improves nix search and naming consistency.

  • New Features

    • Added BinProvider.search() returning non‑loaded Binary objects with provider‑scoped install_args, plus central min_version filtering that scans all description tokens; search uses install_timeout by default.
    • Implemented search for: apt, brew, npm, pnpm, yarn (registry), bun (registry), deno (registry), cargo, gem, nix, docker, pip, uv (PyPI JSON), goget, playwright, puppeteer; registry matches are case‑insensitive.
    • abxpkg search runs providers in parallel and honors --binproviders, --min-version, --no-cache.
  • Bug Fixes

    • load() now tries all PATH candidates only for ambient‑PATH providers; managed providers load strictly from their own bin_dir.
    • Naming hardening: docker uses the image leaf as Binary.name; Chrome Web Store uses the stable ID as Binary.name.
    • nix.search switches to nix eval for exact nixpkgs#<name> lookups, drops GH_TOKEN, GITHUB_TOKEN, and NIX_REMOTE, and only warns on genuine subprocess failures.

Written for commit a349261. Summary will update on new commits.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 42 files

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 issues found across 42 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="abxpkg/binprovider_cargo.py">

<violation number="1" location="abxpkg/binprovider_cargo.py:245">
P2: `min_version` is ignored in Cargo search results, so versions below the requested minimum can be returned.</violation>
</file>

<file name="abxpkg/binprovider_uv.py">

<violation number="1" location="abxpkg/binprovider_uv.py:381">
P2: `default_search_handler` ignores `min_version`, so search can return packages that do not satisfy the requested version constraint.</violation>
</file>

<file name="abxpkg/binprovider.py">

<violation number="1" location="abxpkg/binprovider.py:872">
P1: The deadlock guard over-filters installer providers and effectively disables non-env cross-provider bootstrap in normal configurations.</violation>
</file>

<file name="README.md">

<violation number="1" location="README.md:41">
P3: Guard against empty search results before indexing `matches[0]` to avoid an `IndexError` in the documented example.</violation>
</file>

<file name="abxpkg/binprovider_deno.py">

<violation number="1" location="abxpkg/binprovider_deno.py:221">
P2: The post-search name filter is case-sensitive, which can incorrectly drop valid npm results for mixed-case queries.</violation>
</file>

<file name="abxpkg/binprovider_chromewebstore.py">

<violation number="1" location="abxpkg/binprovider_chromewebstore.py:162">
P1: Using the Web Store title as `Binary.name` can fail `BinName` validation (invalid chars/length), causing valid ID lookups to error. Use the stable extension ID as the binary name instead.</violation>
</file>

<file name="abxpkg/binprovider_npm.py">

<violation number="1" location="abxpkg/binprovider_npm.py:423">
P2: Apply `min_version` filtering in npm search results; the handler currently ignores the argument and can return versions below the requested minimum.</violation>
</file>

<file name="abxpkg/binprovider_docker.py">

<violation number="1" location="abxpkg/binprovider_docker.py:222">
P1: Using the full Docker repo (`namespace/image`) as `Binary.name` can produce slash-containing binary names that break shim/metadata file writes during install.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread abxpkg/binprovider.py Outdated
Comment thread abxpkg/binprovider_chromewebstore.py Outdated
Comment thread abxpkg/binprovider_docker.py Outdated
crate_name = line.split("=", 1)[0].strip()
version_str = line.split('"', 2)[1] if '"' in line else ""
description = line.split("# ", 1)[1].strip() if "# " in line else ""
if not crate_name or str(bin_name) not in crate_name:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: min_version is ignored in Cargo search results, so versions below the requested minimum can be returned.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At abxpkg/binprovider_cargo.py, line 245:

<comment>`min_version` is ignored in Cargo search results, so versions below the requested minimum can be returned.</comment>

<file context>
@@ -213,6 +213,47 @@ def _cargo_package_specs(
+            crate_name = line.split("=", 1)[0].strip()
+            version_str = line.split('"', 2)[1] if '"' in line else ""
+            description = line.split("# ", 1)[1].strip() if "# " in line else ""
+            if not crate_name or str(bin_name) not in crate_name:
+                continue
+            results.append(
</file context>

Comment thread abxpkg/binprovider_uv.py
pkg_name = info.get("name", str(bin_name))
version_str = info.get("version", "")
summary = info.get("summary", "") or pkg_name
return [
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: default_search_handler ignores min_version, so search can return packages that do not satisfy the requested version constraint.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At abxpkg/binprovider_uv.py, line 381:

<comment>`default_search_handler` ignores `min_version`, so search can return packages that do not satisfy the requested version constraint.</comment>

<file context>
@@ -345,6 +349,44 @@ def _version_from_uv_metadata(
+        pkg_name = info.get("name", str(bin_name))
+        version_str = info.get("version", "")
+        summary = info.get("summary", "") or pkg_name
+        return [
+            Binary(
+                name=pkg_name,
</file context>
Suggested change
return [
if min_version:
try:
if SemVer.parse(version_str) < min_version:
return []
except Exception:
return []
return [

Comment thread abxpkg/binprovider_deno.py Outdated
Comment thread abxpkg/binprovider_npm.py
pkg_name = entry.get("name", "")
if not pkg_name or str(bin_name) not in pkg_name:
continue
version_str = entry.get("version", "")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Apply min_version filtering in npm search results; the handler currently ignores the argument and can return versions below the requested minimum.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At abxpkg/binprovider_npm.py, line 423:

<comment>Apply `min_version` filtering in npm search results; the handler currently ignores the argument and can return versions below the requested minimum.</comment>

<file context>
@@ -391,6 +391,47 @@ def _refresh_bin_link(
+            pkg_name = entry.get("name", "")
+            if not pkg_name or str(bin_name) not in pkg_name:
+                continue
+            version_str = entry.get("version", "")
+            description = entry.get("description", "") or pkg_name
+            results.append(
</file context>

Comment thread README.md Outdated
pirate pushed a commit that referenced this pull request May 1, 2026
- binprovider.py: only apply the deadlock filter when ``env`` is NOT in
  the user-selected provider list. With env present (default mode), the
  bootstrap finds the installer on the host PATH first so the cycle
  never materializes — preserving legitimate cross-provider bootstraps
  (e.g. cargo installed via brew) that the previous filter clobbered.
- chromewebstore: use the stable 32-char extension ID as ``Binary.name``
  instead of the scraped Web Store title — titles can contain spaces /
  emojis / chars that fail BinName validation. The human title moves
  to ``description`` and the ``--name=`` install_arg.
- docker: search results now use the leaf of ``namespace/image`` as
  ``Binary.name`` — slashes in the binary name break shim/metadata
  filename writes during install. Full ``namespace/image:latest`` ref
  is preserved in install_args.
- npm/pnpm/yarn/bun/deno/docker: name match is now case-insensitive so
  mixed-case queries don't drop valid registry results.
- BinProvider.search: centrally filter out matches whose discovered
  version (parsed from the leading ``X.Y.Z`` token of ``description``)
  falls below ``min_version``. Replaces per-provider min_version
  filtering across npm/cargo/uv/pip/etc.
- README: guard the documented example against empty search results.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 11 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="abxpkg/binprovider.py">

<violation number="1" location="abxpkg/binprovider.py:2524">
P2: `min_version` filtering only parses the first description token, so providers that include version later in the description bypass the filter.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread abxpkg/binprovider.py Outdated
pirate pushed a commit that referenced this pull request May 2, 2026
…deadlock)

Pulled in from PR #35 — these are orthogonal install-chain fixes that
unblock ``CargoProvider.INSTALLER_BINARY``'s cross-provider attempts on
broken-runner CI environments where my new validation correctly rejects
the libllhttp-broken brew cargo and we need apt/nix to actually be able
to run.

- ``AptProvider.setup_PATH``: seed ``self.PATH`` with apt-get's bin_dir
  before invoking ``self.exec(dpkg -L bash)``. ``self.exec``'s
  ``build_exec_env`` re-enters ``self.setup_PATH``; without a non-empty
  PATH the ``not self.PATH`` guard fires on every recursive entry and
  loops forever.
- ``BinProvider.INSTALLER_BINARY``: drop cross-providers whose own
  bootstrap chain would mutually recurse back through ``self``. Only
  active when ``env`` is NOT in the selected provider list — the env
  fallback short-circuits the cycle in the default configuration so
  legitimate cross-provider bootstraps (cargo installed via brew, etc.)
  keep working.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 10 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="abxpkg/binprovider_brew.py">

<violation number="1" location="abxpkg/binprovider_brew.py:431">
P2: `no_cache` is dropped when resolving the brew installer in search, so `search(..., no_cache=True)` may still use stale cached installer state.</violation>
</file>

<file name="abxpkg/binprovider_pip.py">

<violation number="1" location="abxpkg/binprovider_pip.py:428">
P2: `default_search_handler` now calls `self.INSTALLER_BINARY()`, which can install/bootstrap pip during `search`. That makes search non-read-only and can trigger expensive cross-provider installs unexpectedly.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread abxpkg/binprovider_brew.py Outdated
Comment thread abxpkg/binprovider_pip.py Outdated

# Use ``self.INSTALLER_BINARY`` so pip's auto-install logic
# kicks in if env's pip is missing/broken.
installer = self.INSTALLER_BINARY()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: default_search_handler now calls self.INSTALLER_BINARY(), which can install/bootstrap pip during search. That makes search non-read-only and can trigger expensive cross-provider installs unexpectedly.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At abxpkg/binprovider_pip.py, line 428:

<comment>`default_search_handler` now calls `self.INSTALLER_BINARY()`, which can install/bootstrap pip during `search`. That makes search non-read-only and can trigger expensive cross-provider installs unexpectedly.</comment>

<file context>
@@ -423,13 +423,14 @@ def default_search_handler(
-        proc = pip_binary.exec(
+        # Use ``self.INSTALLER_BINARY`` so pip's auto-install logic
+        # kicks in if env's pip is missing/broken.
+        installer = self.INSTALLER_BINARY()
+        assert installer and installer.loaded_abspath
+        proc = self.exec(
</file context>

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="abxpkg/binprovider.py">

<violation number="1" location="abxpkg/binprovider.py:2556">
P2: Early return on missing `get_abspath()` prevents PATH fallback in ambient providers and can cause false `load()` failures.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread abxpkg/binprovider.py Outdated
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="abxpkg/binprovider_nix.py">

<violation number="1" location="abxpkg/binprovider_nix.py:246">
P2: Only warn when the subprocess actually fails; empty successful searches are expected and should not be logged as warnings.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread abxpkg/binprovider_nix.py Outdated
@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai Bot commented May 2, 2026

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

Adds a uniform .search(query) method on BinProvider that delegates to
per-provider native search commands (apt-cache search, npm search, brew
search, nix search, pip index versions, etc.) and surfaces results as
Binary objects ready to install. Also wires up an 'abxpkg search' CLI
command that runs all providers in parallel.
@pirate pirate force-pushed the claude/add-binprovider-search-6UP5g branch from e88678d to a349261 Compare May 3, 2026 03:38
@pirate pirate merged commit e278e9e into main May 3, 2026
125 of 126 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants