FileAccess
Sandboxed file I/O restricted to a single directory (typically workspace/data/). Allows scripts and AI to read and write files without exposing the full filesystem.
Safety gate
This driver ships with requiresSafetyGates: false — FileAccess operations bypass the safety gate entirely and no audit rows are written. Workspace-state write-locking (Sandbox mode / EULA) still applies. See Per-driver opt-out.
Properties
| Property | Type | Access | Unit | Description |
|---|---|---|---|---|
basePath | string | R | Resolved absolute base path | |
fileCount | int | R | Total number of files (recursive) | |
totalSizeBytes | int | R | bytes | Total size of all files |
exists | bool | R | Whether the base directory exists |
Actions
| Action | Args | Description |
|---|---|---|
listFiles | { path? } | List files in a directory (default: root) |
listDirs | { path? } | List subdirectories |
readText | { path } | Read a text file |
writeText | { path, content } | Write text to a file (creates parent dirs) |
appendText | { path, content } | Append text to a file |
readBinary | { path } | Read a binary file as base64 |
writeBinary | { path, content } | Write base64-decoded bytes to a file |
deleteFile | { path } | Delete a file |
rename | { from, to } | Rename or move a file within the sandbox |
fileInfo | { path } | Get file metadata (name, size, created, modified, extension) |
mkdir | { path } | Create a directory (recursive) |
deleteDir | { path } | Delete an empty directory |
file | { path } | Returns a path-bound file handle (use this in scripts) |
Config Options
| Option | Type | Default | Description |
|---|---|---|---|
basePath | string | — | Required. Root directory for all file operations |
maxFileSizeMB | int | 10 | Maximum file size in MB for read/write |
createIfMissing | bool | true | Create base directory if it doesn't exist |
File Handles
Calling c.file(path) returns a handle bound to a single path, so the rest of your script doesn't have to repeat it. This is the recommended way to write data files from scripts:
const fa = connector("fileaccess");
const log = fa.file("runs/temps.csv");
log.write("t,T\n"); // overwrite (creates parent dirs)
for (let t = 0; t < 10; t++) {
log.append(`${t},${dut.temperature}\n`);
delay(1000);
}
log.size; // bytes (0 if missing)
log.exists; // bool
log.info(); // { name, size, created, modified, extension }
log.read(); // full text
log.rename("runs/done.csv"); // updates the handle in place
log.delete();| Member | Kind | Description |
|---|---|---|
path | property | The sandbox-relative path (forward-slashed) |
exists | property | true if the file exists |
size | property | File size in bytes (0 if missing) |
read() | method | Read as UTF-8 text |
write(content) | method | Overwrite with text (creates parent dirs) |
append(content) | method | Append text |
readBinary() | method | Read as base64 |
writeBinary(base64) | method | Overwrite with base64-decoded bytes |
delete() | method | Remove the file |
rename(newPath) | method | Rename / move within the sandbox; updates the handle |
info() | method | { name, size, created, modified, extension } |
Handles obey the same sandbox boundary, size limits (maxFileSizeMB), and workspace.file.changed notifications as the standalone actions. Methods are synchronous — no await needed.
Direct calls still work
For one-off operations, the bare driver actions accept positional args too: fa.writeText("log.txt", "hi"), fa.readText("log.txt"). Reach for the handle when you'll touch the same file more than once.
Security
All file paths are validated to prevent directory traversal attacks. Operations are confined to the configured basePath — you cannot read or write files outside it.
Example Connector
// workspace/connectors/files.js
export default {
driver: "FileAccess",
config: {
basePath: "./data",
},
methods: {
saveReading: {
fn: (args) => {
const line = `${new Date().toISOString()},${args.value}\n`;
return driver.file("readings.csv").append(line);
},
description: "Append a timestamped reading to readings.csv",
},
writeArray: {
fn: (args) => {
const lines = [args.header, ...args.data.map((row) => row.join(","))];
return driver.file(args.path).write(lines.join("\n") + "\n");
},
description: "Write a CSV file ({ path, header, data: [[...], ...] })",
},
},
};Using writeArray from a script
const data = [];
for (let i = 0; i <= 350; i += 10) { // 0-350 mA in 10 mA steps
psu.current_set = i / 1000;
delay(100);
data.push([psu.current_set, psu.measured_voltage]);
}
connector("fileaccess").writeArray({
path: "data.csv",
header: "I (mA),V (V)",
data,
});CSV output is chart-viewable
Files written with a .csv or .tsv extension open as an interactive line chart when clicked in the File Explorer. See the CSV Charts section of the UI tour.
Open tabs refresh automatically
Any time a FileAccess writeText, appendText, writeBinary, deleteFile, or rename action touches a file you currently have open in an editor tab, the tab reloads on its own — a .csv chart grows row-by-row while a script logs to it, no close-and-reopen needed. Tabs with unsaved edits are skipped so in-progress work isn't clobbered.
Example Script
const files = connector("files");
// Bind the path once with .file() — recommended for any non-trivial use
const run = files.file("log.txt");
run.write("Experiment started\n");
run.append("Reading: 42.5\n");
log.info(run.read());
// One-shot calls still work for trivial cases (positional args accepted)
files.writeText("notes.txt", "first line\n");
log.info(files.readText("notes.txt"));
// Directory listings still take a path
log.info(`Files: ${JSON.stringify(files.listFiles({}))}`);