PicLite: local-first image and GIF compression for desktop and self-hosted web
PicLite 图轻 / PicLite — privacy-first image and GIF compression for Web, Windows, macOS and Linux.
At a glance
- What is it?
- PicLite is a GPL-3.0 Tauri 2 desktop app and Docker-deployable web workbench that compares candidate formats before writing an output. Here is how the compression policy, folder monitoring and plugin container actually work, and where the browser build stops.
- Who is it for?
- Adopt PicLite if you want image compression to stay on the machine, need a size ceiling such as 200 KB or 100 KB enforced against real encoder output, or want a self-hosted Docker endpoint on port 3456 for a team. Do not adopt it if you need server-side automated compression that runs while your workstation is off, because the folder monitor only runs while the app is running and can merely be minimized to the tray.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What PicLite compresses, and the people it is built for
The README frames the audience directly: self-media workers and developers who handle images repeatedly and do not want a cloud round trip for each one. The import surface is JPEG and JFIF, PNG, WebP and GIF, with conversion, compression and proportional scaling across those formats. Output can overwrite the source file, be renamed inside the same directory, or land in a fixed directory with periodic cleanup. Watermarks and image-host uploads (WebDAV, S3/R2, OSS, FTP, SFTP) are optional steps on top of that pipeline, and the README is explicit that a file only leaves the machine when you actively configure an upload. The desktop client is Tauri 2 with a Rust backend; the package description calls it a local-first, self-hostable image and GIF compression workbench. It is a tool for a person sitting at a machine with a folder of images, not a build-system dependency.
The compression policy: candidate formats, then a size ceiling
The interesting mechanism is not the encoders, it is the selection. The README states that PicLite by default compares candidate formats automatically and picks the smaller result while trying to preserve perceived quality. That is a different shape from a fixed quality slider: you give the tool latitude over the container and the encoder settings, and it returns one file. On top of that sits the size constraint. You can cap output at 200 KB, 100 KB, 50 KB or a custom value, and the app adjusts quality and dimensions according to the real encoded result rather than a predicted one. That distinction matters in practice, because a nominal quality of 80 does not produce a predictable byte count on a photograph with fine texture. The trade-off is honest: a hard ceiling means the tool decides how much detail to discard, and the README does not describe a per-image audit trail for which candidate won. The comparison view (original against result, live size readout, continuous quality and dimension controls) is where you check that decision by eye.
Installing the desktop build and compressing a first image
Releases are the distribution channel. The README lists Windows x64 and ARM64 as .exe, .msi or a portable .zip, macOS Apple Silicon and Intel as .dmg, and Linux x64 and ARM64 as .AppImage or .deb. There is no package-manager install documented. macOS builds are ad-hoc signed, so the README says the first launch may require allowing the app under System Settings, Privacy and Security. Building from source requires Node.js 22.13 or newer, Rust stable and the Tauri 2 system dependencies for your platform. The README gives these three commands for a local development run: npm install pulls dependencies, npm run dev starts the web workbench, and npm run desktop:dev starts the Tauri desktop client.
npm install
npm run dev
npm run desktop:devVerification and packaging use the test and build scripts. npm test runs the web tests and the desktop tests, and npm run desktop:build produces the desktop bundle.
npm test
npm run desktop:buildAfter the desktop client launches, the README describes the shortest path to a result: use the global hotkey, copy an image, drag a file in, or choose a local image to summon the floating window without opening the full workbench. Once the automatic format selection finishes, moving the pointer over the preview exposes copy, preview, locate file, undo, keep shrinking, switch format, add watermark and upload actions. A maximum of six action buttons can be selected in settings.
Docker and the self-hosted web endpoint on port 3456
The GitHub Pages demo is a static build that processes images in the browser and never uploads them; the same workbench is available as a GHCR image when you want a fixed domain or LAN access. The default service port is 3456. Compose reads three variables from a .env file in the project directory: PICLITE_BIND, PICLITE_PORT and PICLITE_TAG. The image sets HOST to 0.0.0.0 and PORT to 3456 internally, and the compose file maps the host bind and port onto 3456. A healthcheck fetches the root path every 30 seconds, with a 15 second start period and three retries, so an unhealthy container is detectable without extra tooling.
git clone https://github.com/amiaoapp/PicLite.git
cd PicLite
docker compose pull
docker compose up -dUpgrades and status checks use the same compose file. The README lists pull, up with --remove-orphans, ps and logs -f piclite for this.
docker compose pull
docker compose up -d --remove-orphans
docker compose ps
docker compose logs -f picliteIf you prefer a single container, the README gives a docker run form that publishes 3456 and restarts unless stopped.
docker run -d \
--name piclite \
-p 3456:3456 \
--restart unless-stopped \
ghcr.io/amiaoapp/piclite:latestOpen http://your-server-ip:3456 in a browser. For a reverse proxy, the README forwards the domain to http://127.0.0.1:3456 and shows a Caddyfile with reverse_proxy 127.0.0.1:3456.
Folder monitoring, and what it refuses to do
Folder monitoring is configured on the monitoring page: you add and save tasks, each with its own target format, quality, scaling, maximum width and height, output location, naming rule, completion notification and floating result. Tasks take effect on save and are restored after a restart, but the app has to stay running (minimized to the tray is acceptable). Two behaviours are worth reading twice. The option to process only when format or size does not already match will skip images that already meet the target; turning it off compresses new images regardless. And scaling is proportional and never upscales, so a small image stays small. The monitor waits for file writes to stabilize, ignores results it generated itself, and refuses configurations with overlapping directories or output paths that would form a loop. Naming rules come from the same parent-directory scheme as the batch rename plugin, and the README warns that monitoring does not use batch sequence numbers, so images must be distinguished with {name}. EPUB is not unpacked or repacked; extract the images first. JFIF is handled as JPEG.
Plugins run in a trusted container, not an iframe
The plugin model is the part most likely to surprise an integrator. PicLite no longer embeds plugins in an iframe. The desktop client reads the HTML, CSS and JavaScript and mounts it into the workbench's trusted plugin container, which the README notes avoids being blocked by a site's X-Frame-Options header and allows custom tag names. The consequence is stated plainly: install only code you trust. A minimal plugin is one HTML file that calls window.PicLitePlugin.post, and the settings page imports .html, .js or manifest.json files, or a custom name plus an HTTPS URL that the desktop client fetches and runs. A manifest carries nameZh, nameEn and url. The full runtime API, asset path rules and publishing notes live in docs/PLUGIN_DEVELOPMENT.md.
{
"nameZh": "封面设计大师",
"nameEn": "Banner Maker",
"url": "https://example.com/plugin/"
}Limits, and the case for a different tool
The browser and Docker builds keep the compression workbench but drop system tray, global hotkeys and continuous folder monitoring, because of browser permission limits. That is the sharpest boundary in the project: if your workflow depends on watching a directory, you need the desktop client, not the web endpoint. The monitor also only runs while the app runs, so it is not a substitute for a server-side pipeline that processes files uploaded by other systems. If that is what you need, a headless encoder driven by a queue is the better fit, because it has no GUI lifecycle to keep alive. The other limitation is packaging: no Homebrew, winget or apt repository is documented, so upgrades mean downloading a new release artifact or pulling a new image tag, and PICLITE_TAG is how you pin a version in Docker. The macOS ad-hoc signing is a real friction point for managed fleets, and third-party screenshot tools only respect the capture-blocking setting if their own implementation chooses to.
Licence and upgrade cost
PicLite is GPL-3.0-or-later. The desktop automation workflow is adapted from the GPL project FuzzyIdeas/Clop, and THIRD_PARTY_NOTICES.md carries the details; the README states PicLite does not use the Clop trademark. If you embed PicLite in a product you distribute, GPL-3.0-or-later obligations attach to that distribution, which is a question for your own legal review rather than something this article can settle. Upgrades are cheap for the web path (docker compose pull, then up -d --remove-orphans, with docker compose ps and logs -f piclite for status) and manual for the desktop path. The repository's last push was on 2026-09-15, and releases v1.8.2 through v1.8.4 all landed between 2026-09-12 and 2026-09-15, so the version you download today is close to the tip of main.
Editorial conclusion
Adopt PicLite if you want image compression to stay on the machine, need a size ceiling such as 200 KB or 100 KB enforced against real encoder output, or want a self-hosted Docker endpoint on port 3456 for a team. Do not adopt it if you need server-side automated compression that runs while your workstation is off, because the folder monitor only runs while the app is running and can merely be minimized to the tray. Before rolling it out, verify three things: that your macOS users can get past the ad-hoc signing prompt, that your output directory is not nested inside a watched input directory, and that every plugin you import is code you trust, since desktop plugins are mounted into the workbench container rather than sandboxed in an iframe.
Frequently asked questions
Does PicLite upload my images anywhere?
No, compression runs locally in the browser or desktop client. Files are only sent when you actively use an image-host upload to a service you configured.
Can I run PicLite as a Docker container instead of installing the desktop app?
Yes. The GHCR image is documented for LAN access or a fixed domain, with a default service port of 3456, and compose reads PICLITE_BIND, PICLITE_PORT and PICLITE_TAG from a .env file. The web build keeps the compression workbench but not the system tray, global hotkeys or continuous folder monitoring.
Why does PicLite not compress an image that is already in the target format?
The folder monitoring task has an option to process only when format or size does not already match, which skips images that already meet the target. Turning that option off makes the monitor compress new images regardless.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/amiaoapp-piclite)