Skip to main content
MindStudio
Pricing
Blog About
My Workspace

How to Build a Modular Skill System in Claude Code for Multiple Clients

Isolated skills break at scale. Learn how to build a modular skill system in Claude Code where one update propagates across every client and workflow.

MindStudio Team RSS
How to Build a Modular Skill System in Claude Code for Multiple Clients

The Problem with One-Off Skills at Scale

When you start working with Claude Code across multiple client projects, the temptation is to write skills — custom slash commands, tool definitions, prompt templates — directly inside each project. It feels fast. And it is, for one client.

Then you get five clients. Ten. You fix a bug in a skill for Client A, and Clients B through J are still running the broken version. Someone on your team adds a better version of a search skill, and now you have three variations floating across different repos, none of them talking to each other.

That’s the core problem a modular skill system solves: one authoritative definition, propagated everywhere. This guide walks through how to build that in Claude Code, whether you’re managing a small agency setup or a large multi-team deployment.


What Counts as a “Skill” in Claude Code

Before designing a system, it helps to be precise about what you’re actually modularizing.

In Claude Code, a skill is any reusable capability you give the agent to draw on repeatedly. These fall into a few categories:

Custom Slash Commands

Stored in .claude/commands/ within a project directory, slash commands are Markdown files that define a prompt and optional $ARGUMENTS placeholders. When you type /skill-name in a Claude Code session, Claude reads the file and executes accordingly.

.claude/
  commands/
    summarize-pr.md
    generate-tests.md
    update-changelog.md

These are project-scoped by default, which is exactly the problem for multi-client work.

Global User-Level Commands

TIME SPENT BUILDING REAL SOFTWARE
5%
95%
5% Typing the code
95% Knowing what to build · Coordinating agents · Debugging + integrating · Shipping to production

Coding agents automate the 5%. Remy runs the 95%.

The bottleneck was never typing the code. It was knowing what to build.

Claude Code also reads from ~/.claude/commands/. Anything in that directory is available across every project on your machine. This is the first foothold for modularity — but it only works for a single developer’s machine, not a whole team.

MCP Tool Definitions

Model Context Protocol (MCP) servers expose tools that Claude Code can call. An MCP server running locally or remotely can serve as a centralized skill registry — one server, many clients, all pulling from the same tool definitions.

CLAUDE.md Directives

The CLAUDE.md file at the project root (or at ~/.claude/CLAUDE.md globally) sets behavioral instructions, context, and workflow guidance. Skills can be defined as instruction patterns here, though this approach is better for lightweight conventions than complex tool logic.

Understanding which type of skill you’re dealing with matters because each has different propagation characteristics and different trade-offs.


Designing the Architecture Before Writing a Line

Rushing to build before designing is the fastest way to recreate the mess you’re trying to escape. A modular skill system needs a clear architecture first.

The Core Principle: Single Source of Truth

Every skill should live in exactly one place. Clients consume it — they don’t own it. This sounds obvious, but the default structure of Claude Code makes it easy to accidentally let clients own their skills.

Your target state looks something like this:

skills-repo/           ← single source of truth
  commands/
    code-review.md
    write-tests.md
    generate-docs.md
  mcp-server/
    src/
      tools/
  package.json

client-a/              ← consumer, not owner
  .claude/
    commands/          ← symlinked or generated from skills-repo
  CLAUDE.md            ← references shared skills, client-specific context

client-b/
  .claude/
    commands/
  CLAUDE.md

Three Viable Propagation Strategies

Strategy 1: Git submodule + symlinks

Keep your skills in a dedicated git repository. Each client project adds it as a submodule. A setup script symlinks the relevant commands into .claude/commands/. When you update the skills repo, clients pull the submodule update.

This works well for teams with strong git discipline. The downside: submodule management has rough edges, and developers who aren’t careful will let submodules drift.

Strategy 2: npm package

Package your skills as an npm module. Include a post-install script that copies or symlinks command files into .claude/commands/. Clients add the package to devDependencies, and updating is as simple as bumping the version.

{
  "name": "@yourorg/claude-skills",
  "version": "1.4.0",
  "scripts": {
    "postinstall": "node scripts/install-commands.js"
  }
}

This is cleaner than submodules for most teams. Versioning is explicit, rollback is easy, and npm handles distribution.

Strategy 3: Centralized MCP server

Run a single MCP server that all client Claude Code instances connect to. Skills live on the server — clients just get tool access. Updates deploy once, take effect everywhere immediately.

This is the most powerful option and the most operationally complex. It requires running infrastructure and managing authentication across clients. But for agencies serving many clients simultaneously, it’s often the right call.


Building the Shared Skill Library

With an architecture chosen, here’s how to actually build the library.

Step 1: Audit Existing Skills

Before writing new ones, inventory what you have. Go through each client project and list every .claude/commands/ file. Look for duplicates and near-duplicates — “generate-tests.md” and “write-unit-tests.md” that do roughly the same thing.

Group them:

  • Universal skills: work the same across all clients (code review, changelog generation, PR description writing)
  • Parameterized skills: same structure, different configuration (API doc generation where the base URL changes per client)
  • Client-specific skills: genuinely unique to one project, shouldn’t be shared

Remy doesn't build the plumbing. It inherits it.

Other agents wire up auth, databases, models, and integrations from scratch every time you ask them to build something.

200+
AI MODELS
GPT · Claude · Gemini · Llama
1,000+
INTEGRATIONS
Slack · Stripe · Notion · HubSpot
MANAGED DB
AUTH
PAYMENTS
CRONS

Remy ships with all of it from MindStudio — so every cycle goes into the app you actually want.

Only universal and parameterized skills belong in the shared library. Client-specific ones stay in the project.

Step 2: Write Skills That Accept Parameters

Hardcoded values are the enemy of reuse. Use $ARGUMENTS in slash commands to keep skills flexible:

---
description: Generate API documentation for a specific endpoint
---

Generate comprehensive API documentation for the following endpoint:

$ARGUMENTS

Include: request parameters, response shape, error codes, and a usage example.
Follow the project conventions defined in CLAUDE.md.

For MCP tools, use typed input schemas so Claude knows exactly what to pass:

server.tool(
  "generate-api-docs",
  {
    endpoint: z.string().describe("The API endpoint path"),
    method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]),
    authRequired: z.boolean().default(false)
  },
  async ({ endpoint, method, authRequired }) => {
    // skill logic
  }
);

Step 3: Use CLAUDE.md for Client-Specific Configuration

The CLAUDE.md file is where client-specific context lives — not the skills themselves. A well-structured CLAUDE.md tells the shared skills how to behave for this particular client:

# Project Context

**Client**: Acme Corp
**Tech Stack**: Next.js 14, TypeScript, PostgreSQL, Prisma
**Test Framework**: Vitest
**Code Style**: ESLint with airbnb config

## Skill Configuration
- API base URL: https://api.acme.com/v2
- Default branch: main
- Changelog format: keep-a-changelog

Your shared skills read this context from the project and adapt. Claude Code automatically includes CLAUDE.md content in the context window, so skills can reference these values without any special imports.

Step 4: Version Your Skills Explicitly

Add a version comment to every skill file. This sounds pedantic but it matters when you’re debugging why a skill behaves differently across clients:

---
description: Summarize pull request for review
version: 2.1.0
---

In an npm package setup, the package version pins the skill version. With git submodules, the submodule commit hash does the same job.


Propagating Updates Across Clients

A modular system is only as good as its propagation mechanism. Here’s how to handle updates without manually touching every client.

For the npm Package Approach

Set up a CI pipeline that publishes a new package version when changes merge to main in the skills repo. Clients then have two options:

Option A: Automated dependency updates

Use Renovate or Dependabot to automatically open PRs in each client repo when the skills package publishes a new version. Clients review, approve, and merge. Clean audit trail, explicit consent on each update.

Option B: Pinned ranges with manual bumps

Clients pin to a minor range ("@yourorg/claude-skills": "^1.0.0"). npm update pulls the latest compatible version. Less overhead, slightly less control.

For breaking changes in skills — where you’ve changed argument structure or behavior significantly — bump the major version and document the migration.

For the Git Submodule Approach

Write a short update script that each client project can run:

#!/bin/bash
# update-skills.sh
git submodule update --remote skills
npm run install-commands
echo "Skills updated to $(git -C skills rev-parse --short HEAD)"

Run this in CI on a schedule, or trigger it manually when a skills release goes out. Either way, the update is a one-command operation per client.

For the MCP Server Approach

Cursor
ChatGPT
Figma
Linear
GitHub
Vercel
Supabase
remy.msagent.ai

Seven tools to build an app. Or just Remy.

Editor, preview, AI agents, deploy — all in one tab. Nothing to install.

Updates deploy to the server. Clients pick them up immediately on next tool call — no action required on the client side.

The complexity is in deployment: you need zero-downtime deploys if clients are actively using skills, and you need to handle tool schema changes carefully. Adding a new optional parameter is safe. Removing a parameter or changing its type can break running sessions.

A sensible policy: never remove parameters, only deprecate them. Add new functionality through new tools or new optional parameters.

Testing Before Propagating

Build a test suite for your shared skills before you propagate updates. This can be as simple as a set of input/output pairs that you verify with each release:

describe("code-review skill", () => {
  it("identifies missing error handling", async () => {
    const result = await runSkill("code-review", { 
      code: sampleCodeWithMissingErrorHandling 
    });
    expect(result).toContain("error handling");
  });
});

Run this suite in the skills repo CI before publishing. Catching a regression at the source is far cheaper than debugging it across ten client projects.


Where MindStudio Fits

If you’re building a modular skill system for Claude Code, one of the stickier problems is skills that touch external services: sending emails, generating images, searching the web, triggering workflows in other tools.

Rolling your own integrations for each of these eats time fast. You end up with bespoke API wrappers that need maintenance, rate limiting logic, auth handling — infrastructure that has nothing to do with the actual skill logic.

MindStudio’s Agent Skills Plugin addresses this directly. It’s an npm SDK (@mindstudio-ai/agent) that gives Claude Code — and any other agent — access to 120+ typed capabilities as simple method calls. Your shared skills can call agent.sendEmail(), agent.searchGoogle(), agent.generateImage(), or agent.runWorkflow() without managing any of the underlying infrastructure.

This fits naturally into the npm package propagation strategy. Add @mindstudio-ai/agent as a dependency in your skills package, and every client that pulls the package update gets access to those capabilities immediately.

A concrete example: you have a skill that generates a client-facing summary after a code review. With the Agent Skills Plugin, that skill can automatically send the summary as an email — one method call, no SMTP setup, no API keys to manage per client:

import MindStudio from '@mindstudio-ai/agent';
const agent = new MindStudio();

// Inside your code-review skill handler
await agent.sendEmail({
  to: clientEmail,
  subject: `Code Review Summary — ${prTitle}`,
  body: reviewSummary
});

Because the integration layer is centralized in MindStudio, updates to that infrastructure (better rate limiting, new retry logic, expanded APIs) propagate to your skills automatically — without touching your skill definitions.

You can try MindStudio free at mindstudio.ai.


Common Mistakes to Avoid

Even with a clean architecture, a few patterns consistently cause problems.

Letting Clients Modify Shared Skills Directly

If a client project has edit access to the shared skill files — via a checked-in copy rather than a submodule or package — someone will eventually modify them for that specific client. Now you have divergence again.

Other agents start typing. Remy starts asking.

YOU SAID "Build me a sales CRM."
01 DESIGN Should it feel like Linear, or Salesforce?
02 UX How do reps move deals — drag, or dropdown?
03 ARCH Single team, or multi-org with permissions?

Scoping, trade-offs, edge cases — the real work. Before a line of code.

Enforce a read-only relationship at the tooling level. Package consumers can’t push to the package. Submodule consumers shouldn’t have write access to the submodule remote. If a client needs different behavior, that’s a CLAUDE.md configuration change, not a skill modification.

Building Skills That Are Too Broad

A skill called “do-code-stuff” that tries to cover code review, refactoring, and documentation in one prompt is hard to reuse cleanly. Skills should have a single, well-defined job. If you find yourself writing “or if the user wants X, do Y instead” in a skill, that’s a signal to split it.

Skipping Semantic Versioning

Treating all updates as interchangeable patches causes problems fast. A changed argument structure in a skill is a breaking change — it deserves a major version bump. Teams that skip this end up debugging mysterious failures because a client is running skill v1.2.0 while the documentation assumes v2.0.0.

Hardcoding Model-Specific Behavior

Some skills work well with Claude 3.5 Sonnet but produce different results with Haiku or Opus. If your shared skills are model-agnostic — relying on clear instructions rather than model-specific quirks — they’re more durable. Document any known model dependencies explicitly in the skill’s front matter.

No Rollback Plan

At some point, a skill update will cause problems in production. Have a rollback procedure defined before you need it: which command reverts the submodule, how to pin a previous package version, how to roll back an MCP server deploy. Running a drill before the first real incident is worth the time.


FAQ

Can Claude Code access skills defined outside the project directory?

Yes. Skills in ~/.claude/commands/ are available globally across all projects on a single machine. MCP servers can also expose tools globally, regardless of which project directory Claude Code is running in. The global user-level commands directory is the simplest option for solo developers; MCP servers scale better for teams.

How do you handle client-specific skill variations without forking the shared library?

Use parameterization and CLAUDE.md configuration. The skill definition stays in the shared library, but reads project-specific values from CLAUDE.md. If two clients genuinely need behavior that can’t be unified through parameters, treat them as different skills — don’t try to merge them into one tangled definition. One clean shared skill is better than one overloaded skill.

What’s the best way to test shared skills before deploying to clients?

Build an integration test suite in the skills repository that runs against representative inputs. For slash commands, test the prompt output against known-good responses using Claude’s API directly. For MCP tools, test the tool logic with unit tests and mock the Claude Code integration. Run tests in CI on every merge to the main branch, and block publishing if tests fail.

How do you manage authentication when skills call external APIs?

Keep auth credentials out of the skill definitions. Use environment variables at the project level, or centralize credential management through a service like MindStudio’s Agent Skills Plugin that handles auth at the infrastructure layer. Skills should assume credentials are available in the environment — they shouldn’t know where those credentials came from.

Can multiple developers on a team use the same shared skill library?

Plans first. Then code.

PROJECTYOUR APP
SCREENS12
DB TABLES6
BUILT BYREMY
1280 px · TYP.
yourapp.msagent.ai
A · UI · FRONT END

Remy writes the spec, manages the build, and ships the app.

Yes, and this is one of the primary benefits. Package-based distribution works best for teams: each developer’s machine pulls the same package version, gets the same command files installed, and runs the same skill logic. MCP server-based distribution is even cleaner for teams — everyone connects to the same server, and there’s nothing to install on individual machines.

What happens when you update a skill that’s actively being used by clients?

For slash commands and installed packages, updates take effect the next time a developer updates their dependencies — there’s no live interruption. For MCP servers, changes deploy immediately on next tool call. Document breaking changes clearly in release notes, use semantic versioning to signal them, and give clients advance notice before major version releases that change existing behavior.


Key Takeaways

  • Define skills in one place and have clients consume them — never let clients own or modify shared skills directly.
  • Three viable propagation strategies: git submodules with symlinks, npm package distribution, or a centralized MCP server. Choose based on your team size and operational comfort.
  • Use $ARGUMENTS and typed input schemas to keep skills flexible across clients. Use CLAUDE.md for client-specific configuration.
  • Version your skills explicitly with semantic versioning. Breaking changes get major version bumps.
  • For skills that call external services, handle auth and infrastructure at the distribution layer — not inside the skill definitions.
  • Test skills in the source repo before propagating updates. Catching regressions at the source is cheaper than debugging them across multiple clients.

A modular skill system is an investment that pays off as soon as you hit your third or fourth client. The earlier you build the infrastructure, the less manual repair work accumulates. If you’re already managing Claude Code across multiple projects, MindStudio’s Agent Skills Plugin is worth looking at for the external integration layer — it handles the infrastructure so your shared skills can stay focused on reasoning, not plumbing.

Presented by MindStudio

No spam. Unsubscribe anytime.