Skip to content

Limits & FAQ ​

Compilation ​

  • Every app is bundled by the in-browser compiler, which supports Node built-ins in tiers (the node: prefix works the same way):
    • Browser polyfills that work normally: process / events / util / stream / url / querystring / assert / string_decoder and similar
    • Local implementations: path, buffer and timers are fully usable; crypto covers part of the API (Web Crypto, randomBytes, pbkdf2, and createHash for md5 / sha1 / sha224 / sha256 — no scrypt); zlib supports async gzip / deflate only (*Sync, Brotli and stream APIs throw when called); fs / fs/promises support async APIs only and work only in temporary terminal run scripts — in app source the calls are rejected with WORKSPACE_LEASE_REQUIRED
    • Importable, but every call throws (with an [lf-node-shim] prefix): http / https / net / tls / dns / os / readline / tty and similar
    • Compile errors: child_process / cluster / worker_threads / vm / v8 / inspector / module / repl
  • Use standard ESM import for local modules. @require only accepts built-in ids; a local file (e.g. // @require ./lib.js) fails the compile
  • The plugin build reads @require from the entry file only: built-in libraries used by components or utility files must be declared in the entry too. A @require in a non-entry file's header only applies when that file is run directly from the terminal (the editor shows a Warning)
  • Import Vue normally (import { createApp } from "vue"); it is no longer a built-in runtime alias

Runtime ​

  • LFHttp rejects only the local PluginX client port (41720 on any loopback form), chrome-extension://, file://, and non-http(s) targets, and re-checks the final address after redirects. Only the literal hostname is checked. The local client is reachable only through LFHttp.client. The target domain's existing cookies are attached by default; you can also set headers.Cookie explicitly (it replaces the browser's cookies entirely). Browser-reserved headers such as Referer / User-Agent are written at the network layer — see headerOverrides on the response
  • LFNetwork is available in saved bundles, the liveDebug USER_SCRIPT path, and run --tab MAIN-world scripts (via the network relay bridge); using it directly requires an explicit // @require network (@require dom is not enough)
  • LFRuntime.readFile / writeFile / execTerminalCommand can only be called directly from temporary terminal run scripts (run / run -c / run --tab / run --target background). In app source (liveDebug, enabled / installed, background apps) a direct call fails the compile: register a command with LFRuntime.cli.register({ workspace: ['read' | 'write' | 'exec'] }) and use ctx.workspace.readFile / writeFile / exec in its handler. The lease only lasts for that plugincmd call
  • Local command execution, local file access and CLI registry requests are accepted only from the PluginX editor page; when an app (page-injected, background, or USER_SCRIPT world) sends these extension messages directly they are rejected with EACCES_PERMISSION
  • LFStore stores values as JSON: a value containing a Map / Set / function / Symbol / BigInt / circular reference makes set throw with the offending path (e.g. at value.cache); convert it to plain JSON data first
  • Intercepting page requests with LFRuntime.network.onResponse / interceptRequest / interceptResponse requires an @intercept declaration in the entry header; without it "Compile" fails (liveDebug and run --tab skip this check)

IDE ​

  • Saving (Ctrl+S) only stores the sources; clicking "Compile" (which saves first) compiles and updates the registered artifact. Until you compile, enabled apps and reloaded pages keep running the previous build
  • Create files/folders from the file-tree header, rename or delete from the context menu, or use mv / rm in the terminal; renaming or moving the entry file keeps the entry setting in sync
  • First-time npm dependency compiles download from the network; later ones hit the IndexedDB cache (see "System Info")
  • liveDebug keys page lifecycle to the browser documentId: SPA modals and history.pushState URL changes that retain the document do not reinject or unregister CLI commands. Only a full navigation/reload with a new document destroys the old USER_SCRIPT and interrupts in-flight plugincmd calls; registrations recover automatically after load, while the interrupted call must be retried after injectionHealthy: true
  • If named USER_SCRIPT-world messaging configuration fails, liveDebug retries three times and then stops before injection instead of running a partial instance without LFStore/LFUser/LFNetwork/CLI support. Run liveDebug reload after the environment recovers

Permissions ​

Installed apps only run once the browser grants the extension userScripts capability (the "Allow User Scripts" switch or Developer mode). Until then the app manager shows a guidance banner — follow it, then click "Re-check Permission".