Host.File (Beamlet v0.1.0)

Copy Markdown View Source

File, scoped to your beamlet's files.

Paths are relative to the files root, and a leading / means that same root: "notes.md" and "/notes.md" are the same file, and .. cannot leave it. Names, arguments and results mirror File's. A function returns :ok, {:ok, value} or {:error, reason} with a posix reason such as :enoent; its bang variant returns the value or raises what File's does, naming the path as you wrote it. Code written for File works here. The one addition: writing, copying and renaming create the parent directories they need.

Host.File.write!("journal/2026/today.md", "entry")
Host.File.read!("journal/2026/today.md")
#=> "entry"

case Host.File.read("settings.json") do
  {:ok, json} -> JSON.decode!(json)
  {:error, :enoent} -> %{}
end

There is one filesystem for the whole beamlet: every agent, every defined module and every process sees the same files, including code serving web routes, so organise shared work with directories. Files persist across evals and restarts. Nothing here runs as anyone, so it works the same from an eval, a controller or a LiveView. ls_r/1 shows everything there is.

Summary

Functions

Copies the file at source to dest, creating parent directories as needed, e.g. cp("draft.md", "archive/draft.md").

Like cp/2, returning :ok or raising File.CopyError.

Copies source to dest recursively, creating parent directories as needed, e.g. cp_r("notes", "backup/notes").

Like cp_r/2, returning the paths copied or raising File.CopyError.

Whether path is a directory.

Whether a file or directory exists at path.

Returns the names in the directory at path, sorted, e.g. ls("journal").

Like ls/1, returning the names or raising File.Error.

Returns every file under the directory at path, sorted, as paths relative to the root, ready to pass to read/1.

Like ls_r/1, returning the paths or raising File.Error.

Creates the directory at path; its parent must exist.

Like mkdir/1, returning :ok or raising File.Error.

Creates the directory at path, including missing parents, e.g. mkdir_p("a/b/c").

Like mkdir_p/1, returning :ok or raising File.Error.

Returns the contents of the file at path, e.g. read("notes.md").

Like read/1, returning the contents or raising File.Error.

Whether path is a regular file.

Renames or moves source to dest, file or directory, creating parent directories as needed, e.g. rename("draft.md", "posts/final.md").

Like rename/2, returning :ok or raising File.RenameError.

Removes the file at path.

Like rm/1, returning :ok or raising File.Error.

Removes the empty directory at path.

Like rmdir/1, returning :ok or raising File.Error.

Writes content to the file at path, creating parent directories as needed and overwriting an existing file, e.g. write("journal/today.md", text).

Like write/3, returning :ok or raising File.Error.

Functions

cp(source, dest)

@spec cp(String.t(), String.t()) :: :ok | {:error, File.posix()}

Copies the file at source to dest, creating parent directories as needed, e.g. cp("draft.md", "archive/draft.md").

Files only; see cp_r/2 for a directory.

cp!(source, dest)

@spec cp!(String.t(), String.t()) :: :ok

Like cp/2, returning :ok or raising File.CopyError.

cp_r(source, dest)

@spec cp_r(String.t(), String.t()) ::
  {:ok, [String.t()]} | {:error, File.posix(), String.t()}

Copies source to dest recursively, creating parent directories as needed, e.g. cp_r("notes", "backup/notes").

Returns the paths copied, relative to the root, or the error with the path it happened on.

cp_r!(source, dest)

@spec cp_r!(String.t(), String.t()) :: [String.t()]

Like cp_r/2, returning the paths copied or raising File.CopyError.

dir?(path)

@spec dir?(String.t()) :: boolean()

Whether path is a directory.

exists?(path)

@spec exists?(String.t()) :: boolean()

Whether a file or directory exists at path.

ls(path \\ "/")

@spec ls(String.t()) :: {:ok, [String.t()]} | {:error, File.posix()}

Returns the names in the directory at path, sorted, e.g. ls("journal").

The root when path is omitted. Files and directories alike, names only; for every file beneath a directory use ls_r/1.

ls!(path \\ "/")

@spec ls!(String.t()) :: [String.t()]

Like ls/1, returning the names or raising File.Error.

ls_r(path \\ "/")

@spec ls_r(String.t()) :: {:ok, [String.t()]} | {:error, File.posix()}

Returns every file under the directory at path, sorted, as paths relative to the root, ready to pass to read/1.

The whole filesystem when path is omitted.

Directories appear through the files they contain; an empty directory is not listed. A fresh filesystem lists as {:ok, []}.

ls_r!(path \\ "/")

@spec ls_r!(String.t()) :: [String.t()]

Like ls_r/1, returning the paths or raising File.Error.

mkdir(path)

@spec mkdir(String.t()) :: :ok | {:error, File.posix()}

Creates the directory at path; its parent must exist.

Writing a file creates its parents on its own, so this is for a directory wanted ahead of any file. See mkdir_p/1 for missing parents.

mkdir!(path)

@spec mkdir!(String.t()) :: :ok

Like mkdir/1, returning :ok or raising File.Error.

mkdir_p(path)

@spec mkdir_p(String.t()) :: :ok | {:error, File.posix()}

Creates the directory at path, including missing parents, e.g. mkdir_p("a/b/c").

mkdir_p!(path)

@spec mkdir_p!(String.t()) :: :ok

Like mkdir_p/1, returning :ok or raising File.Error.

read(path)

@spec read(String.t()) :: {:ok, binary()} | {:error, File.posix()}

Returns the contents of the file at path, e.g. read("notes.md").

read!(path)

@spec read!(String.t()) :: binary()

Like read/1, returning the contents or raising File.Error.

regular?(path)

@spec regular?(String.t()) :: boolean()

Whether path is a regular file.

rename(source, dest)

@spec rename(String.t(), String.t()) :: :ok | {:error, File.posix()}

Renames or moves source to dest, file or directory, creating parent directories as needed, e.g. rename("draft.md", "posts/final.md").

rename!(source, dest)

@spec rename!(String.t(), String.t()) :: :ok

Like rename/2, returning :ok or raising File.RenameError.

rm(path)

@spec rm(String.t()) :: :ok | {:error, File.posix()}

Removes the file at path.

Files only: a directory answers {:error, :eisdir}. Use rmdir/1 for an empty directory.

rm!(path)

@spec rm!(String.t()) :: :ok

Like rm/1, returning :ok or raising File.Error.

rmdir(path)

@spec rmdir(String.t()) :: :ok | {:error, File.posix()}

Removes the empty directory at path.

rmdir!(path)

@spec rmdir!(String.t()) :: :ok

Like rmdir/1, returning :ok or raising File.Error.

write(path, content, modes \\ [])

@spec write(String.t(), iodata(), [File.mode()]) :: :ok | {:error, File.posix()}

Writes content to the file at path, creating parent directories as needed and overwriting an existing file, e.g. write("journal/today.md", text).

Pass [:append] to add to the end instead.

write!(path, content, modes \\ [])

@spec write!(String.t(), iodata(), [File.mode()]) :: :ok

Like write/3, returning :ok or raising File.Error.