Import from a folder or another app
If your photos are in folders, whether on your computer, a NAS or an external drive, or exported from another photo app, there are two good ways to bring them into Frameleaf:
| Upload with the command line tool | Add an external library | |
|---|---|---|
| What happens | Files are copied into Frameleaf’s storage. | Frameleaf shows the files where they are, without copying them. |
| Best for | A one-off import, or a folder you’ll stop using afterwards. | An archive you want to keep managing yourself, such as a folder on your NAS. |
| Who can do it | Anyone with an API key for their account. | An administrator. |
| Albums from folders | Yes, with --album. |
No. |
For a Google Takeout export, use Import from Google Photos instead: it reads Google’s metadata files, which a plain upload ignores. For an iPhone or iCloud library, use Import from iCloud Photos. To move a whole library from one Frameleaf server to another, see Move to a new server.
Upload folders with the command line tool
Section titled “Upload folders with the command line tool”The Frameleaf command line tool, frameleaf, uploads files and folders from any computer that can reach your server. It hashes each file first, so files already on the server are skipped, and Frameleaf removes duplicates on its side too. This section covers bulk uploads; for everything else the tool does, see API and CLI.
Install it
Section titled “Install it”You need Node.js 22 or later and npm:
npm i -g @immich/cliThe package is still called @immich/cli, but it installs the frameleaf command. If you installed the very old immich package before, remove it first with npm uninstall -g immich.
If you can’t install Node.js, use the Docker image instead. It mounts the current folder read-only as /import:
docker run -it -v "$(pwd)":/import:ro \ -e FRAMELEAF_INSTANCE_URL=https://your-frameleaf-server/api \ -e FRAMELEAF_API_KEY=your-api-key \ ghcr.io/frameleaf/frameleaf-cli:latest upload --album --recursive /importCreate an API key
Section titled “Create an API key”- Select your avatar in the top-right corner and choose Account settings.
- In Your preferences, open Account access.
- Under API keys, select Create API key.
- Give the key a name and choose only the permissions the tool needs, or full access.
- Create the key and copy it. It’s shown only once.
Sign in
Section titled “Sign in”frameleaf login https://photos.example.com/api YOUR_API_KEYYour server address ends in /api. The tool saves your credentials in auth.yml in ~/.config/frameleaf/ (or another folder you choose with -d or FRAMELEAF_CONFIG_DIR). Keep that file safe, and run frameleaf logout when you’ve finished.
Upload
Section titled “Upload”Try a dry run first to see what would be uploaded, without changing anything:
frameleaf upload --dry-run --recursive ~/Pictures/ArchiveThen upload for real. This example includes subfolders and makes an album for each folder:
frameleaf upload --recursive --album ~/Pictures/ArchiveMore examples:
# Put everything into one albumframeleaf upload --recursive --album-name "Summer 2019" ~/Pictures/Summer
# Skip RAW folders and TIFF filesframeleaf upload --recursive --ignore '**/Raw/**' '**/*.tif' ~/Pictures/Archive
# Send everything straight to the archiveframeleaf upload --recursive --visibility archive ~/Pictures/Scans
# Keep watching a folder and upload new files as they appearframeleaf upload --recursive --watch ~/Pictures/InboxUpload options
Section titled “Upload options”| Option | What it does | Default |
|---|---|---|
-r, --recursive |
Includes subfolders. | Off |
-a, --album |
Creates an album for each folder, named after the folder. | Off |
-A, --album-name <name> |
Adds everything to one album. | None |
-i, --ignore <pattern> |
Skips files matching a glob pattern. You can give several. | None |
-H, --include-hidden |
Includes hidden files and folders. | Off |
--visibility <visibility> |
Sets visibility: archive, timeline, hidden or locked. |
Not set |
-n, --dry-run |
Shows what would happen without uploading. | Off |
-c, --concurrency <number> |
Files uploaded at the same time. | One less than your computer’s processor cores |
--skip-hash |
Doesn’t hash files before uploading. Faster on a quick connection; the server still removes duplicates. | Off |
-j, --json-output |
Prints a JSON list of new files, duplicates and new photos. | Off |
--watch |
Keeps running and uploads new files as they appear. | Off |
--delete |
Deletes your local files after they upload. | Off |
--delete-duplicates |
Deletes local files that are already on the server. | Off |
--no-progress |
Hides the progress bars. | Progress shown |
Every option can also come from an environment variable, such as FRAMELEAF_RECURSIVE, FRAMELEAF_ALBUM_NAME or FRAMELEAF_UPLOAD_CONCURRENCY. Older scripts that use IMMICH_ names, and the old immich command, still work for the current major version.
Add an external library
Section titled “Add an external library”An external library leaves your files where they are. Frameleaf scans the folder, adds what it finds to the owner’s timeline, and scans it again every night to pick up changes. The folder must be mounted into the Frameleaf containers. See External libraries for how to set one up.
After a big import
Section titled “After a big import”- Rejoin Live Photos. If an export split Live Photos into a separate photo and video, open Utilities, then Live Photo pairing. It matches pairs on the identifier Apple embeds in both files, and suggests lower-confidence matches on file name and capture time for you to review. See Library Care.
- Tidy duplicates. Imports from several sources often overlap. Duplicates helps you find them and keep the best copy.
- Let the background work finish. Thumbnails, faces, search and descriptions are worked out after upload. Big imports take a while; follow them in Activity.