Skip to content
Merged
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Breaking Changes

- The CLI self-updater moved from `apm update` to `apm self-update`. Inside an `apm.yml` project the bare `apm update` verb now refreshes project dependencies (matching `npm update`, `uv lock --upgrade`, `cargo update`); outside a project it forwards to `apm self-update` with a deprecation banner for one release. CI scripts that called `apm update` to refresh the binary should migrate now: `sed -i 's/apm update/apm self-update/g' your_scripts`. (#1244)

### Added

- `apm update` now does what every npm/pip/cargo user expects -- resolve latest refs, show a structured plan, and ask before touching anything. Refreshes APM dependencies in the current project: resolves `apm.yml` against the latest refs, prints a structured plan (added/updated/removed/unchanged) with an inline legend, and prompts `[y/N]` before mutating anything (`--yes` skips the prompt; `--dry-run` previews). (#1244)
- `apm self-update`: updates the APM CLI binary itself (or shows distributor guidance when self-update is disabled at build time). Replaces the former `apm update` self-update path; supports `--check` to only check for a newer version. (#1244)
- `apm install --frozen` performs a CI-safe, read-only install that fails fast (exit 1) 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 on-disk SHA integrity. (#1244)
- `apm install` now emits a one-line "Run 'apm update' to check for newer versions." hint on the no-op path when a lockfile is already present, pointing users at the verb that actually checks for newer refs. (#1244)
- Virtual subdirectory and raw-file packages now resolve from self-hosted Git services (Gitea, Gogs) via raw URL with API v1/v3 fallback. (#587)
- `shared/apm.md` gh-aw shared workflow exposes a `target:` import input (default `all`) so consumer workflows can ship slim, single-harness bundles instead of always packing every layout. (#1184)
- **GitLab host support:** `gitlab.com` and self-managed instances (via `GITLAB_HOST` / `APM_GITLAB_HOSTS`) use GitLab REST **v4** for `marketplace.json` and install-time raw file reads; nested GitLab group paths are disambiguated in dependency references with object-form `git:` + `path:` where shorthand is ambiguous. GitHub, GHES, Azure DevOps, and registry-proxy behavior remain unchanged. (#1149)
Expand All @@ -17,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- `apm install --force` help text now states explicitly that the flag does NOT refresh refs; users who want newer commits should run `apm update`. (#1244)
- `apm update` now walks parent directories to find `apm.yml` (matching npm/cargo ergonomics), emits a one-time CI banner when invoked from a project root under `CI`/`GITHUB_ACTIONS` so pipelines see the dependency-refresh shift, and the no-op nudge copy now reads "Lockfile already satisfied -- run `apm update` to resolve latest refs." `apm install --frozen` adds a post-success "Run `apm audit` for on-disk content integrity." footer to set the right expectation, and FrozenInstallError now renders identically across `install` and `update`. (#1244)
- `apm marketplace browse/search/add/update` route through the registry proxy when `PROXY_REGISTRY_URL` is set; `PROXY_REGISTRY_ONLY=1` blocks direct GitHub and GitLab host API fallbacks. (#1149)
- Registry proxy now warns when `PROXY_REGISTRY_TOKEN` is set and `PROXY_REGISTRY_URL` uses `http://`, since the bearer token would be transmitted in plaintext; set `PROXY_REGISTRY_ALLOW_HTTP=1` to silence the warning for trusted internal proxies. (#1149)
- Integration tests now use marker-driven discovery: 21 `pytestmark = pytest.mark.skipif(...)` chains across `tests/integration/` are replaced with declarative `requires_*` markers, with precondition logic centralized in `tests/integration/conftest.py` and auto-skipping at collection time. PR1 of #1166. (#1167)
Expand Down
38 changes: 38 additions & 0 deletions docs/src/content/docs/guides/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,44 @@ apm compile
# Instructions with matching applyTo patterns are merged from all sources
```

## Updating dependencies

`apm update` refreshes the APM packages declared in your `apm.yml` to their latest matching refs. It resolves the dependency graph against the network, prints a structured plan (added / updated / removed), and prompts before mutating anything.

```bash
# Interactive: resolve, show plan, prompt [y/N], then install
apm update

# Show the plan and exit -- no on-disk changes
apm update --dry-run

# CI-safe: skip the prompt
apm update --yes
```

The plan output uses the standard bracket symbols (`[~]` updated, `[+]` added, `[-]` removed) and includes an inline legend in the footer. When nothing has changed, `apm update` prints `All dependencies already at their latest matching refs.` and exits cleanly.

For lockfile-only enforcement in CI, pair `apm update` (in your branch / PR) with `apm install --frozen` (in CI):

```bash
# In CI -- exit 1 if apm.lock.yaml is missing or out of sync with apm.yml
apm install --frozen
```

:::note[--frozen scope]
`apm install --frozen` is a **structural presence check**: it verifies every direct dependency in `apm.yml` has a lock entry. It does NOT verify that on-disk content matches the locked SHA. Use `apm audit` for end-to-end integrity verification of deployed files.
:::

:::caution[Breaking change: `apm update` now refreshes dependencies]
In earlier releases, `apm update` updated the APM CLI binary. That behaviour moved to `apm self-update`. Inside an `apm.yml` project, the bare `apm update` verb now refreshes project dependencies (matching `npm update`, `cargo update`, `uv lock --upgrade`).

Outside a project, `apm update` still forwards to `apm self-update` with a deprecation banner for one release. CI scripts that called `apm update` to refresh the binary should migrate now:

```bash
sed -i 's/apm update/apm self-update/g' your_scripts
```
:::

## Development Dependencies

Some packages are only needed during authoring — test fixtures, linting rules, internal helpers. Install them as dev dependencies so they stay out of distributed bundles:
Expand Down
17 changes: 16 additions & 1 deletion docs/src/content/docs/reference/lockfile-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ The lock file serves four goals:
|-------|----------------------|
| `apm install` (first run) | Created. All dependencies resolved, commits pinned, files recorded. |
| `apm install` (subsequent) | Read. Locked commits reused. New dependencies appended. File only written when semantic content changes (dependencies, MCP servers/configs, `lockfile_version`); no churn from `generated_at` or `apm_version` fields. |
| `apm install --update` | Re-resolved. All refs re-resolved to latest matching commits. |
| `apm install --frozen` | Read-only. Fails fast (exit 1) if the lockfile is missing or any direct dependency in `apm.yml` is absent from the lockfile. Mutually exclusive with `--update`. Use in CI to catch drift between manifest and lockfile. |
| `apm update` | Re-resolved with confirmation gate. Resolves `apm.yml` against the latest matching refs, prints a structured plan (added/updated/removed/unchanged), and writes only after the user confirms (default `[y/N]`; bypass with `--yes`, preview with `--dry-run`). |
| `apm install --update` | Re-resolved. All refs re-resolved to latest matching commits without a confirmation prompt. Prefer `apm update` for interactive flows. |
| `apm deps update` | Re-resolved. Refreshes versions for specified or all dependencies. |
| `apm pack` | Enriched. A `pack:` section is prepended to the bundled copy (see [section 6](#6-pack-enrichment)). Both `--format plugin` (default) and `--format apm` embed the enriched copy when a project lockfile exists. |
| `apm uninstall` | Updated. Removed dependency entries and their `deployed_files` references. |
Expand Down Expand Up @@ -261,6 +263,19 @@ The dependency resolver interacts with the lock file as follows:
to their latest commits. If a resolved commit matches the existing lock
file entry and the local checkout is intact, the download is skipped.
Otherwise, the package is re-fetched. The lock file is always refreshed.
4. **Interactive update** (`apm update`) -- re-resolve all refs and render
a structured plan (added/updated/removed/unchanged) before any
mutation. Defaults to a confirmation prompt; `--dry-run` exits after
the plan with no on-disk changes; `--yes` skips the prompt for CI
automation. On confirmation, behaves like (3) and refreshes the lock
file.
5. **Frozen** (`apm install --frozen`) -- read `apm.lock.yaml` and
structurally verify every direct dependency declared in `apm.yml`
has a corresponding lock entry. Exit code 1 when the lockfile is
missing or any direct dep is unlocked; never resolves, never
mutates. Mutually exclusive with `--update`. Note: this is a
structural presence check; on-disk SHA integrity is the job of
`apm audit`.

When a locked commit is no longer reachable (force-pushed branch, deleted tag),
APM MUST report an error and refuse to install until the lock file is updated.
Expand Down
5 changes: 3 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` refresh refs, `--force` overwrite, `--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; `--target all` deprecated, see `apm compile --all`; use `copilot-cowork` with `--global` after `apm experimental enable copilot-cowork`), `--dev`, `-g` global, `--trust-transitive-mcp`, `--parallel-downloads N`, `--allow-insecure`, `--allow-insecure-host HOSTNAME`, `--skill NAME` install named skill(s) from SKILL_BUNDLE (repeatable; persisted in apm.yml; `'*'` resets to all), `--legacy-skill-paths` restore per-client skill dirs, `--mcp NAME` add MCP entry, `--transport`, `--url`, `--env KEY=VAL`, `--header KEY=VAL`, `--mcp-version`, `--registry URL` custom MCP registry |
| `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, `--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; `--target all` deprecated, see `apm compile --all`; use `copilot-cowork` with `--global` after `apm experimental enable copilot-cowork`), `--dev`, `-g` global, `--trust-transitive-mcp`, `--parallel-downloads N`, `--allow-insecure`, `--allow-insecure-host HOSTNAME`, `--skill NAME` install named skill(s) from SKILL_BUNDLE (repeatable; persisted in apm.yml; `'*'` resets to all), `--legacy-skill-paths` restore per-client skill dirs, `--mcp NAME` add MCP entry, `--transport`, `--url`, `--env KEY=VAL`, `--header KEY=VAL`, `--mcp-version`, `--registry URL` custom MCP registry |
| `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 | `--dry-run`, `-g` global |
| `apm prune` | Remove orphaned packages | `--dry-run` |
Expand Down Expand Up @@ -161,6 +161,7 @@ Experimental flags MUST NOT gate security-critical behaviour (content scanning,
| `apm config get [KEY]` | Get a config value (`auto-integrate`, `temp-dir`, `copilot-cowork-skills-dir`) | -- |
| `apm config set KEY VALUE` | Set a config value (`auto-integrate`, `temp-dir`; `copilot-cowork-skills-dir` requires `apm experimental enable copilot-cowork`) | -- |
| `apm config unset KEY` | Remove a stored config value (`temp-dir`, `copilot-cowork-skills-dir`) | -- |
| `apm update` | Update APM itself (or show distributor guidance when self-update is disabled at build time) | `--check` only check |
| `apm update` | Refresh APM dependencies in the current project: resolves `apm.yml` against the latest refs, prints a structured plan (added/updated/removed/unchanged), and prompts before mutating anything (default `[y/N]`). Skips the prompt with `--yes`; previews without changes with `--dry-run`. | `--yes`, `--dry-run`, `--verbose` |
| `apm self-update` | Update the APM CLI itself (or show distributor guidance when self-update is disabled at build time). | `--check` only check |

`apm config set copilot-cowork-skills-dir <absolute-path>` persists the Cowork skills directory across shells. `apm config get copilot-cowork-skills-dir` and `apm config unset copilot-cowork-skills-dir` remain available even when the `copilot-cowork` flag is disabled so leftover state can still be inspected or cleared. In `apm config` and bare `apm config get`, the `copilot-cowork-skills-dir` entry is shown only when the `copilot-cowork` flag is enabled.
2 changes: 2 additions & 0 deletions src/apm_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from apm_cli.commands.prune import prune
from apm_cli.commands.run import preview, run
from apm_cli.commands.runtime import runtime
from apm_cli.commands.self_update import self_update
from apm_cli.commands.targets import targets
from apm_cli.commands.uninstall import uninstall
from apm_cli.commands.update import update
Expand Down Expand Up @@ -90,6 +91,7 @@ def cli(ctx):
cli.add_command(uninstall)
cli.add_command(prune)
cli.add_command(update)
cli.add_command(self_update)
cli.add_command(compile_cmd, name="compile")
cli.add_command(run)
cli.add_command(preview)
Expand Down
Loading
Loading