Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- `apm install --target intellij` now configures JetBrains Copilot MCP support
while routing package file primitives through the Copilot profile.
(by @sergio-sisternes-epam; closes #1957) (#2041)

## [0.24.1] - 2026-07-10

### Fixed
Expand Down
19 changes: 12 additions & 7 deletions docs/src/content/docs/integrations/ide-tool-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The full slot-by-slot capability table lives in [Targets matrix](../reference/ta
| OpenCode | `.opencode/` | Skills, MCP |
| Windsurf | `.windsurf/` | Rules + Skills + Workflows + MCP |
| Kiro | `.kiro/` | Steering + Skills + Hooks + MCP |
| JetBrains Copilot | user-scope config dir (global) | MCP only (user-scope path, `${env:VAR}` env substitution) |
| JetBrains Copilot | user-scope config dir (global) | MCP (user-scope path, `${env:VAR}` substitution); file primitives use the Copilot profile |
| Agent-Skills (cross) | `.agents/skills/` | Vendor-neutral skill sharing |

For exact per-target capabilities (which primitives are supported, transformer used, file layout), see [Targets matrix](../reference/targets-matrix/).
Expand Down Expand Up @@ -141,19 +141,24 @@ that directory is the auto-detect signal.

```bash
# Install an MCP server into the JetBrains user-scope config
apm install --mcp --runtime intellij <package>
apm install --mcp io.github.github/github-mcp-server --target intellij
```

Notes and limits:

- **Auto-detect is user-scope only.** Unlike project markers such as `.cursor/`
or `.windsurf/`, JetBrains is detected from the global config directory, not a
file in your repo. It is therefore detected for every project on the machine
once the plugin directory exists. Use `--runtime intellij` to target it
explicitly regardless of auto-detect.
- **MCP auto-detect is user-scope only.** Unlike project markers such as
`.cursor/` or `.windsurf/`, MCP runtime discovery detects JetBrains from the
global config directory. It is therefore considered for MCP configuration in
every project once the plugin directory exists. This signal does not select a
file-primitive profile; use `--target intellij` explicitly.
- **Composed targets stay exact.** `--target intellij,claude` writes the
JetBrains and Claude MCP configs. `--target all,intellij` adds JetBrains to
the normal `all` target set; plain `all` excludes it.
- **Runtime env substitution.** JetBrains Copilot resolves `${env:VAR}` in
`mcp.json` at server start. APM preserves env-var placeholders as
`${env:VAR}` instead of writing matching host secrets into the config.
- **Policy evaluation.** APM maps `intellij` to `copilot` for organization
allow-lists, so a policy that allows `copilot` also covers IntelliJ installs.

## Per-tool reference pages

Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/reference/cli/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ With no arguments it installs everything from `apm.yml`. With one or more `PACKA

| Flag | Default | Description |
|---|---|---|
| `--target`, `-t VALUE` | auto-detect | Force deployment targets. Comma-separated for multiple (`-t claude,cursor`). Values: `copilot`, `claude`, `cursor`, `opencode`, `codex`, `gemini`, `antigravity`, `windsurf`, `kiro`, `intellij`, `vscode`, `agent-skills`, `all`; experimental `copilot-cowork` and `copilot-app` are also accepted when enabled. `all` expands to every harness above except `agent-skills` and `antigravity`; combine `all,agent-skills` or `all,antigravity` to add them. Highest precedence in the chain `--target` > `apm.yml targets:` > `apm config set target ...` > auto-detect. With nothing to detect, install exits `2` with a teaching message. |
| `--target`, `-t VALUE` | auto-detect | Force deployment targets. Comma-separated for multiple (`-t claude,cursor`). Values: `copilot`, `claude`, `cursor`, `opencode`, `codex`, `gemini`, `antigravity`, `windsurf`, `kiro`, `intellij`, `vscode`, `agent-skills`, `all`; experimental `copilot-cowork` and `copilot-app` are also accepted when enabled. IntelliJ-specific integration is MCP-only and writes JetBrains Copilot's user-scope MCP config; package file primitives use the Copilot profile. `all` excludes `agent-skills`, `antigravity`, and `intellij`; combine them explicitly to add them, for example `all,intellij`. Explicit MCP target lists are exact: `intellij,claude` writes only those two client configs. Highest precedence in the chain `--target` > `apm.yml targets:` > `apm config set target ...` > auto-detect. With nothing to detect, install exits `2` with a teaching message. |
| `--runtime VALUE` | unset | Legacy alias for `--target` (single value only). Still accepted; prefer `--target`. |
| `--exclude VALUE` | unset | Skip a single runtime that auto-detect or `targets:` would otherwise enable. |
| `--only apm\|mcp` | both | Install only APM packages or only MCP servers. |
Expand Down
28 changes: 28 additions & 0 deletions docs/src/content/docs/reference/targets-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@ see [Primitive types](./primitive-types/).
| opencode | `.opencode/` | [ ] | [ ] | [x] | [x] | [x] | [ ] | [x] |
| windsurf | `.windsurf/` + `.agents/` | [x] | [ ] | [ ] | [x] | [x] | [x] | [x] |
| kiro | `.kiro/` | [x] | [ ] | [ ] | [x] | [ ] | [x] | [x] |
| intellij | user MCP config; files via Copilot | [x] (*) | [x] (*) | [x] (*) | [x] (*) | [ ] | [x] (*) | [x] |
| agent-skills | `.agents/` | [ ] | [ ] | [ ] | [x] | [ ] | [ ] | [ ] |

Skills deploy to `.agents/skills/` for Copilot, Cursor, OpenCode,
Gemini, Antigravity, Codex, and Windsurf by default (see [Skills convergence](#skills-convergence)
below). Claude and Kiro keep target-native skill directories.

(*) For `intellij`, file primitives route through the Copilot profile:
instructions, prompts, agents, and hooks use `.github/`, while skills use
`.agents/skills/`. The IntelliJ-specific adapter configures MCP only.

`copilot-cowork` (Microsoft 365 Copilot), `copilot-app` (GitHub
Copilot desktop App), `openclaw` (OpenClaw agent runtime), and `hermes` are
gated behind experimental flags and not listed above. See
Expand Down Expand Up @@ -64,6 +69,12 @@ list before `compile` or `install`.
| opencode | `.opencode/` directory |
| windsurf | `.windsurf/` directory |
| kiro | `.kiro/` directory |
| intellij | Global `github-copilot/intellij/` config directory (MCP runtime discovery only) |

IntelliJ-specific integration is MCP-only and writes JetBrains Copilot's
user-scope `mcp.json`. That global signal does not auto-select file-primitive
deployment. When `intellij` is selected explicitly, package file primitives use
the Copilot profile. `intellij` does not participate in plain `all` expansion.

`agent-skills` is a canonical target key; `antigravity` is explicit-only for
auto-detection. Both are available with `--target` and can be listed in a
Expand Down Expand Up @@ -212,6 +223,23 @@ Kiro IDE.
- **MCP shape.** JSON `mcpServers` entries use `command`/`args`/`env` for stdio and `url`/`headers` for remote servers. Kiro resolves `${VAR}` placeholders at runtime, so APM preserves them rather than writing secrets to disk.
- **Scope.** This is the documented Kiro IDE layout only. Kiro CLI differences are tracked separately and are not part of this target.

## intellij

GitHub Copilot for JetBrains IDEs.

- **Detection.** MCP runtime discovery uses the global
`github-copilot/intellij/` config directory. It does not auto-select a
file-primitive target.
- **Deploy directory.** User-scope `mcp.json`; see the
[JetBrains integration guide](../integrations/ide-tool-integration/#jetbrains-intellij-idea-pycharm-goland-and-others)
for OS-specific paths.
- **Supported primitives.** The IntelliJ-specific adapter supports MCP.
Instructions, prompts, agents, and hooks deploy through the Copilot profile
under `.github/`; skills deploy under `.agents/skills/`.
- **Scope.** MCP configuration is user scope only. File primitives use the
project or user scope selected for the Copilot profile. IntelliJ does not
participate in plain `all` expansion.

## agent-skills

Cross-client shared skills directory.
Expand Down
9 changes: 7 additions & 2 deletions packages/apm-guide/.apm/skills/apm-usage/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

| Command | Purpose | Key flags |
|---------|---------|-----------|
| `apm install [PKGS...]` | Install APM and MCP dependencies (supports APM packages, Claude skills (SKILL.md), and plugin collections (plugin.json)) | `--update` (deprecated; prefer `apm update`) refresh refs, `--refresh` re-fetch all deps from upstream and re-resolve all ref pins, `--force` overwrite (does NOT refresh refs; use `apm update` for that), `--frozen` CI-safe install that fails fast when `apm.lock.yaml` is missing or out of sync with `apm.yml` (mutually exclusive with `--update`; structural presence check only -- use `apm audit` for SHA integrity), `--dry-run`, `--verbose`, `--only [apm\|mcp]`, `--target` (comma-separated, e.g. `--target claude,cursor`; highest-priority entry in the resolution chain `--target` > apm.yml `targets:` > auto-detect; on auto-bootstrap when no `apm.yml` exists, recognized manifest target(s) are persisted to the new manifest's `targets:` so a later bare `apm update` reuses them; `--target all` deprecated, see `apm compile --all`; use `kiro` for Kiro IDE; use `copilot-cowork` with `--global` after `apm experimental enable copilot-cowork`; use `hermes` after `apm experimental enable hermes` to deploy skills + `AGENTS.md` and, at `--global`, MCP servers to `~/.hermes/config.yaml`), `--dev`, `-g` global (MCP deploys only to user-scope runtimes: Copilot CLI, Claude Code, Codex CLI, Gemini CLI, Antigravity CLI, Kiro, Windsurf, JetBrains Copilot, and Hermes when enabled), `--trust-transitive-mcp`, `--parallel-downloads N`, `--allow-insecure`, `--allow-insecure-host HOSTNAME`, `--skill NAME` install named skill(s) from a skill collection (SKILL_BUNDLE or plugin manifest; repeatable; plugin manifests accept a leaf name or manifest path; persisted in apm.yml; additive across separate installs -- a later `--skill X` adds to the existing pin (union) rather than replacing it, so previously deployed skills are never silently removed; `'*'` resets to the full bundle; drop a single skill by editing the `skills:` list in apm.yml then re-running install), `--legacy-skill-paths` restore per-client skill dirs, `--mcp NAME` add MCP entry (NAME goes through the same `--target` > `targets:` > auto-detect resolver as APM packages, so a project whitelisting `targets: [copilot]` will not write `.cursor/mcp.json` even if `.cursor/` exists; `apm install -g --mcp NAME` writes user-scope and bypasses the project-scope gate by design), `--transport`, `--url`, `--env KEY=VAL`, `--header KEY=VAL`, `--mcp-version`, `--registry URL` custom MCP registry, `--root DIR` redirect writes (`apm_modules/`, lockfile, `.gitignore`, integrated harness files) under DIR while `apm.yml`/`.apm/`/local deps resolve from `$PWD` (mirrors `pip install --target`; created if missing; not valid with `-g`/`--global`, which exits 2) |
| `apm install [PKGS...]` | Install APM and MCP dependencies (supports APM packages, Claude skills (SKILL.md), and plugin collections (plugin.json)) | `--update` (deprecated; prefer `apm update`) refresh refs, `--refresh` re-fetch all deps from upstream and re-resolve all ref pins, `--force` overwrite (does NOT refresh refs; use `apm update` for that), `--frozen` CI-safe install that fails fast when `apm.lock.yaml` is missing or out of sync with `apm.yml` (mutually exclusive with `--update`; structural presence check only -- use `apm audit` for SHA integrity), `--dry-run`, `--verbose`, `--only [apm\|mcp]`, `--target` (comma-separated, e.g. `--target claude,cursor`; highest-priority entry in the resolution chain `--target` > apm.yml `targets:` > auto-detect; `intellij` is MCP-only and writes JetBrains Copilot's user-scope config; explicit lists are exact, so `intellij,claude` writes those two MCP configs and `all,intellij` adds JetBrains to `all`; on auto-bootstrap when no `apm.yml` exists, recognized manifest target(s) are persisted to the new manifest's `targets:` so a later bare `apm update` reuses them; `--target all` deprecated, see `apm compile --all`; use `kiro` for Kiro IDE; use `copilot-cowork` with `--global` after `apm experimental enable copilot-cowork`; use `hermes` after `apm experimental enable hermes` to deploy skills + `AGENTS.md` and, at `--global`, MCP servers to `~/.hermes/config.yaml`), `--dev`, `-g` global (MCP deploys only to user-scope runtimes: Copilot CLI, Claude Code, Codex CLI, Gemini CLI, Antigravity CLI, Kiro, Windsurf, JetBrains Copilot, and Hermes when enabled), `--trust-transitive-mcp`, `--parallel-downloads N`, `--allow-insecure`, `--allow-insecure-host HOSTNAME`, `--skill NAME` install named skill(s) from a skill collection (SKILL_BUNDLE or plugin manifest; repeatable; plugin manifests accept a leaf name or manifest path; persisted in apm.yml; additive across separate installs -- a later `--skill X` adds to the existing pin (union) rather than replacing it, so previously deployed skills are never silently removed; `'*'` resets to the full bundle; drop a single skill by editing the `skills:` list in apm.yml then re-running install), `--legacy-skill-paths` restore per-client skill dirs, `--mcp NAME` add MCP entry (NAME goes through the same `--target` > `targets:` > auto-detect resolver as APM packages, so `apm install --mcp NAME --target intellij` writes only JetBrains Copilot's MCP config; compilation target policy applies to every explicitly selected target; `apm install -g --mcp NAME` writes user-scope and bypasses the project-scope gate by design), `--transport`, `--url`, `--env KEY=VAL`, `--header KEY=VAL`, `--mcp-version`, `--registry URL` custom MCP registry, `--root DIR` redirect writes (`apm_modules/`, lockfile, `.gitignore`, integrated harness files) under DIR while `apm.yml`/`.apm/`/local deps resolve from `$PWD` (mirrors `pip install --target`; created if missing; not valid with `-g`/`--global`, which exits 2) |
| `apm targets` | Show resolved deployment targets for the current project (Click group; reads filesystem signals; works with or without `apm.yml`) | `--all` also include the `agent-skills` meta-target (only meaningful with `--json`), `--json` machine-readable output. No provenance line is printed (the table is the provenance). |
| `apm uninstall PKGS...` | Remove packages (accepts `owner/repo` or `name@marketplace`) | `--dry-run`, `-g` global |
| `apm prune` | Remove orphaned packages | `--dry-run` |
Expand Down Expand Up @@ -40,7 +40,12 @@ When a default registry is configured, plain shorthand deps (`owner/repo#<ref>`)
1. `--target` flag (highest; CSV form: `--target claude,cursor`).
2. `apm.yml` `targets:` list (or singular `target:` sugar).
3. `apm config set target <value>` default.
4. Auto-detect from filesystem signals (`.claude/` or `CLAUDE.md` -> claude, `.cursor/` -> cursor, `.github/copilot-instructions.md` or any of `.github/instructions/`, `.github/agents/`, `.github/prompts/`, `.github/hooks/` -> copilot, `.codex/` -> codex, `.gemini/` or `GEMINI.md` -> gemini, `.opencode/` -> opencode, `.windsurf/` -> windsurf, `.kiro/` -> kiro, the user-scope JetBrains Copilot MCP config directory `github-copilot/intellij/` -- `%LOCALAPPDATA%\github-copilot\intellij\` on Windows, `~/Library/Application Support/github-copilot/intellij/` on macOS, `~/.local/share/github-copilot/intellij/` on Linux -> intellij). All signals except JetBrains are project-scoped repo markers; the JetBrains signal is a machine-global user-scope directory, so once the Copilot plugin is installed it is detected for every project on that machine.
4. Auto-detect file-primitive targets from project signals (`.claude/` or `CLAUDE.md` -> claude, `.cursor/` -> cursor, `.github/copilot-instructions.md` or any of `.github/instructions/`, `.github/agents/`, `.github/prompts/`, `.github/hooks/` -> copilot, `.codex/` -> codex, `.gemini/` or `GEMINI.md` -> gemini, `.opencode/` -> opencode, `.windsurf/` -> windsurf, `.kiro/` -> kiro).

MCP runtime discovery separately recognizes the user-scope JetBrains Copilot
config directory (`github-copilot/intellij/`). That machine-global signal can
select IntelliJ for MCP configuration in every project, but it never
auto-selects a file-primitive target.

`apm install` prints a one-line provenance summary before any mutation:

Expand Down
11 changes: 9 additions & 2 deletions src/apm_cli/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ def _validate_and_add_packages_to_apm_yml(
# ---------------------------------------------------------------------------


def _handle_mcp_install(
def _handle_mcp_install( # noqa: PLR0913
*,
mcp_name,
transport,
Expand All @@ -789,6 +789,7 @@ def _handle_mcp_install(
dev,
force,
runtime,
target,
exclude,
verbose,
logger,
Expand Down Expand Up @@ -839,6 +840,9 @@ def _handle_mcp_install(
registry=False if _is_self_defined else None,
url=url,
)
from ..core.target_detection import normalize_policy_targets

policy_targets = normalize_policy_targets(target or runtime)

try:
_pf_result, _pf_active = run_policy_preflight(
Expand All @@ -847,6 +851,7 @@ def _handle_mcp_install(
no_policy=no_policy,
logger=logger,
dry_run=logger.dry_run,
effective_target=policy_targets,
)
except PolicyBlockError:
# Diagnostics already emitted by the helper + logger.
Expand Down Expand Up @@ -878,6 +883,7 @@ def _handle_mcp_install(
dev=dev,
force=force,
runtime=runtime,
target=target,
exclude=exclude,
logger=logger,
apm_dir=mcp_apm_dir,
Expand Down Expand Up @@ -944,7 +950,7 @@ def _handle_mcp_install(
"target",
type=TargetParamType(),
default=None,
help="Target harness(es) to deploy to. Comma-separated for multiple: --target claude,cursor. Repeating the flag (e.g. '-t a -t b') is NOT supported -- only the last value wins; use commas. Highest-priority entry in the resolution chain (--target > apm.yml targets: > apm config target > auto-detect). Values: copilot, claude, cursor, opencode, codex, gemini, antigravity, windsurf, kiro, agent-skills, all. 'agent-skills' deploys to .agents/skills/ (cross-client). 'antigravity' (alias 'agy') deploys to .agents/ (AGENTS.md + rules + skills + hooks.json + mcp_config.json) and is explicit-only -- not part of 'all' or auto-detection. 'all' = copilot+claude+cursor+opencode+codex+gemini+windsurf+kiro (excludes agent-skills and antigravity); combine with 'agent-skills' or 'antigravity' to add them. 'copilot-cowork' is also accepted when the copilot-cowork experimental flag is enabled (run 'apm experimental enable copilot-cowork'). 'copilot-app' is also accepted when the copilot-app experimental flag is enabled (run 'apm experimental enable copilot-app'). Note: '--target all' on 'apm compile' is deprecated; use 'apm compile --all' instead.",
help="Target harness(es) to deploy to. Use commas for multiple targets; repeating the flag keeps only the last value (use commas instead). Values: copilot, claude, cursor, opencode, codex, gemini, antigravity (agy), windsurf, kiro, intellij, agent-skills, all. IntelliJ-specific integration is MCP-only; file primitives use the Copilot profile. 'all' = copilot+claude+cursor+opencode+codex+gemini+windsurf+kiro; combine agent-skills, antigravity, or intellij explicitly when needed. Experimental copilot-cowork and copilot-app values require their feature flags. Resolution order: --target > apm.yml targets: > apm config target > auto-detect. With nothing to detect, install exits 2 with a teaching message. For 'apm compile', use '--all'; '--target all' is deprecated.",
)
@click.option(
"--allow-insecure",
Expand Down Expand Up @@ -1405,6 +1411,7 @@ def install( # noqa: PLR0913
dev=dev,
force=force,
runtime=runtime,
target=target,
exclude=exclude,
verbose=verbose,
logger=logger,
Expand Down
Loading
Loading