# Cloud Skill Sync And Execution Flow

Updated: 2026-03-26

## 1. Purpose

This document describes the current real implementation of the cloud skill chain in QianjiangClaw.

It covers:

- how desktop pulls skills from cloud
- where skills are stored locally
- how UI reads skill state
- how chat uses a selected skill
- what runtime mode is required
- what is currently implemented vs. what is still a limitation

This document should be treated as the source of truth for the current code path, not the older planning docs.

## 2. High-Level Summary

Current behavior is:

1. Desktop starts.
2. Electron Main fetches `openclaw-employee-config` from cloud.
3. Returned `skills` are downloaded to local disk under `userData/skills`.
4. Main process writes a local `manifest.json`.
5. UI reads skill availability from that local manifest-derived summary.
6. When the user selects a skill in chat, Main resolves the local file by `skillId`.
7. Main materializes that skill into the OpenClaw runtime's actual skill directory as a temporary `qjclaw-cloud-*` skill.
8. Main rewrites the outgoing prompt so OpenClaw is instructed to use that installed local skill.
9. OpenClaw runtime discovers and reads the materialized local skill and executes it.

Important:

- Cloud skill execution is currently supported only in `bundled-runtime` mode.
- `external-gateway` mode cannot safely assume access to the same local disk, so Main rejects local skill execution in that mode.

## 3. Main Components

### 3.1 Cloud config client

File:

- `apps/desktop/src/main/services/cloud-api.ts`

Responsibilities:

- fetch `openclaw-employee-config`
- validate payload
- keep runtime cloud status cache
- expose remote skill asset metadata
- notify listeners when payload changes

Relevant behavior:

- startup fetch uses `init`
- background sync uses `sync`
- payload updates trigger downstream local skill reconcile

### 3.2 Local skill store

File:

- `apps/desktop/src/main/services/skill-store.ts`

Responsibilities:

- persist downloaded cloud skills under local user data
- maintain `manifest.json`
- expose workspace skill summaries to UI
- expose execution target lookup by `skillId`

Local storage layout:

- `userData/skills/manifest.json`
- `userData/skills/<skillId>/<file_name>`

Manifest tracks:

- `skillId`
- `bindingId`
- `name`
- `description`
- `category`
- `fileName`
- `fileSize`
- `downloadUrl`
- `localPath`
- `downloadState`
- `lastSyncedAt`
- `lastDownloadedAt`
- `lastError`
- `remoteConfigVersion`

Current states:

- `pending`
- `downloading`
- `ready`
- `failed`
- `removed`

### 3.3 Runtime skill bridge

File:

- `apps/desktop/src/main/services/runtime-skill-bridge.ts`

Responsibilities:

- resolve the local downloaded skill file selected by the user
- materialize it as an OpenClaw-readable runtime skill
- assign a runtime skill name like `qjclaw-cloud-*`
- rewrite `SKILL.md` frontmatter `name:` to match that runtime skill name
- clean up old temporary cloud skills

Important implementation detail:

The runtime bridge does not execute directly from `userData/skills/...`.

Instead it:

1. reads the downloaded local skill file from `userData/skills/...`
2. finds the real OpenClaw skill root by reading `vendor/openclaw-runtime/runtime-manifest.json`
3. resolves `sourceOpenClawEntry`
4. writes the temporary runtime skill into the real OpenClaw skill directory next to that entry

This is required because current OpenClaw runtime resolves skills from its own actual installed skill directory, not from `OPENCLAW_HOME/skills`.

### 3.4 IPC chat integration

File:

- `apps/desktop/src/main/ipc.ts`

Responsibilities:

- build workspace summary for renderer
- resolve execution policy
- prepare prompt for gateway
- clear temporary runtime skills when no skill is selected
- reject local skill execution in `external-gateway`

Prompt flow:

- no skill selected:
  - clear temporary `qjclaw-cloud-*` skills
  - send original prompt
- skill selected:
  - ensure runtime mode is `bundled-runtime`
  - resolve local downloaded skill
  - materialize runtime skill
  - rewrite prompt to explicitly instruct OpenClaw to use the installed runtime skill
  - send rewritten prompt to gateway

## 4. End-To-End Data Flow

### 4.1 Sync flow

1. App bootstraps Main services in `apps/desktop/src/main/index.ts`.
2. `OpenClawConfigClient.fetchConfig("init")` fetches runtime cloud config.
3. `runtimeCloudClient.onPayloadUpdated(...)` fires.
4. `skillStore.reconcile(skills, configVersion)` compares remote skills and local manifest.
5. New or changed skills are downloaded to `userData/skills/...`.
6. `manifest.json` is rewritten.
7. Renderer reads `workspace.getSummary()` and `skills.list()` from manifest-derived summaries.

### 4.2 Chat execution flow

1. Renderer sends `chat.streamPrompt(sessionId, prompt, skillId?)`.
2. Main checks `skillId`.
3. If present:
   - find local skill file via `skillStore.getExecutionTarget(skillId)`
   - materialize it into OpenClaw skill root as `qjclaw-cloud-*`
   - rewrite prompt to require that installed skill
4. Gateway receives the rewritten prompt.
5. OpenClaw runtime reads the installed local skill file and executes its own skill logic.

## 5. Timing And Sync Policy

Current actual sync policy:

- app startup: one `init` fetch
- runtime running in `bundled-runtime` mode: periodic `sync`
- current default background config sync interval: 4 hours

Implementation:

- `apps/desktop/src/main/services/runtime-cloud-supervisor.ts`

Current default:

- `DEFAULT_CONFIG_SYNC_INTERVAL_MS = 4 * 60 * 60 * 1000`

Notes:

- this is not a daily 6:00 task
- if the app is not running, no sync runs
- the interval can still be overridden by environment variable:
  - `QJCLAW_RUNTIME_CLOUD_CONFIG_SYNC_INTERVAL_MS`

## 6. UI Behavior

File:

- `apps/ui/src/App.tsx`

Current renderer behavior:

- skill list comes from workspace summary
- only `ready === true` skills are selectable in chat
- skill page can show non-ready states
- default chat means no cloud skill selected

This means UI is already driven by local readiness, not by raw cloud payload.

## 7. Runtime Modes

### 7.1 Bundled runtime

Supported for cloud skill execution.

Reason:

- Electron Main, local downloaded files, and OpenClaw runtime are all on the same machine
- Main can materialize the runtime skill into the actual OpenClaw skill root

### 7.2 External gateway

Not supported for local cloud skill execution.

Reason:

- external gateway may be remote or otherwise not share the same local disk
- Main cannot guarantee the external gateway can read the local skill file

Current behavior:

- Main throws an explicit error when a selected cloud skill is used under `external-gateway`

## 8. Cleanup Behavior

Current cleanup logic exists to avoid stale temporary runtime skills:

- startup cleanup
- no-skill-selected cleanup
- app before-quit cleanup

What gets cleaned:

- only temporary `qjclaw-cloud-*` skill directories

What does not get cleaned:

- downloaded source files under `userData/skills/...`
- manifest entries

This separation is intentional:

- `userData/skills/...` is the persistent cache
- `qjclaw-cloud-*` runtime skills are ephemeral execution projections

## 9. Real Verified Behavior

Verified with a real employee `api_key`:

- cloud config fetch succeeded
- remote skills were downloaded to local disk
- manifest was updated correctly
- selected cloud skill was materialized into OpenClaw's real skill root
- OpenClaw could discover and read the materialized skill
- renderer streaming worked for at least one real skill end-to-end

Observed limitation from real testing:

- some cloud skills have external prerequisites of their own
  - example: `tmux`, `ralphy`, ACP runtime
  - example: browser automation and login requirements
- in those cases the chain from desktop to runtime skill is working, but the skill's own runtime workflow may still fail or hang based on environment

This is a skill-content/runtime-environment problem, not a cloud-download-chain problem.

## 10. Current Limitations

### 10.1 Prompt rewrite instead of protocol-level skill execution

Current implementation does not send a dedicated `skillPath` or `skillId` execution contract through gateway protocol.

Instead it relies on:

- materializing a runtime skill locally
- rewriting prompt to instruct OpenClaw to use it

This works today, but it is not the cleanest long-term contract.

### 10.2 OpenClaw skill discovery path is external to QianjiangClaw-managed userData

Current runtime bridge has to project skills into the OpenClaw skill root derived from `runtime-manifest.json`.

That means:

- execution currently depends on how bundled OpenClaw resolves its skill directory
- changes in upstream OpenClaw skill resolution may require bridge updates

### 10.3 Skill prerequisites are not preflight-validated

Current desktop chain does not yet perform a formal preflight for skill-specific dependencies.

Examples:

- `tmux`
- `ralphy`
- ACP runtime backend
- browser automation login state

Recommended future improvement:

- add preflight validation and fast-fail reporting for skills with known dependencies

## 11. Recommended Future Work

### 11.1 Add protocol-level skill execution contract

Possible direction:

- extend gateway/chat protocol with explicit selected skill metadata
- allow runtime to resolve local skill execution through a structured contract instead of prompt rewriting

### 11.2 Add skill preflight checks

For example:

- dependency availability
- browser automation availability
- login-required capabilities
- ACP runtime availability

### 11.3 Add dedicated smoke coverage

Recommended smoke layers:

- cloud config fetch smoke
- local download + manifest smoke
- runtime materialization smoke
- end-to-end execution smoke for a simple non-interactive skill

## 12. Key Files

Core files for future development:

- `apps/desktop/src/main/index.ts`
- `apps/desktop/src/main/ipc.ts`
- `apps/desktop/src/main/services/cloud-api.ts`
- `apps/desktop/src/main/services/skill-store.ts`
- `apps/desktop/src/main/services/skill-client.ts`
- `apps/desktop/src/main/services/runtime-skill-bridge.ts`
- `apps/desktop/src/main/services/runtime-cloud-supervisor.ts`
- `apps/ui/src/App.tsx`
- `packages/shared-types/src/index.ts`

## 13. One-Sentence Mental Model

Cloud returns skill metadata and download URLs, desktop downloads the skill to local cache, chat selection causes Main to project that cached file into OpenClaw's real skill directory, and bundled runtime then executes that local projected skill.
