# AppImageHub Provider And Query Fallback Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Add AppImageHub as a first-class provider, remove the `custom-json` stub, and make positional `aim ` fall back to cross-provider search when no direct installable match exists. **Architecture:** Keep strict source classification in `aim-core::app::query`, add AppImageHub through the existing source-adapter and search-provider seams, and move positional install-versus-search behavior into a higher-level orchestration path in `aim-cli` and shared app logic. Reuse existing search models and add-plan flows rather than creating parallel provider plumbing. **Tech Stack:** Rust workspace, Cargo tests, Clap CLI parsing, existing provider adapter/search abstractions, fixture-driven tests. --- ### Task 1: Extend source identity for AppImageHub **Files:** - Modify: `crates/aim-core/src/domain/source.rs` - Modify: `crates/aim-core/src/app/query.rs` - Test: `crates/aim-core/tests/query_resolution.rs` **Step 1: Write the failing tests** Add tests covering: - `resolve_query("https://www.appimagehub.com/p/2338455")` - `resolve_query("appimagehub/2338455")` - malformed shorthand such as `appimagehub/firefox` Expected assertions: - `SourceKind::AppImageHub` - appropriate `SourceInputKind` - `NormalizedSourceKind::AppImageHub` - canonical locator `Some("2338455")` **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-core --test query_resolution` Expected: FAIL with unknown source kinds or unsupported AppImageHub inputs. **Step 3: Implement the minimal source model changes** Update enums and `as_str()` mappings in `crates/aim-core/src/domain/source.rs`, then extend query classification so AppImageHub URLs and `appimagehub/` normalize into a stable `SourceRef`. **Step 4: Run the focused tests to verify pass** Run: `cargo test --package aim-core --test query_resolution` Expected: PASS for the new AppImageHub cases and existing provider cases. **Step 5: Commit** ```bash git add crates/aim-core/src/domain/source.rs crates/aim-core/src/app/query.rs crates/aim-core/tests/query_resolution.rs git commit -m "feat: classify AppImageHub sources" ``` ### Task 2: Add the AppImageHub source adapter and remove `custom-json` **Files:** - Create: `crates/aim-core/src/adapters/appimagehub.rs` - Modify: `crates/aim-core/src/adapters/mod.rs` - Delete: `crates/aim-core/src/adapters/custom_json.rs` - Test: `crates/aim-core/tests/adapter_smoke.rs` - Test: `crates/aim-core/tests/adapter_contract.rs` **Step 1: Write the failing tests** Add adapter expectations for: - `all_adapter_kinds()` contains `"appimagehub"` - `all_adapter_kinds()` no longer contains `"custom-json"` - AppImageHub adapter supports exact resolution and search **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-core --test adapter_smoke --test adapter_contract` Expected: FAIL because AppImageHub is not registered and `custom-json` is still present. **Step 3: Implement the adapter registration changes** Create `appimagehub.rs` with `SourceAdapter` support for AppImageHub sources, wire it into `mod.rs`, and remove `custom-json` from module registration and adapter-kind reporting. **Step 4: Run the focused tests to verify pass** Run: `cargo test --package aim-core --test adapter_smoke --test adapter_contract` Expected: PASS with AppImageHub present and `custom-json` removed. **Step 5: Commit** ```bash git add crates/aim-core/src/adapters/appimagehub.rs crates/aim-core/src/adapters/mod.rs crates/aim-core/tests/adapter_smoke.rs crates/aim-core/tests/adapter_contract.rs git rm crates/aim-core/src/adapters/custom_json.rs git commit -m "feat: add AppImageHub adapter" ``` ### Task 3: Add AppImageHub transport-backed resolution **Files:** - Modify: `crates/aim-core/src/adapters/appimagehub.rs` - Create or Modify: `crates/aim-core/src/source/appimagehub.rs` - Modify: `crates/aim-core/src/app/add.rs` - Test: `crates/aim-core/tests/install_payload.rs` - Test: `crates/aim-core/tests/adapter_contract.rs` **Step 1: Write the failing tests** Add fixture-backed tests for: - resolving `appimagehub/` into an installable AppImage artifact URL - returning `NoInstallableArtifact` when the item exists but exposes no installable AppImage asset **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-core --test adapter_contract --test install_payload` Expected: FAIL because AppImageHub resolution is not implemented. **Step 3: Implement the transport and resolution path** Add the minimal AppImageHub/OCS transport wrapper, teach the adapter to resolve the latest installable artifact, and update add-plan selection to route AppImageHub through the adapter path rather than the generic fallback branch. **Step 4: Run the focused tests to verify pass** Run: `cargo test --package aim-core --test adapter_contract --test install_payload` Expected: PASS with deterministic fixture-backed AppImageHub resolution. **Step 5: Commit** ```bash git add crates/aim-core/src/adapters/appimagehub.rs crates/aim-core/src/source/appimagehub.rs crates/aim-core/src/app/add.rs crates/aim-core/tests/adapter_contract.rs crates/aim-core/tests/install_payload.rs git commit -m "feat: resolve AppImageHub artifacts" ``` ### Task 4: Add AppImageHub search provider integration **Files:** - Modify: `crates/aim-core/src/app/search.rs` - Create or Modify: `crates/aim-core/src/source/appimagehub.rs` - Test: `crates/aim-core/tests/query_resolution.rs` - Test: `crates/aim-core/tests/github_source_discovery.rs` - Create or Modify: `crates/aim-core/tests/appimagehub_search.rs` **Step 1: Write the failing tests** Add fixture-backed search tests covering: - AppImageHub hit mapping into `SearchResult` - `install_query = appimagehub/` - canonical locator matching for installed-status annotation - mixed-provider search returning GitHub and AppImageHub hits together **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-core --test appimagehub_search` Expected: FAIL because AppImageHub search is not wired into the provider list. **Step 3: Implement the provider integration** Add an AppImageHub `SearchProvider`, wire it into `build_search_results(...)`, and update installed-hit annotation logic so AppImageHub-installed apps are recognized by canonical ID. **Step 4: Run the focused tests to verify pass** Run: `cargo test --package aim-core --test appimagehub_search` Expected: PASS with deterministic AppImageHub search coverage. **Step 5: Commit** ```bash git add crates/aim-core/src/app/search.rs crates/aim-core/src/source/appimagehub.rs crates/aim-core/tests/appimagehub_search.rs git commit -m "feat: add AppImageHub search provider" ``` ### Task 5: Add positional query fallback from install to search **Files:** - Modify: `crates/aim-cli/src/lib.rs` - Modify: `crates/aim-core/src/app/add.rs` - Modify: `crates/aim-core/src/app/search.rs` - Test: `crates/aim-cli/tests/end_to_end_cli.rs` - Test: `crates/aim-cli/tests/cli_smoke.rs` **Step 1: Write the failing tests** Add CLI/app-flow tests covering: - `aim firefox` falls back to search results when direct resolution is unsupported - positional query falls back to search results when a provider item has no installable artifact - positional query still installs directly for valid direct provider inputs **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-cli --test end_to_end_cli --test cli_smoke` Expected: FAIL because positional queries still surface add errors instead of search results. **Step 3: Implement the orchestration change** Add a small decision path in dispatch or shared app logic that tries the add flow first, then converts `Unsupported` and `NoInstallableArtifact` outcomes into `SearchResults` for positional queries only. **Step 4: Run the focused tests to verify pass** Run: `cargo test --package aim-cli --test end_to_end_cli --test cli_smoke` Expected: PASS with positional-query fallback behavior. **Step 5: Commit** ```bash git add crates/aim-cli/src/lib.rs crates/aim-core/src/app/add.rs crates/aim-core/src/app/search.rs crates/aim-cli/tests/end_to_end_cli.rs crates/aim-cli/tests/cli_smoke.rs git commit -m "feat: fall back to search for positional queries" ``` ### Task 6: Update CLI rendering and messaging for fallback search **Files:** - Modify: `crates/aim-cli/src/ui/render.rs` - Modify: `crates/aim-cli/src/ui/theme.rs` - Test: `crates/aim-cli/tests/ui_summary.rs` - Test: `crates/aim-cli/tests/cli_commands.rs` **Step 1: Write the failing tests** Add renderer expectations for: - fallback search rendering from positional `aim ` - empty search state instead of `unsupported source query` - AppImageHub provider labels and install query formatting where they are visible **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-cli --test ui_summary --test cli_commands` Expected: FAIL because fallback-search rendering and AppImageHub labels are not represented. **Step 3: Implement the minimal rendering changes** Reuse existing search rendering as much as possible, only adjusting dispatch/result handling and any provider-label formatting needed for AppImageHub. **Step 4: Run the focused tests to verify pass** Run: `cargo test --package aim-cli --test ui_summary --test cli_commands` Expected: PASS with stable search output for fallback scenarios. **Step 5: Commit** ```bash git add crates/aim-cli/src/ui/render.rs crates/aim-cli/src/ui/theme.rs crates/aim-cli/tests/ui_summary.rs crates/aim-cli/tests/cli_commands.rs git commit -m "feat: render AppImageHub and fallback search results" ``` ### Task 7: Update docs and run full verification **Files:** - Modify: `README.md` - Modify: `.plans/011-appimagehub-and-query-fallback/2026-03-21-appimagehub-and-query-fallback-design.md` if implementation details drift - Modify: `.plans/011-appimagehub-and-query-fallback/2026-03-21-appimagehub-and-query-fallback-implementation-plan.md` if task wording needs correction **Step 1: Update user-facing docs** Document: - AppImageHub direct query forms - positional-query fallback-to-search behavior - removal of `custom-json` from the supported-provider story **Step 2: Run formatting and full verification** Run: ```bash cargo fmt --all cargo test --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings ``` Expected: all commands succeed. **Step 3: Commit** ```bash git add README.md .plans/011-appimagehub-and-query-fallback/2026-03-21-appimagehub-and-query-fallback-design.md .plans/011-appimagehub-and-query-fallback/2026-03-21-appimagehub-and-query-fallback-implementation-plan.md git commit -m "docs: document AppImageHub provider and query fallback" ```