SuperAPI AI Directory

stow

Office & productivity

View repository

Updated 11-02 08:37

About this skill

Stow

Stow stores a file and gives back a public URL: https://stow.sh/{26-character id}/{filename}. Anyone with the link can open the file; nobody can list or guess links. Give the user the URL exactly as returned.

Pick a route

  1. Stow MCP tools available (put_file, put_text, put_from_url, create_upload_url, list_files, delete_file, transform_url, get_account): use them. They are signed in already.
  2. A stow command on PATH: use the CLI (below).
  3. Otherwise: use the HTTP API with curl (below).

The CLI and API need an API key. Look in STOW_TOKEN, then ~/.config/stow/token. If neither exists, ask the user to create a key at https://stow.sh/account (under API keys) and save it to ~/.config/stow/token with chmod 600. Never print the key or put it in a file that gets committed.

Upload

With the CLI:

stow put ./render.png                 # prints the URL
stow put a.jpg b.mp4                  # one URL per line
stow put https://example.com/x.jpg    # re-host a remote file
stow put ./clip.mp4 --json            # { url, key, size, contentType }

With curl:

TOKEN="${STOW_TOKEN:-$(cat ~/.config/stow/token)}"
curl -sS -T ./render.png -H "Authorization: Bearer $TOKEN" \
  https://stow.sh/api/files/render.png
# => {"url":"https://stow.sh/.../render.png","key":"...","size":1234,"contentType":"image/png"}

The last part of the path becomes the filename in the link, so URL-encode it. The extension sets the content type. To re-host a remote file without the CLI or MCP, download it first, then upload it.

Limits and errors

Files can be up to 100 MB. A Personal plan holds 10 GB and a Studio plan 100 GB. Errors come back as {"code", "error"}:

Status and code What to do
401 unauthorized The key is missing, wrong or revoked. Ask for a new one.
402 payment_required The account has no plan. Tell the user to subscribe at https://stow.sh/account. Don't retry.
413 too_large Over 100 MB. Compress or trim it, or link the source instead.
413 storage_full The plan is full. Tell the user; they can delete files or move to Studio.
404 not_found No such file, or not theirs.

CLI exit codes: 1 failed (retry once), 2 bad request, too large or storage full, 3 not found, 4 no key, unauthorised or no plan. With --json, stderr gets {"error": {"code", "status", "message"}}.

Transforms

Add query params to any Stow URL. stow url <url> w=800 f=avif builds one, or the transform_url tool. Results are cached, so the same URL is cheap the second time. Unknown params are ignored.

A transform that can't be applied serves the original file instead. Before handing over a thumbnail or poster, check with a GET (HEAD never transforms): curl -s -o /dev/null -D - '<url>' | grep -i x-stow-transform gives ok for a variant and original for a fallback.

Images:

Param Values
w, h pixels, up to 4096
q 1-100, default 80
f webp (default), avif, jpeg, png
fit scale-down (default), contain, cover, crop, pad
gravity auto (subject-aware), face, left, right, top, bottom, center
trim border removes flat borders

Videos (MP4 H.264, up to 100 MB and 10 minutes):

Param Values
w, h pixels, 10-2000
fit contain (default), cover, scale-down
t start time: 5, 5s, 500ms, 1m
d duration, same format
audio=false silent MP4
mode video (default), frame (still), spritesheet, audio (M4A)
f jpg or png for mode=frame
count frames in a spritesheet

Common recipes:

  • Thumbnail: ?w=400&h=400&fit=cover&gravity=auto
  • Poster frame for a video: ?mode=frame&t=1s&w=1280
  • Small preview clip: ?w=480&t=0&d=5s&audio=false

For playback in a <video> tag, use the untransformed URL: it seeks everywhere, while a transformed clip only does once cached. There is no HLS; for long videos, link the original.

List and delete

stow rm https://stow.sh/{id}/{filename}
curl -sS -H "Authorization: Bearer $TOKEN" https://stow.sh/api/files
curl -sS -X DELETE -H "Authorization: Bearer $TOKEN" \
  https://stow.sh/api/files/{id}/{filename}

Only the account that uploaded a file can delete it. Resized copies can keep serving from caches for a while after a delete, so treat a shared link as published.