Skip to content

[FEATURE] Support URL-based marketplace registration for Agent Skills discovery indexes #676

@Vicente-Pastor

Description

@Vicente-Pastor

Summary

Extend APM marketplace support so a marketplace can be registered from a URL-based discovery index, including standards-compliant Agent Skills discovery endpoints such as:

  • https://example.com/.well-known/agent-skills/index.json
  • or an origin that resolves to that index, such as https://example.com

The primary UX should be:

apm marketplace add https://example.com/.well-known/agent-skills/index.json --name workbooks
apm install code-review@workbooks

and optionally also:

apm marketplace add https://example.com --name workbooks --type well-known
apm install code-review@workbooks

This keeps the existing NAME@MARKETPLACE install flow intact while allowing marketplace backends that are not GitHub repos with marketplace.json.

Why

Today APM marketplace registration assumes a Git repository source:

  • apm marketplace add OWNER/REPO
  • fetch marketplace.json
  • install with plugin-name@marketplace-name

That works for GitHub/Git-hosted indexes, but it does not work for the open Agent Skills discovery model, where the source of truth is an HTTP origin exposing a standards-based index at /.well-known/agent-skills/index.json.

Supporting URL-based marketplace registration would:

  • preserve the current name@marketplace UX
  • let APM consume standards-compliant Agent Skills catalogs
  • avoid inventing a separate skill install syntax
  • reduce implementation duplication by treating well-known discovery as another marketplace backend
  • make APM friendlier for internal enterprise domains and non-GitHub publishers

Reference Specs

Related Issues

Relevant points:

  • Skills are centered on SKILL.md with required name and description.
  • Discovery is origin-based through /.well-known/agent-skills/.
  • Publishers should expose /.well-known/agent-skills/index.json.
  • The index lists skill entries with metadata such as name, type, description, url, and optional digest.
  • RFC 8615 security considerations apply because /.well-known/ is origin-scoped metadata.

Design Direction

This should follow marketplace flow, not introduce a separate install model.

That means:

  • registration remains apm marketplace add ... --name workbooks
  • install remains apm install code-review@workbooks
  • browse/search/update/remove continue to work under the marketplace command group
  • the implementation generalizes the marketplace source model rather than adding a second discovery subsystem with different UX

In short:

  • same install UX as current marketplaces
  • new marketplace backend for URL-based discovery indexes

Update Semantics

The issue should explicitly preserve the same update model APM already uses for marketplaces:

1. Marketplace index updates

These update discovery metadata, not the installed dependency itself.

For URL-backed marketplaces:

apm marketplace update workbooks

should:

  • re-fetch the registered URL-backed index
  • refresh the local marketplace cache
  • update what browse, search, and future name@marketplace resolutions see
  • not silently change already-installed skills in the project

2. Installed dependency updates

Installed skills should continue to be controlled by normal install/update flows and the lockfile.

That means:

  • apm install code-review@workbooks resolves using the current marketplace index
  • the resolved artifact URL, digest, and provenance are then written into apm.lock.yaml
  • once installed, the project stays pinned to what was resolved at install time
  • if the publisher later changes /.well-known/agent-skills/index.json, the existing project should not drift automatically
  • users must explicitly re-run install/update flows to adopt the newly published artifact

3. Publisher behavior at the well-known URL

Publishers manage updates by changing the well-known discovery index.

Examples of publisher-managed changes:

  • updating a skill's description
  • changing the artifact url
  • publishing a new digest
  • adding or removing skills from the index

APM should consume those changes only after the user refreshes marketplace metadata and then performs an install/update action.

4. Lockfile responsibility

The lockfile is the boundary between discovery and installation.

The well-known URL controls:

  • what skills are discoverable
  • what artifact URL and digest are currently advertised

The lockfile controls:

  • what artifact was actually installed in this project
  • what provenance should be shown later
  • whether future installs count as an update or remain unchanged

5. Required provenance for update management

To make update behavior clear and auditable, URL-backed marketplace installs should record at least:

  • marketplace name
  • marketplace source type
  • index URL and/or origin URL
  • resolved artifact URL at install time
  • digest from the index if present
  • locally computed content hash of the fetched skill artifact or fetched file set

This allows APM to distinguish:

  • marketplace metadata changed
  • publisher-advertised artifact changed
  • installed artifact changed
  • lockfile still points to the previous artifact

6. Digest-first update algorithm

When the discovery index provides a digest, APM should use it as the fast-path signal for update detection.

Recommended behavior during explicit install/update flows:

  1. Resolve skill-name@marketplace against the latest marketplace index.
  2. If the index provides a digest:
  • compare the advertised digest to the digest stored in the lockfile
  • if the digest matches, treat the install as a no-op unless the user explicitly forces a reinstall
  • if the digest differs, fetch the artifact and verify the fetched content matches the advertised digest before accepting the update
  1. If the index does not provide a digest:
  • fetch the skill files needed for installation
  • compute a deterministic local content hash
  • compare that hash to the value stored in the lockfile
  1. After a successful install/update:
  • store the advertised digest if present
  • store the locally computed content hash

This gives APM two useful signals:

  • publisher digest for cheap update detection
  • local content hash for integrity verification and fallback when digest is missing

7. Metadata-only changes

If only index metadata changes, such as:

  • description text
  • ordering in the index
  • non-install-affecting index fields

and the digest or local content hash does not change, APM should treat the installed skill as unchanged.

Scope

In scope

  • allow apm marketplace add <URL> --name <marketplace>
  • support well-known Agent Skills indexes as a marketplace backend
  • resolve skill-name@marketplace-name against the registered URL-based index
  • download and install the selected skill through the existing APM install pipeline
  • persist provenance in apm.lock.yaml
  • add trust/policy controls for URL-based marketplace origins
  • document the new registration flow
  • document how marketplace metadata updates differ from installed dependency updates
  • document digest-first update checks with local hash fallback

Out of scope for the first iteration

  • replacing the existing Git-based marketplace flow
  • publisher tooling for generating /.well-known/agent-skills/
  • arbitrary multi-origin search/federation
  • background crawling outside explicit marketplace registration
  • remote activation without install/lockfile resolution
  • automatic background upgrade of installed skills when the well-known index changes

Detailed Plan

1. Generalize the marketplace source model

Goal: make one marketplace registry capable of storing either repo-backed sources or URL-backed sources.

Steps:

  • Review the current MarketplaceSource shape in src/apm_cli/marketplace/models.py and list which fields are GitHub/repo-specific.
  • Add a source_type discriminator such as repo, url_index, or well_known.
  • Add URL-capable fields such as url, index_url, and optional origin_url.
  • Decide which fields are required for each source type.
  • Update to_dict() so repo-backed entries serialize exactly as they do today unless new fields are needed.
  • Update from_dict() to load both old registry entries and new URL-backed entries.
  • Keep existing registry files valid without migration if possible.
  • If migration is required, add a one-time compatibility path and document it in code comments.

Definition of done:

  • Existing repo-backed marketplace entries still load unchanged.
  • New URL-backed marketplace entries can be persisted and reloaded.
  • ~/.apm/marketplaces.json can contain a mix of both source types.

2. Extend apm marketplace add to accept URLs

Goal: users can register a well-known Agent Skills index without referencing a Git repo.

Steps:

  • Inspect src/apm_cli/commands/marketplace.py add() and identify where input is currently assumed to be OWNER/REPO or HOST/OWNER/REPO.
  • Add input detection for full HTTP/HTTPS URLs.
  • Decide the CLI contract:
  • support direct index URL form: apm marketplace add https://example.com/.well-known/agent-skills/index.json --name workbooks
  • optionally support origin form: apm marketplace add https://example.com --name workbooks --type well-known
  • If --type well-known is supported, resolve the origin to https://example.com/.well-known/agent-skills/index.json.
  • Validate marketplace names using the existing NAME@MARKETPLACE rules.
  • Reject unsupported URL schemes.
  • Reject malformed origin URLs.
  • Add explicit errors for:
  • missing index
  • invalid JSON
  • unsupported schema
  • non-HTTPS URLs if those are disallowed

Definition of done:

  • apm marketplace add OWNER/REPO still works.
  • apm marketplace add https://example.com/.well-known/agent-skills/index.json --name workbooks works.
  • The command stores a URL-backed marketplace source and confirms registration.

3. Add parsing for well-known Agent Skills indexes

Goal: parse /.well-known/agent-skills/index.json into a structure the marketplace layer can use.

Steps:

  • Create index and entry dataclasses for the discovery document.
  • Parse the top-level $schema field.
  • Parse the skills array.
  • For each entry, parse at least:
  • name
  • type
  • description
  • url
  • digest
  • Normalize relative url values against the registered index URL.
  • Define how unsupported entry types are handled.
  • Decide whether invalid entries are skipped with warnings or fail the whole index.
  • Keep enough schema/version metadata to support future compatibility checks.

Definition of done:

  • A valid index produces a typed model.
  • Relative entry URLs resolve correctly.
  • Unsupported or malformed entries produce deterministic behavior.

4. Generalize marketplace fetching and caching

Goal: one marketplace client can fetch both Git-hosted marketplace.json and URL-based skill indexes.

Steps:

  • Inspect src/apm_cli/marketplace/client.py and separate repo-specific fetch logic from generic cache logic.
  • Introduce a source-type-based fetch path.
  • Keep current repo-backed fetch behavior unchanged.
  • Add URL-based fetch behavior for index URLs.
  • Reuse the existing cache directory and TTL strategy if appropriate.
  • Define cache keys that cannot collide between repo-backed and URL-backed sources.
  • Decide whether the cache key should include marketplace name, resolved index URL, or both.
  • Add stale-if-error behavior for URL-backed indexes if it matches current marketplace semantics.
  • Decide how redirects are handled and whether the final resolved URL is persisted.
  • Define what exactly apm marketplace update <name> refreshes for URL-backed marketplaces.
  • Make sure marketplace update only refreshes index metadata and does not modify installed dependencies.

Definition of done:

  • Repo-backed marketplaces still fetch exactly as before.
  • URL-backed marketplaces can be fetched, parsed, cached, and refreshed.
  • Cache invalidation works for both source types.
  • Marketplace update semantics are documented in code and tests.

5. Map URL-based index entries into marketplace items

Goal: name@workbooks resolves using the same marketplace flow regardless of backend type.

Steps:

  • Review src/apm_cli/marketplace/resolver.py and identify where it assumes a plugin source comes from repo metadata.
  • Define a normalized internal item shape for marketplace results so both backend types can emit comparable entries.
  • For URL-backed marketplaces, map each skill index entry to that normalized shape.
  • Preserve user-facing fields such as name, description, and source marketplace name.
  • Add enough fields for later install resolution, such as artifact URL and digest.
  • Ensure find_plugin()/search-style behavior can work for URL-backed entries too.

Definition of done:

  • Browse and search can list items from URL-backed marketplaces.
  • Resolver can look up code-review@workbooks from a URL-backed marketplace.

6. Resolve name@marketplace into an installable artifact

Goal: the install command can resolve a marketplace item into a concrete remote artifact without changing user syntax.

Steps:

  • Trace the current name@marketplace resolution path from CLI input through parse_marketplace_ref() to resolve_marketplace_plugin().
  • Keep that syntax unchanged.
  • Add a resolution branch for URL-backed marketplaces.
  • For well-known index entries, resolve the selected skill to:
  • a final artifact URL
  • an optional digest
  • a resolved display/provenance structure
  • Decide the canonical in-memory representation passed into the install/downloader layer.
  • Ensure error messages include both marketplace name and backing URL when resolution fails.
  • Define how resolution behaves if the marketplace cache is stale versus freshly refreshed.

Definition of done:

  • apm install code-review@workbooks resolves to a specific URL-backed skill artifact.
  • Existing name@marketplace repo-backed resolution still works.

7. Download and normalize discovered skill artifacts

Goal: remote artifacts discovered through a URL-backed marketplace are converted into something APM already knows how to install.

Steps:

  • Decide first-iteration supported artifact types.
  • Support skill-md first.
  • Decide whether archive support lands in v1 or phase 2.
  • For skill-md entries:
  • download the SKILL.md
  • create a temporary package directory
  • place the downloaded file in the expected location
  • attach source/provenance metadata needed later
  • For archive entries, if supported:
  • download archive
  • verify digest if present
  • unpack to a temp directory
  • reject path traversal or unsafe entries
  • validate resulting directory structure
  • Decide behavior when the remote artifact contains only SKILL.md and not related assets referenced from the file.
  • Ensure temp directories are cleaned up on success and failure paths.
  • Compute a deterministic local content hash for the fetched artifact or fetched file set after download.

Definition of done:

  • A URL-discovered skill-md artifact can be turned into a local temporary package.
  • That package can move through the existing validation/install path.
  • A local content hash is available for lockfile storage and fallback update checks.

8. Reuse the existing package validation and skill integration flow

Goal: keep the implementation centered on the current APM install pipeline rather than a custom remote-skill path.

Steps:

  • Trace how current SKILL.md packages are validated in src/apm_cli/models/validation.py.
  • Trace how they are deployed through src/apm_cli/integration/skill_integrator.py.
  • Feed URL-backed marketplace artifacts into this same pipeline after normalization.
  • Add any missing metadata plumbing so PackageInfo and APMPackage still carry what downstream code needs.
  • Verify deployment still works for supported targets such as Codex, Claude, Cursor, and VS Code.
  • Verify partial install, reinstall, and update flows do not bypass the new source type.
  • Verify reinstall/update flows only change deployed content when the user explicitly runs install/update, not when marketplace metadata alone is refreshed.

Definition of done:

  • URL-backed marketplace installs land in the same target directories as existing skill installs.
  • No separate deployment subsystem is required.
  • Metadata refresh and installed-content refresh are clearly separated.

9. Tighten validation for standards-based remote skills

Goal: standards-based indexes should get standards-based validation.

Steps:

  • Review the current loose SKILL.md handling in validation code.
  • For URL-backed standards-based sources, require name and description.
  • Validate skill name rules from the Agent Skills spec:
  • lowercase letters, numbers, and hyphens only
  • 1 to 64 characters
  • no leading/trailing hyphen
  • no consecutive hyphens
  • Preserve optional fields when present:
  • license
  • compatibility
  • metadata
  • allowed-tools
  • Decide whether non-compliant remote skills are rejected or allowed behind a compatibility flag.
  • Keep backward compatibility for existing non-standard Git-hosted skill installs unless intentionally changed in a separate issue.

Definition of done:

  • Standards-based URL-backed skills are validated against the spec.
  • Existing legacy skill installs are not accidentally broken.

10. Capture provenance in the lockfile

Goal: installs remain auditable and reproducible even when the backing index changes.

Steps:

  • Review current marketplace provenance fields in the lockfile.
  • Add any new fields needed to represent URL-backed marketplace discovery.
  • Store at least:
  • marketplace name
  • marketplace source type
  • index URL and/or origin URL
  • resolved artifact URL
  • digest from the index if present
  • locally computed content hash
  • Decide how update behavior works when the same skill name later points to a different URL or digest.
  • Ensure deps list, deps tree, and view can surface useful provenance for these installs.
  • Define how APM determines whether a later install/update should be reported as no change, metadata changed only, or artifact changed.
  • Define precedence rules:
  • if digest is present, compare digest first
  • if digest differs, fetch and verify content before accepting the update
  • if digest is absent, fall back to local content hash comparison

Definition of done:

  • Lockfile data is sufficient to explain where the skill came from.
  • The recorded provenance distinguishes repo-backed and URL-backed marketplaces.
  • Lockfile data is sufficient to reason about future updates.
  • Digest-first and hash-fallback update checks are possible from lockfile state.

11. Add security and governance controls

Goal: URL-based marketplaces introduce origin trust concerns that need explicit policy.

Steps:

  • Review current policy structures under src/apm_cli/policy/.
  • Decide whether URL-backed marketplace origins should be controlled by existing dependency policies or a dedicated marketplace/origin policy section.
  • Add allow/deny evaluation for URL-backed marketplace origins or index URLs.
  • Enforce HTTPS for production usage unless there is an explicit dev/test exception.
  • Apply digest verification when digest is present in the index.
  • Reuse hidden-character/content scanning before final deployment.
  • Decide whether untrusted origins are blocked automatically or surfaced for explicit user approval.
  • Add clear failure messaging when a policy denies a source.

Definition of done:

  • URL-backed marketplace installs are subject to trust and policy checks.
  • Digest mismatch and disallowed-origin failures are explicit and actionable.

12. Make all marketplace commands work with URL-backed sources

Goal: adding a new backend should not fragment the marketplace UX.

Steps:

  • Update apm marketplace list to show the source kind for each registration.
  • Update apm marketplace browse so it can render entries from URL-backed indexes.
  • Update apm marketplace update to refresh URL-backed caches.
  • Update apm marketplace remove to unregister URL-backed marketplaces cleanly.
  • Ensure apm search "query@marketplace" still works from the user’s perspective.
  • Add help text and examples for both repo-backed and URL-backed forms.
  • Ensure command help and output clearly explain that marketplace update refreshes index metadata and does not auto-upgrade already-installed skills.

Definition of done:

  • Users can add, list, browse, search, update, and remove URL-backed marketplaces using the same command group.
  • Update behavior is explicit in command output/help text.

13. Document the new flow

Goal: explain the feature in terms users and maintainers can actually follow.

Steps:

  • Update marketplace docs with side-by-side examples of repo-backed and URL-backed registration.
  • Document the primary command:
  • apm marketplace add https://example.com/.well-known/agent-skills/index.json --name workbooks
  • Document install flow:
  • apm install code-review@workbooks
  • If supported, document origin shorthand with --type well-known.
  • Explain what gets stored in apm.yml and apm.lock.yaml.
  • Explain trust and policy expectations for URL-backed marketplaces.
  • Explain the difference between Git-hosted marketplace.json indexes and standards-based well-known indexes.
  • Add a dedicated section explaining update semantics:
  • apm marketplace update <name> refreshes discovery metadata only
  • install/update flows change deployed content and lockfile state
  • well-known URL changes do not auto-update existing projects
  • digest is used first for update detection when present
  • local content hash is used for verification and fallback when digest is absent

Definition of done:

  • A user can follow the docs end-to-end without needing to inspect source code.
  • A user can understand exactly how marketplace refresh differs from dependency update.

14. Add tests in implementation order

Goal: land the feature with enough coverage to refactor safely.

Steps:

  • Add unit tests first for:
  • source model serialization/deserialization
  • URL input parsing
  • well-known index parsing
  • relative URL resolution
  • cache key generation and cache behavior
  • resolver behavior for name@marketplace
  • digest verification
  • local content hash generation
  • policy evaluation for allowed/denied origins
  • marketplace update behavior for URL-backed sources
  • Add integration tests next for:
  • registering a marketplace from a direct index URL
  • browsing/searching a URL-backed marketplace
  • installing skill-name@workbooks
  • writing lockfile provenance for a URL-backed marketplace install
  • updating and removing URL-backed marketplaces
  • confirming that marketplace update does not modify installed artifacts on disk
  • confirming digest-match no-op behavior
  • confirming digest-mismatch triggers fetch and verification
  • confirming hash fallback works when digest is absent
  • blocking untrusted or invalid origins
  • Add acceptance coverage last for:
  • end-to-end add -> browse/search -> install
  • refresh marketplace metadata and verify no deployment drift until explicit install/update
  • mixed projects containing repo-backed and URL-backed marketplaces

Definition of done:

  • Tests cover both happy paths and the main failure paths.
  • Existing repo-backed marketplace tests still pass.
  • Update semantics are explicitly tested.
  • Digest-first and hash-fallback behavior are explicitly tested.

15. Deliver in phases

Goal: keep the first merge small enough to review and ship.

Phase 1:

  • Generalize marketplace source model.
  • Support apm marketplace add https://example.com/.well-known/agent-skills/index.json --name workbooks.
  • Parse well-known indexes.
  • Enable browse/search for URL-backed marketplaces.
  • Support skill-md install via name@marketplace.

Phase 2:

  • Add lockfile provenance enhancements.
  • Add policy/trust enforcement.
  • Add digest verification.
  • Add local content hash generation.
  • Document and test update semantics.

Phase 3:

  • Add archive support if deferred.
  • Add origin shorthand such as --type well-known if deferred.
  • Polish docs and compatibility behavior.

Acceptance Criteria

  • A user can register a marketplace from a URL-based Agent Skills index.
  • A user can run apm install code-review@workbooks after registering workbooks from a URL-based index.
  • Existing repo-backed marketplace behavior continues to work unchanged.
  • URL-backed marketplace installs reuse the existing APM install/deploy pipeline.
  • apm.lock.yaml captures marketplace name plus backing URL provenance, advertised digest when present, and a local content hash.
  • apm marketplace update <name> refreshes only marketplace metadata and does not silently upgrade already-installed skills.
  • Explicit install/update flows use digest-first checks and local hash fallback to determine whether the artifact changed.
  • Invalid indexes, unsupported entry types, bad digests, and untrusted origins fail with actionable errors.
  • Documentation clearly explains the new marketplace registration flow and update behavior.

Open Questions

  • Should --type well-known be required for origin URLs, or should APM infer it?
  • Should both direct index URL and origin URL forms be supported in v1?
  • Should URL-based marketplace sources be limited to well-known Agent Skills indexes in the first iteration, or generalized to arbitrary JSON indexes?
  • Should first iteration support only skill-md, or also archives?
  • Should strict Agent Skills validation apply only to URL-backed standards-based sources, or to all skill installs?

Notes on Current Code Fit

Relevant existing areas that appear reusable:

  • marketplace caching and index parsing under src/apm_cli/marketplace/
  • marketplace source modeling in src/apm_cli/marketplace/models.py
  • marketplace registry in src/apm_cli/marketplace/registry.py
  • marketplace resolution in src/apm_cli/marketplace/resolver.py
  • dependency normalization in src/apm_cli/models/dependency/reference.py
  • package validation in src/apm_cli/models/validation.py
  • skill deployment in src/apm_cli/integration/skill_integrator.py
  • install and resolver pipeline under src/apm_cli/commands/install.py and src/apm_cli/deps/
  • policy infrastructure under src/apm_cli/policy/

This should be implemented as a generalization of the current marketplace model so the user-facing install experience remains name@marketplace regardless of whether the marketplace is backed by a Git repo or a URL-based discovery index.

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedDirection approved, safe to start workenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions