Is your feature request related to a problem? Please describe.
The extension's manifest commands were designed against winappcli ~v0.3.1, but scripts/download-cli.ps1 downloads the latest release — currently v0.6.1. We ship a 0.6.x CLI behind a 0.3.x UI, so most of the manifest surface is unreachable from VS Code.
Against the v0.6.1 schema (docs/cli-schema.json in microsoft/winappcli):
| Command |
Surfaced today |
Unsurfaced |
manifest generate |
--template |
directory (positional), --package-name, --publisher-name, --version, --description, --logo-path, --executable, --if-exists |
manifest update-assets |
image-path |
--light-image, --manifest |
manifest add-alias |
(nothing — runs bare) |
--name, --app-id, --manifest |
The naive fix — bolt seven more QuickPick/InputBox steps onto winapp.manifestGenerate — is the wrong fix, because of what this extension already owns.
Describe the solution you'd like
1. Generate is a bootstrap, not a form — "generate minimal, then open the editor"
Recommendation: do not prompt for name/publisher/version/description/logo/executable.
src/manifest-editor/manifest-types.ts already models every one of those values — IdentityData.name/.publisher/.version, PropertiesData.description/.logo/.publisherDisplayName, ApplicationData.executable — with browse buttons (browseImage, browseExe) and XSD-backed validation (manifest-validator.ts, src/manifest-intellisense/). A QuickPick chain for the same six values is a strictly worse, unvalidated, non-revisable duplicate of a UI we already ship. Get the publisher DN wrong in a one-shot prompt and your only recovery is editing the file anyway.
Proposed flow:
- Resolve the project dir (existing
resolveProjectDirectory).
- QuickPick template —
packaged / sparse — with real descriptions from the schema ("full MSIX app" / "desktop app with package identity for Windows APIs") rather than today's bare two strings.
- Run with the positional
directory argument (never passed today) and --if-exists per §3.
- On success, show "Manifest created. [Open in Manifest Editor] [Show File]", reusing
vscode.openWith … ManifestEditorProvider.viewType.
That makes generate the front door to the editing story rather than a competitor to it.
2. If prompts are wanted, the minimum viable subset
Template → package name (InputBox prefilled with path.basename(projectDir), which is the CLI's own default, plus MSIX name validation in validateInput) → publisher DN (prefilled CN=<os.userInfo().username>; the CLI auto-wraps bare names, so hint rather than hard-validate).
Stop there. --version (defaults 1.0.0.0), --description (defaults My Application), --logo-path and --executable belong in the editor. --executable especially defaults to <package-name>.exe and is usually wrong until after the first build — prompting for it at generate time invites a stale value.
3. --if-exists maps to a VS Code confirmation, not a QuickPick
Don't leak the error/skip/overwrite enum into the UI. Instead, probe for an existing Package.appxmanifest / appxmanifest.xml first (the extension already has isManifestPath and MANIFEST_SELECTOR):
- None exists → run with
--if-exists error. That's the CLI default and acts as a race guard.
- One exists → skip the CLI and show a modal: "<file> already exists in <dir>." with [Open in Manifest Editor] (default) and [Overwrite]. Only the latter re-runs with
--if-exists overwrite, as a showWarningMessage({ modal: true }) since it's destructive and unrecoverable through the extension.
skip has no user-facing analogue — "do nothing" is just cancelling the dialog.
This turns the common "I already have one" case into a one-click route into the editor.
4. Reachability, and the init overlap
The manifest editor is a CustomTextEditor bound to an existing document, so it can't host "create a manifest that doesn't exist yet". Keep generate → editor as the primary link and don't add a Generate button inside the webview. Instead, add an explorer/context menu contribution on folders (when: explorerResourceIsFolder) — today winapp.manifestGenerate has no menu contributions at all, palette only.
init overlap — flagging, not redesigning. Per the schema, init also "creates Package.appxmanifest with default assets", and the CLI's own generate description says "For full setup, use 'init' instead." The two commands use different flag spellings for the same concepts: --package-name/--publisher-name vs --name/--publisher; --template sparse vs --sparse; --if-exists overwrite vs --force. Whoever does this work should extract shared helpers (a single package-name prompt, a single publisher-DN prompt, and the §3 "already exists" confirmation) into e.g. src/manifest-prompts.ts so both commands consume them.
Separately flagged: winapp.init today hardcodes --use-defaults and never passes --name/--publisher, so it has the same under-surfacing problem. Out of scope here.
5. Sibling gaps worth folding into the same change
manifest update-assets (extension.ts:1468)
- Add
--light-image — the only way to get theme-specific assets.
- Pass
--manifest explicitly instead of relying on "search current directory". Matters when resolveProjectDirectory picked a non-root project.
- Accept
svg and ico in the file filter. The schema lists SVG, PNG, ICO, JPG, BMP, GIF; the extension's filter omits svg and ico — and the editor's own browseImage filter already includes them, so this is an internal inconsistency.
- Mirror
--light-image/--manifest in the editor's "Regenerate Assets" handler (manifest-editor-provider.ts ~line 392) so both entry points stay equivalent.
manifest add-alias (extension.ts:1635)
- Runs completely bare today — no way to choose the alias name or target Application.
- Add an optional alias-name InputBox (empty = CLI infers from
Executable).
- Add
--app-id only when the manifest has more than one <Application>; manifest-parser.ts can already enumerate them, so the QuickPick can list real IDs. Single-app manifests get no prompt.
- Pass
--manifest for the same multi-project reason.
- Consider an "Add Execution Alias" button in the editor's Application card, next to the existing "Regenerate Assets".
Additional context
Mechanical implication: runWinappCommand (extension.ts:220) creates a terminal and sendTexts — fire-and-forget, no exit code. Any post-generate action (open the editor, report "already exists") requires moving to runWinappCapture (extension.ts:281), which spawns with progress + cancellation and resolves { code, output }.
Existing precedent: the editor webview already shells out to the CLI — manifest-editor-provider.ts handles an updateAssets message by execFile-ing winapp manifest update-assets <image> with WINAPP_CLI_CALLER set, driven by the "Regenerate Assets" button (webview-script-applications.ts:247). Editor→CLI invocation is established, not new.
Testability: extract the shared prompt/validation helpers into a module with no vscode import, following the existing project-resolver.ts / winapp-tool.ts dependency-injection convention, so they get unit tests like test/project-resolver.test.ts.
Open questions:
- Generate-minimal-then-open-editor (recommended) vs. the middle path in §2 vs. a full prompt chain.
- After a successful generate: auto-open the editor, or notification with an "Open in Manifest Editor" action?
- Are the
explorer/context menu contributions in scope?
- Do the
update-assets / add-alias gaps belong in the same PR or a follow-up?
Schema referenced: gh api repos/microsoft/winappcli/contents/docs/cli-schema.json?ref=v0.6.1
Is your feature request related to a problem? Please describe.
The extension's manifest commands were designed against winappcli ~v0.3.1, but
scripts/download-cli.ps1downloads thelatestrelease — currently v0.6.1. We ship a 0.6.x CLI behind a 0.3.x UI, so most of themanifestsurface is unreachable from VS Code.Against the v0.6.1 schema (
docs/cli-schema.jsonin microsoft/winappcli):manifest generate--templatedirectory(positional),--package-name,--publisher-name,--version,--description,--logo-path,--executable,--if-existsmanifest update-assetsimage-path--light-image,--manifestmanifest add-alias--name,--app-id,--manifestThe naive fix — bolt seven more QuickPick/InputBox steps onto
winapp.manifestGenerate— is the wrong fix, because of what this extension already owns.Describe the solution you'd like
1. Generate is a bootstrap, not a form — "generate minimal, then open the editor"
Recommendation: do not prompt for name/publisher/version/description/logo/executable.
src/manifest-editor/manifest-types.tsalready models every one of those values —IdentityData.name/.publisher/.version,PropertiesData.description/.logo/.publisherDisplayName,ApplicationData.executable— with browse buttons (browseImage,browseExe) and XSD-backed validation (manifest-validator.ts,src/manifest-intellisense/). A QuickPick chain for the same six values is a strictly worse, unvalidated, non-revisable duplicate of a UI we already ship. Get the publisher DN wrong in a one-shot prompt and your only recovery is editing the file anyway.Proposed flow:
resolveProjectDirectory).packaged/sparse— with real descriptions from the schema ("full MSIX app" / "desktop app with package identity for Windows APIs") rather than today's bare two strings.directoryargument (never passed today) and--if-existsper §3.vscode.openWith … ManifestEditorProvider.viewType.That makes generate the front door to the editing story rather than a competitor to it.
2. If prompts are wanted, the minimum viable subset
Template → package name (InputBox prefilled with
path.basename(projectDir), which is the CLI's own default, plus MSIX name validation invalidateInput) → publisher DN (prefilledCN=<os.userInfo().username>; the CLI auto-wraps bare names, so hint rather than hard-validate).Stop there.
--version(defaults1.0.0.0),--description(defaultsMy Application),--logo-pathand--executablebelong in the editor.--executableespecially defaults to<package-name>.exeand is usually wrong until after the first build — prompting for it at generate time invites a stale value.3.
--if-existsmaps to a VS Code confirmation, not a QuickPickDon't leak the
error/skip/overwriteenum into the UI. Instead, probe for an existingPackage.appxmanifest/appxmanifest.xmlfirst (the extension already hasisManifestPathandMANIFEST_SELECTOR):--if-exists error. That's the CLI default and acts as a race guard.--if-exists overwrite, as ashowWarningMessage({ modal: true })since it's destructive and unrecoverable through the extension.skiphas no user-facing analogue — "do nothing" is just cancelling the dialog.This turns the common "I already have one" case into a one-click route into the editor.
4. Reachability, and the
initoverlapThe manifest editor is a
CustomTextEditorbound to an existing document, so it can't host "create a manifest that doesn't exist yet". Keep generate → editor as the primary link and don't add a Generate button inside the webview. Instead, add anexplorer/contextmenu contribution on folders (when: explorerResourceIsFolder) — todaywinapp.manifestGeneratehas no menu contributions at all, palette only.initoverlap — flagging, not redesigning. Per the schema,initalso "creates Package.appxmanifest with default assets", and the CLI's own generate description says "For full setup, use 'init' instead." The two commands use different flag spellings for the same concepts:--package-name/--publisher-namevs--name/--publisher;--template sparsevs--sparse;--if-exists overwritevs--force. Whoever does this work should extract shared helpers (a single package-name prompt, a single publisher-DN prompt, and the §3 "already exists" confirmation) into e.g.src/manifest-prompts.tsso both commands consume them.Separately flagged:
winapp.inittoday hardcodes--use-defaultsand never passes--name/--publisher, so it has the same under-surfacing problem. Out of scope here.5. Sibling gaps worth folding into the same change
manifest update-assets(extension.ts:1468)--light-image— the only way to get theme-specific assets.--manifestexplicitly instead of relying on "search current directory". Matters whenresolveProjectDirectorypicked a non-root project.svgandicoin the file filter. The schema lists SVG, PNG, ICO, JPG, BMP, GIF; the extension's filter omitssvgandico— and the editor's ownbrowseImagefilter already includes them, so this is an internal inconsistency.--light-image/--manifestin the editor's "Regenerate Assets" handler (manifest-editor-provider.ts~line 392) so both entry points stay equivalent.manifest add-alias(extension.ts:1635)Executable).--app-idonly when the manifest has more than one<Application>;manifest-parser.tscan already enumerate them, so the QuickPick can list real IDs. Single-app manifests get no prompt.--manifestfor the same multi-project reason.Additional context
Mechanical implication:
runWinappCommand(extension.ts:220) creates a terminal andsendTexts — fire-and-forget, no exit code. Any post-generate action (open the editor, report "already exists") requires moving torunWinappCapture(extension.ts:281), which spawns with progress + cancellation and resolves{ code, output }.Existing precedent: the editor webview already shells out to the CLI —
manifest-editor-provider.tshandles anupdateAssetsmessage byexecFile-ingwinapp manifest update-assets <image>withWINAPP_CLI_CALLERset, driven by the "Regenerate Assets" button (webview-script-applications.ts:247). Editor→CLI invocation is established, not new.Testability: extract the shared prompt/validation helpers into a module with no
vscodeimport, following the existingproject-resolver.ts/winapp-tool.tsdependency-injection convention, so they get unit tests liketest/project-resolver.test.ts.Open questions:
explorer/contextmenu contributions in scope?update-assets/add-aliasgaps belong in the same PR or a follow-up?Schema referenced:
gh api repos/microsoft/winappcli/contents/docs/cli-schema.json?ref=v0.6.1