System & files

ScriptWeaver reaches the operating system through the global sw object: sw.fs (files), sw.sys (processes, paths, environment), and sw.app (application lifecycle). Dialogs live under sw.dialog, and HTTP is the standard global fetch. The system clipboard is app.clipboard.

Files — sw.fs

Synchronous, text-oriented file operations on the real filesystem — or, with a //zipfs: path, on your packaged app's own bundle (see below). Each throws a JavaScript error on failure, so wrap calls that might fail in try / catch.

sw.fs.writeFile('/tmp/notes.txt', 'hello\nworld');
const text = sw.fs.readFile('/tmp/notes.txt');

if (sw.fs.exists('/tmp/notes.txt')) {
  /* … */
}
Call Returns Notes
readFile(path) string Whole-file contents.
writeFile(path, content) Creates or overwrites.
exists(path) boolean
list(dir) string[] Entry names in dir.
stat(path) object { name, isDir, isFile, size, mtime }.
mkdir(path) Creates the path, including parents.
remove(path) Deletes a file or empty directory.

Reading bundled assets. A path that starts with // (e.g. //zipfs:/app/data.json) reads from your packaged app's bundle, not the real disk — the read operations (readFile, exists, list, stat) understand the virtual filesystem, so an app can load its own data files. writeFile, mkdir, and remove target the real disk only. See Packaging apps.

Processes, paths & environment — sw.sys

Run a program. sw.sys.exec returns a Promise resolving to { stdout, stderr, exitCode }; the options object accepts cwd and env:

sw.sys.exec('git', ['status', '--short'], { cwd: project }).then((r) => {
  console.log(r.stdout, r.exitCode);
});

Open something in its default app — a URL, file, or folder:

sw.sys.open('https://scriptweaver.dev');
sw.sys.open(downloadPath);

Standard locations. sw.sys.paths is an object of OS directories:

sw.sys.paths.home; // user home
sw.sys.paths.config; // per-user config directory
sw.sys.paths.cache; // per-user cache directory
sw.sys.paths.temp; // temporary directory
sw.sys.paths.exe; // the Player executable's path

Environment variables, and a beep:

sw.sys.env.get('EDITOR'); // string, or undefined
sw.sys.env.set('MY_FLAG', '1');
sw.sys.env.has('HOME'); // boolean
sw.sys.beep(); // a system bell

Clipboard — app.clipboard

Read and write the system clipboard via app.clipboard (it lives on the application window, not under sw). Copying is a clear followed by an append — Tk appends to the clipboard rather than replacing it:

// Copy
app.clipboard.clear();
app.clipboard.append('text to copy');

// Paste — the current contents, or '' if empty / not text
const text = app.clipboard.get();
Method Description
clear() Empty the clipboard.
append(data, type?) Append data (optionally a Tk selection type, e.g. STRING).
get(type?) Return the contents, or '' if empty / unavailable.

Archives — sw.zip

Create a .zip archive. sw.zip(outputPath, files) takes an object mapping archive paths to their contents — a string for text, or an ArrayBuffer / typed array for binary:

sw.zip('/tmp/export.zip', {
  'readme.txt': 'Exported by my app\n',
  'data/records.json': JSON.stringify(records, null, 2),
  'logo.png': pngBytes, // an ArrayBuffer / Uint8Array
});

This is for writing archives. To read an asset bundled inside a packaged app, hand its //zipfs:/app/… path to sw.fs.readFile (above) — see Packaging apps.

Application — sw.app

sw.app.quit(); // close the app
sw.app.tclVersion; // e.g. "9.0.3"
sw.app.tkVersion;

sw.app.themes; // every theme name, flat (aliases included)
sw.app.themesByType; // { light: [...], dark: [...] } — engine names only
sw.app.systemDark; // OS prefers dark? true | false | null (unknown)
sw.app.reducedMotion; // get/set: skip widget animations (e.g. StatusBar 'busy')

The theme properties drive runtime theme pickers and the "follow the system theme" startup pattern — see Theming.

Platform — app.windowingSystem / app.platform

Query the host platform when you need to branch on it:

app.windowingSystem; // 'x11' | 'win32' | 'aqua'
app.platform; // { os: 'Linux' | 'Darwin' | 'Windows NT', arch: 'x86_64' | 'arm64' | …, family: 'unix' | 'windows' }

For DPI/density scaling of absolute pixel coordinates use app.scale / app.dp(n) instead — see UI scale.

Help — sw.openHelp / F1

Pressing F1 anywhere opens documentation in its own window, as a separate Player process — so it never blocks or disturbs the running app. The help window opens in your app's current theme (app.theme is passed through), so it matches what the user is looking at. You can also open it yourself, for example from a Help menu:

help.addCommand({ label: 'Documentation', accelerator: 'F1', command: sw.openHelp });

Your app can ship its own manual

If your app bundles a help/ folder (or docs/) with an index.md, F1 opens that — your app's own manual — instead of the ScriptWeaver docs. It works whether your app runs from a .zip bundle or loose from disk (the help folder sits beside your entry script). Write the manual in the same Markdown the viewer renders here; relative links and images resolve against the help folder. Apps that ship no help/ or docs/ fall back to the ScriptWeaver documentation, so F1 always shows something.

help/ is preferred over docs/, so you can keep developer docs in docs/ and the end-user manual your app surfaces on F1 in help/.

You can preview an app's bundled help without launching the app:

scriptweaver --help myapp.zip     # render myapp's help/ (or docs/)
scriptweaver --help ./myapp/      # ... or a project directory
scriptweaver --help               # the ScriptWeaver docs (no target)

Taking over F1

To use F1 for something of your own, replace or clear the global binding:

__native_tcl('bind', 'all', '<F1>', ''); // disable the built-in help key

Next