Manage files and directories within sandboxes through the fs module of Blaxel SDK. This module provides essential operations for creating, reading, writing, copying, and deleting files and directories.

Complete code examples demonstrating all operations are available on Blaxel’s GitHub: in TypeScript and in Python.

Basic file system operations

Create directory

Create a new directory at a specific path in the sandbox:


import { SandboxInstance } from "@blaxel/core";

const sandbox = await SandboxInstance.get("my-sandbox")

await sandbox.fs.mkdir(`/Users/user/Downloads/test`)

List files

List files in a specific path:


const dir = await sandbox.fs.ls(`/Users/user/Downloads`);

if (dir.files?.length && dir.files?.length < 1) {
  throw new Error("Directory is empty");
}

Read file

Read a file from a specific filepath:


const content = await sandbox.fs.read(`/Users/user/Downloads/test.txt`)

Write file

Create a file in a specific path:


await sandbox.fs.write(`/Users/user/Downloads/test.txt`, "Hello world");

See down below for how to upload/write a binary, or multiple files at once.

Write multiple files

You can write multiple files or directories simultaneously. The second path parameter in writeTree specifies the base directory for writing the file tree, eliminating the need to repeat the full path for each file.


const files = [
    { path: "file1.txt", content: "Content of file 1" },
    { path: "file2.txt", content: "Content of file 2" },
    { path: "subfolder/subfile1.txt", content: "Content of subfile 1" },
    { path: "subfolder/subfile2.txt", content: "Content of subfile 2" },
  ]

await sandbox.fs.writeTree(files, "/blaxel/tmp")

Write binary

Write binary content to a file in the sandbox filesystem:


// Read archive.zip as binary
const archiveBuffer = await fs.readFile("tests/sandbox/archive.zip")

await sandbox.fs.writeBinary("/blaxel/archive.zip", archiveBuffer)

The binary content to write can be provided as:

  • Buffer: Node.js Buffer object
  • Blob: Web API Blob object
  • File: Web API File object
  • Uint8Array: Typed array containing binary data

Copy file

Copy a file from a path to another path:


await sandbox.fs.cp(`/Users/user/Downloads/test.txt`, `/Users/user/Documents/private/test.txt`);

Delete file or directory

Delete a file or directory by specifying its path:


await sandbox.fs.rm(`/Users/user/Downloads/test.txt`);

Watch filesystem for events

The watch function monitors all file system changes in the specified directory. You can also watch subdirectories by passing a /my/directory/** pattern.

By default (whenΒ withContent: false), the events will only include metadata about the changes, not the actual file contents. Here’s what you’llΒ get in the callbackΒ events:

  1. For ALL operations (CREATE, WRITE, DELETE, etc.), you’ll receive:
    1. op: TheΒ operation type (e.g., β€œCREATE”, β€œWRITE”, β€œDELETE”)
    2. path: The directory path whereΒ the change occurred
    3. name: The name of the file/directory thatΒ changed
  2. You will NOT receive:
    1. The actual content of the files
    2. File contents for CREATE or WRITE operations

import { SandboxInstance } from "@blaxel/core";

// Test the default watch functionality:
async function testWatch(sandbox: SandboxInstance) {
  try {
    const user = process.env.USER;
    const testDir = `/Users/${user}/Downloads/watchtest`;
    const testFile = `/file.txt`;

    // Ensure correct type for fs
    const fs = sandbox.fs;

    // Clean up before test
    try { await fs.rm(testDir, true); } catch {}
    await fs.mkdir(testDir);

    // Watch without content
    const events: string[] = []
    const contents: string[] = []
    const handle = fs.watch("/", (fileEvent) => {
      events.push(fileEvent.op)
      if (fileEvent.op === "WRITE") {
        contents.push(fileEvent.content ?? "")
      }
    }, {
      withContent: true
    });
    await new Promise((resolve) => setTimeout(resolve, 100));
    await fs.write(testFile, "content");

    await new Promise((resolve) => setTimeout(resolve, 100));
    await fs.write(testFile, "new content");

    await new Promise((resolve) => setTimeout(resolve, 100));
    await fs.rm(testFile)
    await new Promise((resolve) => setTimeout(resolve, 100));

    handle.close();

    // Clean up after test
    await fs.rm(testDir, true);

    if (!events.includes("CREATE") || !events.includes("WRITE") || !events.includes("REMOVE")) {
      throw new Error("Watch callback not consistent with expected events: " + events.join(", "));
    }
    if (!contents.includes("content") || !contents.includes("new content")) {
      throw new Error("Watch callback not consistent with expected contents: " + contents.join(", "));
    }
    console.log("testWatch passed");
  } catch (e) {
    console.error("There was an error => ", e);
  }
}

async function main() {
  try {
    const sandbox = await SandboxInstance.get("my-sandbox")
    await testWatch(sandbox)
  } catch (e) {
    console.error("There was an error => ", e);
  }
}

main()
  .catch((err) => {
    console.error("There was an error => ", err);
    process.exit(1);
  })
  .then(() => {
    process.exit(0);
  })

Watch sub-directories

Watch all sub-directories recursively with /**:


async function testWatchWithSubfolder(sandbox: SandboxInstance) {
    const fs = sandbox.fs;
    const handle = fs.watch("/folder/**", (fileEvent) => {
      console.log(fileEvent)
    }, {
      ignore: ["folder/test2.txt"]
    });
    await fs.write("folder/folder2/test.txt", "content");
    await fs.write("folder/test2.txt", "content");
    await new Promise((resolve) => setTimeout(resolve, 100));
    handle.close();
  }

Ignore files or directories

You can ignore changes in certain files or directories by providing an array of filepaths to ignore:


// Test the watch functionality, ignoring of some files:
async function testWatchWithIgnore(sandbox: SandboxInstance) {
  const fs = sandbox.fs;
  const handle = fs.watch("/", (fileEvent) => {
    console.log(fileEvent)
  }, {
    withContent: true,
    ignore: ["app/node_modules", "folder/test2.txt"]
  });
  await fs.write("folder/folder2/test.txt", "content");
  await fs.write("folder/test2.txt", "content")
  await fs.write("test2.txt", "content");
  await fs.write("test3.txt", "content");
  await new Promise((resolve) => setTimeout(resolve, 100));
  handle.close();
}

async function main() {
  try {
    const sandbox = await SandboxInstance.get("my-sandbox")
    await testWatchWithIgnore(sandbox)
  } catch (e) {
    console.error("There was an error => ", e);
  } 
}

main()
  .catch((err) => {
    console.error("There was an error => ", err);
    process.exit(1);
  })
  .then(() => {
    process.exit(0);
  })

SpecifyΒ withContent: trueΒ so the events include the actual file contents.