Skip to content

Drive File Management

A drive is a shared, persistent filesystem that your services mount as a directory. Unlike a container's local filesystem — which is wiped on every redeploy — a drive keeps its contents across deploys, and can be mounted read-write by multiple replicas at once.

This page covers how to declare a drive and how to browse, upload, download, and manage its files with mecca drive — no need to shell into a container.

Where drives are declared

Drives are declared in your appmecca.yaml under storage.drives and mounted into services under deploy[].drives. See Configuration: Storage for the schema, size limits, and how mounts work.

Drives are per-branch

Each branch of your app gets its own copy of every declared drive — data written by dev is not visible to main, and vice versa. Every mecca drive command accepts -b/--branch; omit it and the command resolves your production branch.

Drive or bucket?

A drive is a filesystem — your code opens paths, and the CLI can browse and transfer files. A bucket is object storage reached with an S3-compatible client, is far cheaper per gigabyte, and has no CLI transfer commands. Use a drive when your framework expects a directory; use a bucket for bulk storage.

Listing Drives

To see the drives declared for an app and their current usage:

mecca drive list myapp
DRIVE                    SIZE          USED  PERCENT     MEASURED
-----------------------------------------------------------------
media                   10 GB       2.4 GB    24.0%     3 min ago
exports                  5 GB        118 MB     2.3%     3 min ago

For a single drive with its mount points and access-point detail:

mecca drive du myapp media

Both accept -b/--branch (omit to resolve the app's production branch) and the global --json flag.

Browsing Files

ls lists one directory; tree walks a subtree; stat shows one entry's metadata.

# List the root of the drive
mecca drive ls myapp media

# List a subdirectory
mecca drive ls myapp media uploads/2026 -b dev

# Walk a subtree (depth-bounded)
mecca drive tree myapp media uploads --max-depth 3

# Metadata for a single file (never follows a symlink)
mecca drive stat myapp media uploads/photo.jpg

ls and tree accept -n/--limit to cap how many entries are returned, and print a truncation notice if the cap is hit.

Uploading Files

mecca drive upload moves a local file or directory onto the drive. The optional remote_path sets the destination path (or prefix, for a directory); omit it to land at the drive root.

# A single file to the root
mecca drive upload myapp media ./photo.jpg

# A single file to a specific path
mecca drive upload myapp media ./photo.jpg 2026/holiday.jpg

Uploading a whole folder

upload takes one file. Point it at a directory and it refuses:

Error: './photos/' is a directory. Upload files individually.

Use a shell loop, preserving the tree yourself:

cd ./photos
find . -type f -print0 | while IFS= read -r -d "" f; do
  mecca drive upload myapp media "$f" "archive/2026/${f#./}"
done

Pass --overwrite to replace a file that is already there.

Recursive upload is Python-CLI only

pipx run appmecca's mecca drive upload accepts a directory and walks it recursively, with -i/--include filters, skip-if-present resume, and automatic exclusion of symlinks, .DS_Store / Thumbs.db and VCS directories. The mecca you installed from npm or Homebrew does not — see FEATURES #366.

The loop above does none of that filtering, so exclude what you do not want before running it.

Uploads count against the drive's quota

If an upload would push the drive past its declared size_gb, it stops early with a quota exceeded message. Raise the drive's size_gb in appmecca.yaml and redeploy, then re-run — already-uploaded files are skipped. size_gb accepts 1–100 GiB per drive; 100 is the hard platform ceiling, and anything above the free allowance needs a storage grant from your operator. If you need more than that, use a bucket. See Storage for the details.

Add --json for a machine-readable summary (uploaded/skipped/failed counts + a failures[] list).

Downloading Files

# Save to the file's basename in the current directory
mecca drive download myapp media uploads/photo.jpg

# Save to a specific local path
mecca drive download myapp media uploads/photo.jpg -o ./photo.jpg

Managing Files

# Make a directory (-p creates intermediate directories)
mecca drive mkdir myapp media uploads/2026 -p

# Move / rename within the drive
mecca drive mv myapp media uploads/old.jpg archive/old.jpg

# Copy within the drive
mecca drive cp myapp media uploads/photo.jpg backups/photo.jpg

Deleting files

Deletes are destructive and ask you to type the drive's name back:

# Delete one file
mecca drive rm myapp media uploads/photo.jpg

# Delete a directory and everything under it
mecca drive rm myapp media uploads/2026 -r

# Empty an ENTIRE drive (the drive itself stays)
mecca drive purge myapp media

purge additionally requires you to re-type the drive name to confirm. Pass --force to skip the yes/no prompt (you still enter your password for rm, and re-type the name for purge).

The Dashboard

Every mecca drive operation is also available in the dashboard: open your app and choose the Drives tab to browse directories, drag-and-drop uploads (with a progress bar), download, delete (password-confirmed), and create folders.

Downloading a Whole Drive

mecca drive archive myapp media -o ./media.tar.gz

Streams the entire drive into a single .tar.gz and hands back a short-lived download link (omit -o to print the URL instead). The archive is staged in transit storage and expires within a day.

There is a size ceiling (50 GiB / 250,000 files). Over it the command refuses and reports the measured size rather than running unbounded. If the platform cannot size the drive at that moment it also refuses — deliberately, because an uncapped archive is not recoverable while a retry is.

The whole drive, not a subdirectory

Archiving is all-or-nothing per drive. Scoping it to a subdirectory would hand the archiver a caller-chosen path, which sits outside the containment that protects every other drive operation — so it is not offered.

How It Works

The AppMecca API never touches the shared filesystem directly — each read or write is handed to the deploy agent, which performs the operation on the host with kernel-enforced path containment (a file can never escape its drive root, even via a symlink).

Uploads and downloads stage through a private, per-app transit area in AppMecca object storage: an upload goes straight from your machine to that staging area, and the agent then moves it onto the drive; a download is copied off the drive into staging and handed back to you as a short-lived link. Your file never passes through the API.

Next Steps