Skip to main content

How AXM works

The mechanics behind AXM — desired state, accepted resolution, canonical packages, projections, and safe reconciliation.

AXM has one core job: take something you install once and make it show up in every coding agent you use, then keep it in sync. This page explains the mechanics behind that — what AXM writes, where, and how it stays out of the way of files you maintain by hand.

When you install a skill, subagent, MCP server connection, or hook, AXM does two things:

  1. Stores a canonical package — acquired packages live under agent_extensions/ under the actual source host and package boundary, or _local source coordinates. Inspect the resolved path with AXM rather than deriving it from a source type. Packages you create live in the matching authored root such as skills/<name>/.
  2. Materializes it into your agents — it projects selected extensions into the locations supported by each coding agent you've configured. Skills also have a shared universal location.
your-project/
├── axm.json                              # desired project state
├── axm.lock                              # accepted external resolutions
├── agent_extensions/
│   └── registry.agentxm.ai/@acme/skills/code-review/ # acquired canonical package
├── skills/                               # authored skill packages, when present
├── .axm/                                 # ignored project runtime scratch
├── .agents/skills/code-review/      # universal (always synced)
├── .claude/skills/code-review/      # Claude Code
└── .cursor/skills/code-review/      # Cursor

Every projection is derived from its canonical package. Running axm sync reconciles desired state, accepted external resolutions, canonical packages, and AXM-owned projections. It blocks an affected closure when acquired content or an owned target has drifted rather than silently replacing unfamiliar bytes.

For skills, AXM materializes the universal .agents/skills/ location alongside the native locations required by configured agents. A host that reads that location can discover those skills directly. Other extension types use their own supported projection mechanisms; a skill directory does not establish MCP, hook, or subagent support.

Inspect AXM's projection results for the selected agents. Materialization makes content available, while the host's discovery settings and model determine whether and how it is used.

Two project-root files carry different kinds of truth:

  • axm.json is your intent. It records the coding agents you use and workspace configuration such as instructionFiles (see Rules). You edit it — directly or through commands like axm setup and axm agents add.
  • axm.lock is accepted external resolution. It pins immutable registry, Git, or local-source identity and the strict integrity of each complete acquired package tree. Workspace-authored and inline entries do not get package rows. The TOML file uses lockfile version 1 and also records projection currency. AXM rewrites it canonically; do not hand-edit it.

Settings answer "what should be true"; the lockfile answers "which exact external bytes were accepted." Observed canonical packages and projections are a third state family. Commit both with your repo so your team reproduces the same workspace.

Most installed external extensions have a canonical package under agent_extensions/. Inline MCP server connections are the exception: they live directly in axm.json when the connection is local workspace configuration rather than a reusable extension. AXM still syncs them into each configured agent and does not need an external-resolution lock row.

Everything installs at one of two scopes:

  • Project (default) — root axm.json, axm.lock, authored roots, and agent_extensions/, committed with your repo.
  • User — settings, lock, and canonical packages under ~/.axm/workspace/, applied across every project on your machine.

Most commands target project scope and accept a flag to switch to user scope.

AXM records accepted external packages in the lockfile and marks or structurally owns its projections, which lets it draw a clear line:

  • Managed files are the projections and regions AXM owns. It will update, disable, or remove them on command — and clean them up when you remove an agent or uninstall an extension.
  • Unmanaged files are anything you wrote by hand or another tool created. AXM never touches them. When it merges into a shared file like an agent's MCP configuration, it adds only its own entries and leaves yours alone.

This separation is why you can adopt AXM in an existing project without fear: it operates within recorded ownership. Inspect axm lint --json and an axm sync --preview --json plan before repair. Resolve unowned collisions explicitly; sync does not grant authority to delete unfamiliar files.

Extensions come from sources. AXM resolves three kinds:

  • The AgentXM.ai registry — the central catalog, by reference like @owner/skills/code-review.
  • A Git repository — install straight from owner/repo.
  • A local path — install from a folder you're developing in.

The registry is also where you publish so others can install your work. AXM can additionally surface extensions tied to a library or framework from any package ecosystem (npm, PyPI, crates.io, and more), so the tools you depend on can ship their own agent extensions.

Now that the concrete types are grounded, the generalization is worth naming. An extension is the umbrella term for everything AXM installs and syncs — a skill, a subagent, an MCP server connection, a rule, a hook, a Knowledge bundle, or a pack that bundles them. Each type has its own format and its own job, but they share the same lifecycle: desired state, canonical content, and reconciliation into applicable agents. External packages also have accepted lock state. When this documentation says "extension," it means any of those concrete types managed the same way.

Operational sources: axm help workspace-state and axm help basic-usage for your installed CLI. This explanation was reconciled with AXM 0.51.0.