File System
The file system API provides CRUD operations on files and directories within the vault. All paths are validated against the vault root -- any attempt to traverse outside it returns 403 Forbidden.
All paths are relative to the vault root directory (configured via the VAULT_PATH environment variable). Path traversal attacks (e.g., ../../etc/passwd) are blocked by the path validator. Hidden files and directories (names starting with .) are excluded from listings.
Endpoints
List Directory
GET /api/fs/list
List files and directories at the given path. Directories are sorted first, then alphabetically.
Authentication: Required
Query Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
path | string | No | Directory path relative to vault root (default /) |
recursive | string | No | Set to "true" for recursive listing with nested children |
Response: 200 OK
{
"data": [
{
"name": "projects",
"path": "/projects",
"type": "directory",
"modifiedAt": "2026-02-18T10:00:00.000Z",
"children": []
},
{
"name": "readme.md",
"path": "/readme.md",
"type": "file",
"size": 1420,
"modifiedAt": "2026-02-17T15:30:00.000Z"
}
]
}
Errors:
| Status | Condition |
|---|---|
403 | Path outside vault |
404 | Directory not found |
Read File
POST /api/fs/read
Read the contents of a file as UTF-8 text.
Authentication: Required
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
path | string | Yes | File path relative to vault root |
Response: 200 OK
{
"data": {
"path": "/notes/meeting.md",
"content": "# Meeting Notes\n\nDiscussed the new API...",
"modifiedAt": "2026-02-18T09:00:00.000Z"
}
}
Errors:
| Status | Condition |
|---|---|
400 | Missing path or path is a directory |
403 | Path outside vault |
404 | File not found |
Write File
POST /api/fs/write
Write content to a file. Creates the file and any missing parent directories if they do not exist. Overwrites existing files.
Authentication: Required
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
path | string | Yes | File path relative to vault root |
content | string | Yes | File content (UTF-8) |
Response: 200 OK
{
"data": {
"path": "/notes/new-note.md",
"created": true
}
}
The created field is true when the file did not previously exist, false when overwriting.
Create Directory
POST /api/fs/mkdir
Create a new directory. Supports recursive creation (nested paths).
Authentication: Required
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
path | string | Yes | Directory path relative to vault root |
Response: 200 OK
{
"data": {
"path": "/projects/new-project",
"created": true
}
}
Errors:
| Status | Condition |
|---|---|
400 | Missing path |
403 | Path outside vault |
409 | Path already exists |
Rename
POST /api/fs/rename
Rename a file or directory. Both source and destination must be within the vault.
Authentication: Required
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
oldPath | string | Yes | Current path |
newPath | string | Yes | New path |
Response: 200 OK
{
"data": {
"oldPath": "/notes/draft.md",
"newPath": "/notes/published.md"
}
}
Errors:
| Status | Condition |
|---|---|
400 | Missing oldPath or newPath |
403 | Either path outside vault |
404 | Source path not found |
409 | Destination path already exists |
Delete
POST /api/fs/delete
Delete a file or directory. Directories are removed recursively.
Authentication: Required
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
path | string | Yes | Path to delete |
Response: 200 OK
{
"data": {
"path": "/notes/old-note.md",
"deleted": true
}
}
Errors:
| Status | Condition |
|---|---|
400 | Missing path |
403 | Path outside vault |
404 | Path not found |
Move
POST /api/fs/move
Move a file or directory into a destination directory. The destination must be an existing directory -- the source filename is preserved.
Authentication: Required
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
sourcePath | string | Yes | Path of the file/directory to move |
destinationPath | string | Yes | Target directory to move into |
Response: 200 OK
{
"data": {
"oldPath": "/inbox/todo.md",
"newPath": "/projects/webapp/todo.md",
"moved": true
}
}
Errors:
| Status | Condition |
|---|---|
400 | Missing paths, or destination is not a directory |
403 | Either path outside vault |
404 | Source or destination directory not found |
Type Reference
See Database Schema for the full FileEntry type definition.
interface FileEntry {
name: string
path: string // Relative to vault root
type: 'file' | 'directory'
size?: number // Bytes, files only
modifiedAt?: Date
children?: FileEntry[] // Recursive listings only
}