yanzi-extension-dev

star 203

Build, inspect, edit, and install Yanzi extensions. Use when an agent needs to create or modify `manifest.json`, author C# or PowerShell extensions, call Yanzi's local extension HTTP API, or troubleshoot extension loading and execution.

luoluoluo22 By luoluoluo22 schedule Updated 6/11/2026

name: yanzi-extension-dev description: Build, inspect, edit, and install Yanzi extensions. Use when an agent needs to create or modify manifest.json, author C# or PowerShell extensions, call Yanzi's local extension HTTP API, or troubleshoot extension loading and execution.

Yanzi Extension Development

Use this skill when working on local extensions for Yanzi.

Quick Start

Yanzi stores runtime extensions under the app's Extensions/ directory. On Windows development/runtime environment, the actual path is %LOCALAPPDATA%\OpenQuickHost\Extensions\ (and configuration/storage files under %LOCALAPPDATA%\OpenQuickHost\). The Local Agent API authentication Token is located in %LOCALAPPDATA%\OpenQuickHost\appsettings.local.json under the "agentApiToken" field. Each extension lives in its own folder.

Two extension shapes are supported:

  1. JSON extension
  2. C# or PowerShell action extension
  3. Hosted view extension

For lightweight action extensions inside a single manifest.json, choose the runtime by task:

  • use runtime = csharp for complex logic, JSON/HTTP/file processing, native WPF windows, P/Invoke, and strongly typed .NET APIs
  • use runtime = powershell for Windows automation, registry/service/process/scheduled-task/system-command work, clipboard/file automation, and tasks with existing PowerShell cmdlets
  • entryMode = inline
  • script.source

Minimum layout:

Extensions/
  my-extension/
    manifest.json

Script extension layout:

Extensions/
  my-script/
    manifest.json
    main.ps1

Manifest Model

Common fields:

  • id
  • name
  • version
  • category
  • description
  • keywords
  • globalShortcut
  • hotkeyBehavior

JSON action fields:

  • openTarget
  • queryPrefixes
  • queryTargetTemplate

Script fields:

  • runtime
  • entryMode
  • entry
  • script.source
  • permissions

Hosted view fields:

  • hostedView.type
  • hostedView.title
  • hostedView.description
  • hostedView.inputLabel
  • hostedView.inputPlaceholder
  • hostedView.outputLabel
  • hostedView.actionButtonText
  • hostedView.actionType
  • hostedView.emptyState

Web app fields:

  • app.type
  • app.entry
  • app.singleInstance
  • app.window.width
  • app.window.height
  • app.window.minWidth
  • app.window.minHeight

Read references/manifest.md when editing manifests.

Script Execution

Current script runtimes:

  • csharp
  • powershell

Choose the runtime by task. C# is best for complex logic, native windows, P/Invoke, and strongly typed .NET APIs. PowerShell is often simpler and more reliable for Windows automation, registry/service/process/scheduled-task/system-command work, and tasks with existing cmdlets. If the task is essentially a cmd/bat command sequence, wrap it with PowerShell or use an external script entry instead of forcing C#.

Capability strategy:

  • Prefer native language/system capabilities for feature implementation: C#/.NET/WPF/Windows APIs for complex app logic; PowerShell/cmdlets for system automation.
  • Treat YanziActionContext as a small host concierge API for input, launch metadata, extension directories, state, and local/cloud storage.
  • Do not invent host wrapper methods such as context.SetTheme(), context.GetTheme(), context.OpenFilePicker(), context.ShowMessage(), or context.GetStateAsync<T>().
  • For windows, dialogs, file pickers, clipboard, processes, registry, HTTP, system settings, and Win32 calls, write native C# directly unless the manifest/reference docs explicitly name a host API.
  • The compiler injects the runtime namespace for YanziActionContext; extension source should not add host runtime usings. The app assembly is Yanzi; do not generate legacy product-name pack URIs, assembly references, resource paths, or assumed theme dictionaries.

Inline C# example:

{
  "id": "csharp-echo",
  "name": "C# 输入回显",
  "runtime": "csharp",
  "entryMode": "inline",
  "permissions": [],
  "script": {
    "source": "public static class YanziAction\\n{\\n    public static Task<string> RunAsync(YanziActionContext context)\\n    {\\n        return Task.FromResult(context.InputText);\\n    }\\n}"
  }
}

C# entry contract:

public static class YanziAction
{
    public static Task<string> RunAsync(YanziActionContext context)
}

Entry file example:

{
  "id": "script-clipboard",
  "name": "读取剪贴板",
  "runtime": "powershell",
  "entry": "main.ps1",
  "permissions": ["clipboard.read"]
}

PowerShell conventions:

  • param(...) must be the first statement
  • then set output encoding if needed
  • write user-facing result to stdout
  • write failure detail to stderr or throw

The host passes:

  • -InputText
  • -ContextPath
  • env YANZI_INPUT
  • env YANZI_CONTEXT_PATH
  • env YANZI_EXTENSION_ID
  • env YANZI_EXTENSION_DIR
  • env YANZI_LAUNCH_SOURCE

Read references/script-extensions.md when authoring scripts.

Local Agent API

Yanzi exposes a localhost HTTP API for extension CRUD. It is intended for same-machine agents.

Default:

  • base URL: http://127.0.0.1:53919
  • header: X-Yanzi-Token

Useful endpoints:

  • GET /health
  • GET /v1/extensions
  • GET /v1/extensions/template
  • GET /v1/extensions/{id}
  • POST /v1/extensions
  • PUT /v1/extensions/{id}
  • PATCH /v1/extensions/{id}/rename
  • PATCH /v1/extensions/{id}/shortcut
  • DELETE /v1/extensions/{id}

Read references/local-agent-api.md for request and response shapes.

Encoding Considerations

When communicating with the local agent API (especially using legacy clients like Windows PowerShell 5.1), requests with non-ASCII text (e.g. Chinese characters) may cause encoding issues (garbled characters / 乱码) because the client defaults to sending ANSI/GBK payload instead of UTF-8.

To prevent encoding issues:

  1. Always specify '; charset=utf-8' in the 'Content-Type' header (e.g. '"Content-Type": "application/json; charset=utf-8"').
  2. Manually encode the payload to a UTF-8 byte stream before sending it as the request body. For PowerShell:
    $bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($jsonPayload)
    Invoke-RestMethod -Uri "..." -Method Post -Headers $headers -Body $bodyBytes
    

Working Rules

  • CRITICAL: When creating a NEW extension, you MUST use the Local Agent API (POST /v1/extensions) rather than directly writing files to the disk. Creating extensions via the API ensures the host application correctly registers them and applies the "Recently Added" sorting boost (置顶排列) so the user sees them at the top of their list. After creation, you may edit the files directly.
  • CRITICAL: When using ProcessStartInfo to call external processes (like ADB) from C# extensions, ensure that you explicitly set StandardOutputEncoding = System.Text.Encoding.UTF8; (and StandardErrorEncoding) and use ReadToEndAsync() to prevent Chinese character garbling (中文乱码).
  • CRITICAL: If you execute dotnet build to compile the host application or an extension, you MUST automatically launch the compiled application (e.g., Start-Process or dotnet run) immediately afterwards, so the user doesn't have to restart it manually.
  • Prefer editing extension folders through the local API when you are acting as an external agent.
  • When working inside the Yanzi codebase, update both the runtime behavior and the bundled skill docs if behavior changes.
  • Prefer C# inline actions for new extensions unless the task is specifically Windows shell automation. For complex or large extensions, prefer multi-file format (e.g. entryMode = entry pointing to main.cs) over inline source to maintain code clarity.
  • For PowerShell extensions, keep files ASCII unless non-ASCII output is required; when Chinese text is required, ensure the file is written with BOM-compatible UTF-8 handling.
  • When debugging inline scripts, prefer using the editor test flow first, then inspect logs/host.log and dev-debug.log on the development machine.
  • C# extensions loaded via in-process AssemblyLoadContext persist in memory. If your extension registers global event hooks (e.g. keyboard/mouse hooks via Win32 SetWindowsHookEx), use a static manager to keep the hook alive and running in the background even after RunAsync completes or the setting window closes.
Install via CLI
npx skills add https://github.com/luoluoluo22/yanzi --skill yanzi-extension-dev
Repository Details
star Stars 203
call_split Forks 15
navigation Branch main
article Path SKILL.md
More from Creator