Frequently asked questions.

云一会儿 / CloudYiCFAW is a Wails desktop shell around signed React plugins and native Go/C helper functions. These notes cover the common setup, development, and plugin workflow questions.

How do I run the desktop app from source?

For a fresh checkout, the expected contributor flow is:

pnpm install
cd apps/desktop
wails dev

Embedded plugins are unpacked by the desktop app at startup. Existing cached plugin folders are refreshed from the embedded version when needed.

What does the root dev task do?

The repository root uses Turborepo because this is a workspace, not a single web app. It coordinates the web site, the Wails desktop frontend, shared packages, and plugin source packages.

pnpm install
pnpm dev
# same as: turbo run dev

The Turbo task UI is only a log dashboard. Selecting @cloudyicfaw/web or @cloudyicfaw/desktop-frontend focuses that task log; it does not start the task on demand.

Run a single target when you only need one surface:

pnpm --filter @cloudyicfaw/web dev
cd apps/desktop && wails dev

If next dev appears to stay on Starting..., open http://localhost:3001/ first. If the page loads, the server is already running. If it does not load, close old dev processes, remove apps/web/.next, and start the web package again.

Can I use tools directly in the browser?

Yes. Tool detail pages include a browser runner, so temporary web usage does not require downloading the desktop client.

Tools that already have a clean C native core run through WebAssembly: hash, base64, hex, url-encode, uuid, password, timestamp, and numfmt.

Tools that map better to browser semantics run through TypeScript: json-format, jwt, regex, and diff.

pnpm build-web-wasm
# generates apps/web/public/wasm/cloudyic-native.wasm

The root pnpm build script runs this WASM build first. During web-only development, rerun it after changing C native code or the WASM wrapper.

How does the plugin SDK work?

A plugin is a default-exported ToolPlugin plus a manifest. The host injects React, the SDK, and native bindings.

pnpm add @cloudyicfaw/plugin-sdk @cloudyicfaw/ui @cloudyicfaw/design-tokens
import type { ToolPlugin } from '@cloudyicfaw/plugin-sdk'
import manifestRaw from '../manifest.json'

const plugin: ToolPlugin = {
  manifest: manifestRaw as Manifest,
  Component({ ctx }) {
    return <div>Hello, {ctx.sdk.host.platform}</div>
  },
}

export default plugin

What does a plugin manifest include?

Every plugin ships a manifest that the desktop host validates before loading.

{
  "id": "jwt",
  "version": "0.1.0",
  "name": "JWT Inspector",
  "description": "Decode and verify JSON Web Tokens",
  "category": "text-data",
  "icon": "JWT",
  "entry": "index.js",
  "minClientVersion": "0.1.0",
  "permissions": ["clipboard:write"]
}

What does the security model verify?

The desktop client refuses to load a plugin if one of these checks fails:

  • SHA-256 of entry matches manifest.checksum
  • Manifest signature verifies against the embedded public key
  • minClientVersion is satisfied

How do I publish signed plugins?

scripts/publish-plugin.ts bundles source, fills checksum and signature fields, then writes the signed plugin to apps/desktop/embedded-plugins.

pnpm publish-all-plugins

Want the release notes for the current plugin store?

Read the changelog