How to Configure the Userspace Dev Shim for Local Development

Set the environment variable FUSE_MOUNT=shim and define a MOUNT_POINT directory to run computerd with the userspace development shim, which creates a bidirectional sync between the in-process virtual file system and a host directory without requiring kernel FUSE.

The computerd daemon from the cloudflare/computer repository supports multiple filesystem backends for local development. When you configure the userspace dev shim, you enable a pure-userspace alternative to kernel FUSE that materializes the virtual file system onto your host machine, allowing standard tools to interact with the VFS through a regular directory.

How the Userspace Dev Shim Works

The shim creates a bidirectional, polling-driven synchronization between the in-process virtual file system (VFS) provided by @platformatic/vfs and a regular directory on your host. According to the source code in packages/computerd/src/shim/shim.ts, the implementation uses two distinct paths:

  • VFS → Disk: A watcher (vfs.provider.watchAsync) streams VFS changes to the host directory immediately
  • Disk → VFS: A periodic poll (default ~250 ms) walks the host directory, diffs it against a shadow snapshot, and pushes changes back into the VFS

The shadow map records each path’s kind, size, modification time, and SHA-1 content hash, allowing the shim to suppress echo-loops, skip no-op writes, and resolve conflicting writes on the next reconcile tick.

Selecting the Shim Backend

The computerd daemon can run with three different filesystem backends: real kernel FUSE, macFUSE, or the pure-userspace development shim. The backend is determined in packages/computerd/src/fuse/backend.ts.

To force the userspace shim, set the environment variable:

export FUSE_MOUNT=shim

When set to auto (the default), the daemon attempts kernel FUSE first and falls back to the shim if /dev/fuse is unavailable.

Running the Daemon with Shim Configuration

To start local development with the shim, configure your mount point and run the daemon:

PORT=45678 MOUNT_POINT=/tmp/workspace FUSE_MOUNT=shim \
  npx -p @cloudflare/computerd computerd

This command:

  1. Sets the HTTP port to 45678
  2. Defines /tmp/workspace as the host mount point where VFS contents will materialize
  3. Forces the shim backend instead of kernel FUSE

On startup, the daemon calls materialiseVfsToDisk (defined at packages/computerd/src/shim/shim.ts#L19) to write the entire VFS subtree to the host directory before beginning the sync loops.

Embedding the Shim Programmatically

For custom tooling, import mountShim directly from the package to embed the shim in your own scripts:

import { mountShim } from "@cloudflare/computerd/shim";
import { createVfs } from "@cloudflare/dofs";

// Create an in‑process VFS instance
const vfs = await createVfs();

// Mount the shim at ./local-mount, poll every 200 ms
const shim = await mountShim({
  vfs,
  mountPoint: "./local-mount",
  pollIntervalMs: 200,
});

// Use the mount point for child processes
await exec("npm install", { cwd: "./local-mount" });

// Ensure all VFS writes are flushed to disk before exiting
await shim.flush();
await shim.unmount();

The mountShim function accepts options including vfs, mountPoint, and pollIntervalMs for finer control over synchronization timing.

Forcing Synchronization

While the shim runs automatically, you can force immediate consistency using methods exposed on the ShimMount instance:

  • flush(): Forces a full VFS-to-disk sync (implementation at packages/computerd/src/shim/shim.ts#L99)
  • reconcileNow(): Forces an immediate disk-to-VFS sync, walking the host tree and applying changes via reconcileDiskToVfs (defined at packages/computerd/src/shim/shim.ts#L44)

Use these when you need guaranteed consistency before or after RPC-driven operations:

// After applying remote changes to the VFS
await shim.reconcileNow();   // Guarantees host directory reflects new state

Development Limitations

The userspace dev shim is intended for development only. According to the source analysis, it does not support:

  • Symlinks or hard links
  • Extended attributes (xattrs)
  • Permission bits (chmod/chown)
  • Large file optimization (full reads occur on each change)

Write conflicts resolve on the next tick with the VFS winning ties.

Summary

  • Set FUSE_MOUNT=shim to force userspace mode when kernel FUSE is unavailable or undesirable
  • Configure MOUNT_POINT to define where the virtual file system appears on your host filesystem
  • The shim maintains consistency through a shadow map tracking SHA-1 hashes and polls the host directory every ~250 ms by default
  • Call flush() or reconcileNow() for immediate synchronization outside the normal polling cycle
  • Limitations apply: No symlink support, no extended attributes, and not suitable for production workloads

Frequently Asked Questions

What triggers the userspace shim to activate?

The shim activates automatically when FUSE_MOUNT=shim is set, or when FUSE_MOUNT=auto detects that /dev/fuse is unavailable. The backend selection logic resides in packages/computerd/src/fuse/backend.ts.

How do I adjust the polling speed for disk-to-VFS synchronization?

When embedding the shim programmatically via mountShim, pass the pollIntervalMs option (default 250ms). For CLI usage, you may need to wrap the daemon or modify the environment variable FUSE_SHIM_POLL_MS if your version supports it.

Why are my files not appearing immediately on the host?

The disk-to-VFS path operates on a polling interval (~250ms by default), so changes made directly to the host directory may take up to that interval to reflect in the VFS. Use shim.reconcileNow() to force an immediate sync.

Can I use the shim with large files?

While functional, the shim reads large files fully on each change detection, making it inefficient for big binaries or large datasets. It is optimized for development workflows with source code and configuration files, not media or database files.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →