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, andremovetarget 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
- Packaging apps — ship your app as a
.zip - Dialogs
- Widget reference