# upgit: a clipboard-aware uploader that puts your images in a Git repository

> upgit is a Rust CLI that uploads a file, or whatever is on your clipboard, to a Git repository or one of about thirty image hosts and prints a URL back. Its selling point is the editing workflow it targets, with a Typora image uploader and a VSCode extension, and its cost is that the repository has to be public.

**pluveto/upgit** — Another upload hub that supports clipboard. It works well with Typora, Snipaste, VSCode.

- Repository: https://github.com/pluveto/upgit
- Stars: 627 · Forks: 51
- Language: Rust
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/pluveto-upgit

## The problem is leaving the editor to upload a picture

upgit is a native and lightweight tool that uploads any file to your GitHub repository and then gives you a raw URL for it. The framing in the repository description is more specific than that, calling it an upload hub that supports the clipboard and works well with Typora, Snipaste, and VSCode. That points at a particular workflow. You are writing a document, you take a screenshot, and you want an image URL in the text without opening a browser, logging into a web uploader, and pasting the result. The tool is for that moment. It is not a general asset pipeline, and the difference matters. The image ends up in a Git repository you control rather than in a hosted image service with its own account, its own terms, and its own expiry rules, which is the appeal for anyone who has had a link rot in a published document.

## Two input paths: a file argument or the clipboard

The interface offers both. You pass a file path as an argument, and the README notes the file can be a local path or an `http(s)` URL, which is downloaded and then uploaded. Separately there is a `--clipboard` flag for the image currently on the clipboard and a `--clipboard-files` flag for files copied on the clipboard as a file list. The two are deliberately distinct, which tells you the tool is aimed at the case where you have copied a screenshot rather than a file, and at the case where your system clipboard holds files rather than image data. The output side is symmetric. The `-o` option takes stdout or clipboard, with the clipboard choice copying the URL, and the default is stdout, so the URL lands in your terminal where a pipe or a shell script can pick it up.

## Uploading a file is one command and one line of output

The tutorial in the README is short. To upload `logo.png` with rename rules, you execute:

```shell
./upgit logo.png
# for windows: .\upgit.exe logo.png
```

and then you see a link to `logo.png`. To place the same file in a remote folder such as `/my_images/demo`, you add the target directory flag:

```shell
./upgit logo.png -t /my_images/demo
# for Windows: .\upgit.exe logo.png -t /my_images/demo
```

The `-t` option keeps the original filename under that remote directory, which is how you organise a repository that will hold years of screenshots. There is also a `-f` option for the output format, taking url, markdown, or named, so the same upload can emit a plain URL or a ready to paste markdown image reference, and an `-r` flag to skip the link replacements that turn a GitHub URL into a CDN URL. The `--jobs` option sets concurrent uploads with a default of one, meaning serial, which is the sensible default for a tool invoked from a shell script.

## About thirty uploaders, and a warning attached to one of them

The built-in uploader list is long. The CLI help enumerates the identifiers you pass to `--uploader`, including github, s3, aliyunoss, qcloudcos, upyun, qiniu, smms, imgur, catbox, cloudinary, easyimage, lskypro, lskypro2, hello, niupic, imgurlorg, imgbb, chevereto, gitee, dalexni, imgtg, juejin, moetu, netease, sougou, and upload_cc, and the `upgit uploaders` command lists them at runtime. The S3 entry covers a family of compatible services, naming Amazon S3, MinIO, Cloudflare R2, Backblaze, Wasabi, DigitalOcean Spaces, Ceph, Flexify.IO and IBM Cloud Object Storage. One entry carries an explicit warning in the README: Gitee blocks public image bed repositories, so the recommendation there is to prefer SM.MS, S3, or OSS instead. That is a small detail with a large practical meaning, since a uploader that silently fails on a given host is a trap rather than a feature.

## The repository must be public, and the token needs real scope

The configuration section contains the one hard constraint in the project. The repository must be public, because private repos make raw URLs return 404. That single sentence rules out using upgit as a way to distribute private or internal assets, and it also means the images you upload are readable by anyone who knows or guesses the URL. The credential side is spelled out just as precisely. The Personal Access Token can be a classic token with the `repo` scope, or a fine-grained token with Contents: Read and write on that repository, created through GitHub Settings, Developer settings, Personal access tokens. Configuration lives in a `config.toml` written by `upgit init`, which also prints the path, and the sample is `config.sample.toml`. You can also place a `config.toml` next to the upgit binary itself. The README also notes that values can be supplied through environment variables, which is the piece that matters for CI.

## Config, recipes, and a self-updating binary

Two repository features are worth understanding before you commit. First, the `recipes/` directory. The README mentions custom auto renaming rules and CDN support through replacing rules, and a recipe is how those are expressed, so the extension mechanism is a data file rather than a plugin you compile. Second, the update command. `upgit update` replaces the binary with the latest stable GitHub release, with `--beta` and `--alpha` opting into those channels, and the README states that `config.toml` and customized recipes are left in place. That last property is what makes in-place updates safe, and it is also a reminder that a tool which can replace its own binary is one you should be deliberate about. The `--application-path` option exists for the same reason, letting you point at a directory that owns `config.toml`, `history.log`, and `upgit.log`, and the `-n` flag disables writing those log files at all.

## A young Rust project, currently on a beta channel

The release history shows how young this is. v0.3.0 was published on 2026-09-01, v0.3.1-beta.1 an hour and a half later, and v0.3.1-beta.2 about an hour after that, and the workspace version in `Cargo.toml` reads 0.3.1-beta.2, with the edition set to 2021 and the licence MIT. The last push was on 2026-09-02. The repository is a Cargo workspace with three members, `crates/upgit-core`, `crates/upgit-uploaders`, and `crates/upgit`, and the release profile enables link time optimisation, sets a single codegen unit, strips symbols, and aborts on panic, which is the configuration you would expect from a tool distributing a single small binary across three operating systems. The repository also carries `release.toml` for release automation, a `rust-toolchain.toml`, a `scripts/` directory, and `.githooks/`. The practical advice is to pin a version and read the changelog before the next beta lands in your workflow.

## Conclusion

upgit fits a writer or developer who wants to paste an image into a document without leaving the editor, and who is willing to host the files in a public Git repository or an image bed account. It is the wrong tool for confidential material, since the repository must be public for raw URLs to resolve, and the wrong tool for a team that already has a working upload pipeline and needs audit trails or retention rules. Before adopting it, read `config.sample.toml` and the `recipes/` directory, run `upgit uploaders` to see the full uploader list, and set a size limit, because the default of zero bytes means no limit at all.

## FAQ

### How do I install upgit?

Download the latest zip from the Releases page, unzip it, rename the binary to `upgit`, or `upgit.exe` on Windows, and put it somewhere on your PATH. The README lists the archive names per platform, and `upgit update` replaces the binary with the latest stable release afterwards.

### Does upgit work with a private Git repository?

No. The README states that the repository must be public, because private repos make raw URLs 404. The token needs either the classic `repo` scope or fine-grained access with Contents: Read and write on that repository.

### Which uploaders does upgit support?

About thirty, including github, s3, aliyunoss, qcloudcos, upyun, qiniu, smms, imgur, catbox, cloudinary, easyimage, lskypro, lskypro2, hello, niupic, imgurlorg, imgbb, chevereto, gitee, dalexni, imgtg, juejin, moetu, netease, sougou, and upload_cc. The `upgit uploaders` command lists the built-in identifiers.

### How do I upload a screenshot from the clipboard with upgit?

Use the `--clipboard` flag to upload the image currently on the clipboard, or `--clipboard-files` for files copied on the clipboard as a file list. The output can go to stdout by default or to the clipboard with the `-o` option, and the `-f` option can format it as a markdown image reference.

### Can upgit upload a file from a URL?

Yes. The README states the file argument can be a local path or an `http(s)` URL, in which case it is downloaded and then uploaded. The `-t` option keeps the original filename under a chosen remote directory.

## Sources

- [Issues](https://github.com/pluveto/upgit/issues)
- [License: MIT](https://github.com/pluveto/upgit/blob/main/LICENSE)
- [pluveto/upgit on GitHub](https://github.com/pluveto/upgit)
- [README](https://github.com/pluveto/upgit/blob/main/README.md)
- [Releases](https://github.com/pluveto/upgit/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pluveto-upgit
