Skip to main content
Mastra 1.0 is available 🎉 Read announcement

LocalFilesystem

Stores files in a directory on the local filesystem.

info

For interface details, see WorkspaceFilesystem Interface.

Installation
Direct link to Installation

LocalFilesystem is included in @mastra/core:

npm install @mastra/core@latest

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

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

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().

destroy()
Direct link to destroy

Clean up filesystem resources.

await filesystem.destroy();

Called by workspace.destroy().

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.encoding?:

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

Returns: Promise<string | Buffer>

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.recursive?:

boolean
= false
Create parent directories if they don't exist

options.overwrite?:

boolean
= true
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.force?:

boolean
= false
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.overwrite?:

boolean
= true
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.overwrite?:

boolean
= true
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.recursive?:

boolean
= false
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.recursive?:

boolean
= false
Remove contents recursively

options.force?:

boolean
= false
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' }]

Returns: Promise<FileEntry[]>

interface FileEntry {
name: string;
type: 'file' | 'directory';
size?: number;
modifiedAt?: Date;
}

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');
// { type: 'file', size: 1234, modifiedAt: Date, createdAt: Date, path: '/docs/guide.md' }

Returns: Promise<FileStat>

interface FileStat {
type: 'file' | 'directory';
size: number;
modifiedAt: Date;
createdAt: Date;
path: string;
}

getInfo()
Direct link to getinfo

Returns metadata about this filesystem instance.

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

Returns: FilesystemInfo

interface FilesystemInfo {
id: string;
name: string;
provider: string;
basePath?: string;
readOnly?: boolean;
}

getInstructions()
Direct link to getinstructions

Returns a description of how paths work in this filesystem. Used in tool descriptions.

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

Returns: string

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.md → docs/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.