Claude shipped a plugin dependency manager
Claude Code recently shipped dependency management for plugins, and as someone working on making collaboration better, I feel very excited about it. It means a skill can now be built on top of another skill. It means a platform team can publish a foundation and a hundred other teams can build on it without copying a single file. An entire layer of reuse that simply was not possible a few weeks ago is now sitting in the changelog, described in one modest sentence. I read it twice, and then I sat back, because I have seen this exact moment before in other corners of our industry, and I know what comes after it. It is a new frontier. Think about the introduction of pom.xml, or of package.json.
A quick word on how this post came together. I worked through most of this thinking out loud with Claude itself, tracing the feature from the docs into the actual GitHub issues, arguing about what counts as a dependency manager and what does not. Some of the sharpest framing here came out of that back and forth. I mention it because the irony is not lost on me that I used the tool to understand the tool.
Why those two files are the right comparison
The reason I reach for Maven and npm is that I have leaned on both, and the contrast between them taught me what dependency management actually buys.
In Maven, a dependency is an intent rather than a list of files.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.0</version>
</dependency>
I ask for one artifact and Maven brings in dozens, because Spring Boot declares its own dependencies, and those declare theirs, all the way down. The transitive set arrives without my touching it. The project owns a pom.xml, and when the build runs, Maven reads that file and provisions the world it describes. The project is the thing that sets resolution in motion.
npm expresses the same idea, with one addition I have come to value.
{
"dependencies": {
"express": "^4.18.0",
"pino": "~9.0.0"
}
}
Those carets and tildes are quietly profound. They are a contract about change. The caret welcomes compatible updates but refuses to cross a major boundary in silence. When I install, npm intersects every package's constraint, settles on versions that satisfy all of them at once, and writes the exact resolved set into a lockfile so the next machine reproduces it down to the patch. The constraint expresses tolerance for change, and the lockfile expresses intolerance for surprise, and a mature ecosystem needs both.
Both files, underneath the syntax, do the same four things. They let a consumer declare what it needs, version what it needs, resolve the transitive graph so one install pulls in everything below it, and reproduce that resolution elsewhere. Declare, version, resolve, reproduce. That quartet is what turned two configuration files into the foundation of entire economies, and it is the lens I want to hold Claude Code up against.
What actually shipped
https://github.com/anthropics/claude-code/issues/64457A plugin now declares its dependencies in its manifest, in a form anyone who has opened a package.json will recognize.
{
"name": "platform-observability",
"version": "2.3.0",
"description": "Shared observability conventions and tooling",
"dependencies": [
"audit-logging",
{ "name": "metrics-core", "version": "~2.1.0" }
]
}
There are two forms, and the choice between them is the same lesson npm teaches. A bare name accepts whatever the marketplace currently offers. An object with a version field pins a semantic version range, and the highest release that satisfies it is selected.
Now a higher-level plugin builds on that foundation.
{
"name": "team-incident-toolkit",
"version": "1.0.0",
"dependencies": [
{ "name": "platform-observability", "version": "^2.0.0" }
]
}
Someone installs the leaf.
claude plugin install team-incident-toolkit@acme-marketplace
The runtime reads the manifest, sees the declared dependency, and pulls in platform-observability automatically, and with it the things that plugin in turn depends on. One command, the entire closure. The top of the tree arrives with the tree attached. Versions are anchored to git tags on the marketplace repository, and when two installed plugins constrain the same dependency, the runtime intersects their ranges and chooses the highest version satisfying both, raising a clear error when no version can satisfy everyone rather than quietly loading something that will misbehave later. That last behavior is the one I respect most, because the failures that hurt are never the loud ones.
Three of the four properties are unmistakably here. Declaration, versioning with real semantic ranges, and transitive resolution with honest conflict handling. The fourth, reproducibility, is where I have to temper the enthusiasm, because there is no lockfile yet. Resolution happens against live tags at the moment of install, so reproducibility rests on tight pinning by convention rather than on a committed artifact that guarantees every engineer and every build agent lands on an identical set. For anyone who has come to treat a lockfile as the thing that makes a teammate's checkout match their own, its absence is the conspicuous gap, and I expect it to be among the first things to close.
It is worth noting that this did not arrive fully formed, and the community is actively shaping it. The original request lived as issue #9444, asking for exactly this, plugins that declare dependencies on other plugins, with a shared library plugin underneath. Reading that thread is a small lesson in how these features mature in the open. And the rough edges are being found the same way. The version resolution itself was reported broken in issue #64457 and, as I write this, is only partially fixed, with local folder marketplaces still misbehaving, tracked in issue #65337. If you build on this today, build on a remote marketplace and verify your version pins resolve before you trust them.
So far this is a celebration with one footnote. Now I want to turn to the two things that keep me from calling this finished, because a frontier is exciting precisely because it is not yet settled.
It is Claude's, not a standard, and I hope that changes
The first thing to sit with is that this is Claude Code's dependency model, and Claude Code's alone. The manifest format, the tag convention, the resolution behavior, all of it lives inside one vendor's tooling. That is not a criticism. It is how every one of these stories begins. npm was a JavaScript thing before it was a movement. Maven was a Java thing. A dependency model almost always arrives as one ecosystem's local invention and only later, if it earns it, hardens into something the wider world agrees on.
But I find myself wishing for the standard already, because the underlying artifact is more portable than the plumbing around it. The skill itself, the folder with its instructions, is largely tool-agnostic. What differs is the wrapper. A different agent tool expresses the same dependency idea in a different manifest with a different resolver, and a team that lives across more than one tool ends up maintaining two disciplines for one set of skills. We have watched a parallel effort try to standardize the skill format itself. I would love to see the same energy reach the dependency layer, so that "this plugin depends on that plugin, in this version range" means the same thing no matter whose runtime reads it. We already have a standard for how agents talk to tools, and the field is converging on one for how agents talk to each other. A shared way to express how agent capabilities depend on one another feels like the natural third piece, and I hope someone takes it up. Until then, what we have is a very good vendor implementation, and a very good vendor implementation is exactly the seed a standard grows from.
There is no lifecycle, so the trigger is still a person
The second thing is subtler, and it is the one that took me a moment to articulate. Go back to pom.xml for a second. The reason that file is powerful is not only that it declares dependencies. It is that a lifecycle reads it. I run a build, and the build looks at the project, sees what it needs, and provisions it. The project itself is the trigger.
Claude Code has the declarations and the resolution, but not that lifecycle. The dependencies belong to the plugin, and resolution fires when a person installs a plugin, not when a repository is opened. A project can describe the plugins it wants, but nothing yet reads that description on open and provisions it the way a build reads a pom.xml. The engine is solid. What is missing is the project acting as the trigger.
In practice this means onboarding still begins with a deliberate human act. A new teammate clones a repository, and the right capabilities do not simply appear because the repository asked for them. Someone has to issue the first install. The dependency graph beneath that first install is fully automatic and genuinely impressive. The initiating step is not. It is a small manual seam stitched on top of a hard problem that has already been solved, and that ratio is exactly why I am optimistic rather than impatient. The expensive machinery is built. What remains is a convenience, and conveniences tend to follow quickly once the hard part is done.
Why I bothered to write this down
A changelog entry says plugins can declare dependencies. I read the same line and saw the thing I have learned to recognize.
The reason npm and Maven grew into economies was never the syntax. It was that dependency resolution is what turns a shared library into something a hundred teams can build on without copying it. Once that primitive exists, a platform team can own a foundation, publish it, version it, and let others compose on top while pinning the compatibility they have actually tested. That is now possible for agent capabilities, and it was not a month ago. A platform group can own a shared plugin, conventions and wiring and a few well-tested skills, and another team can depend on it in a single line and receive updates inside a range it trusts.
The question for those of us who think in systems is no longer how to share a skill, which has quietly become an ordinary solved problem. It is how to architect a layered set of capabilities the same way we architect a layered set of libraries. Stable foundations underneath, faster-moving work at the edges, version contracts between teams who do not sit together. These are old disciplines, and they have found a new substrate.
I will close with the honesty this deserves, because the ground is still moving as I write. The behavior I have described landed recently. The missing lockfile, the vendor-specific format, the install-time trigger that has not yet become a project-time one, all of it is under active iteration. What I have written is a snapshot. The durable point is not today's exact feature set but the direction, which is that agent tooling is compressing into months the same evolution that language ecosystems took years to work through. We are watching a pom.xml moment happen in real time. I do not know exactly what it grows into, and I am genuinely excited to find out.
If this resonated, I would love to hear your perspective, especially if you are an engineer or engineering leader thinking about how shared capabilities should be built and distributed in an AI-first world.
No comments :
Post a Comment