Module 7 · Lesson 7.4

Building and packaging a custom plugin.

A plugin exists to bundle capabilities that need to travel together. Three conditions gate the decision — if none applies, stay with loose skills. The manifest is the audit surface a future installer reads to decide whether to trust the bundle; the security questionnaire is the disclosure you owe them. In this lesson you wrap your Lesson 7.3 skill into a Cowork plugin, answer all seven questionnaire items, and run the clean-uninstall test that is the gate for freezing the bundle into your capstone.

Stage 1 of 3

Read & Understand

4 concept blocks

Why bundle at all: three conditions CORE

A plugin exists for one reason: a group of capabilities needs to travel together. Installation adds them as a set, uninstallation removes them as a set, updates version them as a set. If your capabilities do not need to travel as a group, you do not need a plugin — a loose skill in .claude/skills/ is enough.

Three conditions suggest the plugin wrapper is worth it. A plugin is the right shape when any one of the three applies — if none applies, the loose-skill approach is better:

Condition 1 — The capabilities share scope. All three skills read the same folder, or all four skills need the same MCP connector, or the skills share a config file you do not want to duplicate. Bundling gives them a shared home and a shared uninstall. A classic example: a project-management plugin that includes a weekly-status skill, a backlog-triage skill, and a sprint-retro skill — three distinct jobs, one shared set of assumptions about how your projects are organized.

Condition 2 — The capabilities share an installation/uninstallation story. A plugin that includes an MCP connector is doing a nontrivial install — wiring the connector, registering credentials, potentially setting defaults. A plugin is the right shape when you want that install to happen once and the uninstall to reverse it cleanly. A loose skill alongside a loose MCP connector does not have a clean uninstall story; a plugin does.

Condition 3 — You intend to share the bundle with someone else. Shareable here means installable by someone other than you, without you present to explain. That person reads your README, your manifest, your SECURITY.md, and knows what they are installing. Loose skills are awkward to share because the recipient has to assemble the pieces themselves; a plugin compresses the sharing to a single install step. (Module 7 does not require you to share publicly — audience-only-you holds — but a plugin you share privately with a family member or a homeschool co-op member is squarely in scope if the bundle delivers only to them in the same way your bundle delivers only to you.)

If none of the three applies, resist the plugin. A single, well-authored loose skill is almost always the right answer for a single, well-scoped job. Module 7 asks you to build a plugin anyway — Lesson 7.4 is the authoring drill — but be honest in the register that the plugin is a pedagogical build. For your second and third plugin in real life, the three conditions will be the gate.

Anatomy of the manifest: the audit surface CORE

The plugin’s manifest is the file at the root of the plugin folder that names the plugin and enumerates what it contains. Different plugin systems use different filenames and formats; the Cowork plugin convention is covered in the Recipe Book. The manifest’s purpose is the same everywhere: it is the top-of-page summary a future installer reads to decide whether to trust this plugin. It is also what an installed-plugin audit reads in month six.

Seven fields any manifest should carry, regardless of the specific plugin framework:

  • Name. Short, unambiguous, kebab-cased. Not cute — a student who names their plugin super-duper-helper will not remember what it did in month four.
  • Version. Semver (major.minor.patch). Increment the patch version for internal tuning, the minor for new capabilities, the major for breaking changes.
  • Description. Two to three sentences. Same discipline as a skill description — specific about what the bundle does, inclusive of the phrases that should invoke its skills, exclusive about what it is not for.
  • Author / contact. A handle, an email, a URL — whatever future-you or future-installer can use to ask a question. Anonymous is not a valid value for something you plan to share.
  • Bundled skills. A list of the skills inside, with one-line descriptions. This is the inventory — the list a re-audit reads to check “did this plugin grow since I installed it?”
  • MCP connectors wired. A list of the connectors the plugin uses, plus which verbs it grants the agent through each. If the plugin uses no MCP connectors, say so explicitly; none is a valid and useful manifest entry.
  • Permission surface. The union of what the bundled skills can read, what they can write, what they can send, and what credentials the plugin inherits. In a well-authored plugin, the permission surface is tight; in a badly-authored one, the surface is sprawling and the install is a blind trust.

Two features of a manifest are easy to underdo and matter:

  • Honesty beats brevity. A manifest that enumerates three read surfaces and two write surfaces is better than a manifest that says “reads files as needed.” The extra specificity is what makes the re-audit possible.
  • The manifest is the contract. If a future version of the plugin adds a send capability not listed in v1.0’s manifest, the changelog should call it out and a re-audit is required before the install goes live. A manifest that does not change while the plugin’s behavior does is worse than no manifest.

Manifest, description, and changelog are the trio

In Lesson 7.2 you learned to read manifest, description, and changelog on third-party extensions. In 7.4 you are writing them. The discipline is the same. When you are uncertain whether something belongs in the manifest, ask: “would a careful future installer want this information before they approve?” If yes, include it.

The security questionnaire CORE

Every plugin the student authors must answer the security questionnaire before the plugin ships. The questionnaire is a superset of the Lesson 7.2 audit — the five audit questions plus two plugin-specific additions. Answers live in a SECURITY.md file at the plugin root.

Figure 7.4 — The security questionnaire as a narrowing funnel
Security questionnaire funnel A vertical funnel. The top rectangle is the wide plugin candidate. Seven horizontal bands, S1 through S7, narrow the funnel as each question is answered. S1 through S5 are labeled AUDIT BASELINE; S6 and S7 are labeled PLUGIN ADDENDA in ember. The bottom rectangle is a tight, ember-bordered install surface. Plugin candidate — a wide, under-examined permission surface Audit baseline — Lesson 7.2 Plugin addenda S1 What does this plugin do? — one tight sentence for the installer, not for you S2 What tools does it grant the agent? — every verb across every skill and every MCP, as a union S3 What data can it read? — folders, mailboxes, calendars, history, cached memories S4 What can it send, post, or write? — Module 7 rule: drafts and own files only; no outbound S5 How does it handle credentials? — where they live, which OAuth scopes, shared vs. isolated S6 What does installing this remove from user control? — the defaults installing it sets without a per-call prompt S7 What is the update posture? — auto-update? notify on permission delta? manual pull? Tight, documented, auditable install surface
Each question narrows the install surface. S1–S5 are the audit questions a careful third-party installer would ask of any extension (Lesson 7.2). S6 and S7 are the two plugin-specific additions — what installing the bundle removes from per-call user control, and how updates reach the installer. Answers live in SECURITY.md at the plugin root.

S1 — What does this plugin do? Same as audit Q1, but written for the installer, not for you.

S2 — What tools does this plugin grant the agent? List every verb, across every skill and every MCP. If the plugin grants read-file, write-file, read-calendar, and list-drafts, write all four. Do not assume the installer will read the bundled skills individually; write the union here.

S3 — What data can this plugin read? Enumerate sources in plain language. Folders, mailboxes, calendars, conversation history, cached memories. If any data source is “anything the user types in chat,” say so — that is a wide surface and the installer should know.

S4 — What can this plugin send, post, or write? This is the Module 6 audience question. For a plugin you authored under the Module 7 rule, the answer must be: drafts and writes to the user’s own files, nothing else. If the honest answer is anything else — any verb that puts text in front of a second human without a click — stop. Either remove the capability, narrow it to drafts-only, or move the plugin outside the Module 7 authoring rule (which means not freezing it as your Module 7 capstone).

S5 — How does this plugin handle credentials? Where credentials live. Which OAuth scopes they request. Whether they are shared across the bundled skills or isolated per skill. If the plugin wires an MCP connector that requires authentication, name the scopes the plugin is asking the installer to grant.

S6 — What does installing this plugin remove from the user’s control? This is the plugin-specific question. Installing any bundle gives the agent new defaults that would otherwise require the user’s per-call decision. A plugin that auto-drafts every morning is taking the “do I run this today” question out of the user’s hands. That is the plugin earning its keep — but it is also a loss of control. Name it. “Installing this plugin means the user will receive a daily draft file at 6:30 AM without a per-day prompt; the user controls this by turning the scheduled task off or uninstalling the plugin.”

S7 — What is the update posture? Does this plugin auto-update? If so, does the installer get notified of permission changes between versions? If not, how is the installer expected to pull updates? A plugin that auto-updates and auto-expands permissions is the worst shape; it must at least notify on permission delta. A plugin that does not auto-update requires a manual update story the installer should know about.

The questionnaire is short. A student can answer all seven in one sitting. A plugin whose questionnaire is too short is either trivial (fine) or under-specified (not fine); a plugin whose questionnaire cannot be finished is a plugin not ready to ship.

Least-privilege, applied CORE

The questionnaire is not only a disclosure tool; it is a design tool. Each “yes” answer to S2, S3, S4 is a capability you are choosing to include in the bundle. A well-authored plugin minimizes the set.

Three moves that narrow a plugin’s permission surface without losing its usefulness:

Move 1 — Prefer reading to writing. Many plugins can do their job by reading the user’s world and producing a draft. They do not need write access to the source. A weekly-status plugin can read the user’s commit log and produce weekly-status.md; it does not need write access to the commit log itself. Default to read; add write only where the capability fails without it.

Move 2 — Scope reads narrowly. If the plugin only needs to read the user’s agent-access label, do not ask for full-mailbox read. If the plugin only needs the active-research/ folder, do not ask for read access to the entire home directory. The narrowest scope that works is the right scope. Many plugin frameworks let you name scopes in the manifest; use them.

Move 3 — Do not wire MCP connectors you are not using. A plugin that wires three MCP connectors “for future capabilities” is a plugin that grants three trust surfaces the user does not benefit from. Wire the MCPs the plugin’s skills actively use, and no more. When a future capability needs a new MCP, add it in a minor-version bump with a changelog entry — that is the honest posture.

Least-privilege is not a purity test. There are reasonable cases where a plugin needs a wider surface to do its job well — a plugin that genuinely needs whole-mailbox read to do inbox triage is not doing anything wrong by asking. The discipline is naming the surface honestly, narrowing it where narrowing does not cost the capability, and treating every widening as a minor-version decision.

Module 9 pointer

Module 7 teaches install-time and author-time hygiene: what to grant, how to narrow, what to disclose. Module 9 extends this into the runtime security posture — prompt injection through skill descriptions, the trust model between installed extensions, supply-chain attacks in plugin updates, and secrets hygiene across an agentic system. If your plugin handles anything sensitive — or you intend to share it beyond yourself — read ahead into Module 9 before shipping. The hand-off is explicit: Module 7 ends with install-time rigor; Module 9 picks up runtime rigor.

Stage 2 of 3

Try & Build

2 recipes + activity

Walkthrough: wrapping your Lesson 7.3 skill in a Cowork plugin RECIPE

Recipe Book entry — verified 2026-04-18 / next review 2026-07-18

Full walkthrough with exact paths, commands, and the current Cowork plugin manifest schema lives in /recipe-book/author-a-cowork-plugin.md. Summary below. If a step here does not match what you see in Cowork, the Recipe Book is canonical — this summary is indexed for teaching, not for bit-perfect reproduction.

The goal is to take the custom skill you built in Lesson 7.3 — likely research-sweep or a student-chosen equivalent — and wrap it in a Cowork plugin. This is the cleanest first plugin because the skill’s contract is already stable from 7.3’s tuning rounds.

Step 1 — Scaffold the plugin folder. Use the create-cowork-plugin skill (a built-in Cowork skill from the cowork-plugin-management family) to scaffold a new plugin directory. The scaffold creates the manifest file, a skills/ subfolder, and a README.md stub. If you are not using the scaffold, create the directory structure manually:

custom-plugin-v1/
├── manifest.(json|yaml)     (the plugin manifest; format per current Cowork schema)
├── skills/
│   └── research-sweep/
│       ├── SKILL.md
│       ├── CHANGELOG.md
│       └── (any appendices/scripts from 7.3)
├── README.md
├── SECURITY.md
├── CHANGELOG.md             (plugin-level, distinct from skill-level)
└── traces/

Step 2 — Populate the manifest. Fill in the seven fields from Content Block 2. For this walkthrough, the plugin’s scope is narrow — one bundled skill, no MCP connector (yet), no slash commands. The manifest looks roughly like:

name: directed-research-kit
version: 1.0.0
description: A small, personal research-helper plugin. Bundles the research-sweep skill
  for triangulating sources on a named topic and producing a sources.md. Drafts only;
  writes to the user's own folders; no outbound capabilities.
author: <your-name>, <your-email-or-handle>
skills:
  - research-sweep: "Runs a multi-source research sweep and produces sources.md."
mcp_connectors: none
permission_surface:
  read: user-named project folders; web (via skill-internal search)
  write: sources.md and traces/ under the user's configured research folder
  send: none

Step 3 — Copy the skill into the plugin’s skills/ folder. The skill you froze under /capstone/custom-skill-v1/ is the same skill that goes into custom-plugin-v1/skills/research-sweep/. Keep the skill’s frontmatter, body, changelog, and appendices intact. (If your Lesson 7.3 skill was user-scope on the machine, you are now also bundling a copy of it inside the plugin; the plugin becomes the canonical home going forward.)

Step 4 — Write SECURITY.md. Answer the seven questionnaire items from Content Block 3, in order. Keep answers short — two or three sentences each, maximum. A future installer or re-auditor should be able to read SECURITY.md in under five minutes and know everything important about the plugin’s permission surface.

Step 5 — Write README.md. Three short sections: (a) what the plugin is and who it is for, in three sentences; (b) how to install — a checklist a stranger could follow without asking questions; (c) how to uninstall. The README is what the installer will read first. It is also what future-you will read when you re-audit.

Step 6 — Install the plugin locally and smoke-test. From the Cowork tab, install the plugin by pointing it at the local folder (see the Recipe Book for the current install syntax). The install should complete without prompting for permissions that are not listed in the manifest. If the Cowork tab prompts for permissions the manifest did not mention, stop and revise the manifest — the manifest is the contract. After install, open a Cowork-tab session and trigger the bundled skill with a phrase from its description. Verify the skill fires and produces sources.md. Save the session trace under traces/.

Step 7 — Run a real-use invocation and save the trace. One real request from your actual work. Not a tuning test. Save the trace.

Step 8 — Uninstall, then reinstall, to verify the uninstall story. Important step students skip. If the plugin advertises a clean uninstall, the uninstall must actually be clean — no orphan files, no dangling credentials, no lingering skills in the Cowork-tab's registry. If the uninstall leaves debris, fix the plugin and re-ship. A plugin with a broken uninstall is a plugin you cannot retire, and Module 7 requires retirable extensions.

Freezing the plugin and filling the register row RECIPE

Once the plugin has a clean install, a clean uninstall, a passing smoke test, two real-use traces, and a completed SECURITY.md, freeze it.

Folder layout under /capstone/custom-plugin-v1/:

custom-plugin-v1/
├── manifest.(json|yaml)
├── skills/
│   └── research-sweep/
│       ├── SKILL.md
│       ├── CHANGELOG.md
│       └── (appendices, scripts)
├── README.md
├── SECURITY.md
├── CHANGELOG.md
└── traces/
    ├── 2026-04-XX-real-run-1.md
    └── 2026-04-XX-real-run-2.md

Register row. Fill in the custom plugin row using the row template. The fields that deserve attention:

  • Type: Cowork plugin, authored.
  • What it does: a tight sentence — same shape as the manifest description.
  • Where it lives: the local folder and the frozen path.
  • Invocation: the phrases that trigger the bundled skill(s).
  • Audience: only me.
  • Budget / model: rough per-invocation cost + the model family.
  • Next review: a date sooner than the standard 90-day cadence, same as the custom skill.
  • Keep/retire: the condition that would make you retire (“retire if I stop doing project-based research or if the research-sweep skill is absorbed into a better off-the-shelf option”).

Plus a separate security field that points at the plugin’s SECURITY.md — the register surfaces the existence of the questionnaire, not the full answers.

Try it — Author, install, invoke, and uninstall-test your custom plugin RECIPE

Deliverables: a plugin live on your machine, the same plugin frozen under /capstone/custom-plugin-v1/, two real-use traces, a completed SECURITY.md, a clean-uninstall confirmation, and the register row.

Step 1 — Plan the plugin on paper.

Open /resources/module-07/plugin-planner.md and fill it in. The planner walks you through: name, version, manifest draft, bundled skill list (your 7.3 skill), MCP connector decision (almost always none for a first plugin), permission surface, and the seven security questions. Fill the planner before you touch any code; the planning is where the least-privilege thinking lives.

Step 2 — Scaffold and populate.

Use the create-cowork-plugin skill to scaffold, or create the folder structure manually. Copy your Lesson 7.3 skill into the plugin’s skills/ folder. Write the manifest. Write README.md. Write SECURITY.md from the planner you filled in Step 1 (transcription, not re-thinking).

Step 3 — Install locally and smoke-test.

Install from the local path. Watch the install prompts; if any permission request is not listed in your manifest, stop and revise. Run the bundled skill through a trigger phrase from its description. Verify sources.md appears as expected. Save the smoke-test trace under traces/.

Step 4 — One real-use invocation.

Use the plugin once in actual work. Save the trace.

Step 5 — Uninstall and reinstall, confirm clean.

Uninstall the plugin. Verify: no orphan files, no lingering skill entries, no leftover credentials. Reinstall. Run the skill again to confirm the cycle completed cleanly. Note any debris in CHANGELOG.md as a known issue.

Step 6 — Freeze the plugin and fill the register row.

Copy the live plugin folder to /capstone/custom-plugin-v1/. Fill the plugin row in the register. Cross-reference SECURITY.md from the row’s security field. Set a next-review date sooner than the standard 90-day cadence.

Step 7 — Update my-first-loop.md.

Add a short paragraph to the Extension Posture section: what you now know about plugin-vs-loose-skill that you did not know before authoring. This is reflective; the paragraph is for future-you to read when deciding whether to author your second plugin.

If the three conditions honestly do not apply

Many students reach Step 1 and notice, correctly, that for their single skill the three bundling conditions do not actually apply. That is fine — Lesson 7.4 is a pedagogical build. Write in the register’s keep/retire column: “pedagogical build; in real life would be loose skill.” This honesty is more valuable than pretending the plugin earns its bundling. For your second plugin, outside the course, the three conditions are the gate.

Done with the hands-on?

When the recipe steps and any activity above are complete, mark this stage to unlock the assessment, reflection, and project checkpoint.

Stage 3 of 3

Check & Reflect

key concepts, quick check, quiz, reflection, checkpoint, instructor note

Quick check

  1. Your custom skill research-sweep is working well on its own. You are considering wrapping it in a plugin. Which of the three bundling conditions apply, and do any of them apply to the point that a plugin is worth the overhead?
  2. In your own words, what does question S6 of the security questionnaire add over the five audit questions from Lesson 7.2?
  3. Why is it important to run the uninstall before freezing the plugin?
Check your thinking

(1) Typically none of the three apply for a single-skill research helper — which is why Module 7 is asking you to build the plugin as a pedagogical drill, not because the three-condition gate has been cleared. Honest register note: “pedagogical build; would be loose skill in real life.”

(2) S6 makes you name what defaults installing the plugin is setting for the user — the things installing this plugin takes out of the user’s per-call decision. This surfaces the convenience-vs-control tradeoff explicitly.

(3) An uninstall that leaves debris is an uninstall you cannot actually perform; the plugin becomes un-retireable. Testing uninstall is the same discipline as testing the trigger — don’t ship a behavior you haven’t verified.

Quiz

Five questions. Each <details> reveals the answer and the reasoning — click to check your thinking.

Q1. Which of the following is not one of the three conditions that make a plugin the right shape over loose skills?
  • (A) The capabilities share scope.
  • (B) The capabilities share an install/uninstall story.
  • (C) You intend to share the bundle with someone else.
  • (D) You want the capabilities to auto-update together.
Show explanation

Answer: D. Auto-update is a plugin property but not a reason to bundle in the first place. The three conditions are scope-sharing, install-sharing, and share-with-others. (D) is a consequence of bundling, not a justification for it.

Q2. A plugin’s manifest lists three bundled skills, two MCP connectors, and a permission surface of read: all mail; write: drafts folder; send: none. Six months later, a new version of the plugin lands and you notice a changelog entry: “now auto-sends drafts to invitees after a 24-hour review window.” The right next move is:
  • (A) Install the update; the review window is a reasonable safeguard.
  • (B) Reject the update, pin to the previous version, and either retire the plugin or re-audit the new version against your posture. Do not install the update silently.
  • (C) Install the update but configure the 24-hour window to be 72 hours.
  • (D) Install and turn off the new sending capability after the fact.
Show explanation

Answer: B. A permission-surface expansion between versions is the exact thing the manifest-as-contract discipline is designed to catch. (A), (C), and (D) all accept a widened surface because the update looked innocuous in the changelog. The posture is: a widening requires a fresh audit, not an implicit approval.

Q3. You are authoring a plugin whose bundled skill only needs to read the student’s agent-access mail label to do its job. The plugin framework lets you request either mail:read or mail:read+draft. What should you request?
  • (A) mail:read+draft — more flexibility is better.
  • (B) mail:read — the skill does not draft, so granting draft capability violates least-privilege.
  • (C) Whichever the framework defaults to.
  • (D) Both, in separate skills, for clarity.
Show explanation

Answer: B. Request the narrowest scope that does the job. (A) and (D) expand the permission surface unnecessarily. (C) is a non-answer — defaults are frequently wrong. Least-privilege is not an optional best practice; it is the discipline that keeps the plugin safe to install.

Q4. The security questionnaire adds question S6 to the five audit questions from Lesson 7.2. What does S6 ask?
  • (A) What this plugin costs per invocation.
  • (B) What installing this plugin removes from the user’s control — what defaults it sets that the user no longer decides per-call.
  • (C) Whether the plugin has been independently reviewed.
  • (D) How fast the plugin is.
Show explanation

Answer: B. S6 is specific to the plugin-as-bundle surface: installing a plugin is choosing a set of defaults on the user’s behalf. The question makes the tradeoff explicit.

Q5. You complete your plugin build. Install works, the skill fires, the real-use traces look clean. You are about to freeze. What is the one test you must still run before freezing?
  • (A) Run the skill on a new topic.
  • (B) Uninstall the plugin and verify it leaves no debris.
  • (C) Increment the version number.
  • (D) Check the spelling in the manifest.
Show explanation

Answer: B. The uninstall test is the gate for freezing. A plugin that does not uninstall cleanly cannot be retired, and an extension that cannot be retired violates the module’s hygiene posture. (A) is already done in the real-use traces. (C) is not a test. (D) is hygiene but not a blocker.

Reflection

Write a short paragraph (4–6 sentences):

What changed in how you think about “installing a plugin” once you tried authoring one? Where did authoring surface considerations — permission surface, update posture, uninstall hygiene — that you had not weighed when you were only an installer? If a classmate asked you “should I author a plugin or stay with loose skills?”, what is the one-sentence answer you would give them?

Project checkpoint

By the end of this lesson, you should have:

1. Your custom plugin live on your machine, installed cleanly, uninstalled-and-reinstalled to verify the cycle.

2. /capstone/custom-plugin-v1/ containing manifest, bundled skill folder, README.md, SECURITY.md, CHANGELOG.md, and traces/ with two real-use invocation traces.

3. The custom-plugin row filled in /capstone/extension-register-v1-draft.md, cross-referencing the SECURITY.md.

4. A short update paragraph in my-first-loop.md on what authoring a plugin taught you about installing one.

Do not proceed to Lesson 7.5 until the plugin passes the clean-uninstall test. Lesson 7.5 runs the hygiene ritual across every register row; it assumes each extension is retirable, and a plugin that will not uninstall cleanly is not.

Next in Module 7

Lesson 7.5 — The hygiene ritual: keep, refactor, replace, retire.

With the authored skill frozen in Lesson 7.3 and the authored plugin frozen here, the register is complete. In 7.5 you run the five-step ritual across every row, make the keep/refactor/replace/retire call, handle the three kinds of drift, and freeze extension-register-v1.md as the seventh capstone artifact. This is where Module 7 comes together.

Continue to Lesson 7.5 →