Skip to main content

LocalFilesystem

Added in: @mastra/core@1.1.0

Stores files in a directory on the local filesystem.

info

For interface details, see WorkspaceFilesystem Interface.

Usage
Direct link to Usage

Add a LocalFilesystem to a workspace and assign it to an agent. The agent can then read, write, and manage files as part of its tasks:

import { Agent } from '@mastra/core/agent'
import { Workspace, LocalFilesystem } from '@mastra/core/workspace'

const workspace = new Workspace({
filesystem: new LocalFilesystem({
basePath: './workspace',
}),
})

const agent = new Agent({
id: 'file-agent',
model: 'openai/gpt-4o',
workspace,
})

// The agent now has filesystem tools available
const response = await agent.generate('List all files in the workspace')

Constructor parameters
Direct link to Constructor parameters

basePath:

string
Base directory path on disk. All file paths are resolved relative to this directory.

id?:

string
= Auto-generated
Unique identifier for this filesystem instance

contained?:

boolean
= true
When true, all file operations are restricted to stay within basePath. Prevents path traversal attacks and symlink escapes. See [containment](/docs/workspace/filesystem#containment).

allowedPaths?:

string[]
= []
Additional absolute paths that are allowed beyond basePath. Useful with `contained: true` to grant access to specific directories without disabling containment entirely. Paths are resolved to absolute paths.

instructions?:

string | ((opts: { defaultInstructions: string; requestContext?: RequestContext }) => string)
Custom instructions that override the default instructions returned by getInstructions(). Pass a string to fully replace them, or a function to extend them with access to the current requestContext for per-request customization.

readOnly?:

boolean
= false
When true, all write operations are blocked. Read operations are still allowed.

Properties
Direct link to Properties

id:

string
Filesystem instance identifier

name:

string
Provider name ('LocalFilesystem')

provider:

string
Provider identifier ('local')

basePath:

string
The absolute base path on disk

readOnly:

boolean | undefined
Whether the filesystem is in read-only mode

allowedPaths:

readonly string[]
Current set of additional allowed paths (absolute, resolved). These paths are permitted beyond basePath when containment is enabled.

Methods
Direct link to Methods

init()
Direct link to init

Initialize the filesystem. Creates the base directory if it doesn't exist.

await filesystem.init()

Called by workspace.init().

Lazy initialization
Direct link to Lazy initialization

LocalFilesystem initializes on first operation if not already initialized, creating the base directory automatically. Calling init() explicitly is optional but can be useful to pre-create directories before the first operation.

destroy()
Direct link to destroy

Clean up filesystem resources.

await filesystem.destroy()

Called by workspace.destroy().

setAllowedPaths(pathsOrUpdater)
Direct link to setallowedpathspathsorupdater

Update the allowed paths at runtime. Accepts a new paths array (replaces current) or an updater callback that receives the current paths and returns the new set.

// Set directly
filesystem.setAllowedPaths(['/home/user/.config'])

// Update with callback
filesystem.setAllowedPaths(prev => [...prev, '/home/user/documents'])

// Clear all allowed paths
filesystem.setAllowedPaths([])

Parameters:

pathsOrUpdater:

string[] | ((current: readonly string[]) => string[])
New allowed paths array or updater function receiving current paths

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
Configuration options.
Options

encoding?:

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

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

Write content to a file.

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

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

Append content to an existing file.

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

Parameters:

path:

string
File path relative to basePath

content:

string | Buffer
Content to append

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

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')
await filesystem.copyFile('/src/config.json', '/backup/config.json', { overwrite: false })

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')
await filesystem.moveFile('/temp/upload.txt', '/files/document.txt')

Parameters:

src:

string
Source file path

dest:

string
Destination file path

options?:

Options
Configuration options.
Options

overwrite?:

boolean
Overwrite destination if it exists

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

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' }]

exists(path)
Direct link to existspath

Check if a path exists.

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

stat(path)
Direct link to statpath

Get file or directory metadata.

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

getInfo()
Direct link to getinfo

Returns metadata about this filesystem instance.

const info = filesystem.getInfo()
// { id: '...', name: 'LocalFilesystem', provider: 'local', basePath: '/workspace', readOnly: false }

getInstructions(opts?)
Direct link to getinstructionsopts

Returns a description of how paths work in this filesystem. When assigned to an agent, this is injected into the agent's system message.

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

Pass requestContext to enable per-request customization when the instructions constructor option is a function:

const instructions = filesystem.getInstructions({ requestContext })

Parameters:

opts.requestContext?:

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

Returns: string

To override the default output, pass an instructions option to the constructor. See constructor parameters.

Path resolution
Direct link to Path resolution

How basePath works
Direct link to how-basepath-works

The basePath option sets the root directory for all file operations. File paths passed to methods like readFile() are resolved relative to this base:

  • Leading slashes are stripped: /docs/guide.mddocs/guide.md
  • The path is normalized and joined with basePath
  • Result: ./workspace + docs/guide.md./workspace/docs/guide.md
const filesystem = new LocalFilesystem({
basePath: './workspace',
})

// These all resolve to ./workspace/docs/guide.md
await filesystem.readFile('/docs/guide.md')
await filesystem.readFile('docs/guide.md')

Relative paths and execution context
Direct link to Relative paths and execution context

When you use a relative path for basePath, it resolves from process.cwd(). In Mastra projects, cwd varies depending on how you run your code:

ContextWorking directory./workspace resolves to
mastra dev./src/mastra/public/./src/mastra/public/workspace
mastra start./.mastra/output/./.mastra/output/workspace
Direct scriptWhere you ran the commandRelative to that location

This can cause confusion when the same relative path resolves to different locations.

For consistent paths across all execution contexts, use an environment variable with an absolute path:

import { LocalFilesystem } from '@mastra/core/workspace'

const filesystem = new LocalFilesystem({
basePath: process.env.WORKSPACE_PATH!,
})

Set WORKSPACE_PATH in your environment to an absolute path like /home/user/my-project/workspace. This ensures the workspace path is consistent regardless of how you run your code.