Skip to main content
Access files in a volume without spinning up a sandbox. This is useful for browsing data, downloading results, or uploading input files.

List Files

List files and directories in a volume:
from moru import Volume

vol = Volume.get("my-workspace")

# List root directory
files = vol.list_files("/")

for f in files:
    if f.type == "directory":
        print(f"[DIR]  {f.name}")
    else:
        print(f"[FILE] {f.name} ({f.size} bytes)")

Download Files

Download file content from a volume:
from moru import Volume

vol = Volume.get("my-workspace")

# Download as bytes
content = vol.download("/README.md")
print(content.decode())

# Save to local file
with open("local_readme.md", "wb") as f:
    f.write(vol.download("/README.md"))

Upload Files

Upload files to a volume:
from moru import Volume

vol = Volume.get("my-workspace")

# Upload from bytes
vol.upload("/data/input.txt", b"Hello, World!")

# Upload from file
with open("local_file.txt", "rb") as f:
    vol.upload("/data/input.txt", f.read())
Upload creates parent directories automatically. You don’t need to create /data/ before uploading to /data/input.txt.

Delete Files

Delete files or directories from a volume:
from moru import Volume

vol = Volume.get("my-workspace")

# Delete a file
vol.delete("/data/old_file.txt")

# Delete a directory recursively
vol.delete("/temp", recursive=True)

File Info

File entries include:
PropertyDescription
nameFile or directory name
pathFull path within volume
type"file" or "directory"
sizeSize in bytes (files only)
modified_at / modifiedAtLast modification time

Pagination

For directories with many files, use pagination:
from moru import Volume

vol = Volume.get("my-workspace")

# Get first page
files, next_token = vol.list_files("/", limit=100)

# Get next page
if next_token:
    more_files, next_token = vol.list_files("/", limit=100, next_token=next_token)

Working with Binary Files

Upload and download binary files like images, archives, and executables:
from moru import Volume

vol = Volume.get("my-workspace")

# Upload binary file
with open("model.bin", "rb") as f:
    vol.upload("/models/model.bin", f.read())

# Download and verify
content = vol.download("/models/model.bin")
with open("downloaded_model.bin", "wb") as f:
    f.write(content)

Common Patterns

Pre-populate Volume Before Sandbox

from moru import Volume, Sandbox

# Create volume and upload data
vol = Volume.create(name="agent-input")
vol.upload("/config.json", b'{"model": "gpt-4"}')
vol.upload("/prompt.txt", b"You are a helpful assistant...")

# Create sandbox with pre-populated volume
sbx = Sandbox.create(
    volume_id=vol.volume_id,
    volume_mount_path="/input"
)

# Config is ready to use
sbx.commands.run("cat /input/config.json")

Download Results After Sandbox

from moru import Volume, Sandbox

vol = Volume.create(name="agent-output")
sbx = Sandbox.create(
    volume_id=vol.volume_id,
    volume_mount_path="/output"
)

# Agent writes results
sbx.commands.run("python generate_report.py > /output/report.txt")
sbx.kill()

# Download results without sandbox
report = vol.download("/output/report.txt")
print(report.decode())

Next Steps