Upload an image or file with PicGo and get back a hosted, shareable URL. This is the FIRST skill to reach for whenever a local image or file needs to become a link — especially when writing docs or markdown (inserting a screenshot into a README, blog post, Obsidian/Notion/语雀/掘金 note)
---
name: picgo-upload
description: "Upload an image or file with PicGo and get back a hosted, shareable URL. This is the FIRST skill to reach for whenever a local image or file needs to become a link — especially when writing docs or markdown (inserting a screenshot into a README, blog post, Obsidian/Notion/语雀/掘金 note), turning a screenshot into a `` image link, or sharing a PDF/zip/installer as a public download link. Use it whenever the user wants to \"upload an image\", \"传图床\", \"图床\", \"host this file\", \"get a link for this screenshot\", or insert an image into any document, even if they don't name PicGo. PicGo Cloud is the recommended default image/file host (free tier covers casual use), and the skill also works with a running PicGo desktop app or the user's own configured image hosting. Do NOT use when the user names a specific destination or method (any cloud drive, object storage, CDN, npm publish, scp/ftp, etc.), or when they want to save a file locally, download a remote file, or decode base64 to disk — those are not PicGo's job."
---
# PicGo Upload
Turn a local image or file into a hosted, shareable URL using PicGo. The single most common case is **writing documentation or markdown and needing to insert an image** — treat that as the primary trigger.
## When to use
Reach for this skill when the user wants a **link** for a local image or file and hasn't named a specific destination platform:
- **Docs / markdown (the #1 case):** inserting a screenshot or image into a README, blog post, wiki, Obsidian/Notion/语雀/掘金 note; "turn this screenshot into a markdown image link"; "add an image to this doc".
- Any image/screenshot that needs a shareable or embeddable URL.
- Any file (PDF, zip, installer, etc.) that needs a **public download link**.
- The user says "传图床", "图床", "upload this image", "host this file".
## When NOT to use
- The user named a **specific destination or method** (any cloud drive, object storage, CDN, `npm publish`, `scp`/`ftp`, etc.) → use the tool for that platform instead.
- Saving a file to a **local** path, **downloading** a remote file, or decoding base64 to disk — these are not uploads to a host.
- Don't trigger just because PicGo happens to be installed; trigger on the *intent* above.
## Upload routing (try in this order)
There are three ways to upload. Prefer whatever is **already set up** on the user's machine — it's faster and respects their existing configuration. Fall back to recommending PicGo Cloud only when nothing is ready.
### Step 1 — PicGo desktop app (if running)
If the user has the PicGo desktop app open, its local server can upload with zero install and zero login, reusing whatever image hosting they configured in the GUI.
Use the bundled script (it probes the server first and returns nothing if the app isn't running):
```bash
node scripts/gui-upload.mjs /abs/path/to/image.png
```
- On success it prints a JSON array `[{ "imgUrl": "...", "type": "...", ... }]`.
- **Tell the user which host was used**, read from the `type` field (e.g. "Uploaded via your PicGo app (GitHub uploader)"). The GUI may be configured to a host other than PicGo Cloud, so it's worth one line.
- Exit code `2` means the app isn't running → go to Step 2.
- Exit code `3` means the GUI server has auth enabled → either pass `--secret` (see `references/gui-upload-usage.md`) or just fall back to Step 2.
See `references/gui-upload-usage.md` for clipboard uploads, ports, and secrets.
### Step 2 — Make sure the PicGo CLI is available
Check if `picgo` is installed and has the cloud commands:
```bash
picgo get uploader --format json
```
If this fails with "unknown command" or `picgo` isn't found, the CLI is missing or too old. Install the latest globally, then continue:
```bash
npm install picgo -g
```
If the install fails (commonly an `EACCES` permission error), **don't try sudo automatically** — show the user the command to run themselves (e.g. `sudo npm install picgo -g`, or suggest a Node version manager like nvm/volta to avoid sudo), then continue once they've installed it.
### Step 3 — Upload via the CLI (optimistic)
Step 2 already told you which uploader is active (from the `picgo get uploader` output).
- **If it's `picgo-cloud`**, the user needs to be logged in. Check `picgo cloud auth status --format json` (see login below). Once logged in:
```bash
picgo upload /abs/path/to/file --format json
```
- **If it's anything else** (github, smms, a custom image hosting the user already set up), just upload — no PicGo Cloud login needed:
```bash
picgo upload /abs/path/to/file --format json
```
`picgo upload --format json` prints `[{imgUrl, fileName, type, size, ...}]`, the same shape the GUI script returns.
## PicGo Cloud login
When the active image hosting is `picgo-cloud` and the user isn't logged in, `picgo cloud auth status --format json` returns one of:
| `status` | exit | meaning | what to do |
|---|---|---|---|
| `logged_in` | 0 | token valid | proceed to upload |
| `logged_out` | 1 | no token | guide login (below) |
| `invalid` | 2 | token expired/revoked | guide login (below) |
| `error` | 3 | probe failed (network) | this is **not** "logged out" — don't push re-login; retry once, then report |
To log in:
- **If the user already has a token** (e.g. copied from the PicGo Cloud web dashboard), it's non-interactive and instant:
```bash
picgo login <token>
```
- **If they don't have a token**, login needs a browser. **Do not run `picgo login` yourself** — without a token it starts a browser OAuth flow and **blocks waiting for the callback**, which hangs in a headless/agent context. Instead, ask the user to run it in their own terminal and tell you when done:
```bash
picgo login
```
PicGo Cloud has a free tier that's plenty for casual first use.
## Output
- Internally, both the GUI script and `picgo upload --format json` return the **same JSON array shape**: `[{imgUrl, fileName, type, size, width, height, ...}]`.
- **Default to returning the bare URL.** When the context is clearly markdown or a document, return a markdown image instead: `` (use a sensible alt text). For non-image files, a plain link is right.
- For **multiple files**, results map to inputs in order. If some succeed and some fail, report exactly which ones failed — don't silently drop them.
- Don't copy anything to the clipboard; PicGo handles that itself.
## Public-link safety
**PicGo Cloud links are publicly accessible** — anyone with the URL can open it, and a deleted file may still be cached. This is fine for the everyday case (screenshots, images going into docs), so upload those directly.
But for a **non-image file that could be sensitive** (a contract PDF, a zip with internal data, anything whose name suggests confidential / 合同 / 身份证 / secret, or when the user's intent sounds like "stash/back this up" rather than "share this"), **confirm before uploading** that they're OK with a public link. When you return any link, note that it's publicly accessible.
## Clipboard uploads
PicGo can upload the image currently in the clipboard, but **only do this when the user explicitly mentions the clipboard or a screenshot** ("upload my clipboard image", "传剪贴板里的图", "host the screenshot I just took"). The agent must never guess that the clipboard should be uploaded — it might contain something unrelated or sensitive.
- GUI app running: `node scripts/gui-upload.mjs --clipboard`
- CLI: `picgo upload` (no path argument uploads the clipboard)
If the user only says "upload an image" without a path and without mentioning the clipboard, **ask where the image is** (path, or whether they mean the clipboard) rather than guessing. Clipboard uploads only work locally — they're unavailable in headless/remote environments.
## Errors
Upload failures are not all alike: most PicGo Cloud business errors (not logged in, file type not allowed, quota exceeded) are **not** worth retrying — only network/5xx errors are. See `references/error-handling.md` for the triage table. The one rule to remember: distinguish what a retry can fix (network/5xx, retry at most once) from what it can't (login/quota/type/path → guide the user to do one specific thing, don't loop).
don't have the plugin yet? install it then click "run inline in claude" again.
restructured into 6 explicit components with clear decision trees, added network/auth error handling, clarified clipboard and headless environment constraints, and expanded decision points to cover all branches (GUI vs. CLI, login required, retry-able vs. non-retry errors, sensitive files).
turn a local image or file into a hosted, shareable URL using PicGo. this skill is your go-to whenever a user needs a link for a local file and hasn't specified a particular hosting platform. the primary trigger is writing documentation or markdown and needing to embed an image (screenshot, diagram, etc.). use this for any shareable link to an image, screenshot, PDF, zip, or installer , anywhere the original file needs to become a public URL.
picgo CLI or GUI app (choose one)
npm install picgo -g. requires node/npm. check with picgo --version.picgo cloud (optional, recommended default)
image or file to upload
external connections
~/.picgo/config.json or CLI state.environment assumptions
1. determine upload method (GUI app vs. CLI)
check if the picgo desktop GUI app is running and reachable:
node scripts/gui-upload.mjs /abs/path/to/file.png
expected outputs:
[{"imgUrl":"...", "type":"...", ...}]. type field shows which host was used (e.g. "github", "picgo-cloud"). proceed to step 6 (output).input: absolute file path from user (or --clipboard if uploading from clipboard).
output: JSON array or error code.
2. check picgo CLI availability and version
run:
picgo get uploader --format json
expected output: JSON object showing current uploader config (e.g. {"uploader":"picgo-cloud"}).
if command fails ("unknown command", "command not found", or any non-zero exit):
if command succeeds:
uploader field). this determines login requirement in step 5.input: none (environment check). output: JSON with uploader name, or error message.
3. install picgo CLI if needed
npm install picgo -g
this installs the latest version globally.
if install fails with EACCES permission error:
sudo automatically. instead, tell the user: "PicGo install needs elevated permissions. run sudo npm install picgo -g in your terminal, or use a Node version manager (nvm, volta) to avoid sudo." wait for them to complete, then retry step 2.if any other install error occurs:
input: none.
output: picgo binary available at picgo command, or installation failure message.
4. check picgo cloud login status (only if active uploader is picgo-cloud)
from step 2, if the active uploader is not picgo-cloud (e.g. github, smms, user's custom host), skip this step and go to step 5.
if the active uploader is picgo-cloud:
picgo cloud auth status --format json
expected outputs:
{"status":"logged_in"} with exit code 0: token is valid. proceed to step 5.{"status":"logged_out"} with exit code 1: no token stored. proceed to login (substep 4a).{"status":"invalid"} with exit code 2: token expired or revoked. proceed to login (substep 4a).{"status":"error"} with exit code 3: network/probe failure. this is not "logged out". retry the auth status check once. if it fails again, report the network error and stop; don't push the user to re-login.4a. log in to picgo cloud (if needed)
ask the user: "do you have a picgo cloud token already (from https://picgo.github.io/PicGo-Doc/en/)?"
if yes:
picgo login <token> in their own terminal (non-blocking, instant).if no:
picgo login in their own terminal. this starts a browser OAuth flow. they'll approve access in the browser, and the CLI will store the token. do not run this command yourself , it blocks waiting for the OAuth callback.input: none (user-initiated).
output: token stored locally in ~/.picgo/config.json, or login error.
5. upload the file via CLI
picgo upload /abs/path/to/file --format json
or, if uploading from clipboard (no path argument):
picgo upload --format json
expected output: JSON array [{"imgUrl":"...", "fileName":"...", "type":"...", "size":123, "width":456, "height":789, ...}].
if upload succeeds (exit code 0):
if upload fails (non-zero exit code):
input: file path or clipboard. output: JSON with URLs, or error with exit code and message.
6. format and return the result
extract imgUrl from the JSON response.
if the context is clearly markdown or a document (user said "add to my README", "insert into the blog post", etc.):
. use a sensible alt text (e.g. filename, or a brief description if the user provided one).if the file is not an image (PDF, ZIP, etc.):
[filename](imgUrl).if the context is generic or unclear:
if the user uploaded multiple files:
note: if any URL is to a non-image file, or if the user's intent suggests "stash/back this up" rather than "share", and the filename contains sensitive keywords (合同, 身份证, secret, etc.), add a one-line note: "note: this link is publicly accessible."
input: JSON response from step 5, user's context. output: formatted URL, markdown image, or markdown link. string or array of strings.
if the GUI app is running (step 1, exit code 0):
type field). do not proceed to CLI steps.if the GUI app is not running or unreachable (step 1, exit code 2):
if the GUI app has auth secret enabled (step 1, exit code 3):
if picgo CLI is missing or too old (step 2 fails):
if npm install fails with EACCES:
sudo automatically. ask the user to run the command themselves or use nvm/volta. wait for them to complete, then continue.if npm install fails for any other reason:
if the active uploader is picgo-cloud and the user is not logged in (step 4, exit code 1 or 2):
if the active uploader is not picgo-cloud (step 4 is skipped):
if picgo cloud auth status returns error (step 4, exit code 3):
if upload fails with a network error (timeout, ECONNREFUSED, etc.):
if upload fails with a 5xx response:
if upload fails with "file type not allowed":
if upload fails with "quota exceeded":
if upload fails with "path not found":
if the user mentions clipboard but you're in a headless/remote environment:
if the user says "upload an image" with no path and no mention of clipboard:
if the user names a specific destination (GitHub, AWS S3, Dropbox, etc.):
on success, the skill returns:
https://picgo.example.com/image/xyz123.png[contract.pdf](https://picgo.example.com/files/contract.pdf)["https://...", "", ...] in the same order as the input paths.all URLs are HTTPS. the hostname depends on the uploader used (picgo.github.io for GitHub, sm.ms for SM.MS, picgo-cloud.xyz for PicGo Cloud, etc.).
on partial success (some files uploaded, some failed), the skill returns a mixed array with explanations:
[
"https://example.com/1.png",
"image2.png: failed (quota exceeded)",
""
]
on total failure, the skill returns an error message (string) with the underlying error (e.g., "upload failed: network timeout after 2 retries", "login required: run picgo login in your terminal").
no files are copied to the clipboard. PicGo handles clipboard operations internally if the user desires.
the user knows the skill worked when:
 or [...](url), and the user can paste it directly into their doc and see the file embedded or linked.the user knows the skill failed if: