All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Parallel subdir install race.
apm installno longer intermittently fails withRuntimeError: Subdirectory '<path>' not found in repositorywhen multiple dependencies resolve to different subdirectories of the samerepo@ref. The shared clone cache now stores subdir-agnostic bare clones and each consumer materializes its own working tree (mirrors the WS3GitCachepattern). (#1135, fixes #1126)
- Cursor slash command support (Cursor 1.6+).
apm installdeploys package.prompt.mdfiles to.cursor/commands/*.mdwhen a.cursor/directory is present, completing cross-tool slash-command parity with Claude Code, OpenCode, and Gemini CLI. (#1046) apm installperformance + UX overhaul: WS3 persistent two-tier cache for git + HTTP (with rev-parse HEAD verification on cache hits), parallel level-batched BFS dependency resolution, parallel MCP registry batch lookups with ETag-revalidated HTTP cache, in-install repo clone dedup for subdirectory deps, reflink-aware file copies with write-dedup for cache checkouts, live progress UI for parallel resolution and download, per-phase timing in--verbose, elapsed time on every exit path, and ASCII-only progress bar. (#1116)
- gh-aw lock workflows: bump
microsoft/apm-actionv1.5.0 -> v1.6.0 so packed bundles use the legacy--format apmlayout thatapm unpackaccepts after the v0.12.0 default flip to plugin format. (#1121) - Windows CI: explicit UTF-8 encoding in the
_make_packagetest helper to unblock Windows runners. (#1124)
--target agent-skillsdeploys skills to.agents/skills/(cross-client shared directory). The new target writesSKILL.mdfiles to the agentskills.io standard location without tying them to a single client. Excluded from--target all(explicit opt-in only); combine with--target all,agent-skillsfor both. Deduplicates with Codex when both targets resolve to the same path. User-scope (-g) deploys to~/.agents/skills/. (closes #737)- Claude Code as MCP install target.
apm install --runtime claude(and auto-detection when.claude/exists or theclaudebinary is on PATH) writes MCP server entries to project-scope.mcp.jsonand user-scope~/.claude.jsonper the Claude Code MCP schema. Project writes are opt-in (gated on the presence of.claude/, mirroring Cursor/OpenCode) and user writes are atomic with0o600permissions on first creation so concurrent Claude Code sessions cannot truncate the shared config or leak embedded OAuth state. Stdio entries are emitted with explicittype: "stdio"soclaude mcp listrenders them identically to entries installed viaclaude mcp add --transport stdio. Schema fidelity is regression-locked by golden fixtures captured live from the upstreamclaudeCLI (seetests/integration/test_claude_mcp_schema_fidelity.py). Stale-cleanup defaults conservatively when the install scope is unspecified -- only the project file is touched without an explicit-g/--globalopt-in. Note: Claude Code's third LOCAL scope (per-project private under~/.claude.json -> projects.<path>.mcpServers) is intentionally not implemented, since APM packages target reproducible team installs (PROJECT/USER), not per-user-per-project private state. (#1104, closes #643) -- by @dmartinol apm install <local-bundle-path>deploys a previously packed bundle (directory or.tar.gz) air-gapped, with sha256 integrity verification against the bundle's embeddedapm.lock.yaml. Honours--target,--global,--force,--dry-run, plus a new--as ALIASlog/display label flag. Local installs record written paths in the project lockfile (local_deployed_files/local_deployed_file_hashes) and never mutateapm.yml.apm unpackis now[Deprecated]and points at this entrypoint. (#1098)apm packnow embedsapm.lock.yamlinside the bundle with two newpack:fields (target,bundle_files: apath -> sha256manifest) so installs can verify integrity and detect target mismatches before writing any file. (#1098)apm compile -t copilotnow emits.github/copilot-instructions.mdwith zero user configuration -- APM's first Copilot-native compile target. Global instructions in.apm/instructions/are assembled into the file VS Code and GitHub Copilot read automatically; switching targets cleans it up. APM dogfoods this target. (#1048)apm marketplace addaccepts full HTTPS URLs and nested HOST/group/sub/.../REPO shorthands. You can now paste a repository URL straight from the browser (e.g.,apm marketplace add https://github.com/acme/plugin-marketplace) and register marketplaces hosted under nested sub-paths on GitHub Enterprise (ghes.corp.example.com/org/team/repo). Path-traversal sequences in the parsed segments are rejected viavalidate_path_segments. Non-GitHub hosts (GitLab, Bitbucket, etc.) are explicitly rejected at registration time with an actionable error -- this avoids forwarding GitHub credentials to unintended hosts and the silent fetch-time 404 that previously resulted; native non-GitHub support is tracked separately. (#1034, closes #1027)- Regression tests for
apm compileplacement of narrowapplyTopatterns: instructions whose matches all live deep inside one subtree are now pinned to the deepest covering directory instead of being hoisted to the project root, across both selective and single-point placement strategies. Also covers the file-walk cache that skips repeated filesystem scans for the same glob. (#871) apm packmarketplace builder hardening. Local source paths are now emitted relative tometadata.pluginRoot(fixes double-prefix bug). New pass-through fields:author,license,repository,keywords(alias fortags). Curator-wins override semantics fordescription/versionon remote entries. Security guards reject path traversal and absolute paths post-subtraction. (#1061)- Plugin manifest schema-conformance tests.
tests/unit/test_plugin_exporter_schema.pyvalidates every shape ofplugin.jsonproduced byapm pack(synthesized, authored, and authored-with-stale-keys) against the vendored official schema. Companion marketplace conformance lives intests/unit/marketplace/test_schema_conformance.py. (#1061) - APM now compiles and integrates to Windsurf/Cascade. New first-class
--target windsurfsupport: instructions deploy as.windsurf/rules/with trigger frontmatter, agents deploy as.windsurf/skills/<name>/SKILL.md, commands as.windsurf/workflows/, hooks merge into.windsurf/hooks.json, and MCP servers configure via~/.codeium/windsurf/mcp_config.json. Auto-detection, user-scope deployment, andapm packall support the new target. (#1066) - Slash commands installed from APM packages now surface argument hints in Claude Code --
apm installautomatically maps promptinput:to Claude'sarguments:front-matter, rewrites${input:name}references to$name, and auto-generatesargument-hint. Argument names are validated against an allowlist to prevent YAML injection from third-party packages, and the mapping is reported at install time. (#1039)
- Skills for Copilot, Cursor, OpenCode, and Codex now deploy to
.agents/skills/by default (skill routing convergence). The four clients whose documentation lists.agents/as a skill discovery path now share a single deployment directory, eliminating up to 4 redundant copies per skill when--target allis used. Claude retains its native per-client routing (.claude/skills/); Gemini joins the convergence in the entry below. Pass--legacy-skill-paths(or setAPM_LEGACY_SKILL_PATHS=1) to restore the previous per-client layout. (closes #1103) - Gemini CLI joins the
.agents/skills/convergence by default. Gemini CLI docs list.agents/skills/as the preferred alias over.gemini/skills/, so Gemini now shares the converged deployment directory with Copilot, Cursor, OpenCode, and Codex (5 clients total). Claude remains on its native.claude/skills/routing. (#737) - Auto-migration:
apm installnow migrates legacy per-client skill deployments (.github/skills/,.cursor/skills/,.opencode/skills/,.gemini/skills/) recorded inapm.lock.yamlto.agents/skills/. Foreign / hand-authored skills outside the lockfile are left untouched. Use--legacy-skill-pathsto opt out. (#737) - Renamed
NOTICE.md->NOTICEto follow the Apache / CNCF convention used by upstream third-party-attribution files (e.g.kubernetes-sigs/kro,kubernetes-sigs/headlamp). The generator (scripts/generate-notice.py),make noticetarget, andNOTICE Drift Checkworkflow now operate on the extension-less path. (#1073) - NOTICE: added "Submitted on behalf of a third-party" section crediting five contributors whose pull requests landed before the
microsoft-github-policy-serviceCLA bot recorded a signature on file -- in keeping with the section-7 wording adopted by CNCF NOTICE files. Driven by a new_third_party_submissionsblock inscripts/notice-metadata.yaml. (#1073) - BREAKING:
apm packnow produces a Claude Code plugin directory by default — zero extra flags, schema-validatedplugin.json, convention dirs auto-discovered. The legacy APM bundle layout is preserved under--format apm. Migration: CI workflows and scripts that consume the legacy bundle must add--format apm(themicrosoft/apm-actionwrapper has been updated accordingly). (#1061) - Plugin manifest schema conformance. The synthesized/written
plugin.jsonno longer emitsagents/skills/commands/instructionskeys pointing at the convention directories — these are auto-discovered by Claude Code, and per the official schema those array entries must be./*.mdpaths to additional files. The convention dirs themselves are still copied to disk. When stripping such keys from an authoredplugin.json,apm packnow emits a warning so authors can clean up their source. (#1061)
--target agentsis deprecated -- it maps tocopilot(.github/), not.agents/. Use--target copilotor--target agent-skills. Removal in v1.0. (closes #627, #640, #664)
- BREAKING: dropped support for
.collection.yml/.collection.yamlvirtual packages. Dependencies whose paths end in.collection.ymlor.collection.yamlnow raise aValueErrorat parse time with a migration message. Convert any such entry to a regularapm.ymlwith adependencies:section under the same subdirectory, then reference the directory itself as a subdirectory virtual package (no extension). The internalVirtualPackageType.COLLECTIONenum value, thedownload_collection_packagecodepath, theis_virtual_collection()reference helper, and theMETA_PACKAGEpackage-type label have been removed -- none were persisted to the lockfile, so existing locks are unaffected. (#1097, closes #1094) Thanks @edenfunf for the original PR.
apm installnow anchors transitivelocal_pathdeps on the declaring package's directory (npm/pip/cargo parity). Sibling/monorepo layouts (e.g.../basedeclared insidepackages/specialized/apm.yml) now resolve relative to the declaring package, not the consumer's project root. Security tightening: remote-cloned packages can no longer declarelocal_pathdeps -- both relative and absolute paths are rejected atERRORseverity at resolve time. (#1111, closes #857) Thanks @JahanzaibTayyab.apm compileno longer silently drops instructions without anapplyTopattern from generatedAGENTS.mdandCLAUDE.md; globals now render under a## Global Instructionssection, matching the optimizer's existing(global)placement (#1088, closes #1072)apm installno longer masks local-bundle install failures withUnboundLocalError. (#1108)apm install <pkg>@<marketplace>no longer fails for all marketplace packages. The install resolver now accepts both legacy and current marketplace key names:repository/repofor github sources,url/repofor git-subdir sources, andtype/sourceas the source-type discriminator. A scheme guard rejects full URLs passed through theurlfallback. (#1106, closes #1105)apm install --updateno longer fails for GHES/generic hosts that rely on git credential helpers (e.g.,git-credential-manager) for authentication. The preflight auth probe was blocking credential helpers by settingGIT_CONFIG_GLOBAL=/dev/null; it now uses the same relaxed environment as the clone fallback path for non-GitHub/non-ADO hosts. (#1082)apm compile --dry-run -t copilotnow faithfully simulates the hand-authored file guard: a.github/copilot-instructions.mdlacking the APM marker is reported asskipped=1(matching the real run) instead of asgenerated=1. Previously dry-run would claim a write that a real run would refuse, giving CI preview gates a false signal. (#1048)apm compile -t claude,copilot(and any multi-target list includingcopilot) now correctly generates.github/copilot-instructions.md; previously it was silently skipped on the multi-target code path. (#1048)apm compileno longer overwrites a hand-authored.github/copilot-instructions.md; if the file lacks the APM-generated marker, regeneration is skipped with a warning that names the literal marker line (<!-- Generated by APM CLI from .apm/ primitives -->) so users can self-serve recovery. Migration: to adopt APM management of an existing file, either delete or rename it and re-runapm compile, or prepend the marker line to the top of the file and re-runapm compile. (#1048)- Generated footer in
.github/copilot-instructions.mdnow readsapm compile(wasspecify apm compile). (#1048) apm compile --targets claudeno longer lists@apm_modules/{owner}/{package}/CLAUDE.mddependencies for packages that don't have aCLAUDE.mdfile on disk (#1047)apm pruneno longer flags directories it put there itself -- skills installed from a subdirectory path (e.g.,owner/repo/.apm/skills/skill-name) no longer cause the parentowner/repo/clone to appear as an orphan. Fixes spurious removal prompts in multi-skill and monorepo-style setups. The same fix applies toapm deps listandapm compile. A genuinely orphanedowner/repopackage is still flagged even when a sibling subdirectory dep shares the sameowner/reporoot. No changes toapm.ymlor the lockfile are required to benefit from this fix. (#1050)
apm packis now the single command for marketplace builds -- with anapm.ymlmarketplace:block it emits.claude-plugin/marketplace.jsondirectly. New flags:--offline,--include-prerelease,--marketplace-output PATH. (#722)- Author marketplaces from
apm.yml. New top-levelmarketplace:block,apm marketplace migrateto consolidate legacymarketplace.yml,apm init --marketplaceto scaffold, and first-classsource: ./local/pathpackage sources. (#1038) - Codex CLI installs are now project-scoped. MCP config lands in
.codex/config.tomlfor project installs (no more polluting the user-global file); user-scope primitive deployment is also supported. (#803) - Cross-org private packages in
shared/apm.mdvia a newapps:array (one GitHub App per credential group, matrix fan-out). The single-app shorthand (app-id/private-key/owner/repositories) is preserved. (#982)
apm marketplace addpreserves the upstream alias -- now defaults to thenamedeclared in the fetchedmarketplace.jsoninstead of the repo name, so install instructions in third-party READMEs work verbatim. (#1032)--policy/--policy-sourcehelp is unified across CLI and docs, with lockstep tests pinning all surfaces against drift. (#1000, closes #998 #994)- BREAKING: invalid
target:values now fail loud. CSV strings (target: a,b,c), unknown tokens, empty values, andallmixed with other targets used to silently no-opapm install/apm compile; they now raise a parse error. Omittingtarget:still auto-detects. (#820) - Rename
DownloadStrategyManager->DownloadDelegateand fix double-checked-locking bug in marketplace registry_load(). (#918)
- BREAKING:
apm marketplace buildremoved --apm packis the replacement; the old verb exits 2 with a migration hint. Themarketplace_authoringexperimental flag is also gone (authoring is GA). (#722)
- Standalone
marketplace.yml-- still loaded with a deprecation warning, removal slated for v0.13. (#1038)
apm installworks with your existing credential chain (SSO, EMU, GHES tokens). Validation now uses the same credentials as the actual clone (PAT header-injected, then git credential helper, then SSH for explicit#refpins) -- enterprise users whose env-var PAT has narrower SSO/EMU access than theirgh auth setup-git/ OS keychain are no longer false-rejected by the installer's API probe. Validation logic is now a separate module (github_downloader_validation.py), laying groundwork for future credential-provider extensibility. (#941)shared/apm.mdsingle-credential-group runs no longer fail validation with a spuriousmissing APM bundles: apm-default-- a normalisation step recreates the per-group subdir layout thatactions/download-artifact@v5+flattens away. (#1051)apm packworks against GitHub Enterprise and other Git hosts -- honorsGITHUB_HOSTfor GHES auth and accepts GitHub / GHES / GitLab / Bitbucket / ADO / SSH URL forms. (#1008)- ADO Entra ID auth no longer silently fails. Bearer tokens from
az account get-access-tokenare plumbed through, errors are typed + actionable (4-case diagnostic), andapm install --updatepre-flights auth before touching files. (#1015) apm marketplace addnow uses thenamefield from the fetchedmarketplace.jsonas the default local alias, falling back to the repo name only when the manifest omits it or declares an invalid value. This restores parity with Claude Code install instructions (e.g.addyosmani/agent-skillsregisters asaddy-agent-skillsas that repo's README documents). Existing marketplace entries are unaffected; use--nameto override explicitly. (#1032)GEMINI.mdis now only created when explicitly targeted. (#1019)- Windows-friendly: auto-discovery CLI output uses POSIX paths so
apm install/apm compileoutput is readable on Windows. (#1018) - Generated-file footer no longer prints stray
specifybeforeapm compile. (#996) - CodeQL
clear-text-storagefalse-positive resolved (variable rename). (#1002)
- Microsoft 365 Copilot Cowork target works end-to-end:
apm install --target cowork --globaldeploys skills to OneDrive (behindapm experimental enable cowork). (#926) - [Experimental]
apm marketplaceauthoring CLI: maintainers can scaffold, build, validate, and publish Anthropic-compliant marketplaces from the CLI (init->package add->build->publish). (#790) - README "Coming from
npx skills add?" 30-second migration table for users arriving from the agentskills.io ecosystem. (#980) NullCommandLoggerclass (src/apm_cli/core/null_logger.py) -- null-object pattern for logger injection, eliminating 32 conditional logger forks inMCPIntegrator. (#918)- Thread-safety infrastructure:
_get_console()double-checked locking singleton, marketplace registry cachethreading.Lock. (#918) - 40 characterisation tests for
MCPIntegratormethods (install(),remove_stale(),collect_transitive()). (#918) _build_children_index()helper in uninstall engine for O(n) reverse-dependency lookups. (#918)- Performance benchmarks and scaling guards for complexity audit refactors (
tests/benchmarks/test_audit_benchmarks.py,test_scaling_guards.py): 16 benchmark tests covering dependency parsing, children index, primitive discovery, registry cache, console singleton, and NullCommandLogger; 3 scaling-ratio guards run in the default test suite to catch O(n^2) regressions. (#918) - Expanded performance benchmark suite with P0 and P1 hot-path coverage:
compute_package_hash,get_all_dependencies,is_semantically_equivalent,flatten_dependencies,to_yaml,compute_deployed_hashes,optimize_instruction_placement,_rewrite_markdown_links,partition_managed_files, LockFile round-trip, andregister_contexts-- 52 new benchmark tests plus 2 additional scaling guards. (#918) - Iteration 2 benchmark coverage:
_match_double_starrecursive glob matcher,ContentScanner.scan_textandstrip_dangeroussecurity scanning,build_dependency_treeBFS resolver,_parse_ls_remote_outputand_sort_remote_refsgit ref parsing,analyze_directory_structurecompiler analysis, andcollect_transitiveMCP integration -- 77 new benchmark tests plus 1 additional scaling guard. (#918)
- [Experimental]
apm marketplace pluginrenamed toapm marketplace package(npm/pip/cargo familiarity);--helpgrouped into Consumer / Authoring sections. (#722) MCPIntegratorlogger handling: methods default toNullCommandLoggerinstead ofNone, removing 32if logger:/elif logger:conditional forks (net -91 production lines). (#918)- Install pipeline lockfile reads reduced from 2x to 1x by caching early lockfile on
InstallContext. (#918) APMPackage.from_apm_yml(): deduplicated dependency parsing via_parse_dependency_dict()classmethod. (#918)- Uninstall engine BFS orphan detection: O(n^2) full-scan replaced with O(n) reverse-dep index. (#918)
- Primitive discovery scanning: 9+
glob.glob()calls replaced with singleos.walk+fnmatchpass. (#918) - MCP registry config reads: O(servers x runtimes) reduced to O(runtimes) via function-scoped cache. (#918)
_get_console(): returns thread-safe singleton instead of creating newConsole()per call. (#918)- Marketplace registry cache:
_load(),_save(),_invalidate_cache()protected withthreading.Lock. (#918) - Complexity audit -- decomposed god functions in
reference.py,audit.py,deps/cli.py, andscript_runner.pyinto focused single-responsibility helpers (largest:audit()290 lines split into thin dispatcher +_audit_ci_gate+_audit_content_scanwith shared_AuditConfigdataclass). (#918) - Decomposed
github_downloader.pyinto three modules:git_remote_ops.py(ref parsing),download_strategies.py(backend downloads), and a slimmed orchestrator. (#918) - Decomposed
install()god function (555 lines) into focused helpers withInstallContextparameter bundle. (#918)
- Docs site auto-deploys again after bot-cut releases (now triggered on tag push). (#981)
- Bare
except:clauses informatters.py(5) andscript_formatters.py(2) now catchExceptioninstead ofBaseException, allowingKeyboardInterruptandSystemExitto propagate correctly. (#918) - Silent auth fallback in
discovery.py:_get_token_for_host()now logslogger.debug()when the token manager fails, making credential resolution failures visible with--verbose. (#918) - Silent
except Exception: passhandlers inagents_compiler.py(3) now emit_logger.debug()traces for config loading and constitution injection failures. (#918) - Double
iterdir()walk inscript_runner.py:_resolve_prompt_file()collapsed to a single pass. (#918)
- Clarify
NullCommandLoggerpartial interface and visible-output semantics in docstring. (#918)
pr-description-skillships an evals suite so PR-description quality regressions are caught in CI without an LLM API key. (#985)pr-description-skillmermaid guidance hardened withassets/mermaid-conventions.md(diagram-type-by-intent + GitHub-renderer gotchasmmdcmisses). (#984)- Cowork tests mock
sys.platformso the macOS auto-detection paths don't false-fail on Windows CI. (#989)
- Day-0 install parity with
npx skills add: every public repo that installs cleanly withnpx skills add owner/reponow installs withapm install owner/repo. APM recognises bareskills/<name>/SKILL.md(vercel-labs/agent-skills, xixu-me/skills, larksuite/cli, the agentskills.io ecosystem) as a first-class shape (SKILL_BUNDLE);apm.ymlis optional.--skill <NAME>(repeatable) selects a subset and persists it toapm.yml+apm.lock.yaml, so bareapm installis reproducible across machines.--skill '*'resets;apm audit --ciflags drift. (#974) curl | shinstall works in air-gapped, GHE, and internal-mirror setups:install.shnow readsAPM_INSTALL_DIR,GITHUB_URL,APM_REPO, andVERSION(or@vX.Y.Zarg) -- pinning a version skips the GitHub API entirely, so corporate runners without api.github.com egress can bootstrap APM. (#660)
apm marketplaceauthoring commands (init, build, check, outdated, doctor, publish, package) ring-fenced behindapm experimental enable marketplace-authoringfeature flag (default: disabled) (#790)
apm installno longer fails behind corporate TLS-intercepting proxies: validation now honoursREQUESTS_CA_BUNDLEinstead of misreporting CA failures as auth errors. (#911)apm experimental <subcommand> --helpnow shows the subcommand's own help; CLI help text and short flags aligned from the 2026-04-24 audit. (#910, #903)
- Untriaged issues are auto-triaged by the
apm-triage-panelskill on a daily oldest-first sweep (max 10/run) plusstatus/needs-triagefor on-demand. Decisions are agentic proposals; any maintainer label edit wins. (#954) - Docs site auto-deploys again after bot-cut releases (workaround for GitHub's
GITHUB_TOKEN-suppressedrelease: publishedevent). Silently broken since v0.9.3. (#953) - Triage-panel themed issues now reach the PGS project board (dispatches
project-syncdirectly; sameGITHUB_TOKENevent-suppression class as #953). (#971) - Issue templates use canonical APM labels;
python-architectagent documents the mermaidclassDiagram :::cssClassGitHub-render trap. (#958, #970)
- Gemini CLI as a supported APM target (
--target gemini): auto-detects.gemini/, writes MCP config to.gemini/settings.json, and addsapm runtime setup|remove gemini. (#917) - Experimental
coworktarget for Microsoft 365 Copilot Cowork custom-skill deployment via OneDrive (apm experimental enable cowork;apm install --target cowork --global; persisted viaapm config set cowork-skills-dir). (#913) apm experimentalcommand group (list/enable/disable/reset) lets you opt into new behaviour before it graduates to default. Ships with theverbose-versionflag. (#849)apm audit --cinow verifies hash integrity of locally deployed.apm/files so hand-edits and config drift fail CI instead of slipping through. (#887)includes:manifest field (autoor list) gives you explicit control over which local.apm/files are deployed; pair withpolicy.manifest.require_explicit_includesto block silent expansion. Audit raises anincludes-consentadvisory while you migrate. (#887)apm-triage-panelskill: three-persona issue triage panel (DevX UX, Supply Chain Security, APM CEO) emitting a single labelled-decision comment, mirroringapm-review-panel. (#915)apm-primitives-architectpersona for designing and critiquing.apm/skill bundles, plus apr-description-skillthat enforces self-sufficient PR bodies (TL;DR/Problem/Approach/Implementation/Diagrams/Trade-offs/Benefits/Validation/How-to-test) with anchored citations and validated mermaid. (#882, #884)- New docs guide
dev-only-primitives: canonical pattern for maintainer-only primitives that must not ride into your published bundle. (#949) - Maintainer tooling: PGS project-board sync workflow keeps issues in lockstep with labels/milestones;
APM Self-CheckCI job dogfoodsapm audit --ciand regeneration-drift gates. (#919, #885)
- HYBRID-skill review pipeline:
apm-review-panelnow produces a single CEO-synthesized verdict per run (no per-persona spam), with Hybrid E auth-expert routing andpython-architect's mandatory three-artifact contract. PRs get one high-signal comment. (#882, #905, #907, #908) - Faster primitive discovery on large repos:
compilation.excludepatterns now prune traversal at the directory level instead of post-filtering. (#870) apm-actionbumped tov1.4.2(used byshared/apm.mdworkflows): fixes restore-mode workspace pollution that was overwriting your trackedapm.lock.yaml/apm.yml/apm_modules. (#904)- CI release-binary smoke (Linux x64/arm64, Windows) only runs on tag/schedule/dispatch instead of every push, cutting ~15 redundant codex downloads/day; release-time gating unchanged. (#878)
- Branch-protection docs: clarify the required check-run name is
gate(not the workflow display stringMerge Gate / gate). (#874)
- HYBRID packages (apm.yml + SKILL.md, no
.apm/) and CLAUDE_SKILL packages with siblingagents//assets//scripts/dirs now install correctly via the skill-bundle path; previouslyapm installrejected them silently and looked like a hang. Direct-dependency integration failures now print[x]and exit 1 instead of failing silently. (#946) apm updateno longer breaks on Debian trixie arm64, Fedora 43, and similar distros where the bundled PyInstallerLD_LIBRARY_PATHwas leaking into systemcurl/tarand triggeringlibssl.so.3: version 'OPENSSL_3.2.0' not found. Closes #894 (#899)apm installat user scope no longer recursive-globs your entire home directory: scan is scoped to~/.apm/. Fixes #830 (#850)apm audit --cinow also catches drift / missing / tampered files for locally-authored.apm/content (not just installed packages);apm packstrips local-content fields so they can't leak into bundled lockfiles. (#887)apm installfor ADO orgs that disable PAT creation: error messages on generic git hosts now surface the custom port too. Custom transport types in MCP-server config are validated up front (defaulting tohttpwhen missing) instead of writing garbage. Closes #791 (#812)- Windows:
apm installno longer false-positivesPathTraversalErroron policy cache dirs that don't yet exist (8.3 short-name resolution mismatch). (#895) - macOS: long inline policy YAML strings (>1023 bytes) no longer crash with
OSError [Errno 63] File name too long; they fall back to string-mode parsing. Closes #848 (#860) - Merge queue:
gatecheck now reports inside the queue (addedmerge_grouptrigger), unblocking PRs that were stuck on "Expected -- Waiting for status to be reported". (#921) apm-review-panelworkflow only runs on PRs labelledpanel-review, eliminating spurious panel runs on every PR. (#948)
- Deleted dead
ci-integration-pr-stub.ymlworkflow stubs left over from the pre-merge-gate model. No user impact; reduces CI noise. (#875)
apm installsupports Azure DevOps AAD bearer-token auth viaaz account get-access-token, with PAT-first fallback for orgs that disable PAT creation. Closes #852 (#856)- New
enterprise/governance-guide.md: flagship governance reference for CISO / VPE / Platform Tech Lead audiences; trims duplication acrossgovernance.md,apm-policy.md,integrations/github-rulesets.md; addstemplates/apm-policy-starter.yml. (#851) - Enterprise docs IA refactor: hub page + merged team guides, deduped governance content. (#858)
- Landing page rewritten around the three-pillar spine. (#855)
- First-package tutorial rewritten end-to-end; fixes
.apm/anatomy hallucinations. (#866) apm install --ssh/--httpsflags andAPM_GIT_PROTOCOL=ssh|httpsenv to pick the initial transport for shorthand dependencies (#778)apm install --allow-protocol-fallbackflag andAPM_ALLOW_PROTOCOL_FALLBACK=1env as the migration escape hatch for cross-protocol fallback (#778)- Add APM Review Panel skill (
.github/skills/apm-review-panel/) and four new specialist personas (devx-ux-expert,supply-chain-security-expert,apm-ceo,oss-growth-hacker) with auto-activating per-persona skills. Routes specialist findings through an APM CEO arbiter for strategic / breaking-change calls, with the OSS growth hacker side-channeling adoption insights viaWIP/growth-strategy.md. Instrumentation per Handbook Ch. 9 (The Instrumented Codebase); PROSE-compliant (thin SKILL.md routers, persona detail lazy-loaded via markdown links, explicit boundaries per persona). apm view plugin@marketplacedisplays marketplace plugin metadata (name, version, source, description) (#514)apm outdatedchecks marketplace plugin refs and shows a "Source" column distinguishing marketplace vs git updates (#514)apm marketplace validatecommand with schema validation and duplicate name detection (#514)- Ref immutability advisory: caches plugin-to-ref pins and warns when a previously pinned plugin's ref changes (#514)
- Multi-marketplace shadow detection: warns when the same plugin name appears in multiple registered marketplaces (#514)
- gh-aw workflows now use
imports:for shared APM context instead of the deprecateddependencies:field. (#864) - CI:
merge-gate.ymlorchestrator turns droppedpull_requestwebhook deliveries into clear red checks instead of stuckExpected -- Waiting for status to be reported. (#865) - CI:
Merge Gate / gateaggregates all PR-time required checks (Build & Test (Linux)+ 4 stubs) into a single verdict; branch protection requires only this one check, decoupling the ruleset from CI workflow topology (Tide / bors pattern). (#867, #868) - CI:
merge-gate.ymlsimplified to a singlepull_requesttrigger withworkflow_dispatchfor manual recovery; the dual-trigger redundancy attempt was poisoning the branch-protection rollup withCANCELLEDcheck-runs. (#868)
apm installsurfaces the custom port in clone /ls-remoteerror messages for generic git hosts. (#804)
apm installenforces orgapm-policy.ymlat install time (deps deny/allow/require, MCP deny/transport/trust-transitive,compilation.target.allow,extends:chains,policy.fetch_failureknob,policy.hashpin);--no-policy/APM_POLICY_DISABLE=1escape hatch;--dry-runpreviews verdicts; failed package installs roll backapm.yml. Newapm policy statusdiagnostic (table /--json, exit-0 by default,--checkfor CI).apm audit --ciauto-discovers org policy. Migration: orgs publishingenforcement: blockmay see installs that previously succeeded now fail -- preview withapm install --dry-run. Closes #827, #829, #831, #834 (#832)pr-review-panelgh-aw workflow: runs theapm-review-panelskill on PRs labelledpanel-reviewand posts a synthesized verdict (#824)
- Docs site publishes only on stable APM releases, not on every push to
main. Closes #641 (#822) - Dogfood APM: authored skills, agents, and instructions live in
.apm/;.github/{skills,agents,instructions}/are regenerated byapm install --target copilotand committed (#823)
pr-review-panelworkflow now runs on PRs from forks: switched topull_request_targetwith label-only triggering and a workflow-dispatch path (#826, #836, #837)- Lowercase the host axis of the
_fallback_port_warneddedup key so deps that differ only in hostname casing collapse to one cross-protocol fallback warning, matching theAuthResolver._cacheconvention (RFC 4343). Closes #800 (#815)
- Strict-by-default git transport selection: explicit
ssh:///https://URLs no longer silently cross-fall back; shorthand defaults to HTTPS (consultsurl.<base>.insteadOf). Opt back into the legacy chain with--allow-protocol-fallbackorAPM_ALLOW_PROTOCOL_FALLBACK=1. Adds--ssh/--https/APM_GIT_PROTOCOLfor explicit shorthand selection. Closes #328 (#778) - MCP entry validation hardened: names must match
^[a-zA-Z0-9@_][a-zA-Z0-9._@/:=-]{0,127}$, URLs limited tohttp/https, headers reject CR/LF, stdio commands reject... Error messages now include a valid positive example. (#807) - Stdio MCP entries with whitespace in
commandand noargsare rejected at parse time with a fix-it error pointing at the canonicalcommand: <binary>, args: [...]shape. Closes #806 (#809)
apm install --mcp NAME(andapm mcp installalias) for declaratively adding MCP servers toapm.yml, with--transport/--url/--env/--header/--mcp-version/--registryflags and stdio passthrough. TTY prompts on replace,--forcerequired in CI. Includes--registry URLandMCP_REGISTRY_URLenv for custom (enterprise) MCP registries. Closes #807 (#810)- HTTP dependency support via
--allow-insecure+allow_insecure: truedual opt-in;--allow-insecure-hostfor transitive HTTP from new hosts; credential-helper suppression on HTTP attempts to prevent token leakage; newapm deps list --insecureview withOrigincolumn. Threat model inenterprise/security.md. Thanks @arika0093! (#700) - Multi-target support:
apm.ymltargetaccepts a list ([claude, copilot]) and CLI--targetaccepts comma-separated values; only specified targets are compiled/installed/packed. Single-string form remains backward compatible. (#628) - Marketplace UX overhaul:
apm view plugin@marketplace,apm outdatedSource column,apm marketplace validate, ref-immutability advisory, multi-marketplace shadow detection. (#514) - New MCP Servers guide (
docs/guides/mcp-servers.md) consolidating stdio / registry / remote shapes, flag reference, validation rules, and the conflict matrix in one page; assorted MCP doc drift fixes (#808) - Build-time
update_policymodule so package-manager distributions (conda-forge, brew, pixi) can disableapm updateand show custom guidance. Thanks @joostsijm! (#675) - APM Review Panel skill (
.github/skills/apm-review-panel/) plus four specialist personas (devx-ux, supply-chain-security, apm-ceo, oss-growth-hacker) routing through an APM CEO arbiter (#777)
- Preserve custom git ports across protocols: non-default ports on
ssh:///https://dependency URLs (e.g. Bitbucket Datacenter SSH 7999, self-hosted GitLab HTTPS 8443) are captured asDependencyReference.portand reused on HTTPS fallback. Closes #661, #731 (#665) - Token resolution now discriminates by port, fixing credential collisions across multiple self-hosted Git instances on the same host. Thanks @edenfunf! Closes #785 (#788)
- Detect port-like first path segment in SCP shorthand (
git@host:7999/path) and raise an actionable error suggesting thessh://form. Closes #784 (#787) --allow-protocol-fallbackemits a one-shot[!]warning when a dependency's custom port is about to be tried across both SSH and HTTPS, recommending pinning the scheme. Closes #786 (#789)apm install --globalnow installs MCP servers to global-capable runtimes (Copilot CLI, Codex CLI) instead of skipping all MCP at user scope;--trust-transitive-mcpno longer ignored under--global. Lockfile-path behavior at--globaltracked in #794 (#638)apm installno longer silently drops skills/agents/commands when a Claude Code plugin also shipshooks/*.json: detection cascade now classifies plugin-shaped packages asMARKETPLACE_PLUGINfirst; emits a[!]warning when a hook-only classification disagrees with package contents (#780)apm mcp search/list/shownow honourMCP_REGISTRY_URL(previously hardcoded to the public registry), print aRegistry: <url>diagnostic when set, and surface the configured URL in network-error messages (#813)- VS Code adapter defaults to
httptransport whentransport_typeis missing from remote registry data, matching Copilot adapter behavior (#654) apm initno longer prompts to overwrite three times on Windows CP950 terminals. Closes #602 (#647)apm initNext Steps panel surfaces install/marketplace/plugin workflows instead of the dead-endapm run startreference. Closes #603 (#649)
MCP_REGISTRY_URLvalidated at startup (schemeless / unsupported schemes rejected;http://rejected by default, opt in viaMCP_REGISTRY_ALLOW_HTTP=1); APM fails closed when a custom registry is unreachable during install pre-flight, instead of silently approving every MCP dep. Default registry keeps assume-valid for transient errors. (#814)apm install --mcpdefense-in-depth: rejects embedded..in dep names with a valid positive example, redacts URL credentials in diagnostic output (https://user:token@host/->https://host/), warns on--registry/MCP_REGISTRY_URLpointing at loopback / link-local / RFC1918 / cloud-metadata hosts (including decimal-encoded loopback). (#810)SimpleRegistryClientapplies a(connect=10s, read=30s)timeout on every registry HTTP call, removing the unbounded-hang failure mode. Tunable viaMCP_REGISTRY_CONNECT_TIMEOUT/MCP_REGISTRY_READ_TIMEOUT. (#810)
apm installnow automatically discovers and deploys local.apm/primitives (skills, instructions, agents, prompts, hooks, commands) to target directories, with local content taking priority over dependencies on collision (#626, #644)- Deploy primitives from the project root's own
.apm/directory alongside declared dependencies, so single-package projects no longer need a sub-package stub to install their own content (#715) - Add
temp-dirconfiguration key (apm config set temp-dir PATH) to override the system temporary directory, resolving[WinError 5] Access is deniedin corporate Windows environments (#629)
- Refactor
apm installinto a modular engine package (apm_cli/install/) with discrete phases and apply Strategy / Template Method / Application Service patterns; public CLI behaviour and the#762cleanup chokepoint unchanged (#764) apm marketplace browse/search/add/updatenow route through the registry proxy whenPROXY_REGISTRY_URLis set;PROXY_REGISTRY_ONLY=1blocks direct GitHub API calls (#506, #617)- CI: adopt GitHub Merge Queue with tiered CI (Tier 1 unit + binary on
pull_request+merge_group; Tier 2 integration + release-validation onmerge_grouponly) plus an inertpull_request_targetstub workflow for required-check satisfaction. CODEOWNERS now requires Lead Maintainer review for any change to.github/workflows/**(#770, #771) - Bump
pytestfrom 8.4.2 to 9.0.3 (#698) - Bump
dompurifyfrom 3.3.2 to 3.4.0 in/docs(#730) - Bump
lodash-esandlangiumin/docs(#761) - Add
.editorconfigto standardize charset, line endings, indentation, and trailing whitespace across contributions (#671) - Add
@sergio-sisternes-epamas maintainer (#623) - Close install/uninstall/update CLI integration coverage gaps surfaced by the
#764review (#767) - Add 55 unit tests for
commands/deps/_utils.pyandcommands/view.pyto address Test Improver backlog items #4 and #5 (#682)
- Harden
apm installstale-file cleanup to prevent unsafe lockfile deletions, preserve user-edited files via per-file SHA-256 provenance, and improve cleanup reporting during install and--dry-run(#666, #750, #762) - Local
.apm/stale-cleanup now uses pre-install content hashes for provenance verification. Previously the lockfile was re-read after regeneration, which always yielded empty hashes, causing the user-edit safety gate to be silently skipped for project-local files (#764) - Fix
apm install --target claudenot creating.claude/when the directory does not already exist (auto_create=Falsetargets now get their root directory created when explicitly requested) (#763) - Fix content hash mismatch on re-install when
.git/is absent from installed packages by falling back to content-hash verification before re-downloading (#763) - Make
apm installidempotent for hook entries: upsert by_apm_sourceownership marker instead of unconditionally appending, so re-running install no longer duplicates per-event hook commands (#709) - Rewrite Windows backslash paths in hook commands'
windowskey during integration; previously only Unix-style./references were rewritten, leavingwindowsscript paths unresolved at runtime (#609) - Add explicit
encoding="utf-8"to.prompt.mdopen()calls inscript_runnerto preventUnicodeDecodeErroron Windows non-UTF-8 locales (CP950/CP936/CP932) (#607) - Validate the
project_nameargument toapm initand reject/and\to prevent confusing[WinError 3]and silent path-traversal behaviour (#724) - Use
yaml.safe_dumpwhen generatingapm.ymlfor virtual-file and collection packages, sodescriptionvalues containing:no longer breakapm installwith a YAML parse error (#707) _count_package_filesinapm deps listnow reads the canonical.apm/context/(singular) directory; previously it scanned.apm/contexts/and always reported0 context filesper package (#748)apm pack --format pluginno longer emits duplicatedskills/skills/nesting for bare-skill dependencies referenced through virtual paths likeskills/<name>(#738)- Provide an ADO-specific authentication error message for
dev.azure.comremotes so users get actionable guidance instead of a generic GitHub-flavored hint (#742) - Fix
apm compile --target codex(andopencode,minimal) being a silent no-op;AgentsCompiler.compile()now routes these through the AGENTS.md compiler instead of returning an empty success result that left staleAGENTS.mdfiles (#766) - Support
codeload.github.com-style archive URLs in Artifactory archive URL generation, unblocking JFrog Artifactory proxies configured againstcodeload.github.com(#712) _parse_artifactory_base_url()now readsPROXY_REGISTRY_URLfirst (withARTIFACTORY_BASE_URLfallback +DeprecationWarning), and the virtual-subdirectory download path checksdep_ref.is_artifactory()before falling back to env-var detection, fixing lockfile reinstall failures when proxy config is only on the lockfile entry (#616)- Fall back to SSH URLs when validating git remotes for generic / self-hosted hosts so
apm installno longer fails the pre-install validation step against private SSH-only servers (#584) - Suppress internal config keys (e.g.
default_client) fromapm config getoutput, removing the get/set asymmetry that confused users and was flagged as a Medium security issue (#571) - Include dependency instructions stored in
.github/instructions/(not only.apm/instructions/) when runningapm compile --target claudewithout--local-only(#631, #642) - Fix
apm marketplace addsilently failing for private repos by using credentials when probingmarketplace.json(#701) - Harden marketplace plugin normalization to enforce that manifest-declared
agents/skills/commands/hookspaths resolve inside the plugin root (#760) - Pin codex setup to
rust-v0.118.0for security and reproducibility; update config towire_api = "responses"(#663) - Propagate headers and environment variables through OpenCode MCP adapter with defensive copies to prevent mutation (#622)
- Fix
apm installhanging indefinitely when corporate firewalls silently drop SSH packets by settingGIT_SSH_COMMANDwithConnectTimeout=30(#652, #653) - Stop
test_auto_detect_through_proxyfrom making realapi.github.comcalls by passing a mockauth_resolver, fixing flaky macOS CI rate-limit failures (#759) - Fix the Daily Test Improver workflow creating duplicate monthly activity issues; Task 7 now finds and updates the existing month's issue instead of opening a new one each run (#681)
- Artifactory archive entry download for virtual file packages (#525)
apm view <package> [field]command for viewing package metadata and remote refs (#613)apm view <package> versionsfield selector lists remote tags and branches viagit ls-remote(#613)apm outdatedcommand compares locked dependencies against remote refs (#613)--parallel-checks(-j) option onapm outdatedfor concurrent remote checks (default: 4) (#613)- Rich progress feedback during
apm outdateddependency checking (#613) --globalflag onapm viewfor inspecting user-scope packages (#613)
- Rename
apm infotoapm viewfor npm convention alignment;apm infokept as hidden alias (#613) - Scope resolution now happens once via
TargetProfile.for_scope()andresolve_targets()-- integrators no longer need scope-aware parameters (#562) - Unified integration dispatch table in
dispatch.py-- both install and uninstall import from one source of truth (#562) - Hook merge logic deduplicated: three copy-pasted JSON-merge methods replaced with
_integrate_merged_hooks()+ config dict (#562) apm outdateduses SHA comparison for branch-pinned deps instead of reporting them asunknown(#613)
- Reject symlinked primitive files in all discovery and resolution paths to prevent symlink-based traversal attacks (#596)
apm install -gnow deploys hooks to the scope-resolved target directory instead of hardcoding.github/hooks/(#565, #566)- Hook sync/cleanup derives prefixes dynamically from
KNOWN_TARGETSinstead of hardcoded paths (#565) auto_create=Falsetargets no longer get directories unconditionally created during install (#576)apm deps update -gnow correctly passes scope, preventing user-scope updates from silently using project-scope paths (#562)- Subprocess encoding failures on Windows non-UTF-8 consoles (CP950/CP936) -- all subprocess calls now use explicit UTF-8 encoding (#591)
- PowerShell 5.1 compatibility: replace multi-argument
Join-Pathcalls with nested two-argument calls (#593) apm marketplace addnow respectsGITHUB_HOSTenvironment variable for GitHub Enterprise users (#589)compilation.excludepatterns now filter primitive discovery, preventing excluded files from leaking into compiled output (#477)- Runtime detection in script runner now uses anchored patterns to prevent false positives when runtime keywords appear in flag values (#563)
apm compilenow warns when instructions are missingapplyToacross all compilation modes (#449)- Detect remote default branch instead of hardcoding
main(#574) - Warn when two packages deploy a native skill with the same name (#545)
- Hook integrator now processes the
windowsproperty in hook JSON files, copying referenced scripts and rewriting paths during install/compile (#311) - Standardized
--targetchoices, replaced Unicode with ASCII for cp1252 compatibility, and documented missing CLI flags (#519) apm install -gnow correctly deploys to user-scope directories, skips unsupported primitives, and cleans up on uninstall -- including multi-level paths like~/.config/opencode/(#542)apm deps updatenow correctly re-resolves transitive dependencies instead of reusing stale locked SHAs (#548)
apm installnow deploys.instructions.mdfiles to.claude/rules/*.mdfor Claude Code, convertingapplyTo:frontmatter to Claude'spaths:format (#516)
- Artifactory virtual file downloads now use the Archive Entry Download API to fetch individual files without downloading the full archive; falls back to full-archive extraction when the entry API is unavailable (#525)
apm install NAME@MARKETPLACEnow respectsmetadata.pluginRootfrom marketplace manifests, fixing resolution of bare-name plugins in marketplaces likeawesome-copilot(#512)- Windows unit test assertion tolerates Rich console line-wrapping on long temp paths (#510)
- Release validation scripts match updated
apm deps listscope output (#510)
apm install -g/--globalfor user-scope package installation with per-target support matrix andapm uninstall -glifecycle (#452)- Marketplace integration:
apm install NAME@MARKETPLACEsyntax,apm marketplace add/list/browse/update/remove,apm searchacross registered marketplaces (#503) - Codex as integration target: skills to
.agents/skills/, agents to.codex/agents/*.toml, hooks to.codex/hooks.json,--target codexon install/compile/pack (#504) - Lockfile-driven reproducible installs for registry proxies with
content_hashverification andRegistryConfig-- by @chkp-roniz (#401)
apm deps updateskips download when resolved SHA matches lockfile SHA, making the common "nothing changed" case near-instant (#500)
apm install -g ./local-pkgrejects local path dependencies at user scope with a clear error (#452)- Orphan documentation pages (
ci-policy-setup,policy-reference) added to sidebar navigation; stale GitHub Rulesets content updated (#505, #507)
--target opencodeno longer writes prompts/agents to.github/; dispatch loop now only fires primitives declared by the selected target (#488, #494)--target cursornow correctly deploys skills to.cursor/skills/instead of.github/skills/--SkillIntegratorrespects the explicit target list end-to-end (#482, #494)- Misleading "transitive dep" error message for direct dependency download failures (#478)
- Sparse checkout using global token instead of per-org token from
GITHUB_APM_PAT_<ORG>(#478) - Duplicate error count when a dependency fails during both resolution and install phases (#478)
- Windows Defender false-positive (
Trojan:Win32/Bearfoos.B!ml) mitigation: embed PE version info in Windows binary and disable UPX compression on Windows builds -- by @sergio-sisternes-epam (#490) apm deps updatewas a no-op -- rewrote to delegate to the install engine so lockfile, deployed files, and integration state are all refreshed correctly -- by @webmaxru (#493)
- Integration dispatch is now data-driven:
KNOWN_TARGETSdefines each target's primitives and directory layout; adding a target requires zero code changes (#494) partition_managed_files()uses O(1) component-based path routing instead of linear prefix scan (#494)- Uninstall sync uses pre-partitioned buckets via
partition_bucket_key()instead of re-scanning the full managed-files set (#494)
- Bump
pygmentsfrom 2.19.2 to 2.20.0 (#495)
apm install --targetflag to force deployment to a specific target (copilot, claude, cursor, opencode, all) (#456)- Global
apm install --global/-gandapm uninstall --globalflags for user-scope package installation, backed byInstallScope-based scope resolution incore/scope.py; deploys primitives to~/.copilot/,~/.claude/,~/.cursor/,~/.config/opencode/and tracks metadata under~/.apm/(#452)
- Windows antivirus file-lock errors (
WinError 32) duringapm installwithfile_opsretry utility (#440) - Installer fallback to pip in devcontainers, target registry, and lockfile idempotency fixes (#456)
- Reject path traversal sequences in SSH-style Git URLs — by @thakoreh (#458)
- Exclude bundled OpenSSL libs from Linux binary to prevent ABI conflicts (#466)
- Allow spaces in ADO repository names when parsing URLs (#437)
- Gate
.claude/commands/deployment behindintegrate_claudeflag (#443) - Sort instruction discovery order for deterministic Build IDs across platforms (#468)
- Share
AuthResolveracross install to prevent duplicate auth popups (#424)
- Consolidated path-segment traversal checks into
validate_path_segments()inpath_security.py(#458)
apm audit --ciorg-level policy engine -- experimental Phase 1 for enterprise governance over agents in the SDLC; GitHub / GitHub Enterprise only (#365)-vshorthand for--verbose,show_defaulton boolean options,deps clean --dry-run/--yesflags (#303)--verboseonapm installnow shows auth source diagnostics for virtual package validation failures (#414)- Nightly runtime inference tests decoupled from release pipeline via
ci-runtime.yml(#407)
- CI pipeline optimization: merged test+build jobs, macOS as root nodes, native
setup-uvcaching, removed unnecessarysetup-nodesteps (#407) - Encoding instructions enforce ASCII-only source and CLI output with bracket status symbols (#282)
- Windows path hardening:
portable_relpath()utility, ~23relative_to()call-site migrations, CI lint guard (#411, #422) - Centralized YAML I/O with UTF-8 encoding via
yaml_iohelpers, preventing Windows cp1252 mojibake, based on prior work by @alopezsanchez (#433, #388) - SSL certificate verification in PyInstaller binary via
certifiruntime hook (#429) apm pack --target claudecross-target path mapping for skills/agents installed under.github/(#426)ARTIFACTORY_ONLYenforcement for virtual package types (files, collections, subdirectories) (#418)- Local path install: descriptive failure messages and Windows drive-letter path recognition (#431, #435)
- Windows test fixes in config command and agents compiler (#410)
- Removed stale WIP folder from tracking, strengthened
.gitignore(#420)
- Centralized
AuthResolverwith per-(host, org) token resolution, cached and thread-safe — replaces 4 scattered auth implementations (#394) CommandLoggerandInstallLoggerbase classes for structured CLI output with validation, resolution, and download phases (#394)--verboseflag onuninstall,pack, andunpackcommands (#394)- Verbose output: dependency tree resolution, auth source/type per download, lockfile SHA, package type, inline per-package diagnostics (#394)
- Parent chain breadcrumb in transitive dependency error messages — "root-pkg > mid-pkg > failing-dep" (#394)
DiagnosticCollector.count_for_package()for inline per-package verbose hints (#394)- Auth flow diagram and package source behavior matrix in authentication docs (#394)
- Documented
${input:...}variable support inheadersandenvMCP server fields (#349)
- All CLI output now uses ASCII symbols (
[+],[x],[!]) instead of Unicode characters (#394) - Migrated
_rich_*calls toCommandLoggeracross install, compile, uninstall, audit, pack, and bundle modules (#394) - Verbose ref display uses clean
#tag @shaformat instead of nested parentheses (#394) - Integration tree lines (
└─) no longer have[i]prefix — clean visual hierarchy (#394) - Global env vars (
GITHUB_APM_PAT,GITHUB_TOKEN,GH_TOKEN) apply to all hosts — HTTPS is the security boundary, not host-gating (#394) - Credential-fill timeout increased from 5s to 60s (configurable via
APM_GIT_CREDENTIAL_TIMEOUT, max 180s) — fixes Windows credential picker timeouts (#394)
- Bundle lockfile includes non-target
deployed_filescausingapm unpackverification failure when packing with--target(#394) - Verbose lockfile iteration crashed with
'str' object has no attribute 'resolved_commit'(#394) - CodeQL incomplete URL substring sanitization in test assertions (#394)
- Bumped
h3from 1.15.6 to 1.15.9 in docs (#400)
- Unused image files:
copilot-banner.png,copilot-cli-screenshot.png(#391)
- Plugin authoring —
apm pack --format pluginexports APM packages as standalone plugin directories (plugin.json, agents, skills, commands) consumable by Copilot CLI, Claude Code, and Cursor without APM installed (#379) apm init --pluginscaffolds a hybrid project with bothapm.ymlandplugin.json, including adevDependenciessection (#379)devDependenciesinapm.yml— dev deps install normally but are excluded fromapm packoutput;apm install --devwrites to the dev section (#379)- VS Code runtime detection now falls back to
.vscode/directory presence when thecodebinary is not on PATH — by @sergio-sisternes-epam (#359)
- Content integrity hashing — SHA-256
content_hashper dependency inapm.lock.yaml, verified on subsequent installs to detect tampering or force-pushed commits (#315, #379) apm audit --stripnow preserves a leading BOM while stripping suspicious mid-file BOMs, preventing false negatives — by @dadavidtseng (#372)
- Install URLs now use short
aka.ms/apm-unixandaka.ms/apm-windowsredirects across README, docs, and CLI output (#384) - README highlights link to relevant docs pages; plugin authoring featured as a key value proposition (#385)
DependencyReferencepreserved through the download pipeline so lockfile records the original ref, not an empty object — by @sergio-sisternes-epam (#383)- Refactor command and model modules for readability and maintainability — by @sergio-sisternes-epam (#232)
- CLI docs align
compile --target opencode,audit --dry-run, and plannedaudit --driftwith current behavior (#373)
- JFrog Artifactory VCS repository support — explicit FQDN, transparent proxy via
ARTIFACTORY_BASE_URL, and air-gappedARTIFACTORY_ONLYmode (#354) - GH-AW compatibility gate in release pipeline —
gh-aw-compatjob tests tokenless install + pack before publishing (#356) - Release validation now includes
test_ghaw_compatscenario (#356)
- Credential fill returning garbage token in tokenless CI environments — broke
apm installfor public repos in GitHub Actions (#356)
- Harden dependency path validation — reject invalid path segments at parse time, enforce install-path containment, safe deletion wrappers across
uninstall,prune, andinstall(#364)
- Audit hardening —
apm unpackcontent scanning, SARIF/JSON/Markdown--format/--outputfor CI capture,SecurityGatepolicy engine, non-zero exits on critical findings (#330) - Install output now shows resolved git ref alongside package name (e.g.
✓ owner/repo#main (a1b2c3d4)) (#340) ${input:...}variable resolution for self-defined MCP server headers and env values — by @sergio-sisternes-epam (#344)
- Pinning hint moved from inline tip to
── Diagnostics ──section with aggregated count (#347) - Install ref display uses
#separator instead of@for consistency with dependency syntax (#340) - Shorthand
@aliassyntax removed from dependency strings — use the dict formatalias:field instead (#340)
- File-level downloads from private repos now use OS credential helpers (macOS Keychain,
gh auth login, Windows Credential Manager) (#332) - Lockfile now preserves the host for GitHub Enterprise custom domains so subsequent
apm installclones from the correct server (#338) - MCP registry validation no longer fails on transient network errors (#337)
- Native Cursor IDE integration —
apm installdeploys instructions→rules (.mdc), agents, skills, hooks (hooks.json), and MCP (mcp.json) to.cursor/(#301) - Native OpenCode integration —
apm installdeploys agents, commands, skills, and MCP (opencode.json) to.opencode/— inspired by @timvw (#306) - Content security scanning with
apm auditcommand —--file,--strip,--dry-run; install-time pre-deployment gate blocks critical hidden Unicode characters (#313) - Detect variation selectors (Glassworm attack vector), invisible math operators, bidi marks, annotation markers, and deprecated formatting in content scanning — by @raye-deng (#321, #320)
- Context-aware ZWJ detection — emoji joiners preserved by
--strip;--strip --dry-runpreview mode (#321) TargetProfiledata layer for scalable multi-target architecture (#301)CursorClientAdapterfor MCP server management in.cursor/mcp.json(#301)OpenCodeClientAdapterfor MCP server management inopencode.json(#306)- Private packages guide and enhanced authentication documentation (#314)
- Updated docs landing page to include Cursor and OpenCode (#310)
- Updated all doc pages to reflect full Cursor native support (#304)
- Added OpenCode to README headline and compile description (#308)
- GitHub API rate-limit 403 responses no longer misdiagnosed as authentication failures — unauthenticated users now see actionable "rate limit exceeded" guidance instead of misleading "private repository" errors
- Local filesystem path dependencies — install packages from relative/absolute paths with
apm install ./my-package(#270) - Windows native support (Phase 1 & 2) — cross-platform runtime management, PowerShell helpers, and CI parity — by @sergio-sisternes-epam (#227)
- CLI logging UX agent skill for consistent CLI output conventions (#289)
- Resolve
UnboundLocalErrorinapm prunecrashing all prune operations (#283) - Restore CWD before
TemporaryDirectorycleanup on Windows — by @sergio-sisternes-epam (#281) - Fix Codex runtime download 404 on Windows — asset naming uses
.exe.tar.gz— by @sergio-sisternes-epam (#287) - Fix
UnicodeEncodeErroron Windows cp1252 consoles via UTF-8 codepage configuration — by @sergio-sisternes-epam (#287) - Fix
WinError 2when resolving.cmd/.ps1shell wrappers viashutil.which()— by @sergio-sisternes-epam (#287) - Fix
GIT_CONFIG_GLOBAL=NULfailure on some Windows git versions — by @sergio-sisternes-epam (#287) - Improve sub-skill overwrite UX with content skip and collision protection (#289)
- Lockfile renamed from
apm.locktoapm.lock.yamlfor IDE syntax highlighting; existingapm.lockfiles are automatically migrated on the nextapm install(#280) - Add Windows as first-class install option across documentation site (#278)
- Clarify that
.github/deployed files should be committed (#290)
- Diff-aware
apm install— manifest as source of truth: removed packages, ref/version changes, and MCP config drift inapm.ymlall self-correct on the nextapm installwithout--updateor--force; introducesdrift.pywith pure helper functions (#260) DiagnosticCollectorfor structured install diagnostics (#267)- Detailed file-level logging to
apm unpackcommand (#252) - Astro Starlight documentation site with narrative redesign (#243)
- Resolve WinError 32 during sparse-checkout fallback on Windows — by @JanDeDobbeleer (#235)
- CLI consistency: docs alignment, emoji removal,
show_defaultflags (#266)
- Minimum Python version bumped to 3.10; Black upgraded to 26.3.1 (#269)
- Refactor
cli.pyandapm_package.pyinto focused modules — by @sergio-sisternes-epam (#224) - Revamp README as storefront for documentation site (#251, #256, #258)
- Remove duplicated content from CLI reference page (#261)
- Bump devalue 5.6.3 → 5.6.4 in docs (#263)
- Primitives models coverage 78% → 100%; add discovery and parser coverage tests (#240, #254)
copilotas the primary user-facing target name for GitHub Copilot / Cursor / Codex / Gemini output format;vscodeandagentsremain as aliases (#228)
- Consolidate pack/unpack documentation into cli-reference, rename Key Commands section
apm packandapm unpackcommands for portable bundle creation and extraction with target filtering, archive support, and verification (#218)- Plugin MCP Server installation — extract, convert, and deploy MCP servers defined in plugin packages (#217)
- Plugin agents not deployed due to directory nesting in custom agent paths (#214)
- Skip already-configured self-defined MCP servers on re-install (#191)
- CLI consistency: remove emojis from help strings, fix
apm configbare invocation, update descriptions (#212)
- Extract
MCPIntegratorfromcli.py— move MCP lifecycle orchestration (~760 lines) into standalone module with hardened error handling (#215)
- Plugin management system with CLI commands for installing and managing plugins from marketplaces (#83)
- Generic git URL support for GitLab, Bitbucket, and any self-hosted git provider (#150)
- InstructionIntegrator for
apm install— deploy.instructions.mdfiles alongside existing integrators (#162) - Transitive MCP dependency propagation (#123)
- MCP dependency config overlays, transitive trust flag, and related bug fixes (#166)
- Display build commit SHA in CLI version output (#176)
- Documentation: apm.yml manifest schema reference for integrators (#186)
- Handle multiple brace groups in
applyToglob patterns (#155) - Replace substring matching with path-component matching in directory exclusions (#159)
- Handle commit SHA refs in subdirectory package clones (#178)
- Infer
registry_namewhen MCP registry API returns empty values (#181) - Resolve
set()shadowing and sparse checkout ref issues (#184) - CLI consistency — align help text with docs (#188)
--updateflag now bypasses lockfile SHA to fetch latest content (#192)- Clean stale MCP servers on install/update/uninstall and prevent
.claudefolder creation (#201) - Harden plugin security, validation, tests, and docs (#208)
- Use
CREATE_PR_PATfor agentic workflows in Microsoft org (#144)
- Unified
deployed_filesmanifest for safe integration lifecycle (#163) - Exclude
apm_modulesfrom compilation scanning and cacheSet[Path]for performance (#157) - Performance optimization for deep dependency trees (#173)
- Upgrade GitHub Agentic Workflows to v0.52.1 (#141)
- Fix CLI reference drift from consistency reports (#160, #161)
- Replace CHANGELOG link with roadmap discussion in docs index (#196)
- Update documentation for features from 2026-03-07 (#195)
- Support hooks as an agent primitive with install-time integration and dependency display (hooks execute at agent runtime, not during
apm install) (#97) - Deploy agents to
.claude/agents/duringapm install(#95) - Promote sub-skills inside packages to top-level
.github/skills/entries (#102)
- Fix skill integration bugs, transitive dep cleanup, and simplification (#107)
- Fix transitive dependency handling in compile and orphan detection (#111)
- Fix virtual subdirectory deps marked as orphaned, skipping instruction processing (#100)
- Improve multi-host error guidance when
GITHUB_HOSTis set (#113, #130) - Support spaces in Azure DevOps project names (#92)
- Fix GitHub Actions workflow permissions, integration test skip-propagation, and test corrections (#87, #106, #109)
- Migrated to Microsoft OSS organization (#85, #105)
- Added CODEOWNERS, simplified PR/issue templates, triage labels, and updated CONTRIBUTING.md (#115, #118)
- Added missing
versionfield in the apm.yml README example (#108) - Slim PR pipelines to Linux-only, auto-approve integration tests, added agentic workflows for maintenance (#98, #103, #104, #119)
- SUPPORT.md: Added Microsoft repo-template support file directing users to GitHub Issues and Discussions for community support
- README Rewording: Clarified APM as "an open-source, community-driven dependency manager" to set correct expectations under Microsoft GitHub org
- Microsoft Open Source Compliance: Updated LICENSE, SECURITY.md, CODE_OF_CONDUCT.md, CONTRIBUTING.md, and added Trademark Notice to README
- Source Integrity: Fixed source integrity for all integrators and restructured README
- Install Script: Use
grep -ofor single-line JSON extraction in install.sh - CI: Fixed integration test script to handle existing venv from CI workflow
- Bumped
azure-core1.35.1 → 1.38.0,aiohttp3.12.15 → 3.13.3,pip25.2 → 26.0,urllib32.5.0 → 2.6.3
- Transitive Dependencies: Full dependency resolution with
apm.locklockfile generation
- Install Script and
apm update: Repaired corrupted header in install.sh. Use awk instead of sed for shell subprocess compatibility. Directed shell output to terminal for password input during update process.
- Collection Extension Handling: Prevent double
.collection.ymlextension when user specifies full path - SKILL.md Parsing: Parse SKILL.md directly without requiring apm.yml generation
- Git Host Errors: Actionable error messages for unsupported Git hosts
- Native Skills Support: Skills now install to
.github/skills/as the primary target (per agentskills.io standard) - Skills ≠ Agents: Removed skill → agent transformation; skills and agents are now separate primitives
- Explicit Package Types: Added
typefield to apm.yml (instructions,skill,hybrid,prompts) for routing control - Skill Name Validation: Validates and normalizes skill names per agentskills.io spec (lowercase, hyphens, 1-64 chars)
- Claude Compatibility: Skills also copy to
.claude/skills/when.claude/folder exists
- Auto-creates
.github/directory on install if neither.github/nor.claude/exists
- Selective Package Install:
apm install <package>now only installs the specified package instead of all packages from apm.yml. Previously, installing a single package would also install unrelated packages.apm install(no args) continues to install all packages from the manifest.
- Claude Skills Integration: Virtual subdirectory packages (like
ComposioHQ/awesome-claude-skills/mcp-builder) now correctly trigger skill generation. Previously all virtual packages were skipped, but only virtual files and collections should be skipped—subdirectory packages are complete skill packages.
- SKILL.md as first-class primitive: meta-description of what an APM Package does for agents to read
- Claude Skills Installation: Install Claude Skills directly as APM Packages
- Bidirectional Format Support:
- APM packages → SKILL.md (for Claude target)
- Claude Skills → .agent.md (for VSCode target)
- Skills Documentation: New
docs/skills.mdguide
-
Claude Integration: First-class support for Claude Code and Claude Desktop
CLAUDE.mdgeneration alongsideAGENTS.md.claude/commands/auto-integration from installed packagesSKILL.mdgeneration for Claude Skills format- Commands get
-apmsuffix (same pattern as VSCode prompts)
-
Target Auto-Detection: Smart compilation based on project structure
.github/only → generatesAGENTS.md+ VSCode integration.claude/only → generatesCLAUDE.md+ Claude integration- Both folders → generates all formats
- Neither folder → generates
AGENTS.mdonly (universal format)
-
targetfield in apm.yml: Persistent target configurationtarget: vscode # or claude, or all
Applies to both
apm compileandapm install -
--targetflag: Override auto-detectionapm compile --target claude apm compile --target vscode apm compile --target all
- Virtual package uninstall sync:
apm uninstallnow correctly removes only the specific virtual package's integrated files (usesget_unique_key()for proper path matching)
apm compiledefault: Changed from--target allto auto-detect- README refactored with npm-style zero-friction onboarding
- Documentation reorganized with Claude integration guide
- ADO Package Commands:
compile,prune, anddeps listnow work correctly with Azure DevOps packages
- ADO Path Structure: Azure DevOps packages now use correct 3-level paths (
org/project/repo) throughout install, discovery, update, prune, and uninstall commands - Virtual Packages: ADO collections and individual files install to correct 3-level paths
- Prune Command: Fixed undefined variable bug in directory cleanup
- Azure DevOps Support: Install packages from Azure DevOps Services and Server
- New
ADO_APM_PATenvironment variable for ADO authentication (separate from GitHub tokens) - Supports
dev.azure.com/org/project/_git/repoURL format - Works alongside GitHub and GitHub Enterprise in mixed-source projects
- New
- Debug Mode: Set
APM_DEBUG=1to see detailed authentication and URL resolution output
- GitHub Enterprise Private Repos: Fixed authentication for
git ls-remotevalidation on non-github.com hosts - Token Selection: Correct token now used per-platform (GitHub vs ADO) in mixed-source installations
- Enterprise GitHub host support: fallback clone now respects
GITHUB_HOSTenv var instead of hardcoding github.com - Version validation crash when YAML parses version as numeric type (e.g.,
1.0vs"1.0")
- CI/CD: Updated runner from macos-13 and macos-14 to macos-15 for both x86_64 and ARM64 builds
- Context Link Resolution: Automatic markdown link resolution for
.context.mdfiles across installation and compilation- Links in prompts/agents automatically resolve to actual source locations (
apm_modules/or.apm/context/) - Works everywhere: IDE, GitHub, all coding agents supporting AGENTS.md
- No file copying needed—links point directly to source files
- Links in prompts/agents automatically resolve to actual source locations (
- Agent Integration: Automatic sync of
.agent.mdfiles to.github/agents/with-apmsuffix (same pattern as prompt integration)
sync_integrationURL normalization bug that caused ALL integrated files to be removed during uninstall instead of only the uninstalled package's files- Root cause: Metadata stored full URLs (
https://github.com/owner/repo) while dependency list used short form (owner/repo) - Impact: Uninstalling one package would incorrectly remove prompts/agents from ALL other packages
- Fix: Normalize both URL formats to
owner/repobefore comparison - Added comprehensive test coverage for multi-package scenarios
- Root cause: Metadata stored full URLs (
- Uninstall command now correctly removes only
apm_modules/owner/repo/directory (notapm_modules/owner/)
- Prompt Naming Pattern: Migrated from
@prefix to-apmsuffix for integrated prompts - GitIgnore Pattern: Updated from
.github/prompts/@*.prompt.mdto.github/prompts/*-apm.prompt.md
- Existing Users: Old
@-prefixed files will not be automatically removed - Action Required: Manually delete old
@*.prompt.mdfiles from.github/prompts/after upgrading
- Prompt Integration with GitHub - Automatically sync downloaded prompts to
.github/prompts/for GitHub Copilot
- Improved installer UX and console output
- Package FQDN support - install from any Git host using fully qualified domain names (thanks @richgo for PR #25)
- Security: CWE-20 URL validation vulnerability - proper hostname validation using
urllib.parseprevents malicious URL bypass attacks - Package validation HTTPS URL construction for git ls-remote checks
- Virtual package orphan detection in
apm deps listcommand
- GitHub Enterprise support via
GITHUB_HOSTenvironment variable (thanks @richgo for PR #25) - Build pipeline updates for macOS compatibility
- Virtual Package Support: Install individual files directly from any repository without requiring full APM package structure
- Individual file packages:
apm install owner/repo/path/to/file.prompt.md
- Individual file packages:
- Collection Support: Install curated collections of primitives from Awesome Copilot:
apm install github/awesome-copilot/collections/collection-name- Collection manifest parser for
.collection.ymlformat - Batch download of collection items into organized
.apm/structure - Integration with github/awesome-copilot collections
- Collection manifest parser for
- Auto-Discovery of Prompts: Run installed prompts without manual script configuration
apm run <prompt-name>automatically discovers and executes prompts without having to wire a script inapm.yml- Search priority: local root → .apm/prompts → .github/prompts → dependencies
- Qualified path support:
apm run owner/repo/prompt-namefor disambiguation - Collision detection with helpful error messages when multiple prompts found
- Explicit scripts in apm.yml always take precedence over auto-discovery
- Automatic Runtime Detection: Detects installed runtime (copilot > codex) and generates proper commands
- Zero-Configuration Execution: Install and run prompts immediately without apm.yml scripts section
- Enhanced dependency resolution to support virtual package unique keys
- Improved GitHub downloader with virtual file and collection package support
- Extended
DependencyReference.parse()to detect and validate virtual packages (3+ path segments) - Script runner now falls back to prompt discovery when script not found in apm.yml
- Streamlined workflow:
apm install <file>→apm run <name>works immediately - No manual script configuration needed for simple use cases
- Power users retain full control via explicit scripts in apm.yml
- Better error messages for ambiguous prompt names with disambiguation guidance
- Auto-bootstrap
apm.ymlwhen runningapm install <package>without existing config - GitHub Enterprise Server and Data Residency Cloud support via
GITHUB_HOSTenvironment variable - ARM64 Linux support
- Refactored
apm initto initialize projects minimally without templated prompts and instructions - Improved next steps formatting in project initialization output
- GitHub token fallback handling for Codex runtime setup
- Environment variable passing to subprocess in smoke tests and runtime setup
- Copilot CLI Support
- Fix prompt file resolution for dependencies in org/repo directory structure
- APM dependency prompt files now correctly resolve from
apm_modules/org/repo/paths apm runcommands can now find and execute prompt files from installed dependencies- Updated unit tests to match org/repo directory structure for dependency resolution
- Context Packaging
- Context Dependencies
- Context Compilation
- GitHub MCP Registry integration
- Codex CLI Support