Skip to content

apm.yml inside collections/<name>/ is ignored — Collection detector preempts package resolution #1094

@lirantal

Description

@lirantal

Summary

Two related gaps prevent a natural "meta-package" mental model — i.e., a sub-path inside a monorepo whose apm.yml purely declares dependencies on other skills/MCPs/packages:

  1. /collections/ path segment hard-routes to the .collection.yml parser, shadowing any apm.yml that lives at <repo>/collections/<name>/apm.yml.
  2. Pure dependency-only apm.yml (no .apm/ directory) fails validation, even though APM correctly resolves and installs the declared transitive deps before erroring out.

The first was acknowledged inline on closed issue #74 by @danielmeppiel:

when the subfolder is under a collections/ path, APM currently forces collection detection. I'll make sure apm.yml takes priority there too.

The second is a separate constraint that surfaces as soon as you work around the first.

Mental model the user expects

A monorepo of skills where each subfolder is a curated bundle with its own apm.yml listing transitive deps — installable by sub-path:

lirantal/skills/                          (one repo)
├── skills/                               (authored skills, single SKILL.md each)
│   ├── writing-style-explainer/
│   └── gh-bulk-repo-edit/
└── bundles/                              (curated meta-packages)
    └── writing/
        └── apm.yml                       ← lists skills + 3rd-party deps + MCPs

bundles/writing/apm.yml:

name: writing
version: 1.0.0
dependencies:
  apm:
    - lirantal/skills/skills/writing-style-explainer
    - blader/humanizer
  mcp: []

Goal: from a fresh project, apm install lirantal/skills/bundles/writing should pull in the two skills declared above.

Gap 1 — /collections/ shadowing

Repro

With the bundle at collections/writing/apm.yml:

$ apm install lirantal/skills/collections/writing --verbose
[*] Validating 1 package...
[x] lirantal/skills/collections/writing -- not accessible or doesn't exist

(The "Authentication failed" hint in --verbose is misleading — auth is fine.)

Object form exposes the real cause:

- git: https://github.com/lirantal/skills
  path: collections/writing
Failed to download dependency lirantal/skills: Collection manifest not found:
collections/writing.collection.yml (also tried .yaml)

APM hard-routes any /collections/ path to src/apm_cli/deps/collection_parser.py and never considers that a real apm.yml lives at collections/writing/apm.yml.

Why .collection.yml isn't a substitute

.collection.yml (per collection_parser.py) is a flat list of in-repo primitive files with kind ∈ {prompt, instruction, chat-mode, agent, context}. It cannot express skill deps, MCP server deps, or transitive apm: package deps.

Workaround

Rename collections/bundles/ (or any segment that doesn't contain collections). The /collections/ heuristic stops firing and APM proceeds to the subdirectory-package code path. ✅ Verified empirically.

Gap 2 — pure dependency-only meta-package fails validation

After the rename workaround, apm install lirantal/skills/bundles/writing correctly resolves and installs the two transitive deps:

[+] github.com/lirantal/skills/bundles/writing (cached)
[+] blader/humanizer (cached)
|-- Skill integrated -> .github/skills/
[+] github.com/lirantal/skills/skills/writing-style-explainer (cached)
|-- Skill integrated -> .github/skills/

But the meta-package itself fails post-validation:

Failed to download dependency lirantal/skills: Subdirectory is not a valid APM
package or Claude Skill: Not a valid APM package: writing has apm.yml but is
missing the required .apm/ directory. Add .apm/ with primitives (instructions,
skills, etc.) or add skills/<name>/SKILL.md for a skill bundle.

The install ends with [!] Installed 2 APM dependencies with 1 error(s). — non-zero status, CI-failing — even though the user-visible outcome is correct.

The validator currently rejects an apm.yml whose only role is to declare dependencies. There's no way to express "this is a meta-package, no own primitives, just a curated dependency set."

Workaround

Adding an empty .apm/ directory (committed via .gitkeep) silences the validator and produces a clean install:

$ apm install lirantal/skills/bundles/writing
[*] Installed 3 APM dependencies.

But this is a wart — users have to commit a placeholder file just to satisfy a structural check that doesn't reflect any real requirement, and it pollutes the repo with empty directories that exist only to humor the tool.

Suggested fix

For Gap 1

  1. apm.yml should take priority over the /collections/ heuristic. If <path>/apm.yml exists in the target ref, treat it as a Subdirectory APM package and run the normal resolver. Only fall back to .collection.yml detection when no apm.yml is present.
  2. (Optional) An object-form opt-out, e.g. kind: package, that disables auto-classification.

For Gap 2

  1. Recognize dependency-only meta-packages as a valid package shape. When an apm.yml declares dependencies but no .apm/ content (and is not a skill bundle), don't treat it as malformed — just resolve its deps and exit cleanly. There is no good reason to require an empty .apm/ directory; the CLI should figure this out for users.
  2. (Optional) If a marker is wanted for clarity, allow type: meta (or similar) in apm.yml to make intent explicit, rather than inferring shape from on-disk layout.

Together these would make the user's mental model — "a monorepo of bundles, each a curated dep set, installable by sub-path" — work natively, without renames or placeholder files.

Environment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions