Overview
This issue tracks the future extension of the URL-based marketplace work (#676) to support installing full APM packages directly from a URL — without requiring the package to be hosted on GitHub or registered in a marketplace.
Not in scope for #676. The current implementation must not foreclose this direction. Design decisions in Steps 1–8 of #676 should stay compatible with the constraints listed here.
Motivation
Issue #676 teaches APM to discover skills from a URL-based index. The natural next step is to allow installing any full APM package (apm.yml-bearing repository) directly from a URL:
# Hypothetical future UX
apm install https://example.com/packages/my-agent.tar.gz
apm install https://cdn.corp.com/apm/packages/my-toolkit@2.1.0
apm install https://example.com # origin autodiscovery, analogous to marketplace add
Capabilities Required
| Capability |
Notes |
| URL install source type |
apm install <url> resolved the same way as apm install owner/repo |
| Package manifest fetch |
Download + parse apm.yml from a URL endpoint or inside an archive |
| Archive extraction |
.tar.gz / .zip with safety checks (path traversal, decompression bombs) — overlaps Step 7 of #676 |
| Digest / integrity pinning |
apm install https://…#sha256:<hex> syntax for reproducible installs |
| Lockfile provenance |
source_url + source_digest fields in LockedDependency — overlaps Step 5 of #676 |
| Transitive resolution |
Dependencies declared in apm.yml resolved recursively, same as GitHub installs |
| Auth for private endpoints |
Bearer token or API key in ~/.apm/auth.json, analogous to GHE token support |
Design Constraints for #676
The following decisions in #676 must remain compatible with this direction:
-
source_type discriminator on MarketplaceSource — the "github" / "url" pattern should be extended (not replaced). Avoid hardcoding a two-value enum; leave it open for "url-package" or similar.
-
_fetch_url_direct() in client.py — keep it generic (plain HTTPS GET, no Agent Skills assumptions). Future callers can reuse it for package manifest and archive fetches. Do not embed Agent Skills index logic inside this function.
-
_detect_index_format() heuristic — the detection pattern (inspect a key, dispatch to a parser) is the right abstraction for detecting apm.yml vs Agent Skills vs legacy marketplace.json. Keep it extensible.
-
LockedDependency fields added in Step 5 (marketplace_index_url, marketplace_index_digest) — name and design these to generalise to any URL-sourced install. Consider source_url / source_digest as more neutral names.
-
Archive support in Step 7 — implement extraction as a standalone utility (apm_cli/utils/archive.py) decoupled from the marketplace layer, so the package installer can reuse it without importing marketplace internals.
-
Resolver changes in Step 8 — design the resolver interface so that a future resolve_url_package() is a parallel code path, not a special-case fork inside existing functions.
Security Considerations
- All URL installs MUST use HTTPS — enforced at the fetch layer (
_fetch_url_direct), not just at the command layer.
- Self-signed / internal CA certificates: document
REQUESTS_CA_BUNDLE env var — no APM-specific --ca-bundle flag needed.
- Skill artifact URLs per the Agent Skills RFC may point to a different domain than the index (e.g. CDN). Both the index fetch and downstream artifact fetches must enforce HTTPS independently.
- Per the RFC Security Considerations: clients SHOULD maintain a configurable domain allowlist for skill artifacts. This applies equally to package URLs.
- Digest verification is meaningless over plain HTTP — integrity guarantees only hold when transport is authenticated.
Related
Overview
This issue tracks the future extension of the URL-based marketplace work (#676) to support installing full APM packages directly from a URL — without requiring the package to be hosted on GitHub or registered in a marketplace.
Motivation
Issue #676 teaches APM to discover skills from a URL-based index. The natural next step is to allow installing any full APM package (
apm.yml-bearing repository) directly from a URL:Capabilities Required
apm install <url>resolved the same way asapm install owner/repoapm.ymlfrom a URL endpoint or inside an archive.tar.gz/.zipwith safety checks (path traversal, decompression bombs) — overlaps Step 7 of #676apm install https://…#sha256:<hex>syntax for reproducible installssource_url+source_digestfields inLockedDependency— overlaps Step 5 of #676apm.ymlresolved recursively, same as GitHub installs~/.apm/auth.json, analogous to GHE token supportDesign Constraints for #676
The following decisions in #676 must remain compatible with this direction:
source_typediscriminator onMarketplaceSource— the"github"/"url"pattern should be extended (not replaced). Avoid hardcoding a two-value enum; leave it open for"url-package"or similar._fetch_url_direct()inclient.py— keep it generic (plain HTTPS GET, no Agent Skills assumptions). Future callers can reuse it for package manifest and archive fetches. Do not embed Agent Skills index logic inside this function._detect_index_format()heuristic — the detection pattern (inspect a key, dispatch to a parser) is the right abstraction for detectingapm.ymlvs Agent Skills vs legacymarketplace.json. Keep it extensible.LockedDependencyfields added in Step 5 (marketplace_index_url,marketplace_index_digest) — name and design these to generalise to any URL-sourced install. Considersource_url/source_digestas more neutral names.Archive support in Step 7 — implement extraction as a standalone utility (
apm_cli/utils/archive.py) decoupled from the marketplace layer, so the package installer can reuse it without importing marketplace internals.Resolver changes in Step 8 — design the resolver interface so that a future
resolve_url_package()is a parallel code path, not a special-case fork inside existing functions.Security Considerations
_fetch_url_direct), not just at the command layer.REQUESTS_CA_BUNDLEenv var — no APM-specific--ca-bundleflag needed.Related