skills/cowork-plugin-authoring/SKILL.md
Skill instructions for creating or customizing Cowork plugins, including mode selection, research, implementation, packaging, connector replacement, and plugin delivery
npx skillsauth add mkusaka/ccskills cowork-plugin-authoringInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create a new Cowork plugin from scratch, or customize an existing one for a specific organization. Both paths deliver a ready-to-install .plugin file at the end.
Decide from the user's request:
Nontechnical output: Keep all user-facing conversation in plain language. Never mention file paths, directory structures, schema fields,
~~prefixes, or placeholders unless the user asks. Frame everything in terms of what the plugin will do.
AskUserQuestion: When you need input, use AskUserQuestion. Don't assume "industry standard" defaults are correct. AskUserQuestion always includes a Skip button and a free-text input box for custom answers, so do not include
NoneorOtheras options.
A plugin is a self-contained directory that extends Claude with skills, agents, hooks, and MCP server integrations.
plugin-name/
├── .claude-plugin/
│ └── plugin.json # Required: plugin manifest
├── skills/ # Skills (subdirectories with SKILL.md)
│ └── skill-name/
│ ├── SKILL.md
│ └── references/
├── agents/ # Subagent definitions (.md files)
├── .mcp.json # MCP server definitions
└── README.md # Plugin documentation
Legacy
commands/format: Older plugins may include acommands/directory with single-file.mdslash commands. This format still works, but new plugins should useskills/*/SKILL.mdinstead — the Cowork UI presents both as a single "Skills" concept, and the skills format supports progressive disclosure viareferences/. Treatcommands/*.mdfiles the same way you wouldskills/*/SKILL.mdwhen customizing.
Rules:
.claude-plugin/plugin.json is always requiredskills/, agents/) go at the plugin root, not inside .claude-plugin/Located at .claude-plugin/plugin.json. Minimal required field is name.
{
"name": "plugin-name",
"version": "0.1.0",
"description": "Brief explanation of plugin purpose",
"author": {
"name": "Author Name"
}
}
Name rules: kebab-case, lowercase with hyphens, no spaces or special characters.
Version: semver format (MAJOR.MINOR.PATCH). Start at 0.1.0.
Optional fields: homepage, repository, license, keywords.
Custom component paths can be specified (supplements, does not replace, auto-discovery):
{
"commands": "./custom-commands",
"agents": ["./agents", "./specialized-agents"],
"hooks": "./config/hooks.json",
"mcpServers": "./.mcp.json"
}
Detailed schemas for each component type are in references/component-schemas.md.
| Component | Location | Format |
| ---------------------------------- | ------------------- | --------------------------- |
| Skills | skills/*/SKILL.md | Markdown + YAML frontmatter |
| MCP Servers | .mcp.json | JSON |
| Agents (uncommonly used in Cowork) | agents/*.md | Markdown + YAML frontmatter |
| Hooks (rarely used in Cowork) | hooks/hooks.json | JSON |
| Commands (legacy) | commands/*.md | Markdown + YAML frontmatter |
This schema is shared with Claude Code's plugin system, but you're building for Claude Cowork, a desktop app for knowledge work. Cowork users will usually find skills the most useful. Scaffold new plugins with skills/*/SKILL.md — do not create commands/ unless the user explicitly needs the legacy single-file format.
~~ placeholdersDo not use or ask about this pattern by default. Only introduce
~~placeholders if the user explicitly says they want people outside their organization to use the plugin. You can mention it as an option if they want to distribute externally, but do not proactively ask with AskUserQuestion.
When a plugin is intended to be shared outside the author's company, it might reference external tools by category rather than specific product (e.g., "project tracker" instead of "Jira"). Use generic language and mark these as requiring customization with two tilde characters: create an issue in ~~project tracker.
If any tool categories are used, write a CONNECTORS.md file at the plugin root to explain:
# Connectors
## How tool references work
Plugin files use `~~category` as a placeholder for whatever tool the user
connects in that category. Plugins are tool-agnostic — they describe
workflows in terms of categories rather than specific products.
## Connectors for this plugin
| Category | Placeholder | Options |
| --------------- | ------------------- | ------------------------------- |
| Chat | `~~chat` | Slack, Microsoft Teams, Discord |
| Project tracker | `~~project tracker` | Linear, Asana, Jira |
Use ${CLAUDE_PLUGIN_ROOT} for all intra-plugin path references in hooks and MCP configs. Never hardcode absolute paths.
Build from scratch through a five-phase guided conversation.
Understand what the user wants to build and why. Ask (only what is unclear — skip questions the user's initial request already answers):
Summarize understanding and confirm before proceeding.
Based on discovery, determine which component types are needed:
Present a component plan table including types you decided not to create:
| Component | Count | Purpose |
|-----------|-------|---------|
| Skills | 3 | Domain knowledge for X, /do-thing, /check-thing |
| Agents | 0 | Not needed |
| Hooks | 1 | Validate writes |
| MCP | 1 | Connect to service Y |
Get user confirmation before proceeding.
Specify each component in detail. Resolve all ambiguities before implementation. Present questions grouped by component type and wait for answers.
Skills:
Agents:
Hooks:
MCP Servers:
If the user says "whatever you think is best," provide specific recommendations and get explicit confirmation.
Create all plugin files following best practices.
plugin.json manifestreferences/component-schemas.md for exact formats)README.md documenting the pluginGuidelines:
references/. Frontmatter description must be third-person with specific trigger phrases. Skill bodies are instructions FOR Claude, not messages to the user — write them as directives.<example> blocks showing triggering conditions, plus a system prompt in the markdown body.hooks/hooks.json. Use ${CLAUDE_PLUGIN_ROOT} for script paths. Prefer prompt-based hooks for complex logic..mcp.json at plugin root. Use ${CLAUDE_PLUGIN_ROOT} for local server paths. Document required env vars in README.Summarize what was created — list each component and its purpose
Ask if the user wants any adjustments
Run claude plugin validate <path-to-plugin-json> to check the plugin structure. If this command is unavailable (e.g., when running inside Cowork), verify manually:
.claude-plugin/plugin.json exists and contains valid JSON with at least a name fieldname field is kebab-case (lowercase letters, numbers, and hyphens only)commands/, skills/, agents/, hooks/) actually exist and contain files in the expected formats — .md for commands/skills/agents, .json for hooksSKILL.mdFix any errors, then proceed to Packaging.
Customize a plugin for a specific organization — either by setting up a generic plugin template for the first time, or by tweaking an already-configured plugin.
Run find mnt/.local-plugins mnt/.plugins ~/.claude/plugins/synced -type d -name "*<plugin-name>*" 2>/dev/null to locate the plugin directory, then read its files to understand its structure before making changes.
If you cannot find the plugin directory in any of those locations, let the user know: "I couldn't find an installed plugin named '<plugin-name>'. If it's installed on your desktop, open this task from the Cowork desktop app so I can access it."
After locating the plugin, check for ~~-prefixed placeholders: grep -rn '~~\w' /path/to/plugin --include='*.md' --include='*.json'
Default rule: If
~~placeholders exist, default to Generic plugin setup unless the user explicitly asks to customize a specific part of the plugin.
1. Generic plugin setup — The plugin contains ~~-prefixed placeholders. These are customization points in a template that need to be replaced with real values (e.g., ~~Jira → Asana, ~~your-team-channel → #engineering).
2. Scoped customization — No ~~ placeholders exist, and the user asked to customize a specific part of the plugin (e.g., "customize the connectors", "update the standup skill", "change the ticket tool"). Read the plugin files to find the relevant section(s) and focus only on those. Do not scan the entire plugin or present unrelated customization items.
3. General customization — No ~~ placeholders exist, and the user wants to modify the plugin broadly. Read the plugin's files to understand its current configuration, then ask the user what they'd like to change.
Important: Never change the name of the plugin or skill being customized. Do not rename directories, files, or the plugin/skill name fields.
Check whether the user provided free-form context alongside their request (e.g., "customize the standup skill — we do async standups in #eng-updates every morning").
Use company-internal knowledge MCPs to collect information relevant to the customization scope. See references/search-strategies.md for detailed query patterns.
What to gather (scope to what's relevant):
Sources to search:
Record all findings for use in Phase 3.
Build a todo list of changes to make, scoped appropriately:
grep -rn '~~\w' /path/to/plugin --include='*.md' --include='*.json' to find all placeholder customization points. Group them by theme.Use user-friendly descriptions that focus on the plugin's purpose:
Work through each item using context from Phase 0 and Phase 1.
If the user's free-form input (Phase 0) or knowledge MCPs (Phase 1) provided a clear answer: Apply directly without confirmation.
Otherwise: Use AskUserQuestion. Don't assume "industry standard" defaults are correct — if neither the user's input nor knowledge MCPs provided a specific answer, ask.
Types of changes:
~~Jira → Asana, ~~your-org-channel → #engineeringtickets.example.com/your-team/123 → app.asana.com/0/PROJECT_ID/TASK_IDIf the user doesn't know or skips, leave the value unchanged (or the ~~-prefixed placeholder, for generic setup).
After customization items are resolved, connect MCPs for any tools that were identified or changed. See references/mcp-servers.md for the full workflow, category-to-keywords mapping, and config file format.
For each tool identified during customization:
search_mcp_registry(keywords=[...]) using category keywords from references/mcp-servers.md, or search for the specific tool name if already knownsuggest_connectors(directoryUuids=["chosen-uuid"]) — user completes authplugin.json for custom location, otherwise .mcp.json at root)Collect all MCP results and present them together in the summary output — don't present MCPs one at a time during this phase.
After customization, present the user with a summary of what was learned grouped by source. Always include the MCPs sections showing which were connected and which the user should still connect:
## From searching Slack
- You use Asana for project management
- Sprint cycles are 2 weeks
## From searching documents
- Story points use T-shirt sizes
## From your answers
- Ticket statuses are: Backlog, In Progress, In Review, Done
Then present the MCPs that were connected during setup and any that the user should still connect, with instructions.
If no knowledge MCPs were available in Phase 1, and the user had to answer at least one question manually, include a note at the end:
By the way, connecting sources like Slack or Microsoft Teams would let me find answers automatically next time you customize a plugin.
Then proceed to Packaging.
After create or customize completes, package the plugin as a .plugin file and deliver it with the SendUserFile tool:
cd /path/to/plugin-dir && zip -r /tmp/plugin-name.plugin . -x "setup/*" -x "*.DS_Store"
SendUserFile with files: ["/tmp/plugin-name.plugin"], status: "normal", and a short caption summarizing what was built or changed.The .plugin file will appear in the chat as a rich preview where the user can browse the files and accept the plugin by pressing a button.
Naming: Use the plugin name from
plugin.json(for create) or the original plugin directory name (for customize) as the.pluginfilename. Do not rename the plugin or its files during customization — only replace placeholder values and update content.
references/, working examples in examples/.<example> blocks.${CLAUDE_PLUGIN_ROOT} for intra-plugin paths, never hardcoded paths.references/component-schemas.md — Detailed format specifications for every component type (skills, agents, hooks, MCP, legacy commands, CONNECTORS.md)references/example-plugins.md — Three complete example plugin structures at different complexity levelsreferences/mcp-servers.md — MCP discovery workflow, category-to-keywords mapping, config file locations, example .mcp.jsonreferences/search-strategies.md — Knowledge MCP query patterns for finding tool names and org valuesdevelopment
Skill for syncing a React design system to claude.ai/design by configuring the target project, running the converter, verifying previews, and uploading verified artifacts
development
Design sync sub-skill instructions for using a repo's Storybook as the fidelity oracle when building, validating, matching, uploading, and re-syncing component previews
development
Skill definition for syncing a React design system to claude.ai/design, including project selection, source-shape detection, converter configuration, validation, upload planning, and self-check behavior
development
Shape-specific /design-sync instructions for syncing a React design system from a built package without Storybook