Files
Upload, download, and delete files in the guest, and watch a directory for changes. The examples use the Go SDK, the E2B SDK, and kibo workspace file. Programs transfer file content over /v1/files and manage directories with FilesystemService; see With the API.
Uploading and downloading
The following examples upload a file and then download it again. The Go example uses the client from Connect to ctrl:
session, err := dataplane.Open(client, workspaceID, dataplane.WithScopes(
ctrlv1.DataPlaneScope_DATA_PLANE_SCOPE_FILE_READ,
ctrlv1.DataPlaneScope_DATA_PLANE_SCOPE_FILE_WRITE,
))
if err != nil {
log.Fatal(err)
}
defer session.Close()
content := "hello\n"
if _, err := session.PutFile(ctx, "/data/report.txt", strings.NewReader(content), int64(len(content)), dataplane.PutOptions{}); err != nil {
log.Fatal(err)
}
file, err := session.GetFile(ctx, "/data/report.txt", dataplane.FileOptions{})
if err != nil {
log.Fatal(err)
}
defer file.Close()
data, err := io.ReadAll(file)Uploading
kibo workspace file put and the Go SDK's PutFile check the size and SHA-256 digest after the upload. The flags below are those of kibo.
| Flag | Effect |
|---|---|
--mode | Permissions of a new file, in octal. Defaults to 0600 |
--create-only | Makes the upload fail if the target already exists |
When the local path is -, put reads from standard input. This command writes a short text file:
echo hello | kibo workspace file put "$workspace_id" - /data/hello.txtDownloading
get first writes to a temporary file next to the target and replaces the target only after everything has arrived. On failure, the target is unchanged.
- For the permission rules of download targets, see Writing downloaded files.
- When the local path is
-,getwrites to standard output.
This command prints the first lines of a file in the guest:
kibo workspace file get "$workspace_id" /data/report.txt - | head -n 20Size and time limits
- An upload is at most 1 GiB; a larger file fails with
resource_exhausted. Downloads have no size limit:kiboreads a file over 1 GiB in parts, and if the file is rewritten during the download, it exits with an integrity failure and leaves the local target unchanged. - Each transfer runs at up to 64 MiB/s.
- Uploads and downloads are not limited by the global
--timeoutand can take as long as they need.--timeoutlimits only the requests sent to ctrl before the transfer. - A transfer that sends and receives no data for one continuous minute exits with a failure.
Deleting
delete deletes a file or directory in the guest. A directory is deleted with everything in it. The command is also available as rm, and -y (--yes) skips the confirmation:
kibo workspace file delete "$workspace_id" /data/report-copy.txt --yesWatching a directory
The watch subcommand prints changes to the entries of a directory, one per line, until you press Ctrl-C. This command watches the Volume:
kibo workspace file watch "$workspace_id" /dataEach line gives the event and then the entry's path. --entry also prints the metadata of each entry.
| Event | Meaning | Path |
|---|---|---|
CREATE | An entry was created or moved in | The new entry |
WRITE | File content was written | The written file |
CHMOD | Attributes such as permissions, owner, or timestamps changed | The entry |
REMOVE | An entry was deleted | The deleted entry |
RENAME | An entry was moved out or renamed | The original path |
- Only one level is watched. Creating, deleting, and renaming a subdirectory itself are reported as usual, but changes inside the subdirectory are not.
- Consecutive identical changes may be reported only once.
watch exits with a failure in these cases, and later changes are no longer reported:
- The directory is deleted or moved away.
- The Workspace stops.
- Events cannot be delivered in time.
Guest user and paths
Every subcommand accepts --user to choose which guest user reads and writes. Remote paths can be absolute, or relative to the home directory of that user. For the rules, see User and working directory.
With the API
File content travels over the data-plane HTTP endpoint /v1/files, not over RPC. FilesystemService handles directories and metadata, and watches directories with WatchDir.
- Programs need a data-plane credential with the
FILE_READorFILE_WRITEscope; see Requesting a session credential.kiborequests the credentials it needs by itself. - Paths in
/v1/filesandFilesystemServicerequests can be relative to the home directory of the user. For the rules on theuserfield and paths, see User and working directory. - For every parameter, header, status code, method, and message, see /v1/files and FilesystemService.
Transferring file content
/v1/files is at the same data-plane address as the RPC services. GET reads a file and PUT writes one:
GET <endpoint>/v1/files?path=/data/report.txt
PUT <endpoint>/v1/files?path=/data/report.txt&mode=0644&create_only=trueThe query parameters user, mode, and create_only work like the kibo flags --user, --mode, and --create-only. Unknown or repeated parameters and invalid values return 400 (invalid_argument) before the request reaches the guest.
Reading a file:
- One response carries at most 1 GiB. Read a larger file in parts, one
Range: bytes=…range per request. A request with several ranges returns 400. - To make sure the parts come from the same version of the file, send the
ETagof the first response inIf-Range. If the file has changed, the request answers with the whole file instead of the range, or with 413 (resource_exhausted) when the file is over 1 GiB.
Writing a file:
- The body of one
PUTis at most 1 GiB, and a file cannot be written in parts. - When
PUTreturns 200, the file has been written to storage. The response body is JSON:{"path": …, "size_bytes": …, "sha256": …}. Check the size and digest.
Two write failures are not retryable. In both, any existing file at the target stays unchanged:
| Situation | Response |
|---|---|
| The target directory is read-only, even when writing as root | 403 (permission_denied) |
| The file system space or quota is exhausted | 413 (resource_exhausted) |
Write operations of FilesystemService return the same error codes in these two cases.
Every request runs at up to 64 MiB/s. It is aborted when the caller sends no request body or reads no response for 5 seconds. Time spent waiting for the guest does not count.
An error response carries the Connect error code and the ErrorDetail as JSON, so the program can handle it like an RPC error.
Directories and metadata
| Method | What it does |
|---|---|
Stat | Returns the EntryInfo of one path |
ListDir | Lists the entries below a directory, sorted by path, down to depth levels: 1 lists direct children, and the maximum is 64. A listing with more than 10,000 entries fails as a whole with resource_exhausted; list a smaller depth or a subdirectory |
MakeDir | Creates a directory and any missing parents. mode defaults to 0755. An existing directory returns already_exists, and an existing file returns failed_precondition |
Move | Moves or renames an entry and creates the missing parents of the destination. An existing file at the destination is replaced. Moving between file systems, such as from a Volume to the root file system, returns failed_precondition; copy the entry with a command instead |
Remove | Deletes a file, or a directory with everything in it |
Tracking a directory
WatchDir reports changes to the entries of a directory, so the caller does not need to poll. To keep a complete view of a directory:
- Call
WatchDirand wait for the first message,started. - Fetch the full listing with
ListDir. If you fetch it beforestarted, changes in between may be missing from both the listing and the events. - From then on, update from the events. An event only says which path may have changed. For details, call
Stat, or setinclude_entryin the request. - When the stream ends for any reason, start over from step 1.
After started and until the stream ends, every change in the directory produces at least one event. If that cannot be guaranteed, the stream ends with resource_exhausted.
The event types and the one-level rule are the same as for kibo; see Watching a directory. In addition:
pathis the requested directory plus the entry name. If the requested directory is a symbolic link to a directory, it is followed.include_entrymakesCREATE,WRITE, andCHMODcarry the entry'sEntryInfo, which is omitted when the entry no longer exists.- Each Workspace allows at most 64 watch streams. Beyond that, new requests return
resource_exhausted. - Each stream delivers at most 1000 events per second and sends a heartbeat every 10 seconds when idle.
A stream never ends successfully. It ends for these reasons:
| Reason | Error code |
|---|---|
| Events cannot be delivered in time: the guest queue is full, the guest kernel dropped events, or the caller did not read for 5 seconds | resource_exhausted |
| The directory was deleted or moved away, or its file system was unmounted | not_found |
| The credential was revoked, or the Workspace stopped or was deleted | permission_denied, SESSION_REVOKED |
| The guest stopped or is unreachable | unavailable |
| The node switched to a new data-plane process, for example after a node upgrade | unavailable; you can watch again immediately. Some client libraries report this kind of close as a protocol error; see Stream interruptions |
Notes
- If the Workspace's guest is older than
v0.2.0,WatchDirreturnsfailed_precondition(CAPABILITY_UNAVAILABLE). Restart the Workspace to enable it. - If the Workspace's guest is older than
v0.3.0, file requests accept only absolute paths. See Working directory and relative paths.
Next steps
- Commands and terminals: run commands and open terminals in the guest.
- Volumes, export, and restore: keep data independently of a Workspace.
- kibo CLI reference: global flags and local file output.
- API overview: credentials and conventions for your own program.
Commands and terminals
Run a single command in a Workspace and get its output back, or open an interactive terminal in the guest. Both resume by themselves when the connection to the node drops. The examples use the Go SDK, the E2B SDK, and kibo. Programs that call ProcessService directly are covered in With the API.
Services and ports
You can open a service in a Workspace from a browser or client on your machine, publish it at a public URL for others, or connect your own program to a port or socket inside the guest. This page covers each of these, starting with the kibo commands.