# How to Use Artifacts with Cloudflare Artifacts Binding for Session-Scoped Repositories

> Learn to use Cloudflare Artifacts binding for session-scoped repositories. Initialize an Artifacts client and pass it to Workspace or invoke typed methods directly for automatic namespace isolation.

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

---

**Initialize a session-scoped Artifacts client by calling `createArtifact(env.ARTIFACTS, sessionId)`, then pass it to a `Workspace` or invoke its typed methods directly—all repository names remain local (unprefixed) while the binding handles namespace isolation automatically.**

The Cloudflare Computer SDK provides a built-in **Artifacts** feature that wraps the Cloudflare Artifacts namespace binding with automatic **session-scoping**. This lets multiple concurrent agents share a single namespace without collisions, using a façade that prefixes repository names internally and exposes clean, local names to your code. This guide walks through the architecture, setup, and practical usage based on the actual implementation in [`cloudflare/computer`](https://github.com/cloudflare/computer).

## Architecture: How Session-Scoped Artifacts Work

### The Three Layers

The system separates concerns across three layers:

| Layer | File | Responsibility |
|------|------|----------------|
| **Binding** | Runtime-provided | Cloudflare Artifacts namespace (`env.ARTIFACTS`) with raw operations |
| **Façade** | [`packages/computer/src/artifacts/client.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/client.ts) | `createArtifact(binding, sessionId)` builds a session-scoped `ArtifactClient` |
| **Workspace** | [`packages/computer/src/workspace.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts) | Stores the client as `#artifacts`, exposes via `ws.artifacts` getter |

### Session-Scoping Mechanism

When you create a client with `createArtifact(env.ARTIFACTS, sessionId)`, the SDK:

1. **Prefixes** every repository name with `${sessionId}__` before sending to the binding
2. **Strips** the prefix from returned names so your code sees only local names like `"logs"` rather than `"agent-42__logs"`

This isolation happens transparently in [[`client.ts`](https://github.com/cloudflare/computer/blob/main/client.ts)](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/client.ts), letting you reason about repositories as if each session owns its own namespace.

### Error Handling

Invalid inputs throw specific error types defined in [[`packages/computer/src/artifacts/errors.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/errors.ts)](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/errors.ts):

- `InvalidSessionIdError` — malformed or empty session ID
- `InvalidRepoNameError` — repository name violates naming rules

## Setting Up the Artifacts Binding

### 1. Configure wrangler.toml

Declare the namespace binding in your Worker configuration:

```toml
[[bindings.artifacts]]
name = "ARTIFACTS"
namespace_id = "your-namespace-id-here"

```

### 2. Create the Session-Scoped Client

In your Worker, construct the client once per session:

```ts
import { Workspace } from "@cloudflare/computer";
import { createArtifact } from "@cloudflare/computer/artifacts";

declare const env: {
  ARTIFACTS: Bindings["ARTIFACTS"]; // Cloudflare Artifacts namespace binding
};

const sessionId = "agent-42"; // Typically the worker-agent ID
const artifacts = createArtifact(env.ARTIFACTS, sessionId);

```

The `createArtifact` factory function is implemented in [[`packages/computer/src/artifacts/client.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/client.ts)](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/client.ts).

### 3. Integrate with Workspace

Pass the client to a `Workspace` so downstream code can access it:

```ts
const ws = new Workspace({
  sessionId,
  artifacts: { binding: env.ARTIFACTS, sessionId },
});

// ws.artifacts === artifacts (same client instance)
await ws.artifacts.create("build-cache", {
  description: "CI cache for this agent",
});

```

The workspace stores this as a private `#artifacts` field and exposes it through an `artifacts` getter, per [[`packages/computer/src/workspace.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts)](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts).

## Using the Typed Artifacts API

The `ArtifactClient` provides methods for repository lifecycle management. All accept **local repository names**—the session prefix is applied automatically.

### Creating and Listing Repositories

```ts
// Create a repo scoped to this session
const repo = await ws.artifacts.create("logs", {
  description: "Per-run log storage",
  readOnly: false,
});

// List shows only this session's repositories
const repos = await ws.artifacts.list();
// → [{ name: "logs", description: "Per-run log storage", ... }]

```

### Token Generation

Generate short-lived Git credentials:

```ts
const token = await ws.artifacts.createToken("logs", "write", 3600);
// token: { username: "...", password: "...", expiresAt: ... }

```

### Importing External Repositories

Pin external code into your session namespace:

```ts
await ws.artifacts.import(
  "external-code",
  {
    url: "https://github.com/example/repo.git",
    branch: "main",
    depth: 1,
  },
  {
    description: "Pinned upstream snapshot",
    readOnly: true,
  }
);

```

These methods are documented in [[`docs/15_artifacts_interface.md`](https://github.com/cloudflare/computer/blob/main/docs/15_artifacts_interface.md)](https://github.com/cloudflare/computer/blob/main/docs/15_artifacts_interface.md#typed-surface).

## Using the CLI Inside computerd Shells

The worker-shell backend exposes an `artifacts` command that forwards to the same client. The implementation lives in [[`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)](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-shell/artifacts-command.ts).

### Available Commands

```bash

# Inside a computerd interactive shell

> artifacts repo create cache --description "CI cache"
Repo created: cache (remote https://acct.artifacts.cloudflare.net/git/agent-42__cache.git)

> artifacts repo list
cache

> artifacts token create logs --permission write --ttl 3600

```

The CLI handler calls `ArtifactClient.cli` from [[`packages/computer/src/artifacts/cli.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/cli.ts)](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/cli.ts), which dispatches argv to the appropriate typed method.

## Testing with the Fake Artifacts Binding

Unit tests use `FakeArtifactsBinding` to simulate the Cloudflare Artifacts service without network calls:

```ts
import { FakeArtifactsBinding } from "@cloudflare/computer/tests/utilities/fake-artifacts-binding";
import { createArtifact } from "@cloudflare/computer/artifacts";

const fakeBinding = new FakeArtifactsBinding();
const client = createArtifact(fakeBinding, "test-session");

// Identical API to production
await client.create("tmp");
const list = await client.list(); // → [{ name: "tmp", ... }]

```

The fake binding is implemented in [[`packages/computer/tests/utilities/fake-artifacts-binding.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/tests/utilities/fake-artifacts-binding.ts)](https://github.com/cloudflare/computer/blob/main/packages/computer/tests/utilities/fake-artifacts-binding.ts) and mirrors all production behaviors including session prefixing.

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`docs/15_artifacts_interface.md`](https://github.com/cloudflare/computer/blob/main/docs/15_artifacts_interface.md) | Design documentation, session-scoping rules, method reference |
| [`packages/computer/src/artifacts/client.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/client.ts) | `createArtifact` factory, `ArtifactClient` class |
| [`packages/computer/src/artifacts/cli.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/cli.ts) | Argv-to-client dispatcher |
| [`packages/computer/src/artifacts/errors.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/errors.ts) | `InvalidSessionIdError`, `InvalidRepoNameError` |
| [`packages/computer/src/workspace.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/workspace.ts) | Workspace integration (`ws.artifacts`) |
| [`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) | Shell command implementation |
| [`packages/computer/tests/utilities/fake-artifacts-binding.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/tests/utilities/fake-artifacts-binding.ts) | In-memory test mock |

## Summary

- **Session scoping** isolates repositories by prefixing names with `${sessionId}__` automatically—your code never handles the prefix directly
- **`createArtifact(binding, sessionId)`** in [[`client.ts`](https://github.com/cloudflare/computer/blob/main/client.ts)](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/client.ts) is the single entry point for building a scoped client
- **Workspace integration** stores the client as `#artifacts` and exposes it via `ws.artifacts`
- **CLI commands** inside `computerd` shells route through `ArtifactClient.cli` in [[`cli.ts`](https://github.com/cloudflare/computer/blob/main/cli.ts)](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/cli.ts)
- **Testing** uses `FakeArtifactsBinding` for deterministic, in-memory verification

## Frequently Asked Questions

### What happens if two sessions use the same repository name?

Each session's repositories are isolated by the `${sessionId}__` prefix applied by the façade. Two agents can both create a repo named `"cache"` without conflict—the binding stores them as `agent-42__cache` and `agent-99__cache` respectively, while each client sees only `"cache"`.

### Do I need to manually add the session prefix to repository names?

No. The `ArtifactClient` handles prefixing transparently. Always use local names like `"logs"` or `"build-cache"` in your code. The prefix is stripped from returned names and added to outgoing requests automatically.

### Can I use the Artifacts API outside of a Workspace?

Yes. `createArtifact(env.ARTIFACTS, sessionId)` returns a standalone client you can use directly. The `Workspace` class simply provides convenient storage and access—it's not required for core functionality.

### How do I handle errors from the Artifacts binding?

Catch `InvalidSessionIdError` or `InvalidRepoNameError` from [[`packages/computer/src/artifacts/errors.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/errors.ts)](https://github.com/cloudflare/computer/blob/main/packages/computer/src/artifacts/errors.ts). These are thrown synchronously during validation before any network calls. Binding-level errors (network, permissions) propagate as standard fetch/Cloudflare exceptions.