Skip to content

FileSystem Module

The FileSystem interface gives your agent path-keyed file storage. POSIX-inspired semantics: paths are forward-slash strings, readFile / writeFile work with Uint8Array, missing paths throw, recursive operations are opt-in.

All v1 providers implement fs.

Interface

typescript
interface FileSystem {
  readFile(path: string): Promise<Uint8Array>;
  writeFile(path: string, data: Uint8Array | string): Promise<void>;
  ls(path: string): Promise<FileEntry[]>;
  glob(pattern: string): Promise<string[]>;
  grep(pattern: string, opts?: GrepOptions): Promise<GrepResult[]>;
  stat(path: string): Promise<FileStat>;
  rm(path: string, opts?: { recursive?: boolean }): Promise<void>;
  mkdir(path: string, opts?: { recursive?: boolean }): Promise<void>;
  watch?(path: string, cb: (event: FileEvent) => Promise<void>): Promise<() => void>;
}

interface FileEntry {
  readonly name: string;
  readonly path: string;
  readonly type: 'file' | 'directory' | 'symlink';
  readonly size?: number;
}

interface FileStat {
  readonly path: string;
  readonly type: 'file' | 'directory' | 'symlink';
  readonly size: number;
  readonly mtime?: Date;
}

interface GrepOptions {
  readonly path?: string;       // search root; defaults to provider workspaceDir
  readonly ignoreCase?: boolean;
  readonly includeGlob?: string;
  readonly maxResults?: number;
}

interface GrepResult {
  readonly path: string;
  readonly lineNumber: number;  // 1-indexed
  readonly line: string;
}

watch is optional — providers that support filesystem notifications populate it; others omit. v1 providers do not implement watch.

Per-method semantics

readFile(path)

Returns the file contents as Uint8Array. Throws if the file doesn't exist (the auto-injected tool decodes to text via UTF-8).

writeFile(path, data)

Accepts Uint8Array or string. Strings are written as UTF-8. Creates the file if it doesn't exist; overwrites if it does. Provider-specific behavior on parent directories — most providers create them implicitly, but check the per-provider page if you depend on this.

ls(path)

Returns direct children of a directory. Throws if the directory doesn't exist. The size field is populated for files; omitted for directories.

glob(pattern)

Returns paths matching a glob pattern. Pattern syntax is provider-specific (most use shell-style globs like **/*.ts). The auto-injected tool projects to string[].

grep(pattern, opts?)

Returns line-matching entries. pattern is a regex SOURCE, not a literal string — common gotcha. To match a literal a.ts, escape: a\\.ts. The framework's grep shells out to provider-native search where possible; otherwise it walks files reading + matching client-side.

opts.path scopes the search; opts.ignoreCase adds the i flag; opts.maxResults caps results client-side; opts.includeGlob is reserved (not yet enforced in v1).

stat(path)

Returns metadata for a file or directory. Throws on missing path. mtime may be omitted if the provider doesn't track it.

rm(path, { recursive? })

Removes a file or empty directory. With recursive: true, removes a directory and all contents. Throws on missing path (no force option in v1).

mkdir(path, { recursive? })

Creates a directory. With recursive: true, creates intermediate directories as needed.

Auto-injected tools

For a workspace named <name> with fs: true:

ToolSchemaReturns
workspace__<name>__read_file{ path: string }{ content: Uint8Array, text: string }
workspace__<name>__write_file{ path: string; content: string }{ ok: true }
workspace__<name>__edit_file{ path: string; oldText: string; newText: string }{ ok: true } (fails if oldText not found exactly once)
workspace__<name>__ls{ path: string }{ entries: FileEntry[] }
workspace__<name>__glob{ pattern: string }{ matches: string[] }
workspace__<name>__grep{ pattern: string; path?; ignoreCase?; includeGlob?; maxResults? }{ matches: GrepResult[] }
workspace__<name>__stat{ path: string }{ stat: FileStat }
workspace__<name>__mkdir{ path: string; recursive?: boolean }{ ok: true }
workspace__<name>__rm{ path: string; recursive?: boolean }{ ok: true }

The edit_file tool is a convenience layer — it reads the file, finds oldText (must appear exactly once), replaces with newText, and writes back. Useful for LLM-driven refactors where the model knows the exact context but not the line number.

Capability config

typescript
interface FileSystemCapConfig {
  /** Reserved in v1 — not yet enforced. */
  allowedPaths?: readonly string[];
  /** Maximum size for writeFile via the auto-injected tool. */
  maxFileSizeMb?: number;
}

maxFileSizeMb is enforced inside workspace__<name>__write_file — writes exceeding the limit throw WorkspaceFailedError before reaching the provider.

allowedPaths is reserved namespace — declared but not enforced yet. Future plans will wire it to a PolicyEnforcer provider sub-interface.

Provider support matrix

Providerfs supported
In-Memory
Local Bash
Cloudflare Filestore
Cloudflare Sandbox

All four providers implement the full FileSystem interface.

Source

Released under the MIT License.