Skip to main content

WorkspaceFilesystem

Added in: @mastra/core@1.1.0

The WorkspaceFilesystem interface defines how workspaces interact with file storage.

Methods
Direct link to Methods

readFile(path, options?)
Direct link to readfilepath-options

Read file contents.

const content = await filesystem.readFile('/docs/guide.md')
const buffer = await filesystem.readFile('/image.png', { encoding: 'binary' })

Parameters:

path:

string
File path relative to basePath

options?:

Options
readFile options.
Options

encoding?:

'utf-8' | 'binary'
Text or binary encoding

Returns: Promise<string | Buffer>

writeFile(path, content, options?)
Direct link to writefilepath-content-options

Write file contents.

await filesystem.writeFile('/docs/new.md', '# New Document')
await filesystem.writeFile('/nested/path/file.md', content, { recursive: true })

Parameters:

path:

string
File path relative to basePath

content:

string | Buffer
File content

options?:

Options
Configuration options.
Options

recursive?:

boolean
Create parent directories if they don't exist

overwrite?:

boolean
Overwrite existing file

expectedMtime?:

Date
If provided, the write fails with a StaleFileError when the file's current modification time doesn't match. Use this for optimistic concurrency control to detect external modifications between read and write.

deleteFile(path, options?)
Direct link to deletefilepath-options

Delete a file.

await filesystem.deleteFile('/docs/old.md')
await filesystem.deleteFile('/docs/maybe.md', { force: true }) // Don't throw if missing

Parameters:

path:

string
File path

options?:

Options
Configuration options.
Options

force?:

boolean
Don't throw error if file doesn't exist

appendFile(path, content)
Direct link to appendfilepath-content

Append content to a file, creating it if it doesn't already exist. Parent directories are created automatically.

await filesystem.appendFile('/logs/app.log', 'New log entry\n')

Parameters:

path:

string
File path

content:

string | Buffer
Content to append

copyFile(src, dest, options?)
Direct link to copyfilesrc-dest-options

Copy a file to a new location.

await filesystem.copyFile('/docs/template.md', '/docs/new-doc.md')

Parameters:

src:

string
Source file path

dest:

string
Destination file path

options?:

Options
Configuration options.
Options

overwrite?:

boolean
Overwrite destination if it exists

moveFile(src, dest, options?)
Direct link to movefilesrc-dest-options

Move or rename a file.

await filesystem.moveFile('/docs/draft.md', '/docs/final.md')

Parameters:

src:

string
Source file path

dest:

string
Destination file path

options?:

Options
Configuration options.
Options

overwrite?:

boolean
Overwrite destination if it exists

readdir(path, options?)
Direct link to readdirpath-options

List directory contents.

const entries = await filesystem.readdir('/docs')
// [{ name: 'guide.md', type: 'file' }, { name: 'api', type: 'directory' }]

Returns: Promise<FileEntry[]>

interface FileEntry {
name: string
type: 'file' | 'directory'
size?: number
isSymlink?: boolean
symlinkTarget?: string
}

mkdir(path, options?)
Direct link to mkdirpath-options

Create a directory.

await filesystem.mkdir('/docs/api')
await filesystem.mkdir('/deeply/nested/path', { recursive: true })

Parameters:

path:

string
Directory path

options?:

Options
Configuration options.
Options

recursive?:

boolean
Create parent directories

rmdir(path, options?)
Direct link to rmdirpath-options

Remove a directory.

await filesystem.rmdir('/docs/old')
await filesystem.rmdir('/docs/nested', { recursive: true })

Parameters:

path:

string
Directory path

options?:

Options
Configuration options.
Options

recursive?:

boolean
Remove contents recursively

force?:

boolean
Don't throw if directory doesn't exist

exists(path)
Direct link to existspath

Check if a path exists.

const exists = await filesystem.exists('/docs/guide.md')

Returns: Promise<boolean>

stat(path)
Direct link to statpath

Get file or directory metadata.

const stat = await filesystem.stat('/docs/guide.md')
// { name: 'guide.md', path: '/docs/guide.md', type: 'file', size: 1234, createdAt: Date, modifiedAt: Date }

Returns: Promise<FileStat>

interface FileStat {
name: string // File or directory name (basename only)
path: string // Path relative to the filesystem basePath
type: 'file' | 'directory'
size: number
createdAt: Date
modifiedAt: Date
mimeType?: string
}

Optional methods
Direct link to Optional methods

init()
Direct link to init

Initialize the filesystem. Called by workspace.init().

await filesystem.init?.()

destroy()
Direct link to destroy

Clean up resources. Called by workspace.destroy().

await filesystem.destroy?.()

getInfo()
Direct link to getinfo

Get filesystem metadata.

const info = await filesystem.getInfo?.()
// { id, name, provider, basePath, readOnly, status, storage? }

Returns: Promise<FilesystemInfo>

interface FilesystemInfo {
id: string
name: string
provider: string
basePath?: string
readOnly?: boolean
status?: string
storage?: {
totalBytes?: number
usedBytes?: number
availableBytes?: number
}
}

getInstructions(opts?)
Direct link to getinstructionsopts

Returns a description of how this filesystem works. Injected into the agent's system message when the workspace is assigned to an agent.

const instructions = filesystem.getInstructions?.()
// 'Local filesystem at "/workspace". Files at workspace path "/foo" are stored at "/workspace/foo" on disk.'

Parameters:

opts.requestContext?:

RequestContext
Forwarded to the instructions function if one was provided in the constructor.

Returns: string

walk(path, options?)
Direct link to walkpath-options

Native recursive tree walk executed by the provider in as few calls as possible. When implemented, the workspace list_files tool uses it instead of issuing one readdir round trip per directory, which matters for remote providers (sandboxes, object stores). If walk throws, tools fall back to the readdir-based walk automatically and log a warning through the workspace logger, since the fallback issues one round trip per directory.

const entries = await filesystem.walk?.('.', { maxDepth: 3 })
// [{ name: 'index.ts', type: 'file', path: 'src/index.ts' }, ...]

Parameters:

path:

string
Directory to walk.

options.maxDepth?:

number
Maximum directory depth to descend (root entries are depth 1).

options.includeHidden?:

boolean
Include entries whose names start with ".". Defaults to false.

Returns: Promise<WalkEntry[]>

interface WalkEntry extends FileEntry {
path: string // Relative to the walk root, POSIX separators, no leading "./"
}

grep(options)
Direct link to grepoptions

Native content search executed by the provider (for example with rg or grep inside a sandbox). When implemented, the workspace grep tool delegates to it instead of downloading every file to search host-side. Throw UnsupportedGrepPatternError when a pattern can't run natively so that callers catch it and fall back to the host-side implementation. That fallback is logged at info level; any other error from grep also triggers the fallback but is logged as a warning, since the host-side search reads every candidate file.

const results = await filesystem.grep?.({
pattern: 'TODO',
path: '.',
caseSensitive: true,
includeHidden: false,
})
// [{ path: 'src/index.ts', matches: [{ line: 3, column: 6, text: '// TODO: fix' }] }]

Parameters:

options.pattern:

string
JavaScript regex source to search for.

options.path:

string
File or directory root to search within.

options.caseSensitive:

boolean
Whether matching is case-sensitive.

options.includeHidden:

boolean
Include hidden files and directories in the search.

options.maxCountPerFile?:

number
Maximum matches per file (like grep -m).

options.maxTotalMatches?:

number
Global cap on total matches across all files.

options.contextLines?:

number
Lines of context to include before and after each match.

Returns: Promise<FilesystemGrepResult[]>

interface FilesystemGrepResult {
path: string // Relative to the search root, POSIX separators
matches: FilesystemGrepMatch[]
}

interface FilesystemGrepMatch {
line: number // 1-based line number
column: number // 0-based UTF-16 (JS string) index, not a byte offset
text: string // Full matched line, without trailing newline
before?: string[] // Context lines before the match
after?: string[] // Context lines after the match
}