-
Notifications
You must be signed in to change notification settings - Fork 721
Improve plugin customizer for scoped and general customization #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,46 +1,50 @@ | ||
| --- | ||
| name: cowork-plugin-customizer | ||
| description: > | ||
| Customize or personalize a Claude Code plugin for a specific organization's tools and workflows. | ||
| Use when users want to customize a plugin, replace tool placeholders, or configure MCP servers for a plugin. | ||
| Customize a Claude Code plugin for a specific organization's tools and workflows. | ||
| Use when users want to customize a plugin — whether it's a generic template with placeholders or an already-configured plugin they want to tweak. | ||
| Also use when users want to customize a specific part of a plugin (e.g., connectors, skill, commands, agents). | ||
| This skill requires Cowork mode with mounted plugin directories and will not work in remote or standard CLI sessions. | ||
| compatibility: Requires Cowork desktop app environment with access to mounted plugin directories (mnt/.local-plugins, mnt/.plugins). | ||
| --- | ||
|
|
||
| # Cowork Plugin Customization | ||
|
|
||
| Adapt a generic plugin template to a specific organization by replacing customization points with actual tool names, configuring MCP servers, and applying organization-specific customizations. | ||
| Customize a plugin for a specific organization — either by setting up a generic plugin template for the first time, or by tweaking and refining an already-configured plugin. | ||
|
|
||
| > **Finding the plugin**: To find the plugin's source files, run `find mnt/.local-plugins mnt/.plugins -type d -name "*<plugin-name>*"` to locate the plugin directory, then read its files to understand its structure before making changes. If you cannot find the plugin directory, the user is likely running this conversation in a remote container. Abort and let them know: "Customizing plugins is currently only available in the desktop app's Cowork mode." | ||
|
|
||
| ## Overview | ||
| ## Determining the Customization Mode | ||
|
|
||
| Generic plugins mark customization points with a `~~` prefix. Any line or value starting with `~~` is a placeholder that should be replaced during customization (e.g., `~~Jira` → `Asana`, `~~your-team-channel` → `#engineering`). To find all customization points in a plugin, use: | ||
| After locating the plugin, determine what kind of customization is needed: | ||
|
|
||
| ```bash | ||
| grep -rn '~~\w' /path/to/plugin --include='*.md' --include='*.json' | ||
| ``` | ||
| **1. Scoped customization** — The user asked to customize a specific part of the plugin (e.g., "customize the connectors", "update the standup command", "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. | ||
|
|
||
| > **Important**: Never change the name of the plugin or skill being customized. Only replace `~~`-prefixed placeholder values and update content — do not rename directories, files, or the plugin/skill name fields. | ||
| **2. Generic plugin setup** — The plugin contains `~~`-prefixed placeholders (check with `grep -rn '~~\w' /path/to/plugin --include='*.md' --include='*.json'`). These are customization points in a template that need to be replaced with real values (e.g., `~~Jira` → `Asana`, `~~your-team-channel` → `#engineering`). | ||
|
|
||
| > **Nontechnical output**: All user-facing output (todo list items, questions, summaries) must be written in plain, nontechnical language. Never mention `~~` prefixes, placeholders, or customization points to the user. Frame everything in terms of learning about the organization and its tools. | ||
| **3. General customization** — The plugin is already configured (no `~~` placeholders or they've already been filled in) and the user wants to modify it. Read the plugin's files to understand its current configuration, then ask the user what they'd like to change. | ||
|
|
||
| The process: | ||
| 1. **Gather context** — use knowledge MCPs to learn what tools and processes the organization uses | ||
| 2. **Create todo list** — grep for `~~\w` to find all customization points and build a todo list | ||
| 3. **Complete todo items** — apply gathered context, falling back to user questions when unclear | ||
| 4. **Search for useful MCPs** — find and connect MCPs for identified tools | ||
| > **Important**: Never change the name of the plugin or skill being customized. Do not rename directories, files, or the plugin/skill name fields. | ||
|
|
||
| If an answer cannot be found via knowledge MCPs or user input, leave the customization point unchanged for a future customization cycle. | ||
| > **Nontechnical output**: All user-facing output (todo list items, questions, summaries) must be written in plain, nontechnical language. Never mention `~~` prefixes, placeholders, or customization points to the user. Frame everything in terms of the plugin's capabilities and the organization's tools. | ||
|
|
||
| ## Customization Workflow | ||
|
|
||
| ### Phase 0: Gather User Intent (scoped and general customization only) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It felt broken without this - I asked to customize a single thing and I got peppered with questions before I could say what I wanted to customize |
||
|
|
||
| For **scoped customization** and **general customization** (not generic plugin setup), check whether the user provided free-form context alongside their request (e.g., "customize the standup command — we do async standups in #eng-updates every morning"). | ||
|
|
||
| - **If the user provided context**: Record it and use it to pre-fill answers in Phase 3 — skip asking questions that the user already answered here. | ||
| - **If the user did not provide context**: Ask a single open-ended question using AskUserQuestion before proceeding. Tailor the question to what they asked to customize — e.g., "What changes do you have in mind for the brief command?" or "What would you like to change about how this plugin works?" Keep it short and specific to their request. | ||
|
|
||
| Use their response (if any) as additional context throughout the remaining phases. | ||
|
|
||
| ### Phase 1: Gather Context from Knowledge MCPs | ||
|
|
||
| Use company-internal knowledge MCPs to collect information. See `references/search-strategies.md` for detailed query patterns by category. | ||
| Use company-internal knowledge MCPs to collect information relevant to the customization scope. See `references/search-strategies.md` for detailed query patterns by category. | ||
|
|
||
| **What to gather:** | ||
| - Tool names for each `~~`-prefixed placeholder | ||
| **What to gather** (scope to what's relevant): | ||
| - Tool names and services the organization uses | ||
| - Organizational processes and workflows | ||
| - Team conventions (naming, statuses, estimation scales) | ||
| - Configuration values (workspace IDs, project names, team identifiers) | ||
|
|
@@ -52,42 +56,47 @@ Use company-internal knowledge MCPs to collect information. See `references/sear | |
|
|
||
| Record all findings for use in Phase 3. | ||
|
|
||
| ### Phase 2: Create Todo List from Customization Points | ||
| ### Phase 2: Create Todo List | ||
|
|
||
| Build a todo list of changes to make, scoped appropriately: | ||
|
|
||
| Run `grep -rn '~~\w' /path/to/plugin --include='*.md' --include='*.json'` to find all customization points. Group them by theme and create a todo list with user-friendly descriptions that focus on learning about the organization: | ||
| - **For scoped customization**: Only include items related to the specific section the user asked about. | ||
| - **For generic plugin setup**: Run `grep -rn '~~\w' /path/to/plugin --include='*.md' --include='*.json'` to find all placeholder customization points. Group them by theme. | ||
| - **For general customization**: Read the plugin files, understand the current config, and based on the user's request, identify what needs to change. | ||
|
|
||
| Use user-friendly descriptions that focus on the plugin's purpose: | ||
|
|
||
| - **Good**: "Learn how standup prep works at Company" | ||
| - **Bad**: "Replace placeholders in commands/standup-prep.md" | ||
|
|
||
| ### Phase 3: Complete Todo Items | ||
|
|
||
| Work through each item using Phase 1 context. | ||
| Work through each item using context from Phase 0 and Phase 1. | ||
|
|
||
| **If knowledge MCPs provided a clear answer**: Apply directly without confirmation. | ||
| **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 knowledge MCPs didn't provide a specific answer, ask. Note: AskUserQuestion always includes a Skip button and a free-text input box for custom answers, so do not include `None` or `Other` as options. | ||
| **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. Note: AskUserQuestion always includes a Skip button and a free-text input box for custom answers, so do not include `None` or `Other` as options. | ||
|
|
||
| **Types of changes:** | ||
|
|
||
| 1. **Customization point replacements**: `~~Jira` → `Asana`, `~~your-org-channel` → `#engineering` | ||
| 2. **URL pattern updates**: `tickets.example.com/your-team/123` → `app.asana.com/0/PROJECT_ID/TASK_ID` | ||
| 3. **Organization-specific values**: Workspace IDs, project names, team identifiers | ||
| 1. **Placeholder replacements** (generic setup): `~~Jira` → `Asana`, `~~your-org-channel` → `#engineering` | ||
| 2. **Content updates**: Modifying instructions, commands, workflows, or references to match the organization | ||
| 3. **URL pattern updates**: `tickets.example.com/your-team/123` → `app.asana.com/0/PROJECT_ID/TASK_ID` | ||
| 4. **Configuration values**: Workspace IDs, project names, team identifiers | ||
|
|
||
| If user doesn't know or skips, leave the `~~`-prefixed value unchanged. | ||
| If user doesn't know or skips, leave the value unchanged (or the `~~`-prefixed placeholder, for generic setup). | ||
|
|
||
| ### Phase 4: Search for Useful MCPs | ||
|
|
||
| After all customization points have been resolved, connect MCPs for the tools that were identified. See `references/mcp-servers.md` for the full workflow, category-to-keywords mapping, and config file format. | ||
| After customization items have been 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: | ||
| 1. Search the registry: `search_mcp_registry(keywords=[...])` using category keywords from `references/mcp-servers.md`, or search for the specific tool name if already known | ||
| 2. If unconnected: `suggest_connectors(directoryUuids=["chosen-uuid"])` — user completes OAuth | ||
| 2. If unconnected: `suggest_connectors(directoryUuids=["chosen-uuid"])` — user completes auth | ||
| 3. Update the plugin's MCP config file (check `plugin.json` for custom location, otherwise `.mcp.json` at root) | ||
|
|
||
| Collect all MCP results and present them together in the summary output (see below) — don't present MCPs one at a time during this phase. | ||
|
|
||
| **Note:** First-party integrations (Gmail, Google Calendar, Google Drive) are connected at the user level and don't need plugin `.mcp.json` entries. | ||
|
|
||
| ## Packaging the Plugin | ||
|
|
||
| After all customizations are applied, package the plugin as a `.plugin` file for the user: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -86,4 +86,6 @@ Both wrapped and unwrapped formats are supported: | |
|
|
||
| Use the `url` field from `search_mcp_registry` results. | ||
|
|
||
| **Note:** First-party integrations (Gmail, Google Calendar, Google Drive) are connected at the user level and don't need plugin `.mcp.json` entries. | ||
| ### Directory Entries Without a URL | ||
|
|
||
| Some directory entries have no `url` because the endpoint is dynamic — the admin provides it when connecting the server. These servers can still be referenced in the plugin's MCP config by **name**: if the MCP server name in the config matches the directory entry name, it is treated the same as a URL match. | ||
|
Comment on lines
+89
to
+91
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is useful functionality. The thing I deleted is not accurate - they can still be added like all other mcps |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -294,7 +294,7 @@ Decisions: `approve`, `block`, `ask_user` (ask for confirmation). | |
| } | ||
| ``` | ||
|
|
||
| **SSE** (hosted with OAuth): | ||
| **SSE** (remote server, server-sent events transport): | ||
| ```json | ||
| { | ||
| "mcpServers": { | ||
|
|
@@ -306,7 +306,7 @@ Decisions: `approve`, `block`, `ask_user` (ask for confirmation). | |
| } | ||
| ``` | ||
|
|
||
| **HTTP** (REST API): | ||
| **HTTP** (remote server, streamable HTTP transport): | ||
| ```json | ||
| { | ||
| "mcpServers": { | ||
|
|
@@ -323,11 +323,11 @@ Decisions: `approve`, `block`, `ask_user` (ask for confirmation). | |
|
|
||
| ### Server Type Selection Guide | ||
|
|
||
| | Type | Best for | Auth method | | ||
| |------|----------|-------------| | ||
| | stdio | Local tools, custom servers | Environment variables | | ||
| | SSE | Hosted cloud services | OAuth (automatic) | | ||
| | HTTP | REST API backends | Token headers | | ||
| | Type | Best for | Transport | | ||
| |------|----------|-----------| | ||
| | stdio | Local tools, custom servers | Subprocess (stdin/stdout) | | ||
| | SSE | Remote servers using server-sent events | HTTP + SSE streaming | | ||
| | HTTP | Remote servers using streamable HTTP | HTTP request/response | | ||
|
Comment on lines
+326
to
+330
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thoughts on just removing this section? it isn't helpful |
||
|
|
||
| ### Environment Variable Expansion | ||
|
|
||
|
|
@@ -337,6 +337,10 @@ All MCP configs support `${VAR_NAME}` substitution: | |
|
|
||
| Document all required environment variables in the plugin README. | ||
|
|
||
| ### Directory Servers Without a URL | ||
|
|
||
| Some MCP directory entries have no `url` because the endpoint is dynamic. Plugins can reference these servers by **name** instead — if the server name in the plugin's MCP config matches the directory entry name, it is treated the same as a URL match. | ||
|
|
||
| ## CONNECTORS.md | ||
|
|
||
| **Location**: Plugin root | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Claude recommended deleting this - it's all stated later and this only applies for the generic plugin setup