Skip to content

ctx.files stable

Host-mediated filesystem access — read, write, list, and watch files through the host rather than calling the platform directly. This is the single privileged chokepoint for the filesystem, which is why it's a core primitive — and where workspace scoping is enforced.

ts
ctx.files: FileService

Example

tsx
// read a file into your viewer
const text = await ctx.files.readText(path);

// write it back
await ctx.files.writeText(path, next);

// react to external changes (e.g. another tool rewrote the file)
const sub = ctx.files.watch(path, (evt) => {
  if (evt.kind === "modify") reload();
});
// ...later
sub.dispose(); // stop watching

Methods

FileService (ctx.files):

MethodWhat it does
readText(path)Read a file as UTF-8 text.
readBytes(path)Read a file's raw bytes (ArrayBuffer).
readDir(path)List a directory's entries as FileMeta[].
pathExists(path)Resolve true if something exists at path.
writeText(path, content)Write UTF-8 text, creating or overwriting.
createDir(path)Create a directory (and missing parents).
rename(oldPath, newPath)Rename / move a file or directory.
delete(path)Delete a file or directory.
reveal(path)Reveal a path in the OS file manager.
watch(path, listener)Watch path recursively; listener gets a FileChangeEvent for changes under it. Returns a Disposable.

Types

FileService · FileMeta · FileChangeEvent · Permission · PathDeniedError.

Workspace scoping

A third-party extension's file access is confined to the open workspace. A relative path resolves against the workspace folder ("src/index.ts"<workspace>/src/index.ts); an absolute path is allowed only if it falls inside a workspace folder. A path outside throws PathDeniedError unless the extension declared the matching Permissionfs:read for reads, fs:write for writes — which the user consents to at install. Prefer relative paths; they're portable across machines. See the Permissions & access guide. (First-party bundled extensions are unscoped.)

Notes

Watching is host-owned: watch(path, listener) expresses intent ("tell me about changes under this path") and the host owns the underlying OS watcher(s). Each listener receives only events scoped to its path — an extension never starts or stops watchers, and never depends on another extension owning the watch.