description: Default Tools - Filesystem reference. 11 safety.fs-wrapped tools (list-roots · read · list · stat · grep · count · slice · sort · cut · find · write) over readable roots and a writable working directory.
So a relative path resolves under the working directory; an absolute path may be read anywhere under a readable root, but writes are confined to the working directory. Call listAllowedDirectories first to learn the exact absolute paths before reading or writing.
listAllowedDirectories 🆓
:material-folder-key-outline:
file · pipeline L3
Reports the filesystem boundaries these tools operate within: the readable roots (anything under them can be read) and the working directory (the only writable location; a per-conversation subdirectory when run from a chat). Call this first. Uses safety.fs.readRoots() / workspace().
Click for full reference · params · sandbox · JS source
**More detail**
Reports which directories the filesystem tools may touch: the readable roots (anything under them can be read) and the working directory (the only writable location, where relative paths resolve; a per-conversation subdirectory when run from a chat). Call this first to learn the absolute paths before reading or writing files. Takes no arguments. Uses safety.fs.readRoots() / workspace().
**Parameters**
*(none - takes no arguments)*
**Sandbox** - Sandbox needs **`fileRead`** (L3). Reports the boundaries only; it reads no file contents.
JS source
```javascript
/**
* Reports the filesystem boundaries these tools operate within.
*
* - readRoots — absolute roots that may be READ (recursively).
* - workingDirectory — the single writable dir; relative paths resolve here.
*
* Uses host helpers: safety.fs.readRoots, safety.fs.workspace.
*/
return {
readRoots: Array.from(safety.fs.readRoots()),
workingDirectory: safety.fs.workspace(),
};
```
readTextFile 🆓
:material-file-document-outline:
file · pipeline L3
Reads a UTF-8 text file from disk and returns its contents as a single string.
**Params** `path`
**Env** -
Click for full reference · params · sandbox · JS source
**More detail**
A relative path resolves under the working directory; an absolute path is allowed anywhere under a readable root (the user's home directory by default). Call `listAllowedDirectories` first to learn the working directory and readable roots. Uses safety.fs.readText().
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `path` | `STRING` | ✓ | Path to read - relative (under the working directory) or absolute (under a readable root) |
**Sandbox** - Sandbox needs **`fileRead`** (L3). A relative path resolves under the working directory; an absolute path may sit anywhere under a readable root (`${user.home}` by default). Call `listAllowedDirectories` to see both.
JS source
```javascript
/**
* Reads a UTF-8 text file inside the playground's FS base directory.
*
* Path is resolved RELATIVE to the base path (which is set via
* `spring.ai.playground.tool-studio.fs.base-path` / TOOL_STUDIO_FS_BASE
* env, defaulting to the user's home directory). Anything attempting
* to escape the base (e.g. `../`) is rejected by safety.fs.
*
* Uses host helper: safety.fs.readText.
*/
if (path == null || path === '') throw new Error('path required');
return safety.fs.readText(path);
```
listDir 🆓
:material-folder-outline:
file · pipeline L3
Lists the immediate entries (files and subdirectories) of a directory. Entries in the working directory come back as relative names; entries elsewhere under a readable root come back as absolute paths. Uses safety.fs.list().
**Params** `dir`
**Env** -
Click for full reference · params · sandbox · JS source
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `dir` | `STRING` | | Directory to list - relative (default '.', under the working directory) or absolute (under a readable root) |
**Sandbox** - Sandbox needs **`fileRead`** (L3). A relative path resolves under the working directory; an absolute path may sit anywhere under a readable root (`${user.home}` by default). Call `listAllowedDirectories` to see both.
JS source
```javascript
/**
* Lists immediate entries (files + directories) of a directory.
*
* Returned as an array of leaf names - no recursion, no full paths.
* Use `findFiles` for recursive globbing.
*
* Uses host helper: safety.fs.list.
*/
const target = (dir == null || dir === '') ? '.' : dir;
return safety.fs.list(target);
```
statFile 🆓
:material-information-outline:
file · pipeline L3
Returns size, last-modified timestamp, and a directory flag for a path (relative under the working directory, or absolute under a readable root). Uses safety.fs.stat().
**Params** `path`
**Env** -
Click for full reference · params · sandbox · JS source
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `path` | `STRING` | ✓ | Path to read - relative (under the working directory) or absolute (under a readable root) |
**Sandbox** - Sandbox needs **`fileRead`** (L3). A relative path resolves under the working directory; an absolute path may sit anywhere under a readable root (`${user.home}` by default). Call `listAllowedDirectories` to see both.
JS source
```javascript
/**
* Returns { size, mtime, directory } for a path inside the FS base.
*
* - size - file size in bytes (0 for directories).
* - mtime - ISO timestamp of last modification.
* - directory - true if the path is a directory.
*
* Uses host helper: safety.fs.stat.
*/
if (path == null || path === '') throw new Error('path required');
return safety.fs.stat(path);
```
lineCount 🆓
:material-counter:
file · pipeline L3
Counts the lines in a UTF-8 text file. Uses safety.fs.lineCount().
**Params** `path`
**Env** -
Click for full reference · params · sandbox · JS source
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `path` | `STRING` | ✓ | Path to the file - relative (under the working directory) or absolute (under a readable root) |
**Sandbox** - Sandbox needs **`fileRead`** (L3). A relative path resolves under the working directory; an absolute path may sit anywhere under a readable root (`${user.home}` by default). Call `listAllowedDirectories` to see both.
JS source
```javascript
/**
* Counts lines in a UTF-8 text file inside the FS base.
*
* Uses host helper: safety.fs.lineCount.
*/
if (path == null || path === '') throw new Error('path required');
return safety.fs.lineCount(path);
```
sliceFile 🆓
:material-content-cut:
file · pipeline L3
Returns a slice of lines from a UTF-8 text file (head / tail / range). `start` is 0-based inclusive, `end` is 0-based exclusive (Python-style slice). Negative values count from the end of the file. Uses safety.fs.slice().
**Params** `path` · `start` · `end`
**Env** -
Click for full reference · params · sandbox · JS source
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `path` | `STRING` | ✓ | Path to the file - relative (under the working directory) or absolute (under a readable root) |
| `start` | `INTEGER` | | First line index (0-based inclusive; negatives from end) |
| `end` | `INTEGER` | | End line index (0-based exclusive; negatives from end) |
**Sandbox** - Sandbox needs **`fileRead`** (L3). A relative path resolves under the working directory; an absolute path may sit anywhere under a readable root (`${user.home}` by default). Call `listAllowedDirectories` to see both.
JS source
```javascript
/**
* Returns lines [start, end) from a UTF-8 text file (Python-slice semantics).
*
* - `start` is 0-based and inclusive.
* - `end` is 0-based and exclusive.
* - Negative values count from the end: -1 == size - 1.
* - Missing `start` / `end` defaults to the file's full range.
*
* Uses host helper: safety.fs.slice.
*/
if (path == null || path === '') throw new Error('path required');
return safety.fs.slice(path, start, end);
```
sortFile 🆓
:material-sort:
file · pipeline L3
Sorts the lines of a UTF-8 text file and returns the sorted lines as an array. Options: reverse / numeric / caseInsensitive / unique. Uses safety.fs.sort().
**Params** `path` · `reverse` · `numeric` · `caseInsensitive` · `unique`
**Env** -
Click for full reference · params · sandbox · JS source
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `path` | `STRING` | ✓ | Path to the file - relative (under the working directory) or absolute (under a readable root) |
| `reverse` | `BOOLEAN` | | Sort descending |
| `numeric` | `BOOLEAN` | | Sort lines numerically |
| `caseInsensitive` | `BOOLEAN` | | Ignore case when comparing |
| `unique` | `BOOLEAN` | | Drop duplicate lines |
**Sandbox** - Sandbox needs **`fileRead`** (L3). A relative path resolves under the working directory; an absolute path may sit anywhere under a readable root (`${user.home}` by default). Call `listAllowedDirectories` to see both.
JS source
```javascript
/**
* Sorts a file's lines and returns them as an array.
*
* Options:
* reverse - descending order
* numeric - numeric comparison (otherwise lexical)
* caseInsensitive - compare lowercased
* unique - drop duplicates
*
* Uses host helper: safety.fs.sort.
*/
if (path == null || path === '') throw new Error('path required');
return safety.fs.sort(path, {
reverse: !!reverse,
numeric: !!numeric,
caseInsensitive: !!caseInsensitive,
unique: !!unique,
});
```
grepFile 🆓
:material-file-find-outline:
file · pipeline L3
Searches a UTF-8 text file for lines matching a JavaScript regex. Returns an array of matching lines (optionally numbered). Uses safety.fs.grep().
**Params** `pattern` · `path` · `caseInsensitive` · `numbered` · `limit`
**Env** -
Click for full reference · params · sandbox · JS source
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `pattern` | `STRING` | ✓ | Regex pattern (JavaScript flavour) |
| `path` | `STRING` | ✓ | Path to the file - relative (under the working directory) or absolute (under a readable root) |
| `caseInsensitive` | `BOOLEAN` | | Match case-insensitively |
| `numbered` | `BOOLEAN` | | Prefix each result with 'N:' (1-based line number) |
| `limit` | `INTEGER` | | Max matches to return (0 = no limit) |
**Sandbox** - Sandbox needs **`fileRead`** (L3). A relative path resolves under the working directory; an absolute path may sit anywhere under a readable root (`${user.home}` by default). Call `listAllowedDirectories` to see both.
JS source
```javascript
/**
* Greps a file's lines against a regex and returns the hits.
*
* Result is an array of matching lines. With `numbered=true` each entry
* is prefixed by its 1-based line number, e.g. "42: TODO fix this".
*
* Uses host helper: safety.fs.grep.
*/
if (pattern == null || pattern === '') throw new Error('pattern required');
if (path == null || path === '') throw new Error('path required');
return safety.fs.grep(pattern, path, {
caseInsensitive: !!caseInsensitive,
numbered: !!numbered,
limit: Number.isInteger(limit) ? limit : 0,
});
```
findFiles 🆓
:material-folder-search-outline:
file · pipeline L3
Recursively finds files matching a glob inside a directory. Glob supports `*` and `?`. Optional max recursion depth and type filter ('file' or 'dir'). Uses safety.fs.find().
**Params** `dir` · `glob` · `maxDepth` · `type`
**Env** -
Click for full reference · params · sandbox · JS source
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `dir` | `STRING` | | Directory to search from - relative (default '.') or absolute (under a readable root) |
| `glob` | `STRING` | | Glob pattern (default '*') |
| `maxDepth` | `INTEGER` | | Max recursion depth (0 = unlimited) |
| `type` | `STRING` | | 'file' \| 'dir' \| omit for both |
**Sandbox** - Sandbox needs **`fileRead`** (L3). A relative path resolves under the working directory; an absolute path may sit anywhere under a readable root (`${user.home}` by default). Call `listAllowedDirectories` to see both.
JS source
```javascript
/**
* Recursively finds entries matching a glob inside a directory.
*
* - Glob accepts `*` and `?` wildcards (POSIX glob, NOT regex).
* - maxDepth limits recursion; 0 means unlimited.
* - type='file' / 'dir' filters; omit to return both.
*
* Uses host helper: safety.fs.find.
*/
const target = (dir == null || dir === '') ? '.' : dir;
const pattern = (glob == null || glob === '') ? '*' : glob;
return safety.fs.find(target, pattern, {
maxDepth: Number.isInteger(maxDepth) ? maxDepth : 0,
type: (type === 'file' || type === 'dir') ? type : null,
});
```
cutFileFields 🆓
:material-table-column:
file · pipeline L3
Extracts selected fields from each line of a delimited file (CSV/TSV/etc.). Uses safety.fs.cut(). 1-based field numbers, comma-separated alternatives via the array.
**Params** `path` · `fields` · `delimiter` · `regex`
**Env** -
Click for full reference · params · sandbox · JS source
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `path` | `STRING` | ✓ | Path to the file - relative (under the working directory) or absolute (under a readable root) |
| `fields` | `ARRAY` | ✓ | Array of 1-based field indices to keep, e.g. [1, 3] |
| `delimiter` | `STRING` | | Field delimiter character or regex (default '\t' tab) |
| `regex` | `BOOLEAN` | | Treat `delimiter` as a regex pattern instead of literal |
**Sandbox** - Sandbox needs **`fileRead`** (L3). A relative path resolves under the working directory; an absolute path may sit anywhere under a readable root (`${user.home}` by default). Call `listAllowedDirectories` to see both.
JS source
```javascript
/**
* Extracts selected fields from each line of a delimited file.
*
* - `fields` - 1-based field indices to keep (array). [1, 3] picks columns 1 and 3.
* - `delimiter` - single character (literal) OR a regex pattern when `regex=true`.
* Defaults to tab (\t).
*
* Uses host helper: safety.fs.cut. Each returned row is a delimiter-joined string.
*/
if (path == null || path === '') throw new Error('path required');
if (fields == null) throw new Error('fields required');
const fieldArr = [];
for (const f of fields) fieldArr.push(Number(f));
return safety.fs.cut(path, {
fields: fieldArr,
delimiter: (typeof delimiter === 'string' && delimiter.length > 0) ? delimiter : null,
regex: !!regex,
});
```
writeTextFile 🆓
:material-file-edit-outline:
file · pipeline L4
Writes a UTF-8 text file inside the working directory (creating parent directories as needed). Overwrites any existing file. Requires `fileWrite` permission on the sandbox.
**Params** `path` · `content`
**Env** -
Click for full reference · params · sandbox · JS source
**Parameters**
| Param | Type | Req | Description |
|---|---|---|---|
| `path` | `STRING` | ✓ | Path to write, inside the working directory |
| `content` | `STRING` | ✓ | Full text content to write (UTF-8) |
**Sandbox** - Sandbox needs **`fileWrite`** (L4). `TOOL_STUDIO_FS_BASE` (default `${user.home}/spring-ai-playground/workspace`) is the workspace root; writes from a chat are confined to a per-conversation subdirectory under it, and the returned `path` is the absolute location actually written. The helper auto-creates parent directories.
JS source
```javascript
/**
* Writes a UTF-8 text file inside the workspace directory.
*
* - Overwrites any existing file at `path`.
* - Path is resolved RELATIVE to the workspace; escape attempts are rejected.
* - This tool needs the `fileWrite` sandbox permission (set on the spec).
*
* Uses host helper: safety.fs.writeText.
*/
if (path == null || path === '') throw new Error('path required');
if (content == null) throw new Error('content required');
const writtenPath = safety.fs.writeText(path, String(content));
return { ok: true, path: writtenPath, bytes: new TextEncoder().encode(String(content)).length };
```
These eleven tools mirror the standard Unix-shell pipeline shape, but every step is a JSON-returning function so the agent can reason between calls:
One configuration value, no real secrets.