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:
/collections/ path segment hard-routes to the .collection.yml parser, shadowing any apm.yml that lives at <repo>/collections/<name>/apm.yml.
- 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
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.
- (Optional) An object-form opt-out, e.g.
kind: package, that disables auto-classification.
For Gap 2
- 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.
- (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
Summary
Two related gaps prevent a natural "meta-package" mental model — i.e., a sub-path inside a monorepo whose
apm.ymlpurely declares dependencies on other skills/MCPs/packages:/collections/path segment hard-routes to the.collection.ymlparser, shadowing anyapm.ymlthat lives at<repo>/collections/<name>/apm.yml.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:
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.ymllisting transitive deps — installable by sub-path:bundles/writing/apm.yml:Goal: from a fresh project,
apm install lirantal/skills/bundles/writingshould pull in the two skills declared above.Gap 1 —
/collections/shadowingRepro
With the bundle at
collections/writing/apm.yml:(The "Authentication failed" hint in
--verboseis misleading — auth is fine.)Object form exposes the real cause:
APM hard-routes any
/collections/path tosrc/apm_cli/deps/collection_parser.pyand never considers that a realapm.ymllives atcollections/writing/apm.yml.Why
.collection.ymlisn't a substitute.collection.yml(percollection_parser.py) is a flat list of in-repo primitive files withkind ∈ {prompt, instruction, chat-mode, agent, context}. It cannot express skill deps, MCP server deps, or transitiveapm:package deps.Workaround
Rename
collections/→bundles/(or any segment that doesn't containcollections). 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/writingcorrectly resolves and installs the two transitive deps:But the meta-package itself fails post-validation:
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.ymlwhose 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: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
apm.ymlshould take priority over the/collections/heuristic. If<path>/apm.ymlexists in the target ref, treat it as a Subdirectory APM package and run the normal resolver. Only fall back to.collection.ymldetection when noapm.ymlis present.kind: package, that disables auto-classification.For Gap 2
apm.ymldeclares 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.type: meta(or similar) inapm.ymlto 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
apm --version:Agent Package Manager (APM) CLI version 0.11.0 (dc0b53b)lirantal/skills