本文へ移動
cccskills
無料GitHub で公開

computer-use

Control local desktop applications through Computer Use for tasks that require reading or operating app UI. Prefer purpose-built connectors, APIs, or CLIs when available.

インストール方法を見る

含まれるファイル(3)

  • SKILL.md14.0 KB
  • agents/openai.yaml214 B
  • SKILL.test.ts5.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

node_repl + @qwen-code/cua-sdk (Computer Use)

  • Use node_repl (JavaScript) for all Computer Use actions.
  • If both servers are available, use node_repl from the desktop-node-repl MCP server; the regular server runs on the Qwen Code host.
  • Do not use other technologies besides node_repl for computer interactions, unless specifically requested by the user (e.g. AppleScript, osascript, JXA, System Events, synthesized input).
  • Prefer a dedicated plugin or skill when it can complete the task; use Computer Use for app interactions that are not exposed through a more specific interface.
  • node_repl state is persistent across calls.
  • For text output, use nodeRepl.write(...). It takes a string; use JSON.stringify(...) only for textual metadata. For an observation, write its .text and emit its screenshots as images; do not stringify an observation or driver result containing image bytes.
  • Omit yield_time_ms for ordinary UI calls to use the default 10-second wait. A shorter yield does not speed up the action and can add a node_repl_wait round. Use a shorter yield only when you need control back before completion; if a cell is still running, collect its result with node_repl_wait before issuing dependent actions.

Forwarding results in Codex code mode

When calling node_repl through tools.* inside Codex's outer functions.exec, forward each returned content block by its type. nodeRepl.emitImage(...) produces an MCP image block; the outer script must pass that block to image() for the model to receive an image. Prefer the desktop relay tool when it is present; otherwise use the regular node-repl server:

// A code-mode `tools` object throws on an unknown key, so probe with `in`:
// reading an unbound tool would abort the script before any fallback ran.
const DESKTOP_NODE_REPL = 'mcp__desktop_node_repl__node_repl';
const nodeReplTool =
  DESKTOP_NODE_REPL in tools
    ? tools[DESKTOP_NODE_REPL]
    : tools.mcp__node_repl__node_repl;
const result = await nodeReplTool({ code });
for (const block of result.content ?? []) {
  if (block.type === 'text') {
    text(block.text);
  } else if (block.type === 'image') {
    image(block);
  }
}

Here code is the JavaScript to run in the persistent Node REPL. Keep the forwarding loop in the outer code-mode script, outside that code string. Apply the same loop to node_repl_wait results: images may arrive only when a running cell completes. Forward text blocks too, including running-cell IDs and errors. Direct MCP tool calls do not need this outer forwarding loop.

Do not use text(result), text(block), or JSON.stringify(result) to forward an MCP result containing images: this turns image base64 into text, consuming context without showing the image. image() accepts one image block, not the whole result, so do not use image(result) either.

Bootstrap

If desktop-node-repl is connected, skip the installation commands below: it already provides node_repl and the SDK on the connected computer. Continue with the computer initialization below. Otherwise, if node_repl is unavailable, run:

qwen mcp add --scope user node-repl npx -y @qwen-code/node-repl-mcp@0.1.7
npm install --no-save --package-lock=false @qwen-code/cua-sdk@0.20.11

Tell the user to restart Qwen Code, then stop. If only the SDK import is missing, run the second command and retry.

Reuse an existing computer connected to the intended desktop. Otherwise import once per fresh node_repl session. The same App workflow below applies to macOS, Linux and Windows; no additional platform resource is needed:

globalThis.computer = await (
  await import('@qwen-code/cua-sdk/computer-use')
).ComputerUse.create();
var platform = await computer.getPlatform();
nodeRepl.write(`Connected platform: ${platform}`);

Use the connected platform for shortcuts, not the CLI or Node host operating system. When the task identifies an app, combine initialization with computer.getApp() and its first getState() in the same call. Read that state before editing or input.

API surface

type Point = number | { x: number; y: number };
type ComputerUse = {
  getPlatform: () => Promise<'macos' | 'linux' | 'windows'>;
  getApp: (nameOrIdentifierOrPath: string) => Promise<App>;
  listApps: () => Promise<
    Array<{ id: string; displayName: string; isRunning: boolean }>
  >;
  close: () => Promise<void>;
};
type App = {
  getState: (options?: {
    disableDiff?: boolean;
    includeScreenshot?: boolean;
    maxTextChars?: number;
  }) => Promise<State>;
  click: (
    point: Point,
    options?: { button?: 'left' | 'right' | 'middle'; count?: number },
  ) => Promise<object>;
  doubleClick: (point: Point) => Promise<object>;
  rightClick: (
    point: Point,
    options?: { modifier?: string[] },
  ) => Promise<object>;
  setValue: (element: number, value: string) => Promise<object>;
  performSecondaryAction: (element: number, action: string) => Promise<object>;
  typeText: (text: string) => Promise<object>;
  paste: (
    text: string,
    options?: { format?: 'text' | 'md' | 'html'; signal?: AbortSignal },
  ) => Promise<object>;
  selectText: (
    element: number,
    text: string,
    options?: {
      prefix?: string;
      suffix?: string;
      selection?: 'text' | 'cursor_before' | 'cursor_after';
      signal?: AbortSignal;
    },
  ) => Promise<object>;
  pressKey: (
    key: string,
    options?: { modifiers?: string[] },
  ) => Promise<object>;
  hotkey: (keys: string[]) => Promise<object>;
  scroll: (
    point: Point,
    options: { direction: 'up' | 'down' | 'left' | 'right'; amount?: number },
  ) => Promise<object>;
  drag: (options: {
    fromX: number;
    fromY: number;
    toX: number;
    toY: number;
  }) => Promise<object>;
};
type State = {
  app: string;
  window: string;
  mode: 'full' | 'diff' | 'no_change';
  text: string;
  screenshot?: { images: Array<{ mimeType: string; dataBase64: string }> };
};

Workflow

paste and selectText currently require macOS. On Linux/Windows, use the shared typeText, setValue, pressKey and observed actions. Unsupported text methods fail with unsupported_platform; do not retry them as window failures.

1. Initialize

If initialization already bound the task's app and returned its state, reuse that app and observation. Otherwise, bind the app named by the task, then read its state. getApp() binds identity; getState() can open a discovered stopped app. Combine these steps in one Node REPL call:

var app = await computer.getApp('Microsoft Excel');
nodeRepl.write((await app.getState()).text);

The app handle tracks its current window and dialog. Read the returned window title to confirm the intended document. If the app is unknown or its name is ambiguous, discover applications with computer.listApps() and use a matching application id when it distinguishes the app. Two running instances may have the same ID; retrying that ID cannot resolve the ambiguity. Ask the user to keep only the intended instance open rather than guessing a target or retrying it.

AX text uses short numeric IDs, such as [37] TextField "Name". Use IDs from the current observation for element actions. IDs can change when the app's window or session changes. Disabled and static-text rows are observation-only.

For token efficiency, the accessibility tree will be returned as a diff when appropriate. Prefer this default diff output. A full state replaces the previous state; a diff updates it; no-change preserves it. If you need a full replacement, use disableDiff: true only when the previous state is unavailable or no longer useful. Do not disregard the text and then assume that a subsequent diff will reproduce the information you skipped.

Returned text defaults to at most 12,000 characters. Set maxTextChars (minimum 512) to adjust the limit. A truncation notice means some captured rows were omitted; request app.getState({ disableDiff: true, maxTextChars: 24000 }) when you need more full text. An omitted row does not prove an element is absent. Traversal-limited captures cover only the captured nodes: identical captures can return no-change, while changes return full captured state. Use current captured IDs; after a read failure, use only IDs from the latest observation.

2. Actions using app

After performing one or more UI actions, call app.getState() before deciding what to do next. Batch actions whose target remains the same, then print only the state needed for the next decision:

await app.click(37);
await app.hotkey([platform === 'macos' ? 'super' : 'ctrl', 'a']);
await app.typeText('hello');
await app.pressKey('Return');
nodeRepl.write((await app.getState()).text);

Use the actual ID from your observation; 37 is only an example.

An observation is a decision boundary. When the current state already identifies the controls and the next actions are known, combine those actions and saving in the same call. Read state after the batch. End the batch at a new dialog, menu, changed target or uncertain result; use that state before choosing the next action. Do not split a known sequence merely to put each action in its own call.

  • Prefer element IDs to coordinates. setValue(id, value) changes a writable control, and performSecondaryAction(id, action) invokes a secondary action listed for that element. Use an observed action name rather than guessing.
  • When an action opens or closes a dialog, sheet or menu, end the batch and call app.getState() to read the new window and IDs before continuing.
  • No open application window. means the app is still running without a document window. If closing it completed the task, finish instead of retrying actions; otherwise open the intended file or window first.
  • An action error can occur after the UI already changed. Read state before deciding whether to retry. Partial, unconfirmed or cancelled actions must not be blindly repeated.
  • Coordinate actions use pixels in this app's current screenshot, with (0, 0) at its top-left. Every App observation refreshes that frame internally. Request includeScreenshot: true when you need to inspect the image, especially after a window change. Do not infer coordinates from another window or desktop screenshot.
  • pressKey sends one key, optionally with modifiers. hotkey sends a combination such as ['super', 's']. Use the connected platform's appropriate shortcut: macOS generally uses super; Linux/Windows generally use ctrl.
  • App input manages any required activation internally and restores the previous focus, unless the user has moved it elsewhere. If the platform cannot confirm the target or restore focus, the action reports an error. There is no delivery-mode choice and no automatic replay after an uncertain result.
  • On Linux, some compositor sessions cannot confirm an exact App target. An app_window_unavailable result can mean the session does not support this workflow; ask the user to use a supported desktop session instead of retrying input.
  • Literal \n or \r in typeText sends Return. In a composer or form this may submit rather than insert a newline.
  • If AX is incomplete or does not explain the interface, request a screenshot and inspect it. Only currently captured actionable IDs can be used for element actions.

Paste and select text

These App methods are available on macOS only. Read current state first and use an observed element ID for selection.

await app.selectText(37, 'draft', { prefix: 'Status: ' });
nodeRepl.write((await app.getState()).text);

Use a real ID and text from your observation; the example assumes that the selected element contains exactly one matching draft immediately after Status: .

After confirming the selection, replace it with plain text:

await app.paste('ready');
nodeRepl.write((await app.getState()).text);
  • selectText(element, text) selects one exact, case-sensitive match. Optional prefix and suffix must be immediately adjacent to that match. Missing or ambiguous matches fail; provide enough observed context to identify one.
  • selection defaults to 'text'. Use 'cursor_before' or 'cursor_after' to place the insertion point at a match boundary instead of selecting the text. The element must support a writable text selection; static labels may not.
  • paste(text) defaults to plain text. Use { format: 'md' } for Markdown or { format: 'html' } for HTML; the receiving app determines which supplied format it accepts. Use plain text when markup should remain literal.
  • Paste uses the clipboard temporarily. It restores the previous clipboard only while it still owns that transaction; a newer external clipboard change is preserved.
  • Both methods accept an optional signal. A completed dispatch, error or cancellation does not by itself prove what changed. Observe state before deciding whether to retry; do not blindly repeat unconfirmed text operations.

Reading screenshots

Every App observation captures the current screenshot internally, independent of whether AX returns full state, a diff or no-change. The default return omits the image. includeScreenshot: true exposes it when visual inspection is needed. Prefer the text-only default when it identifies the controls and confirms the requested change. Request an image to resolve missing or ambiguous information, choose coordinates or verify an appearance that AX does not describe.

var state = await app.getState({ includeScreenshot: true });
nodeRepl.write(state.text);
for (const image of state.screenshot?.images ?? []) {
  await nodeRepl.emitImage(`data:${image.mimeType};base64,${image.dataBase64}`);
}

Include connection cleanup at the end of the call that emits the final verification. Inspect that result before reporting success; reconnect and continue if it reveals unfinished work. A separate cleanup-only model turn is unnecessary:

await computer.close();
globalThis.computer = undefined;

Reset the Node REPL only when no other persistent state is needed.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Reference for briefing a subagent or a fork — what to put in the prompt, what not to delegate, and a worked example. Load before writing a delegation prompt; the Agent tool's own description carries the launch rules and the background-agent rules.

日本語の概要は準備中です。原文の説明を表示しています。

QwenLM/qwen-code2.8万2026年10月11日 更新

Use after a Codex or Claude Code feature has been implemented in Qwen Code to run the selected reference agent and Qwen Code under the same scenario, capture HTTP and terminal traces, compare request bodies, tool/function schemas, outputs, and iterate until the reproduced behavior is close enough.

日本語の概要は準備中です。原文の説明を表示しています。

QwenLM/qwen-code2.8万2026年10月11日 更新

Use when reproducing an existing Codex or Claude Code feature in Qwen Code or another agent CLI by choosing a reference agent, capturing HTTP request bodies, prompts, tool/function schemas, terminal output, and then implementing the matching behavior in the target repo.

日本語の概要は準備中です。原文の説明を表示しています。

QwenLM/qwen-code2.8万2026年10月11日 更新

autofix

無料

Review and repair current local changes until they converge, or run Qwen Code Autofix issue and review workflows from GitHub Actions.

日本語の概要は準備中です。原文の説明を表示しています。

QwenLM/qwen-code2.8万2026年10月11日 更新

batch

無料

Execute batch operations on multiple files in parallel. Automatically discovers files, splits into chunks, and processes with parallel worker agents. Use `/batch` followed by operation and file pattern. For many independent single-turn transforms (translate/rewrite/extract each file into a new file) that can wait minutes to hours, you may suggest the user type `/batch-api` themselves for the half-price asynchronous Batch API — you cannot invoke it, and it is not suited to in-place edits or tasks needing tool feedback.

日本語の概要は準備中です。原文の説明を表示しています。

QwenLM/qwen-code2.8万2026年10月11日 更新

batch-api

無料

Prepare a many-file, single-turn transform (translate, rewrite, extract) as a plan and submit it to the asynchronous, half-price DashScope Batch API; results are delivered as new files hours later. Invoke explicitly with /batch-api.

日本語の概要は準備中です。原文の説明を表示しています。

QwenLM/qwen-code2.8万2026年10月11日 更新

QwenLM のスキルをすべて見る

このスキルの問題を報告する