Skip to content

[BUG] installing agents for claude doesn't work if .claude dir is not present #733

@marcusalanen

Description

@marcusalanen

Describe the bug

For some reason, if I have a plugin.json in a repo which points to agents/ with an agent file "foobar.agent.md" and skill files in skills/, the agent doesn't get installed for Claude unless .claude dir is present


{
  "name": "xxx",
  "description": "xxx",
  "skills": "./skills/",
  "agents": "./agents/"
}

To Reproduce
Steps to reproduce the behavior:

mkdir dummy
cd dummy
apm install <redacted> --target claude               

The above does not install the agent. It does install skill files however. It works for --target copilot. Another "apm install" errors out with a "Content hash mismatch" which is likely another bug. A second "apm install" suddenly works and installs the agent.

If I start from scratch but create the .claude dir first, it works:

rm -rf dummy
mkdir dummy
cd dummy
mkdir .claude
apm install <redacted> --target claude               

Expected behavior
The agent defined by the plugin.json is installed for Claude even though .claude is not initially present.

Environment (please complete the following information):

  • OS: MacOs
  • Python Version: 3.14.3
  • APM Version: Agent Package Manager (APM) CLI version 0.8.11 (81082e2)

Additional context
Maybe the following fixes it, as found by an AI coding assistant:

diff --git i/src/apm_cli/commands/install.py w/src/apm_cli/commands/install.py
index 4e39a81..8fed00c 100644
--- i/src/apm_cli/commands/install.py
+++ w/src/apm_cli/commands/install.py
@@ -1671,7 +1671,7 @@ def _install_apm_dependencies(
                 )
 
         for _t in _targets:
-            if not _t.auto_create:
+            if not _t.auto_create and not _explicit:
                 continue
             _root = _t.root_dir
             _target_dir = project_root / _root

Maybe the hash checksum thing is fixed by:


@@ -1846,7 +1846,13 @@ def _install_apm_dependencies(
                     if _PDGitRepo(_pd_path).head.commit.hexsha == _pd_locked_chk.resolved_commit:
                         continue
                 except Exception:
-                    pass
+                    # GitRepo check failed (e.g. .git was removed after download).
+                    # Fall back to content-hash verification so correctly-installed
+                    # packages are not needlessly re-downloaded on every run.
+                    if _pd_locked_chk.content_hash and _pd_path.is_dir():
+                        from ..utils.content_hash import verify_package_hash as _pd_verify_hash
+                        if _pd_verify_hash(_pd_path, _pd_locked_chk.content_hash):
+                            continue
             # Build download ref (use locked commit for reproducibility).
             # build_download_ref() uses the manifest ref when ref_changed is True.
             _pd_dlref = build_download_ref(
@@ -2143,7 +2149,14 @@ def _install_apm_dependencies(
                                 if local_repo.head.commit.hexsha == locked_dep.resolved_commit:
                                     lockfile_match = True
                             except Exception:
-                                pass  # Not a git repo or invalid -- fall through to download
+                                # GitRepo check failed (e.g. .git was removed after
+                                # download).  Fall back to content-hash verification so
+                                # correctly-installed packages are not needlessly
+                                # re-downloaded on every subsequent run.
+                                if locked_dep.content_hash and install_path.is_dir():
+                                    from ..utils.content_hash import verify_package_hash
+                                    if verify_package_hash(install_path, locked_dep.content_hash):
+                                        lockfile_match = True
                 skip_download = install_path.exists() and (
                     (is_cacheable and not update_refs)
                     or (already_resolved and not update_refs)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds-triageNew issue, not yet reviewed by maintainers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions