Build a Plugin
Build a Plugin
Section titled “Build a Plugin”A plugin is a Microsoft 365 app package that composes a declarative agent, one or more skills, and/or one or more remote MCP connectors into a single, independently shippable unit. This guide gets you from nothing to a validated, provisioned, and shared plugin — the same outcome the Microsoft Learn “Build plugins for Copilot Cowork” walkthrough targets, reached the wiqd way. If you haven’t yet, read What is a plugin? first for the mental model.
Prerequisites
Section titled “Prerequisites”-
Install wiqd (the CLI, the VS Code extension, and the GitHub Copilot CLI plugin, all in one step):
Windows (PowerShell):
Terminal window iex "& { $(irm 'https://aka.ms/wiqd/install.ps1') }"macOS/Linux:
Terminal window curl -fsSL https://aka.ms/wiqd/install.sh | bashSee Installation for flags, troubleshooting, and manual steps.
-
Confirm the Copilot CLI plugin is installed (the installer does this by default; run it explicitly if you skipped that step or want to reinstall):
Terminal window wiqd component plugin install -
Sign in — provisioning and sharing a plugin touch your Microsoft 365 tenant:
Terminal window wiqd auth login --interactiveSee Authentication for how sign-in works across providers.
-
Verify your environment:
Terminal window wiqd doctor
With that done, you have two paths to the same result. Start with Path 1 — it’s the fastest way to build a plugin and it teaches you the lifecycle as you go. Reach for Path 2 when you need scripting, CI, or exact reproducibility.
Path 1 — Build it conversationally
Section titled “Path 1 — Build it conversationally”How it works
Section titled “How it works”Once the wiqd plugin is installed, GitHub Copilot CLI carries a plugin-authoring orchestrator: you
describe what you want in natural language, and it drives the wiqd CLI on your behalf —
including the full wiqd plugin ... surface — while orienting you on the underlying
Build → Improve → Preview → Publish agent lifecycle. You never have to remember a flag; you just
say what you want next.
What to say
Section titled “What to say”Saying any of these in GitHub Copilot CLI routes the conversation into the plugin-authoring workflow:
create a standalone plugin · build a plugin with a skill · build a plugin with a connector · add a skill to my plugin · add a connector to my plugin · add an agent to my plugin · validate my plugin · package my plugin · share my plugin · show my plugin · list my plugins · import an open plugin · import a claude plugin · export my plugin for claude · export my plugin for cursor · delete my plugin
A conversational walkthrough
Section titled “A conversational walkthrough”You say: “Create a standalone plugin called Triage Helper.”
wiqd does: runs wiqd plugin create --name "Triage Helper", cds into the new project, and
reports back — then suggests the logical next moves: add a skill, add an MCP connector, or add a
declarative agent.
You say: “Add a skill for triaging incoming issues.”
wiqd does: runs wiqd plugin add skill --name "Triage Issues", scaffolding
appPackage/skills/triage-issues/SKILL.md and registering it in the manifest. It then suggests
adding another capability, or validating what you have so far.
You say: “Validate my plugin.”
wiqd does: runs wiqd plugin validate (the offline static check). On a clean result, it
suggests provisioning the plugin, reusing it inside an existing agent, or exporting it for another
tool.
You say: “Provision it, then package and share it with my team.”
wiqd does: runs wiqd plugin provision, then wiqd plugin package now that the environment
file it needs exists, then wiqd plugin share --scope users --email <you supply>. Each step’s
report tells you what ran and what’s next, so a multi-step request like this one still gives you a
checkpoint after every command.
This mirrors the same create → add → validate → provision → package → share lifecycle you’d run
by hand — the orchestrator just chooses and sequences the commands for you, one reported step at a
time.
Path 2 — Use the CLI directly
Section titled “Path 2 — Use the CLI directly”Reach for the CLI directly instead of the conversational path when you’re scripting a CI/CD pipeline, need fully deterministic and reproducible non-interactive automation, or you simply prefer typing commands yourself. Every command below is the same one the conversational path runs under the hood — nothing here is a different surface, just a different way to drive it.
# 1. Scaffold the plugin containerwiqd plugin create --name my-plugincd my-plugin
# 2. Compose whatever capabilities you need, in any combinationwiqd plugin add agentwiqd plugin add skill --name "Triage Issues"wiqd plugin add connector --name "Contoso Tools" \ --description "Contoso toolbelt over MCP" --url https://tools.contoso.com/mcp
# 3. Validate offline before you provision or packagewiqd plugin validate
# 4. Provision first — it writes the env file package/share both depend onwiqd plugin provision
# 5. Build the deployable .zipwiqd plugin package
# 6. Run the full package-first deep validation against AVLwiqd plugin validate --mode deep
# 7. Share itwiqd plugin share --scope users --email you@contoso.com# …or share with your whole tenant:wiqd plugin share --scope tenant
# Inspect at any pointwiqd plugin showwiqd plugin list --root .
# Tear down what provision created (--yes skips the confirmation prompt for non-interactive use)wiqd plugin delete --env local --yesFor every flag on every one of these commands, see
wiqd plugin in the CLI reference rather than duplicating the
full flag set here.
Import / export (interop)
Section titled “Import / export (interop)”Already have a plugin authored for another host, or want to hand yours to one? Two commands bracket the lifecycle instead of requiring a hand-rolled conversion script:
# Bring a foreign-format plugin into wiqd instead of starting from `create`wiqd plugin import --path ./my-open-plugin \ --privacy-url https://contoso.com/privacy \ --terms-url https://contoso.com/terms
# Hand a wiqd plugin project to another hostwiqd plugin export --format claude-pluginwiqd plugin import recognizes an Open Plugin, Claude plugin, or Cursor plugin source and produces
a new wiqd plugin project from it. --privacy-url/--terms-url are only required on a plugin’s
first import — if the source was produced by a prior wiqd plugin export, the round-trip
metadata already carries them. wiqd plugin export does the inverse, defaulting to
--format open-plugin (also accepts claude-plugin and cursor-plugin), writing an uncompressed
directory under <path>/export/<format>. The output layout uses the core backend:
writes the selected format layout; FxCore always writes plugin.json at the export root and uses
--format only for the default output directory and reported format.
The imported project is ready for the full lifecycle. The TeamsFx importer creates its deployment
environment (currently dev), and wiqd binds the package manifest to that environment’s
TEAMS_APP_ID. For a default import with no app ID, continue with wiqd plugin validate, then run
wiqd plugin provision --env dev before wiqd plugin package --env dev,
wiqd plugin share --env dev, or package-first deep validation. Packaging through either backend
fails closed while the selected environment file is missing or its TEAMS_APP_ID is empty,
unresolved, or malformed, instead of allowing a random package-only ID.
Mock import follows the same finalized project contract: the package manifest keeps the
${{TEAMS_APP_ID}} binding, the generated dev environment is present, and an explicit
--app-id is written to that environment before provision/package checks run.
If you pass --app-id, or a supported source extension carries a real GUID, import writes that ID
into .env.dev; the project is already identity-bound for packaging. A wiqd export does not invent
or preserve an unresolved ${{TEAMS_APP_ID}} token as a round-trip ID, so only a real GUID from a
supported producer qualifies. Provision/update remains the normal tenant lifecycle step before
sharing a newly imported app.
Validation as a first-class step
Section titled “Validation as a first-class step”Rather than assembling a package and hoping upload-time validation passes, validate continuously as you build:
- Static (default) —
wiqd plugin validateruns the offline MVL (Manifest Validation Library) engine over the declarative-agent surface only:declarativeAgent.jsonplus any referenced API-plugin manifest or OpenAPI specs. It does not inspect the top-level Teams manifest or the content ofagentSkills[]/SKILL.mdfiles — so a skill-only or connector-only plugin passes static validation vacuously. This is expected, not a gap: it’s an inner-loop check, not full coverage. - Deep (
--mode deep) — package-first: afterwiqd plugin packagebuilds a.zip,wiqd plugin validate --mode deepvalidates that built package against AVL (App Validation Library) through the Teams Developer Portal, via deep validation. This is where manifest-schema rejections and skill-content issues actually surface. See the Plugin authoring reference for the full validation-code tables and how they map to static vs. deep.
Publishing paths
Section titled “Publishing paths”wiqd carries you through build → validate → provision → package → share. Where you go from there depends on your audience:
- Your tenant —
wiqd plugin share --scope tenantmakes the plugin available org-wide, or an admin can upload the packaged.zipdirectly via the Microsoft 365 admin center’s “Upload custom app” step. - The public store — certification and store submission happen in Partner Center, a human/admin process outside wiqd.
Where wiqd stops: wiqd’s job ends at share (or at handing you the packaged .zip). Admin
center uploads and Partner Center certification/submission are deliberate, human/admin actions —
there is no wiqd plugin publish command, because publishing to the public store isn’t something
wiqd automates today.
What’s Next?
Section titled “What’s Next?”- What is a plugin? — the mental model and the three meanings of “skill”
wiqd plugin— the full command reference- Plugin authoring reference — package anatomy,
SKILL.mdrules, connector requirements, validation codes, and the section-by-section Learn parity table - Quickstart — the equivalent 5-minute walkthrough for a plain
wiqd agentproject