Migration
kp2bw [options] FILE. Reads KeePass and writes
Bitwarden.
command reference
kp2bw --help for a quick reminder; use this page for
semantics.usage and modes
kp2bw [OPTIONS] FILE
python -m kp2bw [OPTIONS] FILE The default mode reads FILE, unlocks Bitwarden through bw serve, then migrates entries, attachments, OTP and
passkey fields, tags, expiry, and login URIs. The two invocation forms
are equivalent.
kp2bw [options] FILE. Reads KeePass and writes
Bitwarden.
--report-uris keepass FILE. Reads KeePass and changes
nothing; no bw CLI or Bitwarden password needed.
--report-uris bitwarden, --migrate-uris,
and --strip-ids need no FILE or KeePass
password.
--doctor [--redact], --version, and --help print information and exit.
Choose one special mode per invocation. Among URI report, strip, and URI migration, report dispatch precedes strip, which precedes migration; relying on that precedence is discouraged.
environment
kp2bw searches upward from the current working directory for .env. A non-empty process environment value wins; an
unset or empty one may be filled from the file. Explicit command
options then win over environment values.
Boolean environment values accept 1/0, true/false, yes/no, y/n, or on/off, case-insensitively. Invalid values exit with
status 2.
KP2BW_KEEPASS_PASSWORD=<keepass password>
KP2BW_BITWARDEN_PASSWORD=<bitwarden password> Protect .env with filesystem permissions and never commit
it. Prompting is safer on shared systems because command-line
passwords can appear in shell history and process listings.
KeePass input and filters
FILEKP2BW_KEEPASS_FILEPath to a KeePass 2.x database. May be omitted only in modes that do not read KeePass.
-k, --keepass-password PASSWORDKP2BW_KEEPASS_PASSWORDKeePass database password. Prefer the prompt or environment over a command-line value.
-K, --keepass-keyfile FILEKP2BW_KEEPASS_KEYFILEKey file required to open the KeePass database, when applicable.
-t, --import-tags TAG [TAG ...]KP2BW_IMPORT_TAGSImport only entries carrying a listed tag. The environment value is a comma-separated list.
--skip-expired, --no-skip-expiredKP2BW_SKIP_EXPIREDExclude or include expired KeePass entries.
--include-recycle-bin, --no-include-recycle-binKP2BW_INCLUDE_RECYCLE_BINInclude or exclude entries under the KeePass Recycle Bin.
--totp-pps, --no-totp-ppsKP2BW_TOTP_PPSRead Pleasant Password Server TOTPSecret/TOTPDigits/TOTPPeriod fields instead of KeePass TimeOtp-* fields. PPS secrets use Base32 and SHA-1.
Bitwarden destination and shape
-b, --bitwarden-password PASSWORDKP2BW_BITWARDEN_PASSWORDPassword used to unlock Bitwarden. Not needed for a KeePass-only URI report.
-o, --bitwarden-org IDKP2BW_BITWARDEN_ORGCreate and scope items in this organization.
-c, --bitwarden-collection ID|auto|nestedKP2BW_BITWARDEN_COLLECTIONUse one existing collection ID, 'auto' for top-level KeePass group names, or 'nested' for full group paths. Requires an organization.
--folder, --no-folderKP2BW_CREATE_FOLDERSCreate personal Bitwarden folders from KeePass groups. --no-folder leaves personal items at the root unless collections apply.
--path-to-name, --no-path-to-nameKP2BW_PATH_TO_NAMEPrefix each item name with its KeePass group path.
--path-to-name-skip NKP2BW_PATH_TO_NAME_SKIPSkip the first N groups when building the item-name prefix. N must be an integer.
--metadata, --no-metadataKP2BW_MIGRATE_METADATAStore tags and expiry in a readable YAML KP2BW_META custom field when present.
--include-oversize-secretsKP2BW_INCLUDE_OVERSIZE_SECRETSAllow oversized hidden OTP, passkey, and KeePass-protected fields to become plaintext .txt attachments. Without consent they are warned about and dropped, not exposed.
reruns and updates
Migrated items carry a KeePass UUID in KP2BW_ID and a
content signature in KP2BW_SYNC. Unchanged reruns are
idempotent. By default, kp2bw updates changed source content but
protects an item edited in Bitwarden after the prior run.
--update, --no-updateKP2BW_UPDATESync changed KeePass content and missing or changed attachments onto matched items. --no-update leaves existing content untouched; collection membership may still sync.
--force-updateKP2BW_FORCE_UPDATEOverwrite matched items even when their KP2BW_SYNC stamp shows a later Bitwarden edit. Use only when KeePass must win.
URI matching and maintenance
Additional KeePass URLs such as KP2A_URL, URL_1, and AndroidApp become Bitwarden login
URIs. Quoted-exact and wildcard URLs keep their interpreted modes; --uri-match controls plain URLs.
--uri-match MODEKP2BW_URI_MATCHPlain-URL match mode: domain, host, startswith, exact, regex, never, default, or null. default and null leave matching unset so the Bitwarden account setting applies.
--interpret-uri-syntax, --no-interpret-uri-syntaxKP2BW_INTERPRET_URI_SYNTAXInterpret KeePassXC additional URLs: double quotes mean exact and * means wildcard. Disable only that syntax handling; invalid, non-web, or unresolved values remain dropped, and Android packages remain transformed.
--report-uris keepass|bitwardenKP2BW_REPORT_URISRead-only report of registrable domains containing multiple URI hosts. KeePass source needs FILE; Bitwarden source honors organization and collection scope.
--migrate-urisKP2BW_MIGRATE_URISBitwarden-only, idempotent upgrade: fold legacy KP2A_URL*/AndroidApp custom fields into login URIs, then exit. Honors URI settings and scope; confirms first.
finalization, diagnostics, and output
--strip-idsKP2BW_STRIP_IDSBitwarden-only finalization: remove KP2BW_ID and KP2BW_SYNC from in-scope migrated items, then exit. Irreversible and makes future reruns unreliable; confirms first.
-y, --yesKP2BW_YESSkip the bw setup prompt and confirmations for mutating Bitwarden-only modes.
-v, --verboseKP2BW_VERBOSEShow per-entry kp2bw detail on the console.
-d, --debugKP2BW_DEBUGShow debug and third-party HTTP request logs on the console.
--doctorPrint kp2bw, bw, server, installation, and .env diagnostics, then exit. Returns non-zero if bw is unusable.
--redactWith --doctor, mask the server URL and home-relative paths before sharing the report.
-V, --versionPrint the installed kp2bw version and exit.
-h, --helpPrint the concise command help and exit.
folders vs collections
This is the main migration trap. KeePass groups look like folders, but
a Bitwarden organization does not have org folders. Shared structure
in an organization is made with collections. Nested collections are
names with slashes, such as Work/Servers.
Work/ServersWork/ServersWorkWork/ServersInternet/BankingInternet/BankingInternetInternet/BankingFor a Vaultwarden organization migration, the usual shape is nested collections and no personal folders. That keeps shared data in the org model instead of creating a private folder tree beside it.
Want both? Pass --folder alongside -o (the
planner's Also create personal folders toggle) and
every item is filed into its org collection and a personal
folder — the same double-filing Bitwarden's own org import does.
Leave it off unless you specifically want that private copy.
-c nested: KeePass Work/Servers becomes
collection Work/Servers. With -o set,
personal folders are already off, so no extra flag is needed.
-c auto: KeePass Work/Servers and Work/Engineering both land in collection Work.
-c 11111111-1111-1111-1111-111111111111: every
imported item lands in one existing collection.
-o with no collection mapping: items are created in
the organization without a generated hierarchy or personal
folders.
KeePass groups become personal Bitwarden folders. Use this only when importing into a personal vault.
--no-folder: items stay at the personal vault root.
safety and operational notes
bw; for self-hosting run bw
config server URL, then log in once with bw
login. kp2bw uses unlock.--report-uris is read-only. --migrate-uris mutates matching fields. --strip-ids is irreversible.-c always requires -o. Organization scope
defaults personal folders off; explicit --folder opts
into double filing.KP2BW_LOG_FILE or directory with KP2BW_LOG_DIR.KP2BW_HTTP_TIMEOUT sets the per-request HTTP timeout in
seconds. It defaults to 180; values above 3600 are clamped to 3600.Default log directories: %LOCALAPPDATA%/kp2bw/logs on
Windows, ~/Library/Logs/kp2bw on macOS, and $XDG_STATE_HOME/kp2bw/logs or ~/.local/state/kp2bw/logs elsewhere. Logs contain debug
transport detail; review before sharing.
examples
# Personal vault; preserve KeePass groups as personal folders
kp2bw vault.kdbx
# Organization; preserve full group paths as nested collections
kp2bw -o 00000000-0000-0000-0000-000000000000 -c nested vault.kdbx
# Organization; map only top-level groups and also create personal folders
kp2bw -o 00000000-0000-0000-0000-000000000000 -c auto --folder vault.kdbx
# Import selected tags, excluding expired and Recycle Bin entries
kp2bw -t work shared --skip-expired vault.kdbx
# Read-only URI collision reports
kp2bw --report-uris keepass vault.kdbx
kp2bw --report-uris bitwarden -o 00000000-0000-0000-0000-000000000000
# Upgrade legacy URL fields in one organization, without reading KeePass
kp2bw --migrate-uris -o 00000000-0000-0000-0000-000000000000
# Final adoption; remove migration stamps after interactive confirmation
kp2bw --strip-ids -o 00000000-0000-0000-0000-000000000000
# Shareable diagnostics
kp2bw --doctor --redact