Skip to content

Process runtime

Every example elsewhere in these guides assumes runtime: "node" — a JavaScript module the app’s plugin host loads and calls directly. runtime: "process" is for a plugin that is its own executable instead: written in any language, run as its own OS process, and called over a process transport rather than an in-process function call. Reach for it when the logic you’re wrapping already exists as a standalone program, or when you’d rather write it in something other than JavaScript.

{
"runtime": "process",
"command": "./bin/my-plugin",
"args": ["--mode", "server"],
"contributes": {
"tools": [
{ "id": "do_thing", "title": "Do thing", "description": "", "schema": "./tools/do-thing.schema.json" }
]
}
}
  • command is required, must be relative to the plugin’s install directory, and must not contain .. — no absolute path on either OS, so the manifest stays portable across machines.
  • args[] is passed to the executable at launch.
  • A tool entry carries no handler — the tool is invoked by its own id over the process transport instead of a JavaScript function reference.

A process plugin does its own I/O and process management, so several node-only mechanisms are rejected outright when runtime is "process":

  • non-empty contributes.hooks
  • non-empty contributes.views
  • contributes.settings[*] of type: "action"
  • sandbox
  • a static permissions.fs.read / fs.write rule without "parameter": true

That last one is worth understanding, not just memorizing: a process plugin never receives the ctx.fs proxy that enforces a static rule — it does its own OS-level file I/O, outside ctx entirely. A static fs.read/fs.write rule would have nothing enforcing it and would silently do nothing, so the loader rejects it up front. Use "parameter": true instead, which is checked at dispatch time against the call’s own arguments rather than through ctx.fs.

  • Manifest reference — the full runtime: "process" rule set
  • Tools — the parts of a tool declaration shared by both runtimes