geode.fs reads and writes files inside the running mod's own directories.
Every call takes a root as its first argument.
The root selects one of the mod's directories, and access is sandboxed to it.
A path that escapes the root (for example with ..) or an absolute path is rejected.
| Root | Directory | Access |
|---|---|---|
"save" |
getSaveDir() |
read + write |
"config" |
getConfigDir() |
read + write |
"persistent" |
getPersistentDir() |
read + write |
"resources" |
getResourcesDir() |
read only |
An unknown root raises a Lua error.
Recoverable failures return nil and an error string. See globals Error shapes.
The sandbox blocks .. and absolute paths and resolves the path inside the root.
It does not block symlinks. A symlink already inside a root can still point outside it.
LuauAPI never creates symlinks, so this only matters if something else placed one.
The sandbox is not a defense against a hostile local filesystem.
geode.fs.read(root: FsRoot, path: string) -> (string?, string?)Reads a file's contents. Returns the contents, or nil and an error message.
geode.fs.write(root: FsRoot, path: string, data: string) -> (boolean?, string?)Writes data to a file, creating parent directories as needed. Returns true, or nil and an error message.
Writing to the read-only resources root fails.
geode.fs.exists(root: FsRoot, path: string) -> (boolean?, string?)Returns true when a file or directory exists, false when missing.
Returns nil and an error message when the path escapes the root or the filesystem fails.
geode.fs.list(root: FsRoot, path: string) -> ({ string }?, string?)Lists the immediate entries of a directory (names, not full paths, not recursive).
Returns an array table, or nil and an error message.
Listings are capped.
geode.fs.mkdir(root: FsRoot, path: string) -> (boolean?, string?)Creates a directory and any missing parents. Returns true, or nil and an error message.
Fails on the read-only resources root.
geode.fs.remove(root: FsRoot, path: string) -> (boolean?, string?)Removes a single file or empty directory (never recursive).
Returns true, or nil and an error message. Fails on the read-only resources root.
Reads, writes, and directory listings are capped.
See Limits and errors.
local data = geode.json.dump({ count = 3 })
assert(geode.fs.write("save", "state.json", data))
if geode.fs.exists("save", "state.json") then
local text = geode.fs.read("save", "state.json")
print(geode.json.parse(text).count) -- 3
endsrc/bindings/geode/GeodeFsBinding.cppsrc/require/PathSandbox.hpptools/luau_codegen/extra_bindings/fs.dluau