Create Uploader Plugin
Use this skill to add a new desktop uploader plugin that matches the current XerahS plugin architecture.
For a concrete native-API example, see docs/proposals/xip/XIP0048-nextcloud-native-plugin-design.md.
Workflow
- Audit existing support before writing code.
- Search the repo for the service name, old uploader code, prior docs, and compatibility layers.
- Determine whether this should be a new plugin, a replacement for an old uploader, or an extension of an existing plugin.
- Research the service's official API and auth model using primary sources.
- Use references/service-research-template.md.
- Prefer the service's native API over generic compatibility endpoints when the native path materially improves auth, chunking, sharing, explorer actions, capability discovery, or reliability.
- Inspect the nearest existing plugin before writing code.
- Read references/pattern-map.md.
- Pick the closest starting point:
- Simple token/manual config:
Bitly.Plugin
- Browser login or OAuth:
Dropbox.Plugin
- File storage + explorer:
AmazonS3.Plugin or Nextcloud.Plugin
- Scaffold the plugin with
scripts/new-uploader-plugin.ps1.
- Replace scaffold placeholders with service-specific logic.
- Keep secrets in
ISecretStore, not in settings JSON.
- Add explorer support only if the destination can browse/list remote files with stable semantics.
- Add or refine the Avalonia config UI when the property-grid experience would be weak.
- For Avalonia control, binding, and styling rules, read ../avalonia-guidelines/SKILL.md.
- For visual redesign of a plugin config view, read ../design-ui-window/SKILL.md and set its
target_view_path to src\desktop\plugins\<Name>.Plugin\Views\ConfigView.axaml.
- Treat uploader config UI as Avalonia AXAML work, not a web frontend workflow.
- Build the new plugin project, then build
src/desktop/XerahS.sln.
Scaffold Command
Run:
.ai\skills\create-uploader-plugin\scripts\new-uploader-plugin.ps1 `
-PluginName "MyService" `
-PluginId "myservice" `
-DisplayName "MyService Uploader" `
-AddToSolution
This creates:
src/desktop/plugins/MyService.Plugin/
XerahS.MyService.Plugin.csproj
plugin.json
- config model, provider, uploader
- Avalonia config view + viewmodel
Required Conventions
- Keep the plugin under
src/desktop/plugins/<Name>.Plugin/.
- Target
net10.0.
- Reuse
src/desktop/plugins/Directory.Build.props.
- Use
ShareX.<Name>.Plugin namespaces and XerahS.<Name>.Plugin assembly/project names.
- Exclude Avalonia/runtime-shared dependencies from plugin output with
ExcludeAssets=runtime.
- Copy
plugin.json to output.
- If credentials are needed, store them through
ISecretStore.
- If importing legacy plaintext settings, implement
IInstanceSecretMigrator.
- Keep upload logic inside the plugin uploader/provider, not in core app code.
Implementation Decisions
Use these rules when filling in the scaffold:
- Use
UploaderProviderBase unless there is a strong reason not to.
- Return a concrete
Uploader or GenericUploader from CreateInstance.
- Override
CreateConfigView() and CreateConfigViewModel() for non-trivial configuration.
- Implement
IUploaderExplorer only when the service supports remote listing/content actions.
- Make
ValidateSettings reflect real minimum runtime requirements.
- Keep
plugin.json metadata aligned with ProviderId, class namespace, and assembly name.
- If the service exposes both generic and native endpoints, document why the chosen path is correct for this plugin.
- If the service has staged login or capability discovery, surface that in the config UI instead of hiding it behind a flat settings form.
- If the service already had legacy plaintext settings, add secret migration rather than silently abandoning stored credentials.
Verification
Run both:
dotnet build src\desktop\plugins\<Name>.Plugin\XerahS.<Name>.Plugin.csproj -m:1
dotnet build src\desktop\XerahS.sln -m:1
Use references/review-checklist.md before finishing.
1---2name: create-uploader-plugin3description: Add a desktop upload destination under src/desktop/plugins. Do not use for configuring an existing plugin.4---56# Create Uploader Plugin78Use this skill to add a new desktop uploader plugin that matches the current XerahS plugin architecture.910For a concrete native-API example, see [docs/proposals/xip/XIP0048-nextcloud-native-plugin-design.md](../../../docs/proposals/xip/XIP0048-nextcloud-native-plugin-design.md).1112## Workflow13141. Audit existing support before writing code.15 - Search the repo for the service name, old uploader code, prior docs, and compatibility layers.16 - Determine whether this should be a new plugin, a replacement for an old uploader, or an extension of an existing plugin.172. Research the service's official API and auth model using primary sources.18 - Use [references/service-research-template.md](references/service-research-template.md).19 - Prefer the service's native API over generic compatibility endpoints when the native path materially improves auth, chunking, sharing, explorer actions, capability discovery, or reliability.203. Inspect the nearest existing plugin before writing code.21 - Read [references/pattern-map.md](references/pattern-map.md).22 - Pick the closest starting point:23 - Simple token/manual config: `Bitly.Plugin`24 - Browser login or OAuth: `Dropbox.Plugin`25 - File storage + explorer: `AmazonS3.Plugin` or `Nextcloud.Plugin`264. Scaffold the plugin with `scripts/new-uploader-plugin.ps1`.275. Replace scaffold placeholders with service-specific logic.286. Keep secrets in `ISecretStore`, not in settings JSON.297. Add explorer support only if the destination can browse/list remote files with stable semantics.308. Add or refine the Avalonia config UI when the property-grid experience would be weak.31 - For Avalonia control, binding, and styling rules, read [../avalonia-guidelines/SKILL.md](../avalonia-guidelines/SKILL.md).32 - For visual redesign of a plugin config view, read [../design-ui-window/SKILL.md](../design-ui-window/SKILL.md) and set its `target_view_path` to `src\desktop\plugins\<Name>.Plugin\Views\ConfigView.axaml`.33 - Treat uploader config UI as Avalonia AXAML work, not a web frontend workflow.349. Build the new plugin project, then build `src/desktop/XerahS.sln`.3536## Scaffold Command3738Run:3940```powershell41.ai\skills\create-uploader-plugin\scripts\new-uploader-plugin.ps1 `42 -PluginName "MyService" `43 -PluginId "myservice" `44 -DisplayName "MyService Uploader" `45 -AddToSolution46```4748This creates:4950- `src/desktop/plugins/MyService.Plugin/`51- `XerahS.MyService.Plugin.csproj`52- `plugin.json`53- config model, provider, uploader54- Avalonia config view + viewmodel5556## Required Conventions57581. Keep the plugin under `src/desktop/plugins/<Name>.Plugin/`.592. Target `net10.0`.603. Reuse `src/desktop/plugins/Directory.Build.props`.614. Use `ShareX.<Name>.Plugin` namespaces and `XerahS.<Name>.Plugin` assembly/project names.625. Exclude Avalonia/runtime-shared dependencies from plugin output with `ExcludeAssets=runtime`.636. Copy `plugin.json` to output.647. If credentials are needed, store them through `ISecretStore`.658. If importing legacy plaintext settings, implement `IInstanceSecretMigrator`.669. Keep upload logic inside the plugin uploader/provider, not in core app code.6768## Implementation Decisions6970Use these rules when filling in the scaffold:71721. Use `UploaderProviderBase` unless there is a strong reason not to.732. Return a concrete `Uploader` or `GenericUploader` from `CreateInstance`.743. Override `CreateConfigView()` and `CreateConfigViewModel()` for non-trivial configuration.754. Implement `IUploaderExplorer` only when the service supports remote listing/content actions.765. Make `ValidateSettings` reflect real minimum runtime requirements.776. Keep `plugin.json` metadata aligned with `ProviderId`, class namespace, and assembly name.787. If the service exposes both generic and native endpoints, document why the chosen path is correct for this plugin.798. If the service has staged login or capability discovery, surface that in the config UI instead of hiding it behind a flat settings form.809. If the service already had legacy plaintext settings, add secret migration rather than silently abandoning stored credentials.8182## Verification8384Run both:8586```powershell87dotnet build src\desktop\plugins\<Name>.Plugin\XerahS.<Name>.Plugin.csproj -m:188dotnet build src\desktop\XerahS.sln -m:189```9091Use [references/review-checklist.md](references/review-checklist.md) before finishing.