The Overkill PDF Password Protector
pwpdf is a compact desktop + CLI utility that adds password protection to existing PDF files without rebuilding pages, rasterizing content, or touching the original document unless you explicitly ask for overwrite behavior in the CLI.
It is built in Go, uses pdfcpu for encryption, ships with a Wails desktop app, and leans into a compact old-school desktop aesthetic instead of pretending to be a web app in a window.
Most people do not need a full PDF suite to put a password on one file.
They need:
- SOUND ON! (optional but recommended)
- pick a PDF
- type a password
- save the protected copy
- move on with your life
That is the whole point of pwpdf.
- Encrypts existing PDF files with
pdfcpu - Preserves layout and appearance by modifying PDF structure instead of recreating pages
- Supports both GUI and CLI workflows
- Accepts drag-and-drop in the desktop app
- Uses native open/save dialogs in GUI mode
- Prompts securely for a password in the terminal when needed
- Defaults output names to
*_encrypted.pdf - Includes optional shell integration helpers for Windows and Linux
pwpdf shares one encryption workflow between the CLI and the GUI:
- Validate that the input exists and is really a PDF
- Resolve the default output path
- Validate the password
- Encrypt the file with
pdfcpuusing standard PDF encryption - Validate that the resulting file exists and is actually protected
Important detail: the app does not rasterize pages, flatten the document into images, or rebuild layout manually. The goal is to keep the document visually identical and only add password protection.
The desktop app is built with Wails and is intentionally focused:
- Drop a PDF into the window or click
Select PDF - Enter the password twice
- Choose where the encrypted copy should be saved
- Done
GUI highlights:
- drag and drop
- native file picker
- native save dialog
- password confirmation
- preloaded file support when the app is launched with a PDF path
- compact layout that adapts for smaller screens
You can also launch the GUI with a file already selected:
go run . /path/to/file.pdfBasic usage:
pwpdf encrypt input.pdf
pwpdf encrypt input.pdf --password "MySecret123"
pwpdf encrypt input.pdf --password "MySecret123" --output output.pdf
pwpdf encrypt input.pdf --password "MySecret123" --output input.pdf --overwriteYou can run it from source as well:
go run . encrypt input.pdf
go run . encrypt input.pdf --password "MySecret123"Supported commands:
pwpdf
pwpdf /path/to/file.pdf
pwpdf encrypt input.pdf [options]
pwpdf install-shell-integration
pwpdf uninstall-shell-integration
pwpdf version
encrypt options:
--password,-p: user password--output,-o: output file path--owner-password: optional owner password--overwrite: allow overwriting the output file, and the input file if you point output back to it
If --password is omitted, the CLI prompts for it securely in the terminal.
Install a right-click context-menu entry for PDF files:
pwpdf install-shell-integrationThat adds Protect PDF with pwpdf and opens the GUI with the selected PDF.
Install a local .desktop entry so the app can appear in Open With flows:
pwpdf install-shell-integrationThere is no invasive Finder integration step. The practical path is:
Open With- drag a PDF onto the app
- launch the app with a file path
- Go
1.26.1or newer - Node.js
18+ - Wails CLI
- On macOS: Xcode Command Line Tools
Install Wails CLI:
go install github.com/wailsapp/wails/v2/cmd/wails@latestLinux desktop builds also need the GTK/WebKit dependencies required by Wails.
On macOS, install the Apple toolchain with:
xcode-select --installThen verify the local environment with:
wails doctormake devor:
./scripts/dev.shmake testmake buildor:
./scripts/build.shPowerShell:
.\scripts\build.ps1On macOS, the direct local build path is:
./scripts/build.sh
scripts/build-all.sh --selector macosmacOS builds export both artifacts:
pwpdf.apppwpdfas a standalone CLI binary copied out ofpwpdf.app/Contents/MacOS/pwpdf
There is a matrix helper for release builds:
scripts/build-all.sh --selector all
make build-all SELECTOR=allArtifacts are written to dist/<platform>/.
Supported selectors:
alllinuxwindowsmacos- exact targets like
linux/amd64,linux/arm64,windows/amd64,windows/arm64,darwin/universal
Notes:
- On macOS, use
scripts/build-all.sh --selector macosorscripts/build-all.sh --selector darwin/universalto build the local.appand a standalonepwpdfCLI binary without Docker - Linux foreign-architecture builds can fall back to Docker automatically
- Windows targets can be built through Wails from Linux in this repository workflow
- macOS desktop packaging still needs a macOS machine or runner for the real
.appoutput
.
├── build/
├── docs/
├── frontend/
├── internal/
│ ├── application/
│ ├── cli/
│ ├── files/
│ ├── gui/
│ ├── pdf/
│ ├── platform/
│ ├── validation/
│ └── version/
├── scripts/
├── main.go
└── wails.json
If you want the architecture write-up instead of the marketing version, read docs/architecture.md.
pwpdfuses standard PDF encryption viapdfcpu- Viewer behavior still depends on the PDF security model being respected by the PDF reader
- PDF passwords are useful, but they are not a substitute for storage-layer or endpoint security controls
- It protects existing PDFs; it is not a PDF editor
- Already encrypted PDFs need to be decrypted before being protected again
- Shell integration is intentionally minimal and optional
- macOS packaging still requires a macOS environment
Yes. That is one of the core requirements of the project. The app does not recreate pages as images and does not intentionally alter fonts, page sizes, or content positioning.
Not by default.
- GUI mode always writes a new file
- CLI mode writes a new file unless you explicitly opt into overwrite behavior
Because both are useful:
- GUI for normal users
- CLI for automation, terminal workflows, shell integration, and quick one-off usage
MIT. See LICENSE.

