Skip to content

feat(cli-hub): add install-all command with per-CLI status#288

Open
RachelXiaolan wants to merge 4 commits into
HKUDS:mainfrom
RachelXiaolan:feat/install-all-with-status
Open

feat(cli-hub): add install-all command with per-CLI status#288
RachelXiaolan wants to merge 4 commits into
HKUDS:mainfrom
RachelXiaolan:feat/install-all-with-status

Conversation

@RachelXiaolan

Copy link
Copy Markdown

Summary

Adds cli-hub install-all command that installs all available CLIs from the registry with per-CLI status reporting.

Closes #235

What changed

  • cli_hub/cli.py: New install-all command that iterates through the full registry, shows progress ([1/N] GIMP (gimp)... ✓), and reports a summary at the end.
  • cli_hub/installer.py: New install_all() helper function.
  • tests/test_cli_hub.py: 4 new tests covering all-success, partial failure, empty registry, and fetch failure scenarios.

Behavior

$ cli-hub install-all
Installing 3 CLIs...

  [1/3] GIMP (gimp)... ✓
  [2/3] Blender (blender)... ✗ pip install failed: timeout
  [3/3] Audacity (audacity)... ✓

  Done: 2 succeeded, 1 failed out of 3
  Failed: blender
  • Exit code 0 when all succeed
  • Exit code 1 when any fail (also lists failed names)
  • Gracefully handles empty registry and network errors

Test plan

  • All 99 tests pass (python -m pytest cli-hub/tests/test_cli_hub.py -v)
  • 4 new tests for install-all: success, partial failure, empty, fetch error

@github-actions github-actions Bot added the cli-anything-hub Changes CLI-Hub, registries, or hub docs label May 18, 2026
@omerarslan0

Copy link
Copy Markdown
Collaborator

A few items before this can land:

  1. installer.py::install_all() is dead code. cli.py reimplements the loop inline and never imports or calls this helper. Either remove the helper, or have the command call it and stream results back via a callback/generator. Adding tests for an unused public function is misleading — please pick one path.

  2. No handling of already-installed CLIs. install_cli will re-run for every entry on every invocation, which is exactly the CI / fresh-machine-setup case from feat(cli-hub): show install status for each CLI during install-all #235. Suggest skipping anything already in get_installed() (or adding a --force flag and skipping by default). Without this, install-all is noisy on repeat runs and a partial failure on the first.

  3. Bundled-strategy CLIs (_bundled_install) return non-success messages by design. Against the real registry, install-all will report most bundled entries as failures and exit 1. Either filter the registry to installable strategies, or treat the bundled "note" return as a distinct skipped bucket in the summary (not failed).

  4. cli_hub.cli.install_cli is patched in the new tests, but the production import is from cli_hub.installer import install_cli. Confirm the patch target matches the call site — track_install is patched at cli_hub.cli.track_install which is correct, but please verify install_cli resolves through cli_hub.cli namespace in these tests rather than silently no-opping.

  5. Minor: install_all_cmd swallows all exceptions from fetch_all_clis with a bare except Exception. The sibling install command lets registry errors propagate. Either match that, or narrow to the specific exceptions fetch_all_clis raises.

…-force

Changes for cli-hub/cli_hub/installer.py
…-force

Changes for cli-hub/tests/test_cli_hub.py
@RachelXiaolan

Copy link
Copy Markdown
Author

Thanks for the thorough review @omerarslan0! All five points addressed in the latest push:

1. Dead code removed. installer.py::install_all() has been deleted. The inline loop in cli.py stays since it couples directly with click output (per-CLI [1/N] progress).

2. Skip already-installed. New default behavior: install-all checks get_installed() and skips CLIs already present. Added --force flag to override and reinstall everything. This also addresses the repeat-run noise from #235.

3. Bundled CLIs → skipped bucket. Bundled-strategy entries are now detected via _install_strategy() before dispatching, and reported as skipped (bundled) with yellow output. They no longer count as failures.

4. Patch targets confirmed. install_cli is imported into cli_hub.cli namespace (from cli_hub.installer import install_cli), so @patch("cli_hub.cli.install_cli") patches the actual name used at the call site inside install_all_cmd. The tests also now explicitly mock _install_strategy and get_installed at the cli_hub.cli namespace to match.

5. Narrowed exception. Changed from bare except Exception to except (requests.RequestException, ValueError) — the only two types fetch_all_clis can raise (through _fetch_json in registry.py).

New tests added: test_install_all_skips_installed, test_install_all_force_reinstalls, test_install_all_skips_bundled. All 7 install-all tests pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli-anything-hub Changes CLI-Hub, registries, or hub docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli-hub): show install status for each CLI during install-all

2 participants