Capabilities
JavaScript APIs, remote files and processes, HTTP/TCP, cloud browser methods, and client permissions.
JavaScript environment
Task code runs as an ES module with top-level await and dynamic import(). Submit JavaScript source and use the exact built-in module names lexmount:remote and lexmount:browser. npm package resolution, CommonJS, Node.js built-ins, and application TypeScript transpilation are unavailable. Editor type completion does not enable TypeScript submissions.
| Capability | Common APIs |
|---|---|
| HTTP requests and responses | fetch, Request, Response, Headers, FormData, Blob, File |
| URL handling | URL, URLSearchParams, URLPattern |
| Bytes, encoding, and streams | TextEncoder, TextDecoder, ReadableStream, WritableStream, TransformStream, CompressionStream |
| Async work and cancellation | setTimeout, setInterval, queueMicrotask, AbortController, AbortSignal |
| Other Web APIs | crypto / WebCrypto, WebSocket client, structuredClone, atob / btoa, basic event types |
| Logs and arguments | console.log/info/warn/error/debug; jsd.args is empty in task mode |
Global fetch makes HTTP(S) requests from the cloud runtime and only allows public targets. DNS resolution and redirects follow the same restriction. Use host.fetch below for services on a client's local machine or private network; those requests originate from the selected client.
A task completes when all active resources finish. HTTP services, timers, and network work can keep execution active; an isolated, unawaited Promise does not keep it alive. Each new execution uses a fresh JavaScript environment without global variables from earlier runs.
Remote clients
import { getRemoteHosts, remoteHosts } from 'lexmount:remote';
const hosts = await getRemoteHosts();
console.log(hosts);
const info = hosts.find((item) => item.id === '<client-id>');
if (!info) throw new Error('Client is offline or unavailable');
const host = remoteHosts[info.id];
console.log(host.id);getRemoteHosts() returns online host information and refreshes the readonly remoteHosts map. Host information includes id, os, osVersion, hostname, uptimeSeconds, cpuModel, totalMemoryBytes, and totalDiskBytes; unavailable fields are null. The initial module import can also query hosts and fail. To catch an import failure, use dynamic import inside try/catch.
The methods below are asynchronous, with streams and iterators read on demand. Start the native client first and replace <client-id> with a client ID belonging to the current user.
File system
| Method | Result and purpose |
|---|---|
host.fs.readFile(path) | Promise<Uint8Array> containing the complete file |
host.fs.readTextFile(path) | Promise<string> decoded as UTF-8 |
host.fs.readDir(path) | AsyncIterableIterator<DirEntry> for directory entries |
host.fs.stat(path) | File type, byte size, and mtime / atime / birthtime (Date or null) |
host.fs.writeFile(path, bytes, options?) | Write a Uint8Array |
host.fs.writeTextFile(path, text, options?) | Write UTF-8 text |
host.fs.mkdir(path, { recursive? }) | Create a directory; nonrecursive by default |
host.fs.remove(path, { recursive? }) | Remove a file or directory; nonrecursive by default |
Paths use the client's native operating system syntax. Relative paths start at the client's startup directory. Directory entries expose name, isFile, isDirectory, and isSymlink; leaving for await closes its cursor. Write options default to { create: true, append: false } and do not create parent directories. Failed chunked writes do not roll back existing changes. Whole-file reads and writes require sufficient memory.
HTTP requests
host.fetch(input, options?) requests a URL from the client and returns a native Response with status, headers, text(), json(), and a streaming body.
| Option | Behavior |
|---|---|
method | Defaults to GET; GET / HEAD cannot carry a body |
headers | HeadersInit, including a header object or Headers |
body | string, Uint8Array, ArrayBuffer, or null; no FormData or upload stream |
signal | AbortSignal for request and response-read cancellation |
redirect | follow (default), manual, or error |
All client-reachable HTTP(S) origins are allowed, including local and private services. There is no separate fetch permission switch. HTTP 4xx / 5xx responses resolve normally; check response.ok. Network failures throw errors. Consume or cancel response bodies to release remote resources. Cross-origin redirects remove sensitive headers such as authentication and cookies; no Cookie Jar is maintained automatically.
Processes
| Method | Result and purpose |
|---|---|
host.process.list() | PID-sorted process snapshot iterator; leaving iteration releases it |
host.process.get(pid) | ProcessInfo or null |
host.process.exec(command) | Run a shell command, send stdin EOF, and return exit status and complete stdout / stderr bytes |
host.process.spawn(command) | Child process with stdin / stdout / stderr streams, a status Promise, and kill() |
ProcessInfo contains PID, parent PID, name, executable path, command line, status, start time, CPU usage, and memory bytes. Unavailable fields are null. A nonzero exit from exec() is returned as exitCode and does not throw automatically.
Commands inherit the client's working directory, environment, and OS user permissions. Linux / macOS uses /bin/sh -c; Windows uses cmd.exe /d /s /c. Match command syntax to the target system. With spawn(), consume stdout and stderr concurrently and close the stdin writer to send EOF. Waiting only for status can block if output pipes fill.
TCP
| Method or object | Purpose |
|---|---|
host.tcp.connect({ hostname?, port }) | Connect from the client; default host 127.0.0.1, port 1–65535 |
host.tcp.listen({ hostname?, port? }) | Listen on the client; default 127.0.0.1:0, with port 0 allocating a free port |
| TcpConnection | localAddr, remoteAddr, readable / writable byte streams, closed, and close() |
| TcpListener | addr, accept(), async iteration, finished, and close() |
Closing a connection's writable stream sends write EOF only. close() closes the entire connection; canceling readable also closes the entire connection. A listener supports one pending accept at a time. Closing a listener leaves accepted connections independent; leaving listener iteration closes the listener.
Client HTTP services
host.http.serve({ hostname?, port?, fetch(request) }) listens for plain HTTP/1.1 on the client. The default address is 127.0.0.1:8080; port 0 allocates a free port. The handler executes in the cloud JavaScript environment, receives a Request, and returns a Response.
The result exposes addr, finished, and shutdown(). Shutdown stops acceptance and waits for existing responses to finish. Do not await a server's shutdown from the request it is draining. This method does not publish a task URL; use a default-export HTTP entry to publish one.
Client permissions
On Clients, select Configure, adjust the switches, and select Save. Defaults on first connection are:
{
"fs": { "enabled": true, "allow_write": false },
"process": { "enabled": true, "allow_exec": true },
"tcp": { "enabled": true },
"http_server": { "enabled": true }
}fs.enabled enables file reads; writes also require allow_write. process.enabled enables process queries; execution also requires allow_exec. Setting fs.allow_write=false only restricts the file API: permitted shell commands can still modify files. Reads follow OS user permissions without an additional path allowlist. tcp.enabled and http_server.enabled control TCP and HTTP listening respectively.
Configuration is scoped to the user and client ID, shared across projects. Offline saves synchronize on reconnection. Use the client-confirmed revision to determine whether settings were applied. Changes affect subsequent operations; started operations continue, and closing and cleanup remain permitted.
Cloud browsers
import browser from 'lexmount:browser';
const session = await browser.create({ browserMode: 'normal' });
try {
const page = await session.openUrl('https://example.com');
console.log(page.title);
} finally {
await session.destroy();
}Browser identity comes from the current task submission; scripts do not supply API keys. Parameters use camelCase, while returned session metadata uses snake_case and omits credentials and CDP URLs.
| Management method | Purpose |
|---|---|
browser.create(options?) | Create a session and wait until ready; return BrowserSession |
browser.get(sessionId, { regionId?, timeoutMs? }) | Attach to an existing session without automatic destruction ownership |
browser.list({ status?, regionId?, timeoutMs? }) | List sessions, with status active or closed |
browser.destroy(sessionId, options?) | Close a specified session |
Create options include browserMode (normal / light), regionId, contextId, contextMode (read_write / read_only), contextDescription, weakLock, officialProxy, localProxyTunnelId, customImageId, windowSize, downloads, recording, extensionIds, and timeoutMs. Availability depends on project entitlements and browser mode. Moli does not support persistent replay.
| Session method | Purpose and result |
|---|---|
getInfo(options?) | Session status and metadata |
targets(options?) | Targets with id, type, title, and url |
keepalive({ intervalMs?, durationMs?, stopOnInactive?, timeoutMs? }) | Periodic checks, returning check count and snapshots |
destroy(options?) | Wait for confirmed closure |
openUrl(url, options?) | Navigate; return navigation, url, and title |
eval(expression, options?) | Evaluate a page expression; return JSON |
waitSelector(selector, options?) | Wait for a selector match |
waitText(text, options?) | Wait for a text condition; return timed_out: true if unmet |
click(selector, options?) | Click an element |
fill(selector, value, options?) | Fill an input |
screenshot({ fullPage?, targetId?, timeoutMs? }) | PNG bytes as Uint8Array |
pdf({ printBackground?, targetId?, timeoutMs? }) | PDF bytes as Uint8Array |
snapshot(options?) | Page snapshot JSON |
raw(method, params?, options?) | Call a lower-level browser method; return JSON |
Pass targetId to keep page operations on a specific target. Otherwise, the first page is selected, or a blank page is created if none exists. waitText also accepts selector, state (present / absent), exact, caseSensitive, includeHidden, and pollMs.
Time parameters use milliseconds; timeoutMs is an integer from 1 to 86400000. Default timeouts are 600000ms for creation, 30000ms for page actions, and 180000ms for confirmed destruction. Cleanup attempts to reclaim sessions created by the task, but explicit destruction in try/finally is recommended. Arrange closure yourself for existing sessions attached with get().
Errors and type declarations
Remote and browser errors are Error objects with name and code, such as RemoteFsError, RemoteFetchError, and BrowserError. These names are not exported constructors; inspect error.code. Network loss, permission changes, and offline clients can cause remote calls to fail.
The declarations loaded by the editor are also available for local development: jsd.d.ts, remote.d.ts, and browser.d.ts. Keep all three in one directory and reference jsd.d.ts. They use TypeScript WebWorker types for completion; actual runtime support follows this page and the runtime implementation.
