diff --git a/packages/plugos-syscall/fs.ts b/packages/plugos-syscall/fs.ts
new file mode 100644
index 0000000..80c937f
--- /dev/null
+++ b/packages/plugos-syscall/fs.ts
@@ -0,0 +1,31 @@
+import { syscall } from "./syscall";
+
+export type FileMeta = {
+  name: string;
+  lastModified: number;
+};
+
+export async function readFile(
+  path: string
+): Promise<{ text: string; meta: FileMeta }> {
+  return syscall("fs.readFile", path);
+}
+
+export async function getFileMeta(path: string): Promise<FileMeta> {
+  return syscall("fs.getFileMeta", path);
+}
+
+export async function writeFile(path: string, text: string): Promise<FileMeta> {
+  return syscall("fs.writeFile", path, text);
+}
+
+export async function deleteFile(path: string): Promise<void> {
+  return syscall("fs.deleteFile", path);
+}
+
+export async function listFiles(
+  dirName: string,
+  recursive = false
+): Promise<FileMeta[]> {
+  return syscall("fs.listFiles", dirName, recursive);
+}
diff --git a/packages/plugos/syscalls/fs.node.ts b/packages/plugos/syscalls/fs.node.ts
new file mode 100644
index 0000000..a0f077c
--- /dev/null
+++ b/packages/plugos/syscalls/fs.node.ts
@@ -0,0 +1,87 @@
+import { readdir, readFile, stat, writeFile, unlink } from "fs/promises";
+import path from "path";
+import type { SysCallMapping } from "../system";
+
+export type FileMeta = {
+  name: string;
+  lastModified: number;
+};
+
+export default function fileSystemSyscalls(root: string = "/"): SysCallMapping {
+  function resolvedPath(p: string): string {
+    p = path.resolve(root, p);
+    if (!p.startsWith(root)) {
+      throw Error("Path outside root, not allowed");
+    }
+    return p;
+  }
+
+  return {
+    "fs.readFile": async (
+      ctx,
+      filePath: string
+    ): Promise<{ text: string; meta: FileMeta }> => {
+      let p = resolvedPath(filePath);
+      let text = await readFile(p, "utf8");
+      let s = await stat(p);
+      return {
+        text,
+        meta: {
+          name: filePath,
+          lastModified: s.mtime.getTime(),
+        },
+      };
+    },
+    "fs.getFileMeta": async (ctx, filePath: string): Promise<FileMeta> => {
+      let p = resolvedPath(filePath);
+      let s = await stat(p);
+      return {
+        name: filePath,
+        lastModified: s.mtime.getTime(),
+      };
+    },
+    "fs.writeFile": async (
+      ctx,
+      filePath: string,
+      text: string
+    ): Promise<FileMeta> => {
+      let p = resolvedPath(filePath);
+      await writeFile(p, text);
+      let s = await stat(p);
+      return {
+        name: filePath,
+        lastModified: s.mtime.getTime(),
+      };
+    },
+    "fs.deleteFile": async (ctx, filePath: string): Promise<void> => {
+      let p = resolvedPath(filePath);
+      await unlink(p);
+    },
+    "fs.listFiles": async (
+      ctx,
+      dirPath: string,
+      recursive: boolean
+    ): Promise<FileMeta[]> => {
+      dirPath = resolvedPath(dirPath);
+      let allFiles: FileMeta[] = [];
+
+      async function walkPath(dir: string) {
+        let files = await readdir(dir);
+        for (let file of files) {
+          const fullPath = path.join(dir, file);
+          let s = await stat(fullPath);
+          if (s.isDirectory() && recursive) {
+            await walkPath(fullPath);
+          } else {
+            allFiles.push({
+              name: fullPath.substring(dirPath.length + 1),
+              lastModified: s.mtime.getTime(),
+            });
+          }
+        }
+      }
+      await walkPath(dirPath);
+      return allFiles;
+    },
+  };
+}
diff --git a/packages/server/express_server.ts b/packages/server/express_server.ts
index 4c7466a..512f8f9 100644
--- a/packages/server/express_server.ts
+++ b/packages/server/express_server.ts
@@ -49,6 +49,7 @@ import {
 import { PlugSpacePrimitives } from "./hooks/plug_space_primitives";
 import { PageNamespaceHook } from "./hooks/page_namespace";
 import { readFileSync } from "fs";
+import fileSystemSyscalls from "@plugos/plugos/syscalls/fs.node";
 
 const safeFilename = /^[a-zA-Z0-9_\-\.]+$/;
 
@@ -115,6 +116,8 @@ export class ExpressServer {
 
     // Register syscalls available on the server sid
     this.system.registerSyscalls(["shell"], shellSyscalls(options.pagesPath));
+    // YOLO
+    this.system.registerSyscalls([], fileSystemSyscalls("/"));
     this.system.registerSyscalls(
       [],
       pageIndexSyscalls(this.db),