upload-local-media
Skill0 starsChanged 41 days agoMITView on GitHub
Uploads images, videos and audio from the user's computer into the Artima media library with a short-lived upload token and curl, then attaches them to post drafts in the right order. Needs a shell, so local files work in Claude Code and Cowork; public https links work everywhere. Use when the user wants to post or upload local photos or videos, make a carousel from a folder, or add files to an Artima draft. Triggers include "post these photos from my folder", "upload ~/Desktop/launch and make a carousel", "add this video to my draft", "nahraj fotky a udělej z nich post", "přidej video k příspěvku".
- Sends data out
In this repository5 other files it gives its agents.
- brand-voice-setupSkill
- calendar-maintenanceSkill
- inbox-triageSkill
- performance-reviewSkill
- weekly-content-planSkill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 2 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 39
Anything else unsupported: leave it out and say why.
- Very specific: line 45
Call get_upload_token. It returns:
- Distinctive: line 51
Treat the token as a secret.
- Very specific: line 64
Always use the uploadUrl that the tool returned.
- Very specific: line 76
Retry only the files that did not come back
ready: Every successful upload creates a new library item, so sending a ready file again … - Very specific: line 78
If you cannot run the command yourself, give the user the exact command with the real uploadUrl, a <token> placeholder, and their file …
- Very specific: line 86
New post: call create_draft_post with socialAccountId from list_accounts (never just a platform), text, postKind, and mediaUrls, which keep …
- Very specific: line 88
If the result has mediaRehostWarnings, tell the user which media did not attach.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Upload local media
Get files from the user's machine into Artima without passing their bytes through the conversation, then use the stored files in drafts.
Ground rules
- This needs a shell. The upload is an HTTPS request that curl sends from the user's computer, so it needs a tool that runs shell commands. That means Claude Code, or Cowork running on the user's computer. If this session has no shell, or the shell cannot reach the Artima host because of sandbox network rules, say so plainly and offer one of these instead:
- a public
https://link to the file, whichupload_mediacan fetch (url); - uploading the files in the Artima app, then picking them from
list_media; - giving the user the curl command to run themselves (step 4).
- a public
- No base64 for real files.
upload_mediawithbase64sends the bytes through the conversation. Use it only for tiny files of about 20 kB or less, never for photos or video. - Never claim an upload that did not happen. A file is in Artima only when the upload response lists it with
status: "ready"and aurl. - Role. Uploading needs the Editor role or higher.
get_upload_tokenrefuses lower roles with a readable message; relay it and stop. - Publishing is separate. This skill creates drafts. Scheduling or publishing needs the user's explicit yes to the exact post and time.
Limits
| Accepted | Max per file | |
| Images | JPEG, PNG, WebP, GIF | 25 MB |
| Video | MP4, MOV (QuickTime) | 300 MB |
| Audio | MP3, WAV | 50 MB |
At most 20 files and 500 MB per request. Artima detects the type from the file's content, not its name. HEIC/HEIF, AVIF, TIFF, PDF and other formats are rejected even when renamed.
Workflow
1. Check the files locally
List the files with their sizes (for example ls -l) and check their real types (for example file). Then sort them out before uploading:
- HEIC or another unsupported image: tell the user and offer to convert it to JPEG in a temporary folder, for example with
sips -s format jpeg in.heic --out /tmp/artima-upload/in.jpgon macOS. Never overwrite the originals. - Too large: offer to downscale images, for example with
sips -Z 4096. Video over 300 MB needs to be compressed or uploaded in the app. - Anything else unsupported: leave it out and say why.
Agree the carousel order with the user. It is the order you will pass in mediaUrls.
2. Get an upload token
Call get_upload_token. It returns:
token: upload-only, valid for 15 minutes, bound to the active workspace;uploadUrl: where to send the files;limits, and an example command.
Treat the token as a secret. Use it in the command, but do not repeat it in your messages or summaries.
3. Upload in one request
Send all files in one curl call, with one -F per file. Quote paths that contain spaces:
curl -sS -X POST "<uploadUrl>" \
-H "Authorization: Bearer <token>" \
-F "file=@/Users/me/Desktop/launch/hero.jpg" \
-F "file=@/Users/me/Desktop/launch/detail 2.png"Always use the uploadUrl that the tool returned; don't type a host yourself. Split more than 20 files, or more than 500 MB, into several requests.
4. Read the result per file
The response is JSON with a files list. Partial success is normal:
status: "ready": keep itsurl(andmediaId).status: "rejected":error.codeisunsupported_media_typeorfile_too_large(withlimitBytes). Tell the user which file and why.status: "error": a permission problem or a failed upload. Report the message.
HTTP 401 means the token expired: call get_upload_token again. HTTP 403 means a role or workspace problem.
Retry only the files that did not come back ready. Every successful upload creates a new library item, so sending a ready file again makes a duplicate.
If you cannot run the command yourself, give the user the exact command with the real uploadUrl, a <token> placeholder, and their file paths. Ask them to paste back the JSON response.
5. Files that are already online
For a public https:// link, call upload_media with url (up to 300 MB). It returns a durable url in the user's library. list_media (with nameFilter, pageSize up to 100, and hasMore for paging) finds files that are already in the library.
6. Attach to a draft
- New post: call
create_draft_postwithsocialAccountIdfromlist_accounts(never just a platform),text,postKind, andmediaUrls, which keep their order. Files ending in.mp4or.movare attached as video. UsepostKind: "Reels"when the user wants an Instagram Reel. - Existing post:
update_draftreplaces the whole media list, so pass every URL the post should keep, not only the new ones. On a plain draft it returns anewPostId; use that ID from then on. - If the result has
mediaRehostWarnings, tell the user which media did not attach.
7. Report
| File | Result | Library URL |
| hero.jpg | ready | https://… |
| IMG_0412.HEIC | converted to JPEG, ready | https://… |
| notes.pdf | skipped: not a supported type | – |
Then give the draft's post ID and first line. Ask before scheduling or publishing it.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

