https://github.com/corca-ai/cf-vfs
Virtual file-system for Cloudflare Durable Objects and R2
https://github.com/corca-ai/cf-vfs
cloudflare-workers durable-objects r2 sqlite virtual-filesystem
Last synced: 2 days ago
JSON representation
Virtual file-system for Cloudflare Durable Objects and R2
- Host: GitHub
- URL: https://github.com/corca-ai/cf-vfs
- Owner: corca-ai
- License: mit
- Created: 2026-07-19T13:09:43.000Z (7 days ago)
- Default Branch: main
- Last Pushed: 2026-07-21T01:21:11.000Z (6 days ago)
- Last Synced: 2026-07-21T01:26:52.588Z (6 days ago)
- Topics: cloudflare-workers, durable-objects, r2, sqlite, virtual-filesystem
- Language: TypeScript
- Homepage:
- Size: 313 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# cf-vfs
`cf-vfs` is a tree-shakable byte-oriented virtual filesystem and Bash-compatible
runtime for Cloudflare Workers. The default shell API executes independent,
complete source units; an optional `/shell/interactive` entry point preserves
shell state between units. One SQLite-backed Durable Object owns a strongly
consistent pathname namespace. Files up to 8 MiB can be stored inline and read
by shell utilities; large payloads live as immutable R2 objects and are
intentionally opaque to the shell.
```ts
import { DurableObject } from "cloudflare:workers";
import { Shell, type RemoteExecuteTextOptions } from "@corca-ai/cf-vfs/shell";
import { defaultShellCommands } from "@corca-ai/cf-vfs/shell/commands/default";
import { DurableObjectFileSystem } from "@corca-ai/cf-vfs/storage/do-sql";
import { R2OpaqueStore } from "@corca-ai/cf-vfs/storage/r2";
interface Env {
WORKSPACES: DurableObjectNamespace;
FILE_BODIES: R2Bucket;
}
export class WorkspaceFiles extends DurableObject {
private readonly fileSystem: DurableObjectFileSystem;
private readonly shell: Shell;
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
this.fileSystem = new DurableObjectFileSystem(ctx.storage, {
opaqueStore: new R2OpaqueStore(env.FILE_BODIES),
workspaceId: ctx.id.toString(),
});
this.shell = new Shell({
fileSystem: this.fileSystem,
commands: defaultShellCommands,
});
}
executeText(options: RemoteExecuteTextOptions) {
return this.shell.executeText(options);
}
override async alarm() {
await this.fileSystem.drainGarbage();
}
}
export async function execute(env: Env, workspaceId: string) {
const workspace = env.WORKSPACES.getByName(workspaceId);
return workspace.executeText({
script: `find src -name '*.ts' | sort > files.txt`,
cwd: "/workspace",
});
}
```
`WorkspaceFiles` extends only Cloudflare's required `DurableObject`; the cf-vfs
parts are composed normally. `DurableObjectFileSystem` stores paths and inline
bytes in `ctx.storage` (SQLite), while `R2OpaqueStore` connects the `FILE_BODIES`
R2 binding for opaque-body verification and garbage collection. `WORKSPACES`
routes each workspace to its Durable Object. See [Getting
started](docs/getting-started.md) for the Wrangler bindings, migration, and
direct-to-R2 upload path.
From a repository checkout, run `npm run repl` for a local line-oriented
session backed by the in-memory VFS. `npm run repl:sqlite` runs the same
terminal UI against a disposable SQLite-backed Durable Object in local
workerd.
This is an application runtime, not an operating-system shell or POSIX ABI. It
does not launch processes, mount a host filesystem, or provide OS TTY/job
control. The supported language is an explicit versioned subset, and every
parser, execution, stream, mutation, and storage boundary is bounded.
The pre-1.0 stream-first redesign is intentionally breaking. The old
`{ command, input }` structured executor and text/binary storage split have
been removed.
Read [docs/index.md](docs/index.md) for setup, language and command semantics,
the SQLite/R2 lifecycle, limits, benchmarks, and compatibility details.
## License
MIT