# How to Integrate Cloudflare Artifacts with the Computer Workspace Filesystem

> Integrate Cloudflare Artifacts with your Computer workspace filesystem. Learn to wrap your Worker entry-point with withWorkspace, register artifacts, and expose bindings in wrangler.toml.

- Repository: [Cloudflare/computer](https://github.com/cloudflare/computer)
- Tags: how-to-guide
- Published: 2026-08-07

---

**Integrate Cloudflare Artifacts with the Computer workspace filesystem by wrapping your Worker entry-point with `withWorkspace`, registering the `artifacts` command via `defineArtifactsCommand`, and exposing an Artifacts binding in [`wrangler.toml`](https://github.com/cloudflare/computer/blob/main/wrangler.toml).**

The **Computer** project (cloudflare/computer) provides a Worker-Shell sandbox with a virtual workspace filesystem backed by Durable Objects and SQLite. This architecture lets you push and pull files to Cloudflare Artifacts without granting the sandbox direct network access—all I/O happens through a host-side bridge.

## How the Artifacts Integration Works

The integration relies on three cooperating layers: a **virtual filesystem** for storage, a **host-side client** for network operations, and a **command bridge** that connects them over RPC.

### The Workspace Filesystem Layer

The workspace is a Cap'n Proto-driven virtual filesystem mounted inside the worker-shell. It stores file hierarchies in SQLite via `@cloudflare/dofs`.

- **Source**: [`packages/computer/src/workspace.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts)
- **Key insight**: The filesystem persists state across Worker invocations through Durable Objects, making it ideal for CI/CD artifacts that must survive between steps.

### The `withWorkspace` Helper

`withWorkspace` transforms a standard Cloudflare Workers script into a workspace-enabled environment. It:

1. Creates the Durable Object client for state persistence
2. Boots the virtual FUSE driver
3. Injects the `git` and `artifacts` commands into the shell

```typescript
// packages/computer/src/with-workspace.ts usage pattern
export default withWorkspace({
  customCommands: [defineArtifactsCommand(host)],
});

```

Without this wrapper, the sandbox lacks both the filesystem mount and the custom command registration.

### The Host-Side Artifacts Bridge

Network access violates the sandbox's "no-network" guarantee. The `defineArtifactsCommand` function solves this by forwarding `artifacts` calls from the sandbox to a host-side implementation that performs actual HTTP requests.

**Core file**: [`packages/computer/src/backends/worker-shell/artifacts-command.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-shell/artifacts-command.ts)

This bridge handles:

| Aspect | Implementation |
|--------|----------------|
| Command forwarding | Receives `argv`, `env`, `cwd` from sandbox |
| Result marshalling | Returns structured `ArtifactsCLIResult` (`stdout`, `stderr`, `exitCode`) |
| Error translation | RPC failures become shell-visible non-zero exit codes |
| Git remote injection | `remoteAdd` callback connects Artifacts `create` flow to workspace remotes |

The `remoteAdd` shim is critical: when you run `artifacts create`, the CLI needs a Git remote to push a bundle. The bridge creates a temporary remote pointing at the workspace's sync driver, which then applies the bundle to the virtual filesystem.

## Configuration Steps

### Step 1: Add the Artifacts Binding

Declare the Artifacts client in your Worker's type definitions:

```typescript
// worker-configuration.d.ts
export interface Bindings {
  /** Cloudflare Artifacts client injected by Wrangler */
  ARTIFACTS: Fetcher;
}

```

Then reference it in your [`wrangler.toml`](https://github.com/cloudflare/computer/blob/main/wrangler.toml):

```toml
[[artifacts]]
binding = "ARTIFACTS"

```

### Step 2: Implement the Host Interface

Create a host object satisfying the interface expected by `defineArtifactsCommand`:

```typescript
// src/index.ts
import { withWorkspace } from "@cloudflare/computer";
import { defineArtifactsCommand } from "@cloudflare/computer/backends/worker-shell/artifacts-command";

interface Host {
  git: { cli(input: GitCLIInput): Promise<GitCLIResult> };
  artifacts: { cli(input: ArtifactsCLIInput): Promise<ArtifactsCLIResult> };
}

const host: Host = {
  git: {
    cli: async (input) => {
      // Your Git implementation (also host-side)
      return { stdout: "", stderr: "", exitCode: 0 };
    },
  },
  artifacts: {
    cli: async (input) => {
      // Forward to the bound Artifacts client
      const { ARTIFACTS } = env;
      return ARTIFACTS.cli(input);
    },
  },
};

export default withWorkspace({
  customCommands: [defineArtifactsCommand(host)],
});

```

The `env` object contains your Workers bindings. The Artifacts client runs outside the sandbox, preserving the security boundary.

### Step 3: Use Artifacts Commands in Shell Scripts

Inside the worker-shell, the `artifacts` command behaves like a standard CLI:

```bash

# Push current workspace to a bucket

artifacts push my-bucket .

# Retrieve artifacts into the workspace

artifacts pull my-bucket .

# Inspect bucket contents

artifacts list my-bucket

```

The shell automatically captures working directory and environment state. For programmatic use:

```typescript
import { exec } from "just-bash";

// Create a new artifact version with automatic Git bundling
await exec(
  ["artifacts", "create", "--name", "release-v1.2.3", "--bucket", "my-bucket"],
  { env: new Map([["CI", "true"]]), cwd: "/build/output" }
);

// Push workspace contents
await exec(["artifacts", "push", "my-bucket", "."], { env: new Map(), cwd: "/" });

// Verify
const { stdout } = await exec(["artifacts", "list", "my-bucket"], { env: new Map(), cwd: "/" });

```

## The `artifacts create` Flow Deep-Dive

The `create` sub-command requires special handling because Artifacts expects to push a Git bundle. The bridge implements this through the `remoteAdd` callback injected into the CLI environment:

1. Sandbox invokes `artifacts create --name X --bucket Y`
2. Bridge forwards to host-side Artifacts client
3. Client calls `remoteAdd(url)` to register a temporary Git remote
4. Remote URL points to the workspace's sync driver (loopback RPC)
5. Artifacts CLI pushes Git bundle to this remote
6. Sync driver applies bundle to the virtual filesystem
7. Operation completes; temporary remote is cleaned up

This design lets the Artifacts CLI use standard Git operations while keeping all network I/O on the host side.

## RPC Contract Reference

Communication between sandbox and host uses the loopback channel defined in [`docs/08_capnweb_interface.md`](https://github.com/cloudflare/computer/blob/main/docs/08_capnweb_interface.md). The sandbox only needs these type shapes:

```typescript
// Input from sandbox to host
interface ArtifactsCLIInput {
  argv: string[];
  env: Map<string, string>;
  cwd: string;
}

// Result returned to sandbox
interface ArtifactsCLIResult {
  stdout: string;
  stderr: string;
  exitCode: number;
}

```

The `remoteAdd` callback signature:

```typescript
type RemoteAddCallback = (url: string) => Promise<void>;

```

All actual HTTP requests to the Artifacts service occur in the host implementation, never in the sandbox.

## Key Source Files

| Path | Purpose |
|------|---------|
| [`packages/computer/src/backends/worker-shell/artifacts-command.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-shell/artifacts-command.ts) | Command bridge implementation |
| [`packages/computer/src/backends/worker-shell/artifacts-command.test.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-shell/artifacts-command.test.ts) | Unit tests for error handling and edge cases |
| [`packages/computer/src/workspace.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts) | Virtual filesystem backed by Durable Objects |
| [`packages/computer/src/with-workspace.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/with-workspace.ts) | Entry-point wrapper enabling workspace + commands |
| [`examples/artifacts/src/index.ts`](https://github.com/cloudflare/computer/blob/main/examples/artifacts/src/index.ts) | Minimal working integration example |

## Summary

- **Cloudflare Artifacts integration** requires three components: a workspace filesystem, a host-side Artifacts client, and the `defineArtifactsCommand` bridge
- **`withWorkspace`** wraps your Worker to enable the virtual filesystem and register custom commands
- **The host object** performs all network I/O; the sandbox sees only structured CLI results
- **`remoteAdd`** enables Git-based artifact creation without violating sandbox constraints
- **RPC over loopback** keeps security boundaries intact while providing full Artifacts functionality

## Frequently Asked Questions

### What prevents the sandbox from making direct network calls to Artifacts?

The worker-shell sandbox has no native `fetch` capability. The `artifacts` command is a synthetic shell built-in that forwards arguments over an RPC channel to the host. The host, running outside the sandbox, possesses the actual `ARTIFACTS` binding and performs HTTP requests. This architecture is enforced by the Cap'n Proto capability system described in [`docs/08_capnweb_interface.md`](https://github.com/cloudflare/computer/blob/main/docs/08_capnweb_interface.md).

### Why does `artifacts create` need a Git remote?

Artifacts stores versions as Git bundles for deduplication and efficient delta transfers. The `create` sub-command builds a bundle from the current workspace state and pushes it to the service. The `remoteAdd` shim creates a temporary remote pointing at the workspace's sync driver, allowing the standard Git push protocol to apply the bundle locally before the host uploads it.

### Can I use Artifacts commands without the workspace filesystem?

No. The `defineArtifactsCommand` function expects a `remoteAdd` callback that connects to the workspace's Git sync driver. Without `withWorkspace`, this callback is unavailable, and `artifacts create` fails. For simple object storage without Git semantics, use the raw `ARTIFACTS` binding directly in your Worker handler instead of routing through the Computer shell.

### How do I debug failed `artifacts` commands?

Check three locations: (1) the `exitCode` and `stderr` in `ArtifactsCLIResult` returned to the shell, (2) the host-side Artifacts client logs in your Worker tail, and (3) the workspace sync driver state in [`packages/computer/src/workspace.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts). The bridge converts all RPC errors to non-zero exit codes, so standard shell error handling applies.