Sophon 2.0 is here
Sophon Docs
Sophon Node

File Access

Listing, reading, and writing files on a node, with the roots you configure, the caps that apply, and what gets refused.

A node can list, read, and write files on the machine it runs on, but only inside folders you name. Everything outside them is refused before it touches disk.

The filesystem.access scope is not granted when you approve a device. This is one of the escalations you opt into deliberately.

Configuring roots

File access is confined to a configured list of root folders. Out of the box that is the user's Desktop, Documents, and Downloads.

An empty roots list denies everything. It is not a wildcard, and it is not "unrestricted". It is the off switch. Setting it to an empty list is the way to keep the scope granted while turning file access off entirely.

Roots live under fileSystemRoots in the node's config file. Note the capital S, and see the configuration file, which also explains why the spelling matters more than it should.

Choose roots as narrowly as the work allows. A node that only needs to drop reports somewhere should have that one folder, not the whole Documents tree.

Containment

A path is fully resolved before it is tested for containment, not after. That means:

  • ~ is expanded.
  • .. segments are collapsed, so a path cannot climb out of a root by walking upward.
  • Symlinks are followed to their final target, and it is the target that must be inside a root. A link sitting in an allowed folder but pointing somewhere else fails the check instead of escaping through it.

Containment is also tested on a folder boundary rather than a string prefix, so a root of /home/you/work does not accidentally permit /home/you/work-secrets.

On Linux the comparison is case-sensitive, matching the filesystem's own behaviour; on Windows and macOS it is not.

Limits

LimitValueApplies to
Read size512 KBfilesystem.read
Write size512 KBfilesystem.write
Listing length500 entriesfilesystem.list
Binary contentrefusedfilesystem.read
Directory targetsrefusedfilesystem.write

A listing that hits the cap comes back flagged as truncated rather than silently short. A read that finds binary content refuses rather than returning something the model would only mangle. These commands are for text.

The three commands

files.list → filesystem.list

Lists entries in a folder inside a configured root.

ParamTypeDefaultNotes
pathstringrequiredMust resolve inside a root

Returns the entries with their names, sizes, and modified times, plus a flag when the result was truncated at the cap.

files.read → filesystem.read

Reads a text file inside a configured root.

ParamTypeDefaultNotes
pathstringrequiredMust resolve inside a root

Rated Low risk. Refuses binary content, and refuses anything over the size cap rather than truncating it.

files.write → filesystem.write

Writes a text file inside a configured root.

ParamTypeDefaultNotes
pathstringrequiredMust resolve inside a root
contentstringrequiredSubject to the size cap

Rated High risk, so it raises an approval — once, before anything is written, and delivered to the channel the conversation is actually in rather than only to the Dashboard.

Refuses a directory as its target. It also does not create folders: the parent has to exist already and be inside a root, and that parent is checked separately from the path being written, so a new file cannot be dropped just outside one.

One caveat on "always": in an interactive chat turn, approving a High-risk desktop action can cover further High-risk actions on that machine for the rest of the run, so a second write inside that window may not ask again. That standing consent lasts thirty minutes, belongs to one conversation, is cleared by a Gateway restart, and never extends to a workflow, a scheduled run, a webhook or an MCP call — those ask every time. See plan-level consent.

What this is not

There is no file transfer between the Gateway and a node. These commands read and write in place, on the machine, and the content travels as part of the command result like any other. Moving a large file between machines is not something a node does.

Files on the Sophon server itself are a different thing entirely, reached with different tools. files.* means the user's machine.

Where to go next