GitHub - cthackers/inpaint: A Linux desktop image editor with local AI object removal, face replacement, restoration, upscaling, and background tools.

GitHub

25 min read Original article ↗

A Linux desktop image editor with local AI object removal, face replacement, restoration, upscaling, and background tools. Open a folder, double-click an image, and combine edits without reloading models between operations.

Inpaint supports PNG, JPEG, and WebP files. Processing stays on your computer; the application only uses the network to install dependencies and download model weights.

Warning

Saving overwrites the original image. The application does not create a backup, so keep a copy of anything you cannot replace.

Features

  • Folder tree and a responsive thumbnail gallery for large photo collections.
  • Image stores for folders laid out like Immich uploads, with Immich thumbnail refresh after saving.
  • Immich compatible though API and stores (see bellow)
  • Exposing HTTP API for all operations
  • Dropbox area where you can drag/drop files from browser/disk/clipboard and automatically save in stores (see bellow)
  • Mask painting with adjustable brush size, zoom, and pan.
  • Five selectable inpainting models for different kinds of repair.
  • GFPGAN face restoration, HAT/RealESRGAN upscaling, Lanczos resizing, and background removal tools.
  • Detail restoration without upscaling: JPEG cleanup, added detail for soft pictures, noise removal, and motion deblurring.
  • Face replacement using a selected source photo, with a persistent InsightFace/INSwapper model.
  • Smart selection, clone/healing brushes, live color adjustments, crop/straighten, and canvas outpainting.
  • Background replacement with a color, another image, or a blurred background, plus cutout edge refinement.
  • Horizontal/vertical image flips and 90° left/right rotations from the top toolbar, with undo/redo.
  • Model weights stored together in the app's data directory.
  • A persistent worker that keeps all used models loaded between edits and tool switches.
  • Reusable workflows, batch queues, export copies, and a visual edit history.

Screenshots

Screenshots of the desktop application. Click any image to view it at full size. Demo photo credits and capture notes are in docs/screenshots.

Object removal

Paint over the unwanted object, then press Space. This example removes the spoon with LaMa while keeping the image at 600 × 400 pixels.

You can also hold Shift and draw and the removal will happen as soon as you release the mouse.

Paint the mask Apply inpainting
Coffee photo with the spoon masked for removal Coffee photo after removing the spoon with LaMa

Face replacement

Select a source photo and press Replace. The selected face is replaced and restored with GFPGAN. This is an altered demonstration image, combining NASA portraits of Neil Armstrong and Eileen Collins.

Face replacement completed, with the source-photo picker and color-matching controls

Upscaling and before/after comparison

Real-HAT enlarges this image from 451 × 300 to 902 × 600 pixels. The comparison slider shows the previous image on the left and the edited image on the right, aligned to the same frame.

Upscale controls and result Before/after slider
Real-HAT 2× upscale with updated output resolution Original and upscaled cat image compared with a draggable divider

Face restoration and detail restoration

GFPGAN restores faces, and Restore detail cleans up compression and noise or adds detail at the same size. These captures show GFPGAN followed by the earlier Restormer defocus model, with the portrait remaining 512 × 512 pixels.

GFPGAN Restore detail
GFPGAN face restoration completed Restormer defocus restoration completed at the original resolution

Background removal, edge refinement, and replacement

Remove the background to transparency, refine the cutout edges, and choose a replacement. Shown here: a BRIA RMBG 1.4 cutout with its edge controls, followed by a solid white background.

Transparent cutout and edge controls Replace the background
Transparent portrait with background-removal and edge-refinement controls Portrait placed on a solid white background

Color, crop, and canvas extension

Preview exposure, contrast, temperature, saturation, shadows, and highlights. Choose a crop ratio and straighten the image, or configure extra canvas space for outpainting. Flip and rotation controls sit in the top toolbar.

Live color preview Square crop preview
Live exposure, contrast, and saturation adjustments Square crop selection with a 600 by 600 pixel output preview

Canvas-extension settings with separate margins for each side

Workflows, batch processing, and export

Build a sequence from the current tool settings, save it as a workflow, and queue multiple pictures. Export settings control format, quality, filename suffix, and output dimensions. The batch capture shows two queued demo images.

Build a workflow Queue pictures
A Photo finish workflow combining color adjustments and Real-HAT upscaling Two demo images queued with the Photo finish workflow

Export settings for format, quality, filename suffix, and output dimensions

Edit history and models in memory

Return to a previous edit using its thumbnail. Used models stay loaded across operations; the memory panel lists them and offers manual unloading.

Visual history Loaded models
History showing restoration, background removal, and background replacement Memory panel showing LaMa, face swap, GFPGAN, Restormer, and background removal loaded together

Folder browsing and keyboard shortcuts

Browse a folder's thumbnails and double-click to edit. The ? overlay lists navigation, painting, and action shortcuts; tool buttons also show their keys.

Image gallery Shortcut overlay
Folder tree and image thumbnail gallery In-app keyboard shortcut overlay

Platform and hardware

The application currently supports Linux only.

The interface is drawn by WebKitGTK on the GPU. With NVIDIA's proprietary driver, WebKit's usual way of handing frames to the window shows a blank white window, so Inpaint passes them through shared memory there instead. If the window stays white or draws badly, start Inpaint with INPAINT_RENDERER=software (slower scrolling in large galleries), or with INPAINT_RENDERER=gpu to use WebKit's default. WebKit variables you set yourself, such as WEBKIT_DISABLE_DMABUF_RENDERER, are left alone.

Portable deployment

./build-portable.sh (or ./build.sh --portable) builds the desktop executable and inpaint-desktop.AppImage at the project root. Use the AppImage for deployment: it packages the Linux desktop libraries; the plain executable still needs those libraries installed on the destination machine. This is an x86-64 Linux build; the destination must meet the build system's glibc and graphics-driver requirements. Building on an older supported Linux distribution gives wider compatibility.

On a fresh machine, the setup screen installs a private Python 3.11 runtime and dependencies using the embedded uv installer. Choose NVIDIA/CUDA or CPU. Setup shows progress and logs and can be retried after a failed download. The first installation requires internet and several gigabytes of free disk space.

Installed runtime data goes into $XDG_DATA_HOME/inpaint-desktop (normally ~/.local/share/inpaint-desktop). The regular executable continues to use an adjacent .venv/ or models/ directory when present. INPAINT_PROJECT_DIR can override the data location.

Model weights download on first use, including the face-swap models and MobileSAM. Downloads show progress and reuse weights already on disk. Some Hugging Face models require approval from their publisher before downloading.

If the destination lacks FUSE, run the AppImage with --appimage-extract-and-run. GPU drivers remain a host requirement and are not bundled.

An NVIDIA CUDA GPU is strongly recommended. The setup script installs the CUDA 12.8 PyTorch wheels, so a recent compatible NVIDIA driver is required. A separate system CUDA Toolkit installation is normally not necessary. The models can fall back to the CPU, but most of them will be impractically slow.

GPU memory requirements vary by model and image. LaMa, MAT, ZITS, and MIGAN are the lighter choices. SDXL is substantially larger and benefits from a GPU with generous VRAM.

Build prerequisites

Install the following tools before building:

  • Git
  • Node.js 20 or newer and npm
  • Rust stable and Cargo (installation through rustup is recommended)
  • Python 3.11 with virtual-environment support
  • Tauri's Linux/WebKitGTK development libraries
  • A recent NVIDIA driver for GPU inference
  • ImageMagick, recommended for fast gallery thumbnails

Fedora

sudo dnf group install "C Development Tools and Libraries"
sudo dnf install \
  webkit2gtk4.1-devel libsoup3-devel openssl-devel libappindicator-gtk3-devel \
  librsvg2-devel python3.11 python3.11-devel nodejs npm git curl wget file ImageMagick

Install Rust if it is not already available:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Ubuntu / Debian

sudo apt update
sudo apt install \
  build-essential libwebkit2gtk-4.1-dev libssl-dev \
  libsoup-3.0-dev libayatana-appindicator3-dev librsvg2-dev python3 python3-venv \
  python3-dev git curl wget file imagemagick

Install Node.js 20+ using your preferred Node.js package source, then install Rust with rustup. Distribution repositories sometimes provide versions of Node.js or Rust that are too old for current Tauri tooling.

For other distributions, follow the Tauri 2 Linux prerequisites.

Run from source

Clone the repository and enter it:

git clone YOUR_REPOSITORY_URL
cd inpaint

Install the frontend and model runtime dependencies:

npm install
./scripts/setup-model.sh

The model setup script creates .venv/ inside the project and installs CUDA PyTorch, simple-lama-inpainting, and IOPaint. It prints whether PyTorch can see CUDA and the detected GPU. If it reports CUDA available: False, verify the NVIDIA driver before continuing.

Start the desktop application:

The first Rust build takes longer than later launches. Model weights are not downloaded during npm install; each model downloads when it is selected and used for the first time.

Inpainting models

All models are provided by their respective upstream projects. Their weights have separate licenses and terms; review the linked sources before redistributing them.

Model Best for Download source
LaMa Fast general-purpose object removal, people, blemishes, and natural textures big-lama.pt from simple-lama-inpainting
MAT Large masks, landscapes, rooms, and broader scene reconstruction Places_512_FullData_G.pth, distributed by IOPaint; original MAT project
ZITS Architecture, fences, horizons, edges, and straight structural lines Four ZITS checkpoints, distributed by IOPaint; original ZITS project
MIGAN Quick small or medium repairs on uncomplicated backgrounds; internally works with 512px crops migan_traced.pt, distributed by IOPaint; original MI-GAN project
SDXL Inpainting Slower, prompt-guided generation when a region needs new semantic detail diffusers/stable-diffusion-xl-1.0-inpainting-0.1 and the sdxl-vae-fp16-fix VAE from Hugging Face

LaMa is approximately 197 MB. MAT, ZITS, and MIGAN are downloaded on demand through IOPaint. SDXL is a multi-gigabyte download.

Model storage

Model weights and caches live under models/ in the app's data directory. In a configured source checkout, they live in the repository's models/ directory.

models/
├── lama/          # LaMa checkpoint
├── torch/         # Inpainting, GFPGAN, and upscaling checkpoints
├── huggingface/   # SDXL, BRIA, and Hugging Face cache data
├── faceswap/      # InsightFace and INSwapper models
├── restormer/     # Detail restoration models
└── .runtime/      # Generated persistent-worker script

In a source checkout, this directory is ignored by Git except for its README. Downloaded models can be used offline. Each model loads when first used and stays in memory across tool and image changes. Upscale factors and denoising settings reuse the same network.

Open Workspace > Memory to unload models you no longer need. This frees RAM and VRAM for other operations, especially on large images. Closing the app releases all loaded models.

Image enhancement plugins

The editor also includes:

  • Smart selection with MobileSAM: click to include an object and Alt-click to exclude an area. Switch back to paint or erase to refine the resulting selection.
  • Mask brushes with size, hardness, opacity, an eraser, grow/shrink, and feathering. Feathered selections blend the result into the untouched image.
  • Clone and healing brushes: Alt-click a source point, then paint a destination. Healing retains sampled texture while matching local lighting.
  • Color and lighting with live exposure, contrast, temperature, saturation, shadows, and highlights previews. Apply renders the full-resolution result.
  • Face color matching with adjustable strength for brightness/skin-tone matching on the next replacement. It is separate from the live GFPGAN slider.
  • Background edge refinement with shrink/expand, softness, and color-halo removal using nearby opaque foreground colors.
  • Outpainting with independent canvas extension on all four sides, a choice of the existing inpainting models, and a prompt for SDXL. Original pixels and transparency stay intact inside the expanded image.
  • Shared restoration strength for GFPGAN and face replacement. After either operation, the slider blends the raw and restored result without another model run. A later edit or history jump ends that live adjustment.
  • Face selection: detect faces, click a numbered face, then choose its source photo. Different faces can have different sources; use Replace individually or Replace all assigned faces. Without a selection, the largest face is used.
  • Before/after comparison against the original or the previous history step, with a draggable divider and shared zoom/pan. Different sizes fit the current frame.
  • Crop and straighten from the top bar, with free cropping, common aspect ratios, and an angle preview. Drag on the image to set the crop. Rotated corners are transparent until cropped away.
  • Background replacement with a color, an image, or a blurred original. The optional first removal step uses the background model selected in the panel.

The top-bar History, Workflows, and Export buttons open the Workspace drawer:

  • History contains named previews for the current picture. Selecting a step restores its image and dimensions; a new edit discards subsequent steps.
  • Workflows save ordered operations with the current tool settings. Add, reorder, and remove steps, then save a named workflow. Workflows persist across restarts; referenced source photos and background images must remain at their saved paths. Reusable face swaps select the largest face in each image.
  • Batch accepts multiple pictures and applies a saved workflow sequentially, reusing loaded models. Each file has progress and error reporting. Stop takes effect after the current operation; completed exports remain available. Batch reads pictures from disk, independently of unsaved editor changes.
  • Export writes PNG, JPEG, or WebP copies with format quality, dimensions, aspect ratio controls, filename suffix, and a JPEG transparency fill color. Zero in both dimensions keeps the edited size. Files are never overwritten: collisions receive numbered names. The original Save button still saves over the source.
  • Memory lists cached models and worker RAM, with individual and all-model unload controls. GPU figures cover PyTorch allocations, not ONNX/driver allocations.

The left panel also provides:

  • GFPGAN 1.4 for restoring facial detail.
  • Face swap with automatic GFPGAN restoration of the replaced face.
  • RealESRGAN with photo, anime, and general-purpose models at 2× to 4× output scale.
  • Real-HAT Sharper for sharper AI upscaling, and Lanczos for standard resizing without AI reconstruction.
  • Background removal with BRIA RMBG 1.4/2.0 and U²-Net general/human models.

BRIA 1.4 works without a login. To use BRIA 2.0, open Set up model access below its dropdown, request access on Hugging Face, and save a read token from the approved account. You can change or remove the token using the links below the dropdown. The token is stored locally with access limited to your Linux user.

Use PNG or WebP to keep a transparent background. JPEG does not support transparency.

Upscaling

The Upscale menu offers 2×, 3×, and 4× output for every method. General v3 also has a Denoising slider: 0% uses the weak-denoising model to retain more texture/noise; 100% uses the strong-denoising model. The initial setting is 25%.

HAT uses the official Real_HAT_GAN_sharper.pth checkpoint from XPixelGroup/HAT, loaded through Spandrel. It processes the image in tiles to limit GPU memory use. Its native 4× output is resized with Lanczos when 2× or 3× is selected. HAT is slower than RealESRGAN and can change textures. Choose Lanczos for ordinary resizing without AI.

The HAT checkpoint (about 170 MB) and General v3 weak-denoising checkpoint (about 4.9 MB) download into models/torch/hub/checkpoints/ on first use. scripts/setup-model.sh installs the required spandrel and gdown packages. To install those dependencies separately:

.venv/bin/python -m pip install spandrel==0.4.2 gdown==5.2.0

Restore detail without upscaling

Restore detail (or Alt+T) repairs the current image at its existing resolution. Choose the mode that matches the picture:

Mode What it does Downloads on first use
Compressed or soft photo (default) Removes JPEG blocks and ringing with FBCNN, then adds detail with Real-ESRGAN 2× and shrinks the result back to the original size. Best for pictures saved from the web. FBCNN (275 MiB), Real-ESRGAN 2× (64 MiB)
Natural detail FBCNN, then Real-HAT 4×, shrunk back. Finer, more natural detail; slower. FBCNN, and Real-HAT (162 MiB) unless the upscaler already downloaded it
JPEG artifacts only FBCNN alone, without sharpening. FBCNN
Photo noise Removes grain and color noise with SCUNet, trained on real camera noise. SCUNet (69 MiB)
Motion blur Restormer's motion deblurring model. Restormer (100 MiB)

Strength blends the result with the original and applies on the next run. Image dimensions and transparency are preserved.

Real-ESRGAN and Real-HAT were trained on realistically degraded photos, so enlarging a picture with them and shrinking the result back leaves sharper edges and texture at the original size. Measured against the clean originals of shrunk, JPEG-compressed and slightly blurred test photos, cleaning compression first and then adding detail came closest. Restormer's defocus and noise models, which this section used before, made compressed pictures worse and were removed; saved workflows and API requests that name them run Compressed or soft photo and Photo noise instead. Detail modes add plausible texture: they cannot bring back detail that is completely gone.

Weights download into models/restore/; Real-HAT stays in models/torch/hub/checkpoints/ and Restormer in models/restormer/. Networks stay loaded once used, so modes that share FBCNN load it once. They process overlapping tiles to limit GPU memory use; if the GPU runs out of memory, they retry with smaller tiles, then continue on the CPU, which is slower. The maximum input size is 64 megapixels.

Restormer's architecture is included in the app's runtime, with its upstream MIT license.

Face replacement

In the left panel, click the square Select photo picker, choose a PNG, JPEG, or WebP containing the face to use, then click Replace. The tool uses the largest face in the source photo. In the target image, it replaces the face you selected, or the largest face if none is selected, then restores that area with GFPGAN. Replacement and restoration form one undoable edit and keep the image's dimensions and transparency. If no face is detected, choose a clearer photo.

Every photo you choose is kept in Saved faces. Hover the tab beside the photo picker to open them in a column next to the panel. Click a photo to use it, to replace the face with that photo once without changing the one in use, or the bin to remove it from the list. Add photos saves several at once.

The first-launch installer and main setup script include face replacement. To reinstall its dependencies in a source checkout:

./scripts/setup-face-swap.sh

The script installs InsightFace 0.7.3 and the CUDA-capable ONNX runtime, which also supports CPU fallback. Model weights go in models/faceswap/ and download on first use. To copy weights from an existing installation, set FACE_SWAP_PROJECT_DIR to a directory containing models/inswapper_128.onnx and INSIGHTFACE_MODELS_DIR to the directory containing the buffalo_l models before running the script.

Face replacement uses InsightFace's INSwapper. Model weights have their own upstream license terms.

Image stores

An image store is a folder whose pictures are kept two levels deep under the first characters of their names, ab/cd/abcd….jpg, the way Immich stores uploads. Open the menu at the top of the browser's sidebar and choose New store…, pick the folder and name it. The menu then lists your stores below Open folder….

A store shows every PNG, JPG, WebP, GIF, BMP and TIFF picture of all its subfolders, newest first. Videos, sidecar files and files outside the layout are skipped and counted as other files. The sidebar shows the number of pictures, their size and the last scan, with Rescan, Rename and Remove. Remove only forgets the store; its folder stays on disk.

Opening a store shows the list saved by its last scan at once and rescans in the background. The scan reads the top folders in parallel, so a store of 30,000 pictures on a network share takes a few seconds. Thumbnails are cached in .cache/thumbnails in the data directory, up to 2 GB.

Editing keeps a picture's file name, so a copy of the original still counts as a duplicate. GIF, BMP and TIFF pictures open as PNG and are saved as a new file.

The bin in the editor's top bar deletes the open picture. It goes to the desktop trash; where there is none, as on some network shares, Inpaint asks before deleting it permanently. Pictures of Immich-compatible stores go to Immich's trash instead.

Immich

For Immich, create a store from one user's upload folder, such as /mnt/immich/upload/<user id>, and check Immich compatible in its sidebar. Folder as Immich sees it is the same folder inside the Immich container, by default /data/upload/<user id>; Immich shows it as the file location of a picture. In SettingsImmich, enter the Immich address and an API key created by the account that owns the pictures, with the asset.read, asset.update, asset.upload, asset.delete, job.create, tag.read, tag.create, tag.asset, album.read, album.create, albumAsset.create and albumAsset.delete permissions.

After Inpaint saves a picture of such a store, it finds the Immich asset by its path and asks Immich to rebuild the thumbnail, and to read the metadata again when the picture's size changed.

In the editor, pictures of such a store get an Immich panel on the right, toggled with the tag button in the top bar. It shows and edits the favorite mark, archive, star rating and description, the picture's tags and albums (search the existing ones or create new ones; Trips/2024 creates nested tags), and lists the people Immich recognized and the photo's details. Changes are saved to Immich at once; Open in Immich shows the picture there.

Drop box

The drop box is a translucent area in a corner of the screen that saves pictures into an image store. Turn it on in SettingsDrop box, and choose the store, the screen, its size and its opacity.

It stays invisible and lets clicks through until you hold Win+Ctrl: drag a picture from the browser, a file manager or any other program, hold the keys and drop it. While holding them, press V to save the picture on the clipboard. Always visible keeps it shown. Right-click it, or use the tray's Drop box menu, to change the store or save the clipboard.

  • Pictures dragged from Chromium-based browsers such as Vivaldi, or from Firefox, are saved from the browser's own copy, so pictures behind a login work too. Local files are copied, and dropped links are downloaded; a link to a page saves the picture the page shows.
  • Only pictures are accepted. They are named after their SHA-1, ab/cd/<sha1>.jpg, and a picture whose hash is already in the store is skipped.
  • Immich-compatible stores get the picture uploaded through Immich, which files it and skips pictures it already has.
  • The area flashes green when a picture is saved, amber when it was already there, and red when saving failed, with the reason shown for a few seconds. Pictures saved into the store open in the browser appear at once.

Holding the keys needs an X11 session; on Wayland, keep the drop box always visible.

Local API server

Other programs can send pictures to the running app over HTTP. Click Settings in the browser's sidebar to enable it, choose between 127.0.0.1 and all network interfaces, copy the access token, and allow the folders that requests may read and write.

Every editor operation has an endpoint, such as POST /upscale or POST /face-swap. POST /workflow/{name} runs a saved workflow, POST /load opens a picture in the editor, and POST /save writes a picture to disk. Pictures can be sent as bytes, URLs or disk paths.

curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"image": "/home/me/Pictures/cat.jpg", "options": {"scale": 2}}' \
  -o cat-2x.jpg http://127.0.0.1:7865/upscale

See the API reference for every endpoint and option.

Browser extension

browser-extension/ holds an extension for Chromium browsers (Chrome, Vivaldi, Brave, Edge, Opera) that sends pictures from web pages and from Immich to Inpaint through the local API server, and shows the results in place. Its README covers setup and use.

Install it unpacked

No build is needed:

  1. Open chrome://extensions (vivaldi://extensions in Vivaldi).
  2. Turn on Developer mode.
  3. Click Load unpacked and choose the browser-extension folder.

After changing the extension's files, click the reload button on its card. This is the easiest way while working on the extension.

Build a package

The script needs only Node.js and writes two files to the project root:

File Use
inpaint-extension.crx Signed package, installed by dragging it onto the extensions page
inpaint-extension.zip The same files unsigned: unzip it and load the folder unpacked on another machine

To install the .crx, turn on Developer mode on the extensions page, drag the file onto the page and confirm. Chromium browsers on Linux accept this; Chrome on Windows and macOS only keeps extensions from the Chrome Web Store. To update, raise version in browser-extension/manifest.json, build again and drag in the new file. Its settings are kept.

Every build has the same extension ID, so a new .crx updates the installed copy, and an unpacked copy uses the same ID and settings too. The ID comes from the "key" field in manifest.json, which is the public half of a signing key:

  • The first build creates the key at ~/.config/inpaint/extension-key.pem, writes its public half into manifest.json, and asks you to commit that change.
  • Later builds check that they sign with the matching key and stop otherwise, so no package can come out with another ID.
  • Keep the key private and back it up. Without it, no update can be built for installed copies. On another machine, copy it to the same place or pass --key.
  • Loading the folder unpacked needs no key, and it still gets the same ID.

Options: --key FILE (or INPAINT_EXTENSION_KEY) signs with another key, and --out FOLDER writes the packages elsewhere. The build stops when manifest.json names a file that does not exist.

Firefox is not supported. The extension runs its background code as a Chromium service worker, and release versions of Firefox only install .xpi packages signed by Mozilla.

System tray

Inpaint shows a tray icon so it can keep serving API requests in the background. Its menu has Start server / Stop server, a Minimize to tray checkbox, a Drop box menu and Exit. With Minimize to tray checked (the default), closing or minimizing the window hides it in the tray; click the icon to bring it back. Unchecked, closing the window exits the app.

Only one copy of Inpaint runs at a time. Starting it again brings the running window back, including from the tray, so a second copy never competes for the API server's port.

The icon uses the StatusNotifierItem protocol, which KDE Plasma and most Linux desktops show natively. GNOME needs the AppIndicator extension. Without a tray, closing the window always exits.

Editor controls

Hover over the ? button in the lower-left corner of the editor to see these controls in the application.

Input Action
Left mouse drag Paint the mask
Mouse wheel Zoom around the pointer
Ctrl + mouse wheel Change brush size
Space + drag or middle mouse drag Pan
Shift + paint Apply the mask when the stroke ends
Space Apply the current mask
Ctrl+Z / Ctrl+Shift+Z Undo / redo
Left / Right or A / D Previous / next image
Home / End First / last image in the folder
Numpad * / Numpad / Fit to window / actual size
Numpad + / Numpad - Zoom in / out
Ctrl+S Overwrite the current image
O Toggle between the original and edited image
Esc Return to the folder browser
Alt+T Restore detail with the selected Restormer model and strength
Alt+U Upscale using the selected method, scale, and denoising
Alt+F Restore faces with GFPGAN and the shared strength
Alt+R Replace the selected/largest face with the selected source
Alt+B Remove the background using the selected model
Alt+G Apply the replacement background settings
Alt+D Detect faces for selection
Alt+E Apply background edge refinement
Alt+C Toggle crop and straighten
Alt+H / Alt+V Flip horizontally / vertically
Alt+[ / Alt+] Rotate left / right

Action shortcuts also appear on tool buttons and in the scrollable help overlay. They use the current tool settings, including when the tool's section is collapsed. Shortcuts are disabled while typing or running an operation.

Every tool section has an icon and a collapsible heading. Expanded states, brush settings, model choices, prompts, color/edge/outpaint settings, background choices, and workspace/export selections persist between pictures and application restarts. The last face source is remembered as a single file path and reloaded when available. Masks, detected face coordinates, crop rectangles, and image edit history belong to the current image and are cleared when you leave it.

Build an executable or package

Plain Linux executable (no installer)

Build and run the desktop executable:

./build.sh
./inpaint-desktop

build.sh builds the frontend and optimized desktop application, verifies that the executable can read its embedded index.html and referenced scripts and styles, then copies it to inpaint-desktop in the project root, replacing an existing copy. It can be invoked from any working directory. If the build or asset check fails, the existing root executable is preserved. Restart a running app to use the update.

The frontend is embedded; dist/ is not needed beside the executable at runtime. To check the embedded assets without opening a window, run:

./inpaint-desktop --check-assets

The executable embeds the Rust backend and web frontend. It still needs the host's Linux desktop libraries. In a configured source checkout, it reuses the adjacent .venv/ and models/. On a fresh machine, the setup screen installs the Python runtime as described under Portable deployment.

AppImage (no system installation)

Build an AppImage with the desktop libraries included:

./build-portable.sh
./inpaint-desktop.AppImage

The script builds the app and copies the AppImage to the project root. Tauri's package output also remains under src-tauri/target/release/bundle/appimage/. Distribute inpaint-desktop.AppImage; Python dependencies install during setup, and model weights download when first used. They are stored outside the AppImage.

DEB or RPM

Create a distribution package only if system installation is desired:

# Debian and Ubuntu
npm run tauri -- build --bundles deb

# Fedora and other RPM-based distributions
npm run tauri -- build --bundles rpm

DEB and RPM packages install the binary, desktop entry, and icons into system locations such as /usr/bin and /usr/share. The first-launch setup installs the Python runtime in the user's app data directory. Model weights download on first use. Set INPAINT_PROJECT_DIR to reuse a prepared runtime directory.

To build all package formats configured in src-tauri/tauri.conf.json, run:

All package output is written below src-tauri/target/release/bundle/. Package compatibility varies by Linux distribution.

License

Inpaint is licensed under the GNU Affero General Public License, version 3 (AGPL-3.0-only). Copyright (c) 2026 Inpaint contributors.

The face-swap integration was adapted from a local project based on Deep-Live-Cam. Its upstream credits and license are recorded in the code provenance notes.

When publishing executables or AppImages, provide the corresponding source for that exact release, including build scripts, alongside the download. Include LICENSE and THIRD_PARTY_NOTICES.md with the release and retain upstream notices. Modified versions offered for remote use over a network must also offer their corresponding source to those users, as required by section 13 of the license. Inpaint is provided without warranty; see LICENSE for the full terms.

Libraries, model weights, and screenshot photos retain their upstream licenses. Some models are restricted to non-commercial use or research. See Third-party software and models for the license notes and links to their terms.

Technology