Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6018a0b
Initial plan
Copilot Mar 25, 2026
0181b05
Initial plan for scoped installation feature
Copilot Mar 25, 2026
a0f2010
feat: add --global / -g flag for user-scope package installation
Copilot Mar 25, 2026
6dfbf6d
docs: add scoped installation guide and update CLI reference and CHAN…
Copilot Mar 25, 2026
4963e63
fix: address code review feedback on scope implementation
Copilot Mar 25, 2026
144c9fa
fix: document per-target user-scope support with evidence and add ins…
Copilot Mar 25, 2026
11ee6ac
test: add integration tests for global scope feature (17 tests)
Copilot Mar 25, 2026
7486d4b
fix: address code review feedback on integration tests
Copilot Mar 25, 2026
e07314d
Update test_install_command.py
sergio-sisternes-epam Mar 26, 2026
0c5959d
Update CHANGELOG.md
sergio-sisternes-epam Mar 26, 2026
4d465a0
Update cli.py
sergio-sisternes-epam Mar 26, 2026
1725400
fix: move InstallLogger creation before scope init to prevent Unbound…
Copilot Mar 26, 2026
98c0a02
fix: differentiate VS Code and Copilot CLI as separate targets in use…
Copilot Mar 26, 2026
46a7e0e
fix: improve warning message clarity and fix user_root consistency fo…
Copilot Mar 26, 2026
4d3c6a8
fix: expand Copilot CLI primitives to include skills and instructions…
Copilot Mar 26, 2026
4af0d4a
refactor: improve test variable naming and assertion structure
Copilot Mar 26, 2026
07af560
fix: change Copilot CLI status to "Partially supported" in docs table
Copilot Mar 26, 2026
e65e128
fix: change copilot_cli and vscode support status to "partial" to mat…
Copilot Mar 26, 2026
559c529
fix: update project scope primitives for target consistency and VS Co…
Copilot Mar 26, 2026
f5dceda
Update scoped-installation.md
sergio-sisternes-epam Mar 26, 2026
aeda09b
fix: tag OpenCode as "Not supported" instead of "Unverified" for cons…
Copilot Mar 26, 2026
8ea0bf5
fix: address pending review feedback - scope-aware hints, VS Code use…
Copilot Mar 26, 2026
70294b3
test: strengthen VS Code user_root assertion to check exact placehold…
Copilot Mar 26, 2026
562fdc2
fix: downgrade copilot_cli and vscode to "Not supported" at user scop…
Copilot Mar 26, 2026
ac56de0
style: break long skills existence check into readable multi-line form
Copilot Mar 26, 2026
81cdfbd
fix: restore tri-state support matrix for Copilot CLI (partial) and V…
Copilot Mar 26, 2026
0f37a14
test: improve unsupported primitives assertion to check exact format
Copilot Mar 26, 2026
b10a6e5
docs: clarify that Copilot CLI does not support prompts
Copilot Mar 26, 2026
1847f50
merge: resolve conflicts with main (--target flag and --global coexist)
Copilot Mar 26, 2026
1b229ed
merge: resolve conflicts with main (data-driven dispatch, auth resolv…
danielmeppiel Mar 31, 2026
f9d8d4e
refactor: merge USER_SCOPE_TARGETS into TargetProfile, add scope-gating
danielmeppiel Mar 31, 2026
a22550b
Merge branch 'main' into copilot/study-apm-installation-scope
danielmeppiel Mar 31, 2026
ea4d554
docs: fold scoped-installation into dependencies.md
danielmeppiel Mar 31, 2026
333fcdc
Merge branch 'main' into copilot/study-apm-installation-scope
danielmeppiel Mar 31, 2026
91ef829
fix: route _rich_* calls through logger in install/uninstall scope bl…
Copilot Mar 31, 2026
9c22785
Merge branch 'main' into copilot/study-apm-installation-scope
danielmeppiel Mar 31, 2026
bffecec
feat(scope): add Cursor/OpenCode global support, deps list -g, scope …
danielmeppiel Mar 31, 2026
d82e112
fix: address 5 PR review comments on scope feature
danielmeppiel Mar 31, 2026
4bd60f6
Merge branch 'main' into copilot/study-apm-installation-scope
danielmeppiel Mar 31, 2026
4c6b573
fix: reject local path dependencies at user scope (--global)
danielmeppiel Mar 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Marketplace integration for plugin discovery and governance: `apm marketplace add/list/browse/update/remove` commands, `apm search QUERY@MARKETPLACE` scoped search, `apm install NAME@MARKETPLACE` syntax for installing plugins from marketplace registries; lockfile provenance fields `discovered_via` and `marketplace_plugin_name` to track marketplace origin; support for Copilot CLI and Claude Code `marketplace.json` formats with 4 source types (github, url, git-subdir, relative path) (#503)

### Fixed

- `apm install -g ./local-pkg` now rejects local path dependencies at user scope with a clear error instead of silently failing (relative paths resolve against `cwd` during validation but against `$HOME` during copy) (#452)
### Changed

- `apm deps update` now skips download and integration for packages whose resolved SHA matches the lockfile SHA, making the common "nothing changed" case near-instant (#495)
Expand Down Expand Up @@ -42,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- `apm install --target` flag to force deployment to a specific target (copilot, claude, cursor, opencode, all) (#456)
- Global `apm install --global` / `-g` and `apm uninstall --global` flags for user-scope package installation, backed by `InstallScope`-based scope resolution in `core/scope.py`; deploys primitives to `~/.copilot/`, `~/.claude/`, `~/.cursor/`, `~/.config/opencode/` and tracks metadata under `~/.apm/` (#452)

### Fixed

Expand Down
55 changes: 55 additions & 0 deletions docs/src/content/docs/guides/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,61 @@ dependencies:

**Pack guard:** `apm pack` rejects packages with local path dependencies — replace them with remote references before distributing.

**User-scope guard:** Local path dependencies are **not supported** with `--global` (`-g`). Relative paths resolve against `cwd`, which is meaningless at user scope where packages deploy to `~/.apm/`. Use remote references (`owner/repo`) for global installs.

## Global (User-Scope) Installation

By default, `apm install` targets the **current project** -- manifest, modules, and lockfile live in
the working directory and deployed primitives go to `.github/`, `.claude/`, `.cursor/`, `.opencode/`.

Pass `--global` (or `-g`) to install to your **home directory** instead, making packages available
across every project on the machine:

```bash
apm install -g microsoft/apm-sample-package
apm uninstall -g microsoft/apm-sample-package
apm deps list -g # user-scope packages only
apm deps list --all # project + user-scope packages
```

| Item | Project scope (default) | User scope (`-g`) |
|------|------------------------|-------------------|
| Manifest | `./apm.yml` | `~/.apm/apm.yml` |
| Modules | `./apm_modules/` | `~/.apm/apm_modules/` |
| Lockfile | `./apm.lock.yaml` | `~/.apm/apm.lock.yaml` |
Comment thread
danielmeppiel marked this conversation as resolved.
| Deployed primitives | `./.github/`, `./.claude/`, ... | `~/.copilot/`, `~/.claude/`, `~/.cursor/`, `~/.config/opencode/` |

### Per-target support

Coverage varies by target and primitive type:

| Target | Status | User-level dir | Primitives | Not supported |
|--------|--------|---------------|------------|---------------|
| Claude Code | Supported | `~/.claude/` | Skills, agents, commands, hooks, instructions | -- |
| Copilot CLI | Partial | `~/.copilot/` | Skills, agents, instructions, hooks | Prompts (not supported by Copilot CLI) |
| Cursor | Partial | `~/.cursor/` | Skills, agents, hooks | Rules |
| OpenCode | Partial | `~/.config/opencode/` | Skills, agents, commands | Hooks |

Target detection mirrors project scope: APM auto-detects by `~/.<target>/` directory presence,
falling back to Copilot. Security scanning runs for global installs.

### When to use each scope

| Use case | Scope |
|----------|-------|
| Team-shared instructions and prompts | Project (`apm install`) |
| Personal commands, agents, or skills | User (`apm install -g`) |
| CI/CD reproducible setup | Project |
| Cross-project coding standards | User |

:::note
MCP servers are not supported at user scope. Each target uses a different MCP configuration format; user-scope MCP support is planned for a future release.
:::

:::caution
Local path dependencies (`./path`, `../path`, `/abs/path`) are rejected at user scope. Relative paths resolve against `cwd`, which differs from the user-scope deploy root (`~/.apm/`). Use remote references for `apm install -g`.
:::

## MCP Dependency Formats

MCP dependencies support three forms: string references, overlay objects, and self-defined servers.
Expand Down
2 changes: 2 additions & 0 deletions docs/src/content/docs/integrations/ide-tool-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ apm compile

For running agentic workflows locally, see the [Agent Workflows guide](../../guides/agent-workflows/).

> **User-scope deployment**: `apm install -g` deploys primitives to user-level directories (`~/.copilot/`, `~/.claude/`, etc.), making packages available across all projects. See [Global Installation](../../guides/dependencies/#global-user-scope-installation) for per-target coverage.

## VS Code Integration

APM works natively with VS Code's GitHub Copilot implementation.
Expand Down
22 changes: 20 additions & 2 deletions docs/src/content/docs/reference/cli-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ apm install [PACKAGES...] [OPTIONS]
- `--verbose` - Show individual file paths and full error details in the diagnostic summary
- `--trust-transitive-mcp` - Trust self-defined MCP servers from transitive packages (skip re-declaration requirement)
- `--dev` - Add packages to [`devDependencies`](../manifest-schema/#5-devdependencies) instead of `dependencies`. Dev deps are installed locally but excluded from `apm pack --format plugin` bundles
- `-g, --global` - Install to user scope (`~/.apm/`) instead of the current project. Primitives deploy to `~/.copilot/`, `~/.claude/`, etc.

**Behavior:**
- `apm install` (no args): Installs **all** packages from `apm.yml`
Expand Down Expand Up @@ -152,6 +153,9 @@ apm install --dev owner/test-helpers
apm install ./packages/my-shared-skills
apm install /home/user/repos/my-ai-package

# Install to user scope (available across all projects)
apm install -g microsoft/apm-sample-package

# Install a plugin from a registered marketplace
apm install code-review@acme-plugins
```
Expand Down Expand Up @@ -274,6 +278,7 @@ apm uninstall [OPTIONS] PACKAGES...

**Options:**
- `--dry-run` - Show what would be removed without removing
- `-g, --global` - Remove from user scope (`~/.apm/`) instead of the current project

**Examples:**
```bash
Expand All @@ -285,6 +290,9 @@ apm uninstall https://github.com/microsoft/apm-sample-package.git

# Preview what would be removed
apm uninstall microsoft/apm-sample-package --dry-run

# Uninstall from user scope
apm uninstall -g microsoft/apm-sample-package
```

**What Gets Removed:**
Expand Down Expand Up @@ -605,13 +613,23 @@ apm deps COMMAND [OPTIONS]
Show all installed APM dependencies in a Rich table format with per-primitive counts.

```bash
apm deps list
apm deps list [OPTIONS]
```

**Options:**
- `-g, --global` - List user-scope packages from `~/.apm/` instead of the current project
- `--all` - List packages from both project and user scope

**Examples:**
```bash
# Show all installed APM packages
# Show project-scope packages
apm deps list

# Show user-scope packages
apm deps list -g

# Show both scopes
apm deps list --all
```

**Sample Output:**
Expand Down
6 changes: 4 additions & 2 deletions src/apm_cli/commands/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,12 +432,13 @@ def _create_plugin_json(config):
f.write(json.dumps(plugin_data, indent=2) + "\n")


def _create_minimal_apm_yml(config, plugin=False):
def _create_minimal_apm_yml(config, plugin=False, target_path=None):
"""Create minimal apm.yml file with auto-detected metadata.

Args:
config: dict with name, version, description, author keys.
plugin: if True, include a devDependencies section.
target_path: explicit file path to write (defaults to cwd/apm.yml).
Comment thread
sergio-sisternes-epam marked this conversation as resolved.
"""
# Create minimal apm.yml structure
apm_yml_data = {
Expand All @@ -455,4 +456,5 @@ def _create_minimal_apm_yml(config, plugin=False):

# Write apm.yml
from ..utils.yaml_io import dump_yaml
dump_yaml(apm_yml_data, APM_YML_FILENAME)
out_path = target_path or APM_YML_FILENAME
dump_yaml(apm_yml_data, out_path)
Loading
Loading