Skip to content

Local Bash Workspace

The LocalBashWorkspace runs files in a real tmpdir on the host filesystem and runs shell commands as subprocesses. POSIX-only. Suitable for local development and testing where you want real filesystem semantics + the ability to shell out, without spinning up a container.

When to use

  • Local POSIX development. When you want files to persist across reads/writes within a session AND you need actual shell commands (grep, find, git, etc.).
  • Integration tests that exercise real filesystem behavior — file modes, symlink behavior, glob expansion, etc.
  • Trusted code only. This provider runs as the host user with full host privileges. Do NOT use with untrusted input.

For untrusted code, use Cloudflare Sandbox (Firecracker microVM isolation).

Capabilities supported

CapabilitySupported
fs
shell
code
snapshot

The provider advertises { fs: true, shell: true } on its WorkspaceRef.capabilities.

POSIX-only

Windows is not supported. The provider throws at open() time with a clear error message:

LocalBashWorkspaceProvider: Windows is not supported. Use WSL and run the agent inside it.

Windows users should run their agents inside WSL.

Sandbox boundaries

The workspace's filesystem is scoped to a per-session tmpdir created via fs.mkdtemp() under os.tmpdir() (configurable via tmpdirRoot). The internal TmpdirFileSystem enforces the boundary using:

  • realpathSync canonicalization on the tmpdir root at construction time.
  • Ancestor-walk symlink resolution on every fs operation — every component of the requested path is resolved through realpath before access, ensuring no symlink can escape the tmpdir.

This protects against deliberate symlink-escape attacks within the fs methods. It does NOT protect against:

  • Untrusted shell commands. Once the LLM calls workspace__<name>__run('rm -rf /'), the boundary is gone — the shell runs as the host user.
  • Race conditions between symlink creation and use (TOCTOU). The ancestor walk happens immediately before the operation but is not atomic.
  • Code that calls fs APIs outside the workspace (e.g., a custom tool that bypasses the registry).

If you need true isolation against untrusted input, use Cloudflare Sandbox.

Provider config

typescript
interface LocalBashWorkspaceConfig {
  kind: 'local-bash';
}

interface LocalBashProviderOptions {
  /** Override the tmpdir root. Defaults to os.tmpdir(). */
  tmpdirRoot?: string;
  /** Constraints applied to subprocess shell calls. */
  shellConstraints?: SubprocessShellConstraints;
}

shellConstraints controls behaviors like maxStdoutBytes, cwd, env, signal, timeoutMs. See the package source for the full type.

Wiring

typescript
import * as os from 'node:os';
import { defineAgent } from '@helix-agents/core';
import { JSAgentExecutor } from '@helix-agents/runtime-js';
import { InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/store-memory';
import { LocalBashWorkspaceProvider } from '@helix-agents/workspace-local-bash';

const agent = defineAgent({
  name: 'my-agent',
  llmConfig: { model: yourModel },
  workspaces: {
    box: {
      provider: { kind: 'local-bash' },
      capabilities: { fs: true, shell: true },
    },
  },
});

const executor = new JSAgentExecutor(
  new InMemoryStateStore(),
  new InMemoryStreamManager(),
  yourLLMAdapter,
  {
    workspaceProviders: new Map([
      ['local-bash', new LocalBashWorkspaceProvider({ tmpdirRoot: os.tmpdir() })],
    ]),
  }
);

Lifecycle

  • open() — calls fs.mkdtemp() to create a per-session tmpdir prefix helix-ws-{sanitizedSessionId}-{random}. Returns the LocalBashWorkspace and a serializable ref { tmpdir, workspaceId }.
  • resolve() — re-attaches to the same tmpdir if it still exists. If the tmpdir has been cleaned (process exit, another session's close, tmpfs clear), throws WorkspaceEvictedError so the executor's withEvictionRetry can re-open via open().
  • close() — removes the tmpdir recursively. Files are gone after close.

Auto-injected tools

All fs tools, plus workspace__<name>__run for shell. See FileSystem and Shell module pages for schemas.

Production unsuitability warning

⚠️ This provider runs commands as the host user with full host privileges. Never use it with untrusted input or in any context where the LLM could be prompted to attack the host. For production code-execution agents, use CloudflareSandboxWorkspace (Firecracker microVM) or another container-based provider.

Source

Released under the MIT License.