@wujie-shell/core
v1.1.2
Published
`@wujie-shell/core` is the runtime and desktop infrastructure layer for `wujie-shell`. It prepares the OpenClaw runtime, generates/syncs OpenClaw configuration, starts the gateway, bridges gateway events, and provides the Electron main/preload implementat
Readme
@wujie-shell/core
@wujie-shell/core is the runtime and desktop infrastructure layer for
wujie-shell. It prepares the OpenClaw runtime, generates/syncs OpenClaw
configuration, starts the gateway, bridges gateway events, and provides the
Electron main/preload implementation used by product UI projects.
Responsibility
- Prepare
apps/<product>/.tmp/runtimefor the product. - Install or validate the configured OpenClaw version.
- Sync product Plugin, Agent, and Skill directories into the runtime.
- Generate and maintain
~/<dataDirName>/<openclaw.configFileName>. - Start/stop/restart the OpenClaw gateway on product-specific ports.
- Maintain a gateway WebSocket client with device identity auth.
- Expose safe renderer APIs through Electron preload.
- Provide shell-owned local IPC capabilities such as connectors, generated files, log reporting, custom model forms, preferences, and market skill mapping.
This package is shell infrastructure. It must not contain product UI business logic or hard-coded product asset lists.
Product-specific historical compatibility lives in
apps/desktop-cn/shell-runtime; that runtime should only keep config migrations.
New shell IPC capabilities should be added to the matching src/* module here,
not to product runtime.
Public Exports
import {
createConfigController,
createGatewayController,
ensureOpenClawDoctorFixed,
loadRuntimeInfo,
prepareRuntime,
runClawOnce,
spawnClaw,
} from '@wujie-shell/core'Runtime helpers are also exported from @wujie-shell/core/runtime.
Source Layout
src/ is grouped by capability:
electron/: Electron main/preload, windows, protocols, and IPC wiring.runtime/: OpenClaw/Node runtime prepare, sync, manifest, plugin copying, and upstream compatibility patches.gateway/: OpenClaw gateway lifecycle and WebSocket client.config/: generated OpenClaw config reads/writes and runtime plugin sync.agents/,skills/: bundled Agent/Skill sync, managed Skill import, and market skill registry mapping.connectors/: OpenClaw plugin/channel config writes and local CLI/QR auth sessions for connector-style capabilities.files/,models/,preferences/,log-reporting/: generated file center, custom model form, local preference, and log report IPC handlers.chat/,sessions/,terminal/: chat media archive, session mapping, and local terminal helpers.common/: diagnostics, logging, runtime logging, and shared utilities.
Only create package exports for modules that are intentionally consumed outside the package.
Runtime Preparation
prepareRuntime(shellConfig, options?)
Prepares the product runtime at:
apps/<product>/.tmp/runtimeOptions:
{
syncOnly?: boolean
}Behavior:
- Builds or refreshes the product-local runtime base when needed.
- Validates Node runtime version.
- Installs the configured OpenClaw version when
prepareis used and versions differ. - Syncs runtime manifest plugin scope with
shell.config.mjs. - Copies product local plugins into
openclaw/dist/extensions. - Copies product agents into
openclaw/agents. - Copies product global skills into
openclaw/skills. - Writes
bin/wujieaiso OpenClaw uses the product data directory and config, and prepends the runtimebindirectory toPATHfor child commands. IfOPENCLAW_HOME,OPENCLAW_STATE_DIR,OPENCLAW_CONFIG_FILE_NAME, orOPENCLAW_CONFIG_PATHis already set, the wrapper keeps the override and prints the effective paths to stderr unlessWUJIE_NO_ENV_DIAGNOSTICS=1. The wrapper plays the Wujie startup logo animation (bin/wujie-logo.mjs, copied fromassets/wujie-logo.mjs) before exec'ing OpenClaw. It only runs on an interactive TTY and can be disabled withWUJIE_NO_LOGO=1. - Updates
runtime-manifest.jsonwith product metadata.
syncOnly: true does not install a new OpenClaw version; it builds any missing
runtime base files, then validates that the prepared runtime already matches the
configured OpenClaw version.
ensureOpenClawDoctorFixed() is available for products that want an explicit
pre-launch repair pass. It compares the embedded runtime version with a
shell-owned marker at ~/<dataDirName>/runtime-state/openclaw-doctor.json, then
runs openclaw doctor --fix when the persisted state has not yet been repaired.
The Wujie desktop currently leaves this pass disabled and relies on OpenClaw's
guarded startup migrations plus Shell runtime compatibility patches.
loadRuntimeInfo(projectRoot)
Reads and validates runtime-manifest.json, returning absolute paths:
{
runtimeRoot,
manifest,
openclawVersion,
nodeExecutable,
npmCli,
openclawWorkingDir,
openclawBin,
plugins
}spawnClaw(projectRoot, args, options?)
Spawns the prepared OpenClaw binary with runtime-aware env variables.
runClawOnce(projectRoot, args, timeoutMs?)
Runs OpenClaw once and resolves with:
{
code,
signal,
stdout,
stderr
}Config Controller
createConfigController(shellConfig) owns product OpenClaw config at
~/<dataDirName>/<openclaw.configFileName>, defaulting to
~/<dataDirName>/wujieai.json.
Important methods:
ensureConfigPathEnv()ensureInitialConfig()ensureGatewaySettings()readConfig()writeConfig(config)syncRuntimePlugins()getModelSettings()setModelSettings(settings, options?)setSelfOperatedModels(params)ensureAskUserQuestionPluginConfig({ callbackUrl, secret })watchConfigChanges()dispose()
The initial config includes:
- product model providers from
shell.config.mjs agents.defaults.workspace- memory and compaction defaults
- runtime plugin bootstrap entries
skills.load.extraDirs- session defaults
Model references must use provider/modelId. Display names must not be used as
request model IDs.
Gateway Controller
createGatewayController({ shellConfig, configController, appVersion }) owns
the OpenClaw gateway lifecycle.
Important methods:
start()stop()restart(reason?)runtimeInfo()getStatus()getRecentLogs(limit?)answerAskUserQuestion(payload)agents.list()skills.status(agentId?)sessions.create(payload?)sessions.list(payload?)sessions.delete(payload)chat.stream(payload)chat.abort(payload)chat.history(payload)
Events:
gateway-statusgateway-logchat-stream-eventsession-updatedagent-eventagents-updatedask-user-question
Renderer-facing session state is exposed by Electron preload and the shell SDK
with snapshot/subscribe naming: sessions.getSnapshot,
sessions.getMessagesSnapshot, sessions.getRuntimeStateSnapshot,
sessions.getEvents, and sessions.subscribe. The previous renderer IPC/API
names sessions:list, sessions:messages, sessions:runtime-state, and
sessions.onChanged are intentionally not retained.
Gateway ports use an operating-system-selected free port when
shellConfig.ports.gatewayStart is auto; an explicit numeric start retains
the 100-port allocation range.
Electron Integration
Electron main entry:
packages/shell-core/src/electron/main.mjsPreload entry:
packages/shell-core/src/electron/preload.mjsMain process responsibilities:
- Load product config from
WUJIE_SHELL_PROJECT_ROOT. - Create config and gateway controllers.
- Register IPC handlers.
- Register shell-owned desktop shortcuts.
DevTools is enabled by default outside
prod; inprodit requires~/<dataDirName>/devtools.flag. - Broadcast gateway events to renderer windows.
- Load Vite dev URL or product
dist/index.html.
Renderer code should only use window.wujieShell, which is exposed by preload.
Do not import Electron IPC directly in UI code.
Shell-level DevTools ability:
- Shortcut:
CommandOrControl+Shift+I - Renderer API:
window.wujieShell.window.openDevTools() - Renderer event:
window.wujieShell.window.onDevToolsShortcut(listener)
CLI
The package exposes wujie-shell:
wujie-shell prepare --project ../desktop-cn
wujie-shell sync --project ../desktop-cnprepare can install/switch OpenClaw version. sync expects the prepared
runtime version to already match config and only syncs product assets/config
metadata.
Product Runtime Files
Generated files should not be hand-edited:
apps/<product>/.tmp/runtime/**~/<dataDirName>/<openclaw.configFileName>~/<dataDirName>/runtime-state/**~/<dataDirName>/identity/device.json
Update the product config/assets, then run:
./scripts/desktop.sh --sync-onlyor restart:
./scripts/desktop.sh