LM Studio plugin that gives the model sandboxed access to your local filesystem.
The model can only read and write under the root directories you list in the per-chat config. Writes use a two-step confirmation flow and existing files are backed up before being overwritten — the previous version is always recoverable.
read_file(path) — read a UTF-8 text file. Files larger than the configured size cap are refused.read_dir(path?) — list entries of a directory (directories first, then files, alphabetical). If path is omitted, lists the allowed root (or the list of roots if several are configured). The internal backup directory is hidden from the listing.write_file(path, content, confirm?, confirm_token?) — write a file. See the confirmation flow below.grep(pattern, path?, ignore_case?, max_results?) — search files for lines matching a regex. Pure-TS scan; skips binary files, dotfiles (except .env and .gitignore), and noise directories (node_modules, dist, target, .git, .lmstudio-fs-backup).All paths are sandboxed: any path that resolves outside the allowed roots is refused, including via .. traversal or symlinks (paths are canonicalised with realpath). Relative paths are resolved against the first allowed root; if the first segment matches a root's basename it is stripped, so passing notes/todo.md when the root is ~/Documents/notes does the right thing.
Before any overwrite, the previous file is copied to <root>/.lmstudio-fs-backup/<relative-path>.<timestamp>.bak. Add .lmstudio-fs-backup/ to your .gitignore.
Tested with google/gemma-4-e2b against an allowed root of ~/Documents/tests-fs.
List files (no path needed):
You: Tu peux énumérer les fichiers ?
Model calls
read_dir()with no arguments.Model: Les fichiers actuellement disponibles sont :
poeme.md,quantic.md.
Create a file (two-step write):
You: Crée un fichier
poeme.mdavec un haïku de ton choix.Model calls
write_file({path: "poeme.md", content: "..."})— preview returned, file not written yet.Model: Voici le contenu que j'ai préparé : Vertes feuilles dansent, / Vent d'été doucement souffle, / Chaleur sur la peau. Voulez-vous que je procède à l'écriture ?
You: oui
Model calls
write_file({path, content, confirm: true, confirm_token: "..."})— file written.Model: Le fichier
poeme.mda été créé avec succès.
Overwrite (backup created automatically):
You: Réécris
poeme.mdavec un autre haïku.
read_fileto fetch the current content → preview new write → user approves → confirmed write.Tool result:
{written: true, path: ".../poeme.md", bytes: 65, backup_path: ".../.lmstudio-fs-backup/poeme.md.2026-05-05T12-05-35-891Z.bak"}
Search:
You: Trouve-moi le fichier qui parle de particules.
Model calls
grep({pattern: "particules"}).Tool result:
{matches: [{file: ".../quantic.md", line: 2, content: "Ondes et particules jouent,"}], files_scanned: 2}
Per-chat settings:
| Field | Type | Default | Notes |
|---|---|---|---|
| Allowed root paths | string array | [] | Absolute paths the model can access. Tilde (~) is expanded. Required. |
| Max file size (KB) | numeric | 512 | read_file refuses anything larger. |
| Max grep matches | numeric | 200 | grep stops after this many matches. |
| Max grep files scanned | numeric | 2000 | grep stops after scanning this many files. |
One-click (macOS, Windows): Run in LM Studio
Linux (AppImage): the lmstudio:// deep link doesn't work out of the box because the AppImage doesn't register a scheme handler. Use the CLI instead:
To fix the deep link permanently, create ~/.local/share/applications/lmstudio.desktop:
Then:
After install: in any chat, click the tools button (bottom right of the chat input) and enable filesystem. Then open the plugin's config and add at least one allowed root path — without it, every tool call returns an error.
MIT
write_file(path, content) with no confirm. The tool returns a preview (size, first lines of old and new content) and a confirm_token derived from (path, content).write_file again with the same path and content, plus confirm=true and confirm_token=<token from step 1>.(path, content). If either changes between the preview and the confirm, the write is refused — protects against the model "hallucinating" different content on the second call.lms clone zexigh/filesystem
cd filesystem
lms dev -i # -i / --install: install the plugin into LM Studio
[Desktop Entry]
Name=LM Studio
Exec=/absolute/path/to/LM-Studio.AppImage %u
Type=Application
MimeType=x-scheme-handler/lmstudio;
Categories=Development;
update-desktop-database ~/.local/share/applications/
xdg-mime default lmstudio.desktop x-scheme-handler/lmstudio