Volume

Volumes: a persistent filesystem you mount into sandboxes and agents.

vol = noclick.Volume.from_name("datasets", create_if_missing=True)
vol.write("/raw/orders.csv", csv_bytes)
with noclick.Sandbox.create(volumes={"/data": vol}) as sb:
    sb.exec("python train.py --data /data/raw")

Paths start at the volume's root (/raw/orders.csv). Folders are real folders, made as files are written into them. What a sandbox or an agent's turn writes is saved every few seconds while it runs, and all of it when it ends; two writers to one file at once: the last one to finish wins.

class Volume

A persistent filesystem: files by path, in folders, that outlive the sandbox or agent turn that wrote them. Mount it with Sandbox.create({ volumes: { "/data": vol } }) or an agent's volumes, or read and write it from your own code. What a sandbox or an agent's turn writes is saved every few seconds while it runs, and all of it when it ends; two writers to one file at once: the last one to finish wins.

Attributes
idstring
namestring
sizeBytesnumber | null
fileCountnumber | null
mountedByVolumeMount[]

The running sandboxes, the agents and the machines that mount it, and at which path.

regionRegionName | null

Always null for now: volumes aren't placed by region yet (region is in invite-only beta).

userIdstring | null
createdAtDate | null
consoleUrlstring | null

This volume in the developer console (null off the hosted API).

createstatic

static create(
  name: string,
  options?: CallOptions & PlacementOptions,
): Promise<Volume>

Create an empty volume (1-64 letters, digits and . _ -), unique by name per user (a taken name throws Conflict with existingId). region is in invite-only beta: the sandbox provider's volumes take no location, so passing one throws NotAvailable.

Parameters
namestringrequired
options.regionRegionNameinvite-only beta

Where it runs or keeps its data (regions()); omitted, your account's default region.

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

The new, empty volume.

fromNamestatic

static fromName(
  name: string,
  options?: CallOptions & PlacementOptions & { createIfMissing?: boolean },
): Volume

A lazy reference to the volume called name. Acting for a user, that user's own volume is found first, then the account's. With createIfMissing the current (or given) user's is created on first use.

Parameters
namestringrequired
options.createIfMissingboolean
options.regionRegionNameinvite-only beta

Where it runs or keeps its data (regions()); omitted, your account's default region.

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

A volume that loads (or is created) the first time it's used. Nothing is sent yet.

fromIdstatic

static fromId(volumeId: string, options?: CallOptions): Volume

A lazy reference to a volume by id.

Parameters
volumeIdstringrequired
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
Returns

A volume that loads the first time you read a field. Nothing is sent yet.

getstatic

static get(volumeId: string, options?: CallOptions): Promise<Volume>

Load a volume by id now; an unknown id raises noclick.NotFound.

Parameters
volumeIdstringrequired
options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

The volume, loaded: its size, how many files it holds, and who mounts it.

liststatic

static list(options?: ReadOptions & { limit?: number }): Promise<Volume[]>

The current user's volumes and the account's (or those userFilter covers).

Parameters
options.limitnumber

Return at most this many.

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

Every matching volume, newest first, fetched page by page.

listPagestatic

static listPage(options?: ReadOptions & PageOptions): Promise<Page<Volume>>

One page of volumes; pass nextCursor back as cursor.

Parameters
options.cursorstring | null

The next_cursor of the page before; omit it for the first page.

options.limitnumber

Return at most this many.

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

A page whose data holds the volumes and whose next_cursor is None on the last page.

write

write(path: string, data: VolumeData): Promise<VolumeEntry>

Write data to path, replacing the file and making any folders it needs (up to 100 MB).

Parameters
pathstringrequired
dataVolumeDatarequired
Returns

The file as written, with its size.

read

read(path: string): Promise<Uint8Array>

The file's bytes (up to 100 MB), as the volume last saved it; a missing file throws NotFound.

Parameters
pathstringrequired
Returns

The file's bytes, exactly as stored; decode text yourself.

listdir

listdir(
  path?,
  options?: VolumeListdirOptions & { limit?: number },
): Promise<VolumeEntry[]>

What's in the folder at path (everything below it with recursive), in path order, fetched page by page.

Parameters
pathstringdefault "/"
options.recursiveboolean

Everything below the folder, not just what's in it.

options.limitnumber

Return at most this many.

Returns

Every entry (or the first limit), fetched page by page.

listdirPage

listdirPage(
  path?,
  options?: VolumeListdirOptions & PageOptions,
): Promise<Page<VolumeEntry>>

One page of listdir; pass nextCursor back as cursor.

Parameters
pathstringdefault "/"
options.recursiveboolean

Everything below the folder, not just what's in it.

options.cursorstring | null

The next_cursor of the page before; omit it for the first page.

options.limitnumber

Return at most this many.

Returns

A page whose data holds VolumeEntrys and whose next_cursor is None on the last page.

remove

remove(path: string, options?: { recursive?: boolean }): Promise<void>

Delete the file or folder at path; a folder that isn't empty needs recursive. A missing path is fine.

Parameters
pathstringrequired
options.recursiveboolean

copy

copy(src: string, dst: string): Promise<VolumeEntry>

Copy the file or folder at src to dst in this volume, replacing what dst held.

Parameters
srcstringrequired
dststringrequired
Returns

The copy at dst.

export

export(): Promise<Operation<ExportBundle>>

Export every file, so the volume can move anywhere: a zip holding them in their folders (under volumes/<name>/files/), with index.jsonl listing each path, its size and when it last changed. wait() resolves to an ExportBundle: the zip at url, valid 7 days.

Returns

An operation whose wait() gives an ExportBundle: the zip at url, valid 7 days.

delete

delete(): Promise<TrashItem>

Delete the volume and its files: it goes to the trash, restorable for 30 days. While a running sandbox or an agent mounts it, this throws Conflict, and a user can't delete the account's (PermissionDenied). Returns its TrashItem.

Returns

Its TrashItem: restore() puts it back.

VolumeEntry

interface VolumeEntry

A file or folder in a volume: its path from the volume's root, its type, a file's size in bytes (null for a folder) and when it last changed.

Attributes
pathstring
type"file" | "directory"
sizenumber | null
updatedAtDate | null
rawJsonObject

The response JSON exactly as the API sent it.