Skip to content

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

PropertyTypeAccessUnitDescription
basePathstringRResolved absolute base path
fileCountintRTotal number of files (recursive)
totalSizeBytesintRbytesTotal size of all files
existsboolRWhether the base directory exists

Actions

ActionArgsDescription
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

OptionTypeDefaultDescription
basePathstringRequired. Root directory for all file operations
maxFileSizeMBint10Maximum file size in MB for read/write
createIfMissingbooltrueCreate 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:

javascript
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();
MemberKindDescription
pathpropertyThe sandbox-relative path (forward-slashed)
existspropertytrue if the file exists
sizepropertyFile size in bytes (0 if missing)
read()methodRead as UTF-8 text
write(content)methodOverwrite with text (creates parent dirs)
append(content)methodAppend text
readBinary()methodRead as base64
writeBinary(base64)methodOverwrite with base64-decoded bytes
delete()methodRemove the file
rename(newPath)methodRename / 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

javascript
// 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

javascript
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

javascript
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({}))}`);

Muxit — Hardware Orchestration Platform