{"record":{"id":"7b54b2eaabe21f9d","repo":"Hmbown/CodeWhale","slug":"unsupported-on-transport","errorCode":"unsupported_on_transport","errorMessage":"app_script runs on the local computer only — the ${computer.transport} transport stays a computer-use channel, never a shell","messagePattern":"app_script runs on the local computer only — the (.+?) transport stays a computer-use channel, never a shell","errorType":"error_code","errorClass":"ServerError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/mcp/server.mjs","lineNumber":912,"sourceCode":"      const focused = await callTool({ name: \"focus\", arguments: { target: args.target, computer: computer.id } });\n      const focusBody = JSON.parse(focused.content[0].text);\n      // For a chord the element's window is what matters — key equivalents\n      // dispatch at window level, so a focus refusal must not block delivery.\n      // Text is different: characters go to the first responder, so a field\n      // that could not be focused cannot receive the string either.\n      if (name === \"type\" && (focused.isError || focusBody.ok === false)) {\n        return { content: [{ type: \"text\", text: JSON.stringify(fail(computer, focusBody.error?.code ?? \"focus_failed\", focusBody.error?.message ?? \"element could not be focused\", { tool: name, stage: \"focus\" })) }], isError: true };\n      }\n      args = { ...args };\n    }\n    // Out-of-process runners (the desktop app for the local computer, the\n    // remote agent for ssh computers) get the request over the wire.\n    const backendMethod = BACKEND_METHOD[name];\n    // Scripting is honored on the local computer only. Remote agents refuse\n    // it too (their handler gates computerId), so a remote channel can never\n    // be steered into a shell — fail here first to save the hop.\n    if (name === \"app_script\" && computer.transport !== \"local\") {\n      throw new ServerError(\"unsupported_on_transport\", `app_script runs on the local computer only — the ${computer.transport} transport stays a computer-use channel, never a shell`);\n    }\n    let data;\n    const ex = computer.transport === \"local\" || computer.transport === \"ssh\" || computer.transport === \"docker\" ? await executorFor(computer, binding) : null;\n    if (ex?.kind === \"app\") binding.usedApp = true;\n    // Zoom needs the bound parent raster up front (server-side check too, not\n    // only the backend) so it can bind the child raster after success.\n    let zoomParent = null;\n    if (name === \"zoom\") {\n      zoomParent = lastRasters.get(computer.id);\n      if (!zoomParent) throw new ServerError(\"no_raster\", \"no screenshot bound on this computer yet — call screenshot first so zoom has a source raster\");\n      if (!Array.isArray(args.region) || args.region.length !== 4) throw new ServerError(\"bad_args\", \"zoom needs region [x, y, w, h] in last-raster pixels\");\n    }\n    const sink = { reacquired: false };\n\n    if (typeof ex?.remote === \"function\" && REMOTE_TOOLS.has(backendMethod)) {\n      // ssh rides the persistent agent channel when the remote supports\n      // --serve; a channel that never produced a reply means an old agent,\n      // so fall back to one-shot for that binding rather than failing.","sourceCodeStart":894,"sourceCodeEnd":930,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/mcp/server.mjs#L894-L930","documentation":"app_script executes local application scripting and is deliberately restricted to computers with the local transport. On ssh/docker (or any remote transport) the server refuses before dispatching, so a remote computer-use channel can never be used as a shell. Remote agents enforce the same gate, so there is no hop that would honor it.","triggerScenarios":"Calling app_script while the bound computer's transport is not \"local\" — e.g. an ssh or docker computer where the tool was expected to run commands remotely.","commonSituations":"Using computer-use against an ssh machine and trying to run scripts; assuming app_script is a general remote-execution tool; environments where only remote computers are configured.","solutions":["Run app_script against a computer whose transport is \"local\"","For remote machines use the proper remote tools (screenshot, type, key, etc.) instead of scripting","If you need remote shell access, use a dedicated SSH/shell mechanism, not the computer-use channel","Add/configure a local computer entry if local scripting is genuinely required"],"exampleFix":"// before\nawait appScript({ computer: \"ssh-box\", script: \"ls\" })\n// after\nawait appScript({ computer: \"local\", script: \"ls\" })","handlingStrategy":"validation","validationCode":"if (computer.transport !== \"local\") throw new Error(\"app_script is local-only; use remote computer-use tools for this transport\");","typeGuard":"const isLocal = (c) => c?.transport === \"local\";","tryCatchPattern":"try { await appScript({ computer, script }) } catch (e) { if (e.code === \"unsupported_on_transport\") { /* fall back to remote tools or select a local computer */ } else throw e; }","preventionTips":["Gate scripting features on computer.transport === \"local\" in your tool-selection logic","Never treat computer-use channels as remote shells","Document per-transport tool availability in automation plans"],"tags":["mcp","computer-use","security","transport"],"backgroundTag":"operation-not-supported","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}