Skip to main content
Providers abstract how agents interact with the filesystem and shell. Instead of coupling tool logic to Node.js APIs, OpenHarness defines two interfaces — FsProvider and ShellProvider — that you can implement for any environment. This lets you run the same agent code locally, in a sandbox, or in the cloud, just by swapping the provider.

Interfaces

FsProvider

interface FsProvider {
  readFile(path: string): Promise<string>;
  writeFile(path: string, content: string): Promise<void>;
  exists(path: string): Promise<boolean>;
  stat(path: string): Promise<FileStat>;
  readdir(path: string): Promise<DirEntry[]>;
  mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;
  remove(path: string, options?: { recursive?: boolean }): Promise<void>;
  rename(oldPath: string, newPath: string): Promise<void>;
  resolvePath(path: string): string;
}

ShellProvider

interface ShellProvider {
  exec(
    command: string,
    options?: {
      timeout?: number;
      cwd?: string;
      env?: Record<string, string>;
    }
  ): Promise<ShellResult>;
}

Environment

The Environment type combines both providers:
interface Environment {
  fs: FsProvider;
  shell: ShellProvider;
}

Built-in Providers

NodeFsProvider

The default filesystem provider for Node.js environments. Uses node:fs under the hood.
import { createFsTools, NodeFsProvider } from "@openharness/core";

const fsTools = createFsTools(new NodeFsProvider());
Options:
OptionDefaultDescription
cwdprocess.cwd()Working directory for resolving relative paths
maxFileSize10 MBMaximum file size readFile will load
const fs = new NodeFsProvider({
  cwd: "/home/user/project",
  maxFileSize: 20 * 1024 * 1024, // 20 MB
});
Safety features:
  • File size guard — throws FileTooLargeError if a file exceeds maxFileSize
  • Auto-mkdirwriteFile creates parent directories automatically
  • Path resolution — relative paths are resolved from cwd

NodeShellProvider

The default shell provider for Node.js. Runs commands via bash -c.
import { createBashTool, NodeShellProvider } from "@openharness/core";

const { bash } = createBashTool(new NodeShellProvider());
Options:
OptionDefaultDescription
cwdprocess.cwd()Default working directory for commands
maxStdout50,000 charsTruncate stdout beyond this length
maxStderr10,000 charsTruncate stderr beyond this length
const shell = new NodeShellProvider({
  cwd: "/home/user/project",
  maxStdout: 100_000,
});
The exec method supports per-call timeout (default 30s), cwd, and env overrides.

VfsFsProvider

A virtual filesystem provider from the @openharness/provider-vfs package. Provides sandboxed, in-memory, or SQLite-backed file access — ideal for testing, isolated execution, or environments without a real filesystem.
npm install @openharness/provider-vfs
import { createFsTools } from "@openharness/core";
import { VfsFsProvider } from "@openharness/provider-vfs";

const fsTools = createFsTools(new VfsFsProvider());
By default, VfsFsProvider uses an in-memory backend mounted at /workspace. It initializes lazily on first use. Options:
OptionDefaultDescription
vfsPre-created VirtualFileSystem instance (skips auto-creation)
providerMemoryProviderVFS storage backend
vfsOptions{ moduleHooks: false, virtualCwd: true }Options passed to vfs.create()
mountPoint"/workspace"Mount point for the virtual filesystem
maxFileSize10 MBMaximum file size readFile will load

Storage Backends

The VFS provider supports three backends via @platformatic/vfs (or the future node:vfs):
In-memory filesystem — fast, ephemeral, no persistence:
const fs = new VfsFsProvider(); // MemoryProvider is the default

Accessing the VFS Instance

For advanced use cases, you can access the underlying VirtualFileSystem:
const provider = new VfsFsProvider();
const vfs = await provider.getVfs();

Custom Providers

Implement the FsProvider and/or ShellProvider interfaces to support any environment:
import type { FsProvider, ShellProvider } from "@openharness/core";

class MyCloudFsProvider implements FsProvider {
  async readFile(path: string) { /* ... */ }
  async writeFile(path: string, content: string) { /* ... */ }
  // ... implement all methods
}
Possible targets:
  • E2B sandboxes for isolated code execution
  • Cloudflare Workers for edge deployment
  • Daytona for managed dev environments
  • Docker containers for reproducible builds
  • Custom APIs wrapping remote filesystems