SkillAgentSearch skills...

generate-ppmplugin-manifest

Validate, reconcile to the chosen target(s), and stage the `manifest.json` for a `.ppmplugin` bundle. In the normal flow the committed `./manifest.json` already exists (authored by /generate-native-extension), so this stage reads it, runs the plugin's upload-compatibility checks locally as a pre-fli…

Install / Use

npx skills add microsoft/power-platform-skills --skill generate-ppmplugin-manifest

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

85/100

Category

Marketing

Supported Platforms

Universal

Our assessment of generate-ppmplugin-manifest

generate-ppmplugin-manifest scores 85/100 on our quality scale, 407th of 596 Marketing skills we index.

Its SKILL.md is 19 KB long, well organised into 8 sections with 3 code examples: a thorough specification that gives an agent plenty to work with.

It has 919 GitHub stars, a meaningful sign that others use it.

Substance
30/30
Structure
18/20
Description
15/15
Adoption
13/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 12 days ago, so generate-ppmplugin-manifest is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

generate-ppmplugin-manifest compared with similar skills

All 4 of these similar skills score higher than generate-ppmplugin-manifest; compare them before choosing.

SkillScoreStarsUpdatedFormat
generate-ppmplugin-manifest (this skill)by microsoft8591912d agoSKILL.md
Agent-Reachby Panniantong10092.4k21d agoCLAUDE.md
algorithmic-artby anthropics100177.9k14d agoSKILL.md
pptxby anthropics100177.9k14d agoSKILL.md
designby nextlevelbuilder100130.2k15d agoSKILL.md

Frequently asked questions

How do I install generate-ppmplugin-manifest?
Run npx skills add microsoft/power-platform-skills --skill generate-ppmplugin-manifest. The install tabs above show the steps for each supported agent.
Which AI agents does generate-ppmplugin-manifest work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is generate-ppmplugin-manifest safe to use?
It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is generate-ppmplugin-manifest still maintained?
The repository was last updated 12 days ago, so generate-ppmplugin-manifest is actively maintained.

name: generate-ppmplugin-manifest description: "Validate, reconcile to the chosen target(s), and stage the manifest.json for a .ppmplugin bundle. In the normal flow the committed ./manifest.json already exists (authored by /generate-native-extension), so this stage reads it, runs the plugin's upload-compatibility checks locally as a pre-flight gate (name regex, canonical prefix, known incompatible names, method and identifier shapes), reconciles entrypoints down to the platform(s) you ship, and writes the gitignored staged copy ppmplugin/staging/manifest.json that /assemble-ppmplugin zips. If no committed manifest exists (a hand-authored module) it falls back to deriving every field from the class name and Android module source, writing both the committed file and the staged copy. No toolchain — pure read, validate, write. Target-aware. Run after the native module exists, before the build skills." allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill model: sonnet

/generate-ppmplugin-manifest

Stages the manifest.json that goes inside a .ppmplugin bundle — the small descriptor the wrap runtime and upload service read to identify the plugin and route calls into it. In the normal flow the committed ./manifest.json already exists (authored by /generate-native-extension next to the code it describes); this stage's job is to validate it, reconcile its entrypoints to the shipped target(s), and write the staged build copy ppmplugin/staging/manifest.json. It is the "get the strings right" gate: it runs instantly, needs no build tools, and catches common upload failures before any Android build. If the repo has no ./manifest.json (a hand-authored native module that skipped the scaffold), this stage authors it from source as a fallback — see Step 2.

Read shared/ppmplugin-format.md — it is the source of truth for the schema, the derivation table, and the validation rules this skill enforces.

Two manifests, one contract. ./manifest.json (repo root, committed) is the source-of-truth contract — it declares every platform the module supports. ppmplugin/staging/manifest.json (gitignored) is the build copy this stage produces — same contract, but entrypoints trimmed to the platform(s) actually being shipped. The build/assemble skills only ever read the staged copy; the committed root file is what the PCF and humans read.

What this skill does NOT do

  • Does not compile anything — no Gradle, no DEX. That's /build-android-binary.
  • Does not zip the bundle — that's /assemble-ppmplugin.
  • Does not verify a declared platform's binary actually exists — it stages the intended entrypoints; /assemble-ppmplugin reconciles them against the binaries actually staged and gates on any mismatch.
  • Does not rewrite the committed ./manifest.json on the normal path — it reads it. It only writes ./manifest.json in the fallback case (no committed manifest existed). It never touches src/, ios/, android/, PRD, or package.json beyond reading them.

Step 1 — Read shared docs + prereq block

  1. Read shared/shared-instructions.md, shared/naming-conventions.md, and shared/ppmplugin-format.md.
  2. This skill does no installs / auth / network. Print the zero-prereq block (per shared-instructions §9.2):
Prereq check — /generate-ppmplugin-manifest: skipped (skill does no installs / auth / network — failures surface at validation).
  1. Confirm the working directory is a third-party-control repo: a package.json (the dev-only, private, plain <kebab>-control name — NOT a published @powerapps/extension-* scope; this track ships a binary, not an npm package — see repo-layout.md) and an android/ and/or ios/ native module exist. If not, STOP with NEEDS_CONTEXT: not a third-party-control repo (no package.json / native module).
  2. Read .extension-state.md — if it carries a ## ppmplugin (third-party controls) block, note the last target choice and last manifest write (the re-run mode below uses them).

Step 1.5 — Locate the source manifest (which mode are we in?)

This stage has two modes, decided by whether the committed ./manifest.json exists:

  • Validate-and-stage mode (the normal flow). ./manifest.json exists at the repo root (authored by /generate-native-extension). This is the source of truth — do not re-author it. Read it, validate it (Step 3), reconcile its entrypoints to the chosen target (Step 2 → Target only), and write the staged copy (Step 4). Step 2's field-derivation is skipped — the contract is already authored; you're verifying and staging it, not regenerating it. (Optionally re-derive methods from the Android module source and, if they've drifted from ./manifest.json — e.g. a @ReactMethod was added by hand after scaffold — surface the diff and offer to update the committed file; never silently rewrite it.)

  • Author-from-source mode (fallback). No ./manifest.json exists — a hand-authored native module that skipped the scaffold. Derive every field mechanically from source (Step 2 in full), then write both the committed ./manifest.json and the staged copy (Step 4).

Re-run within a build session. If the staged copy ppmplugin/staging/manifest.json already exists from a prior run, don't blindly overwrite — diff the target/entrypoints against the committed source and ask via AskUserQuestion: Update (re-stage from the current ./manifest.json + target) / Keep as-is (report and stop). Default the target to the prior choice in .extension-state.md; don't re-ask an answered question.


Step 2 — Determine target(s); derive fields only in author-from-source mode

The structure preflight + target selection below run in both modes (you always need to know which platforms are viable and which to ship). The field-derivation sub-section (items 1–6 + the compute block) runs only in author-from-source mode (Step 1.5) — in the normal validate-and-stage mode the fields already live in ./manifest.json; read them from there and skip derivation, keeping only the target choice.

First, run a structure preflight. The ppmplugin path expects the canonical PAM-extension layout — the shape /generate-native-extension produces (see shared/repo-layout.md). A hand-rolled, foreign, or drifted repo may be missing pieces; flag exactly what, here and now, rather than failing later with a cryptic Gradle/Xcode error or a silently-wrong manifest. Print a visible ✓/✗ block:

  • Common: package.json (dev-only <kebab>-control name — there is no @powerapps/extension-* scope and no src/ TS layer in this track); class name resolvable from the native module (android/.../<Pascal>Module.kt / ios/RCT<Pascal>Module.m), ./manifest.json, or .extension-state.md.
  • Android (if android/ present): android/build.gradle; a Kotlin module class extending ReactContextBaseJavaModule with an override fun getName(); a ReactPackage class; ≥1 @ReactMethod.
  • iOS (if ios/ present): ios/RCT<Pascal>Module.h declaring <RCTBridgeModule>; .m with + (NSString *)moduleName (NOT RCT_EXPORT_MODULE) and ≥1 RCT_EXPORT_METHOD.

A platform whose structure is incomplete is not a valid target — exclude it and say which element is missing. If neither platform is structurally complete, STOP with NEEDS_CONTEXT: repo doesn't match the expected PAM-extension layout — missing <list> pointing at shared/repo-layout.md. (Working on a staged copy protects the source; it does NOT make a missing module appear — that's what this preflight is for.)

Then determine which platform(s) this bundle targets (only from the structurally-complete ones) — it controls which entrypoints get declared:

  • Confirm via AskUserQuestion: Android-only / iOS-only / Both — offer only the targets that passed the preflight. Default to what's present, or — on a re-run in Update mode — to the prior target recorded in .extension-state.md.
  • Note availability: /build-android-binary is stable; /build-ios-binary is v0 (Mac-only; known limitation: its React-Core weak-link config still needs validation against a live PAM/wrap shell). If the user targets iOS/Both, the manifest declares entrypoints.ios; /assemble-ppmplugin will still gate if the iOS binary isn't staged at packaging time.

Then derive fields from the actual files, not from assumptions (author-from-source mode only — in validate-and-stage mode skip to Step 3 with the fields read from ./manifest.json):

  1. Class name <Pascal> — from the native module (the Android <Pascal>Module.kt filename / its getName() = "<Pascal>Module", or the iOS RCT<Pascal>Module), or the .extension-state.md Identity block. There is no src/<Pascal>Extension.ts in this track. This is the basis for name, nativeModule, receivers[].name.

  2. version — package.json version.

  3. nativeModule — read the Android module's override fun getName(): String = "<X>". Use <X> verbatim.

  4. packageClass — read the ReactPackage .kt file: combine its package <...> line with the class name → FQN (e.g. com.powerapps.peninput.PenInputPackage).

  5. methods — scan the Android module (via the Read/Grep tools, not a shell-specific command — this skill is OS-neutral) for @ReactMethod and collect each annotated function name. Cross-check the count against the operations in ARCHITECTURE.md §3 / PRD §4; if a documented operation has no matching @ReactMethod, surface it as a warning (the manifest reflects what the binary actually exposes, but the mismatch usually means an operation wasn't wired).

  6. iOS entrypoint fields (only when targeting iOS / Both) — read ios/RCT<Pascal>Module.h for the class name (@interface RCT<Pascal>Module : NSObject <RCTBridgeModule>) → that is entrypoints.ios.moduleClass. Read ios/RCT<Pascal>Module.m for + (NSString *)moduleName { return @"<X>"; } and assert <X> equals the nativeModule from step 3 — it's the same bridge symbol on both platforms; a mismatch means the iOS and Android modules disagree. (The .m must not use RCT_EXPORT_MODULE — that macro's +load registration is invisible to the framework's dlopen flat namespace, so the module never loads on device.)

Then compute, per ppmplugin-format.md §3:

  • name = kebab(className) — from the class name, not the capability/repo name. If kebab(className) differs from the repo's capability kebab (e.g. repo powerapps-pdf-control but class PdfViewer → name: pdf-viewer), print a one-line note so the user knows the .ppmplugin filename won't match the repo name. This is required for the canonical-prefix rule to pass.
  • receivers[].name — take it from the PCF if one exists, do NOT blindly default. If a sibling PCF is present (pcf/<…>/index.ts), grep it for the dispatch key — COMPOSITE_KEY = "<name>/<receiver>" (or the ReceiverKey it binds) — and use that <receiver> value, because the PCF already dispatches to it; a manifest that registers a different receiver name will fail on first dispatch (real bug: PCF dispatched to Snapshot while the manifest defaulted to DeviceInfoExtension). Only if no PCF exists, fall back to <Pascal>Extension. Either way, surface the chosen value as a confirmation point: "PCF dispatches to <name>/<receiver>; the manifest will register receiver <receiver> — confirm?" (Audit re-checks this — see `/audi

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars919
CategoryMarketing
Updated12d ago
Forks186

Languages

JavaScript

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions