Fork of jampe/kp2bw, modernized.
Migrates KeePass databases to Bitwarden via the bw CLI, with advantages over
the built-in Bitwarden importer:
- Encrypted in-memory transfer -- data never hits disk unencrypted (except attachments, which are cleaned up after upload)
- KeePass REF resolution -- username/password references are resolved: matching credentials merge URLs into one entry; differing ones create new entries
- Passkey migration -- KeePassXC FIDO2/passkey credentials
(
KPEX_PASSKEY_*) are converted to Bitwardenfido2Credentials - Custom properties & attachments -- imported as Bitwarden custom fields or attachments (values > 10k chars auto-upload as files)
- Long notes handling -- notes exceeding 10k chars are uploaded as
notes.txtattachments - Idempotent re-runs that sync changes -- safe to run repeatedly; existing
entries are updated in place when their KeePass content changed (notes,
credentials, URIs, fields) and never duplicated. Disable with
--no-update - Nested folders -- KeePass folder hierarchy is recreated in Bitwarden
- Recycle Bin filtering -- deleted entries are automatically excluded
- Expiry awareness -- expired entries are marked
[EXPIRED]in notes; optionally skip them entirely with--skip-expired - Metadata preservation -- KeePass tags, expiry dates, and created/modified timestamps are stored as Bitwarden custom fields
- Tag filtering -- import only entries matching specific tags
- Organization & collection support -- upload into a Bitwarden organization with automatic or manual collection assignment
- Full UTF-8 & cross-platform -- works on Windows, macOS, and Linux
# install with:
uv tool install kp2bw
kp2bw passwords.kdbx
# or run directly without installing:
uvx kp2bwor from a GitHub URL:
# install with:
uv tool install git+https://github.com/kjanat/kp2bw
kp2bw passwords.kdbx
# run directly without installing:
uvx --from git+https://github.com/kjanat/kp2bw kp2bw passwords.kdbxInstall the Bitwarden CLI and log in once before using kp2bw:
# optional: point to a self-hosted instance
bw config server https://your-domain.com/
# log in (only needed once; kp2bw uses `bw unlock` afterwards)
bw login <user>kp2bw [-h] [-V] [-k PASSWORD] [-K FILE] [-b PASSWORD] [-o ID]
[-t TAG [TAG ...]] [-c ID] [--path-to-name | --no-path-to-name]
[--path-to-name-skip N] [--skip-expired | --no-skip-expired]
[--include-recycle-bin | --no-include-recycle-bin]
[--metadata | --no-metadata] [--update | --no-update] [-y] [-v] [-d]
FILE| Flag | Description | Env var |
|---|---|---|
keepass_file |
Path to your KeePass 2.x database | - |
-k, --keepass-password |
KeePass password (prompted if omitted) | KP2BW_KEEPASS_PASSWORD |
-K, --keepass-keyfile |
KeePass key file | KP2BW_KEEPASS_KEYFILE |
-b, --bitwarden-password |
Bitwarden password (prompted if omitted) | KP2BW_BITWARDEN_PASSWORD |
-o, --bitwarden-org |
Bitwarden Organization ID | KP2BW_BITWARDEN_ORG |
-c, --bitwarden-collection |
Collection ID, or auto to derive from top-level folder names |
KP2BW_BITWARDEN_COLLECTION |
-t, --import-tags |
Only import entries with these tags | KP2BW_IMPORT_TAGS (comma-separated) |
--path-to-name / --no-path-to-name |
Prepend folder path to entry names (default: off) | KP2BW_PATH_TO_NAME |
--path-to-name-skip |
Skip first N folders in path prefix (default: 1) | KP2BW_PATH_TO_NAME_SKIP |
--skip-expired |
Skip entries that have expired in KeePass | KP2BW_SKIP_EXPIRED |
--include-recycle-bin |
Include Recycle Bin entries (excluded by default) | KP2BW_INCLUDE_RECYCLE_BIN |
--metadata / --no-metadata |
Toggle KeePass metadata as custom fields (default: on) | KP2BW_MIGRATE_METADATA |
--update / --no-update |
Update existing entries changed in KeePass (default: on) | KP2BW_UPDATE |
-y, --yes |
Skip the Bitwarden CLI setup confirmation prompt | KP2BW_YES |
-v, --verbose |
Verbose output | KP2BW_VERBOSE |
-d, --debug |
Debug output — includes third-party library logs | KP2BW_DEBUG |
-V, --version |
Print the installed kp2bw version and exit |
- |
Configuration precedence is always: CLI flag > environment variable > built-in default.
kp2bw shells out to the Bitwarden CLI. If bw isn't installed or isn't on
your PATH, kp2bw stops before prompting for any passwords with:
ERROR: Bitwarden CLI ('bw') not found on your PATH. ...
Install the CLI and make sure bw --version runs in the same shell, then retry.
If your password contains special shell characters (?, >, &, etc.), wrap
it in double quotes when prompted. See jampe#10 and
libkeepass/pykeepass#254 for details.
kp2bw starts bw serve on a random localhost port. If it times out after 60s:
- Check that
bwis installed and on yourPATH - Run
bw loginonce if you haven't already - Ensure no firewall rules block localhost connections
- Try
bw serve --port 8087 --hostname 127.0.0.1manually to see if it starts
When importing with --bitwarden-org, items already present in the
organization vault are matched by folder + name. If you're importing into a
specific collection (--bitwarden-collection), only items already in that
collection are matched — items in other collections are created.
Re-running kp2bw against the same database updates matched entries in place
when their KeePass content changed (notes, password, username, URIs or custom
fields), so you no longer need to purge the vault to push edits. Unchanged
entries are left untouched. A re-run also uploads any notes.txt / long-field
/ file attachment that a previously imported entry was missing, and refreshes
one whose contents changed in KeePass even when it keeps the same filename (the
stale copy is removed only once the new one has uploaded). Pass --no-update
(or KP2BW_UPDATE=0) to keep the old skip-only behavior and preserve manual
Bitwarden-side edits.
Attachment uploads are sent through bw serve, which forwards them to your
Bitwarden/Vaultwarden server. A rejected file (for example, an image too large
for your plan, or an upload that needs premium/organization storage) now
reports the server's actual message and is skipped — it no longer aborts the
whole migration, so the rest of your entries still import. Resolve the
underlying limit and re-run to upload the remaining files.