Work in folders
Give a chat a folder and the model can work in it the way a coding assistant does - list, find, read and search the files, and, once you approve each change, write, edit, move and delete them. Everything stays inside that folder, and there is no shell.
Adding a folder
Click the + button next to the message box and choose Add directory, then pick a folder in the system dialog. The same menu’s Add files is something else: it attaches file contents to one message (see Attachments), while a directory gives the model tools over a folder for the rest of the chat.
- Start the chat first on a Space’s page - the message box on a Space’s page starts a new chat, so it has no chat to give a folder to yet: the item is greyed out and reads Send a message first to start this chat. Send the first message, then add the folder in the chat that opens. A new chat started anywhere else can get a folder before its first message.
- Not too wide - the picker refuses a whole drive (
C:\,/) and Loach’s own data folder, which holds every chat. - Switches the tools on - picking a folder turns on Settings → Tools → Workspace files if it was off, and a notice says so. That one switch covers all eight file tools.
The “Working in” notice
For the rest of the chat, the message box reads Working in folder just above where you type, with the full path in its tooltip. Click the folder’s name to open it in your file manager, or remove it with the × beside it; the + menu now offers Change directory. While a reply is running in the chat, the folder can’t be changed or removed - that turn keeps the folder it started with.
The notice shows a LOACHFILE.md badge when the folder has project instructions, and turns amber with tools off if you later switch Workspace files off: while it is off, the model gets neither the tools nor the folder’s instructions.
Forking a chat carries its folder over. Backups and exports never include it - a path means nothing on another machine. If the folder is moved or deleted, the notice still shows it, but the model gets no file tools and no project instructions until you pick the folder again.
What the model can do
Eight tools appear in the model’s catalogue only while the chat has a folder; without one, the model never sees them. All paths are relative to the folder.
list_directory- a tree of a directory, two levels deep by default and at most eight. Dependency and build directories (node_modules,target,dist,.git,.venv, …) are listed but not descended into, and links are marked rather than followed. Stops at 500 entries.find_files- find files by name with a glob, ignoring case:*.rsanywhere, orsrc/**/*.test.tsby path. Stops at 200 results.read_file- a text file’s contents with line numbers, for files up to 4 MB. A bigger file - a log that grows past the limit while it is being read included - is refused with a pointer tosearch_files. Long files come back a page at a time, saying which line to continue from, and lines past 2,000 characters are clipped.search_files- regular-expression search across file contents, case-insensitive by default and optionally limited to some extensions, returning each match with its file and line number. Skips binaries and files over 512 KB, and stops at 100 matches or 2,000 files.write_file- create a file or replace one whole, up to 1 MB, creating missing folders on the way.edit_file- replace an exact snippet in a file of up to 4 MB. A snippet that matches more than once is refused unless the model asks to replace every occurrence, which the approval card points out. One edit may grow a file by at most 1 MB.move_file- rename or move a file or directory, never overwriting anything. A rename that only changes case (readme.md→README.md) works on Windows and macOS too; on a case-sensitive filesystem it is refused when the new name is a separate entry, such as a link.delete_file- remove one file, or one empty directory, per call; there is no recursive delete. Deletion is permanent: nothing goes to the Recycle Bin or Trash.
find_files and search_files go at most eight levels below where they start, and both give up after looking at 50,000 entries. Every tool that stops early says so, so the model can narrow its search rather than conclude a file isn’t there. The skipped dependency and build directories can still be read or searched when the model names one directly.
Deliberately absent: a shell, a recursive delete, and any way to point the tools at a folder other than through the system picker. When something needs a command run - the tests, a build - the model can only tell you which one; the sample LOACHFILE.md asks it to do just that.
Approving changes
Listing, finding, reading and searching never ask. The four tools that change files - write_file, edit_file, move_file and delete_file - pause the reply and ask first, unless you’ve allowed that tool for the chat. The card asks “Allow the model to …?” with the file’s path inside the folder written out in full, and shows the change itself rather than raw arguments:
- Write - the new contents, with their size in lines and bytes, and whether it creates a new file or replaces the existing file (with that file’s size). A long write is cut at 20,000 characters in the card, with a Show all link.
- Edit - a
-/+line diff with removed and added counts. Runs of unchanged lines fold down to three lines of context around each change, and a long diff is cut at 400 rows with a count of what’s below and a Show all link. When an edit adds or removes the line break at the end of its text, the line is marked (no line break after this) - without one, the file’s next line joins it. - Move -
from → to. - Delete - a red card warning that the file is removed from disk and that this can’t be undone from Loach.
Characters that would otherwise display as nothing or reorder the text around them - zero-width spaces, text-direction marks, control characters - are drawn in paths and contents as visible U+… tags, so what you approve reads the way it will be written. Whatever the card cuts for length, the whole change is what gets applied, and the same preview stays in the reply’s tool-call block afterwards.
- Allow once - run this call.
- Allow tool for this chat - run it, and stop asking for that tool in this chat.
- Deny - the model is told you declined and carries on without it.
A card left unanswered for 10 minutes isn’t run, and Stop cancels the reply as usual - though a write, edit, move or delete already running when you press it is let finish, and its real result is recorded before the reply stops.
How far “for this chat” reaches
The answer is kept in memory, never saved, and is tied to the folder it was given for. It ends when you change or remove the chat’s folder, delete the chat, switch Workspace files off, or quit Loach. It covers only Loach’s own tool - never an MCP server’s tool of the same name - and never anything git takes commands from: a .git directory (where a change also shows in no git status or diff), the .husky and .githooks hook folders, a .pre-commit-config.yaml, or a folder laid out as a bare repository (HEAD beside objects and refs), including the change that would complete one. A hook or setting there runs commands the next time you use git, so those always ask.
Staying inside the folder
- Relative paths only - absolute paths and
..are refused up front. - Links are checked - every path is resolved through symbolic links and checked against the folder again before it is used, so a link pointing elsewhere is refused. So is a link whose target doesn’t exist, since writing through it would create that target wherever it points. Deleting or moving a link acts on the link itself, never on what it points to.
- Misleading names are refused - control characters and text-direction characters anywhere in a name (a right-to-left override can make
txt.exelook likeexe.txton the approval card). On Windows also a:(a hidden data stream), a reserved device name (CON,nul.txt,COM1) and a name ending in a dot or a space, which Windows tools can’t open or delete afterwards. - Full names only - on Windows, a path that reaches a file by its 8.3 short name (
IMPORT~1.MDforimportant-notes.md) is refused, since the approval card would name a different file from the one changed; the model is told to use the full name. A file really called something likebackup~1.txtstill works.
Line endings and encodings
Line endings are preserved: editing or overwriting a CRLF file keeps it CRLF. So is the text encoding. Files that aren’t UTF-8 - Windows-1250 or another legacy code page, or UTF-16 with a byte-order mark (what PowerShell 5.1 writes by default) - are read, searched and edited in their own encoding and written back in it, byte-order mark included; only the edited text changes.
- Best guess - a legacy encoding is recognised from the file’s contents - all of it, up to 4 MB, so an accent that first appears deep in the file still counts - and
read_filetells the model which one it used. - Nothing silently lost - a change the encoding can’t store (an emoji in a Windows-1250 file) is refused rather than written as
?, and a file that doesn’t decode cleanly can be read but not edited. Binary files can’t be read or edited at all. - Safe replacement - a write or edit saves a new copy and swaps it in, rather than rewriting the file in place. A write that fails partway leaves the old file intact; a file also hard-linked from elsewhere (a pnpm or uv package store, say) gets its own copy while the other links keep the old contents. Permissions carry over, so a script stays executable, and a read-only file is refused. The new copy has them from the start, so a private
.envis never readable by others mid-write. On Windows, a file with its own access rules keeps them, and if they can’t be copied the write fails rather than widen who can read the file.
Project instructions (LOACHFILE.md)
If the folder has a LOACHFILE.md at its root, its contents are added to the system prompt on every turn - the same idea as a CLAUDE.md or AGENTS.md: the project’s own notes on how to work in it, such as how to run the tests, what not to touch and the house style. A sample is available to start from.
- Read fresh each turn - an edit, yours or one the model makes with
write_file, applies on your next message. - Visible - the “Working in” notice shows a
LOACHFILE.mdbadge with the file’s first line in the tooltip, and the context usage popover lists it as Project instructions (LOACHFILE.md). - Keep it short - anything past 32 KB is cut with a note, and local models follow short instruction files far better. A blank file counts as none.
- Sandboxed like the rest - a
LOACHFILE.mdthat is a link out of the folder is ignored. - The project’s word, not yours - the file goes in ahead of your own instructions, fenced between clear start and end markers, and the model is told it comes from the folder rather than from you: it can’t grant permissions, your instructions win when the two conflict, and anything in it asking to send files or data elsewhere is to be ignored unless you ask for that too. A folder you just cloned can say anything; the approval card on writes, moves and deletions remains the backstop.
Privacy and Private Chat
The tools run inside Loach, but what they read becomes part of the conversation: with a cloud provider, those file contents are sent to it like any other message. The model is also told the folder’s full path, so it knows which project it is working in. Private Chat never gets a folder or the file tools.
The model has to support tool calling to use the folder at all. One reply gets at most 10 rounds with the model, so pointing it at the right files up front - or in LOACHFILE.md - saves rounds spent searching. See “Stopped after 10 tool-use turns”.