Convert Bitwarden vaults into KeePass databases
Project description
bw2kp
Export Bitwarden vault data into a KeePass database.
Python CLI
Install from PyPI:
pip install bw2kp
Then run:
bw2kp --help
To get BW_SESSION, log in with bw login and then run:
export BW_SESSION="$(bw unlock --raw)"
By default, bw2kp syncs in place using a stored bitwarden_id custom field so existing KeePass icons and metadata stay intact. Use --rebuild when you want a full refresh: bw2kp archives the current KeePass root group, recreates the tree from Bitwarden, and uses ARCHIVED_GROUP only for that archive target. If ARCHIVED_GROUP is omitted, the previous root group is moved to the Recycle Bin.
CLI env vars / flags:
BW_SESSION/--bw-sessionDATABASE_PATH/--database-pathDATABASE_PASSWORD/--database-passwordDATABASE_KEYFILE/--database-keyfileBW_PATH/--bw-pathROOT_GROUP/--root-group(optional; if omitted, syncs directly at KeePass root)ARCHIVED_GROUP/--archived-group(only used with--rebuild)--rebuild(archive the current KeePass root group and recreate it from Bitwarden instead of syncing in place)
Notes
- Bitwarden
login.totpis stored in KeePassotp. - Bitwarden passkeys are imported into KeePassXC-compatible
KPEX_PASSKEY_*fields. - KeePassXC 2.7.10+ is recommended for passkey support.
- Back up existing databases before importing (the Docker container does this by default).
- Folder renames update KeePass group names; item moves relocate matching entries between groups.
- Written with AI assistance, verified line by line by a human.
Docker (alternative)
Use the provided Dockerfile or docker-compose.yaml if you prefer a containerized run. The compose file pulls ghcr.io/lanjelin/bw2kp, runs it as UID/GID 1000:1000 by default, and the image pre-creates /exports and /home/bw2kp/.config.
The container accepts plain env values or file paths. If a required variable points to a readable file, entrypoint.sh reads the file contents first. This makes Docker secrets work out of the box.
Required container vars:
DATABASE_PASSWORDBW_CLIENTIDBW_CLIENTSECRETBW_PASSWORD
Optional container vars:
DATABASE_PATH(default:/exports/bitwarden-export.kdbx)DATABASE_KEYFILEROOT_GROUPARCHIVED_GROUP(only used with--rebuild)NO_BACKUP(set to any non-empty value to skip the automatic pre-sync backup)BITWARDEN_URL(default:https://bitwarden.com)
Compose volumes:
./exports:/exports./bw-config:/home/bw2kp/.configIf Docker creates either bind mount path for you, chown it to1000:1000before the first run so the container user can write to it. Keep the./bw-configmount persistent; if the Bitwarden config directory is recreated on every run, Bitwarden will treat each start as a new device and send a new-device email.
Runtime user:
1000:1000by default; override withdocker run --userwhen needed.
Run:
docker compose up
Example secret-based values:
-e BW_CLIENTID=/run/secrets/client-id
-e BW_CLIENTSECRET=/run/secrets/client-secret
-e BW_PASSWORD=/run/secrets/bw_password
-e DATABASE_PASSWORD=/run/secrets/export_password
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bw2kp-0.5.0.tar.gz.
File metadata
- Download URL: bw2kp-0.5.0.tar.gz
- Upload date:
- Size: 30.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
04653903d5489e1ab1ff0fbcbda28e68e94f15d5a747a8a916d4200603bf4868
|
|
| MD5 |
371dcbd1587b3a7e87d18e9352d14f1c
|
|
| BLAKE2b-256 |
9539a0a7e2418b808a57e8d5c4d5b6bac9b2e752158ea72f03ae0d39e5a6850e
|
Provenance
The following attestation bundles were made for bw2kp-0.5.0.tar.gz:
Publisher:
release.yml on Lanjelin/bw2kp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bw2kp-0.5.0.tar.gz -
Subject digest:
04653903d5489e1ab1ff0fbcbda28e68e94f15d5a747a8a916d4200603bf4868 - Sigstore transparency entry: 2164969670
- Sigstore integration time:
-
Permalink:
Lanjelin/bw2kp@32c73fe57ac2dfada8c655220e0a3a0980274ee9 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/Lanjelin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@32c73fe57ac2dfada8c655220e0a3a0980274ee9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bw2kp-0.5.0-py3-none-any.whl.
File metadata
- Download URL: bw2kp-0.5.0-py3-none-any.whl
- Upload date:
- Size: 28.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc6881254e99b26015ba29179dd9f868965717bbb42da94fa6b77162a60fa7d6
|
|
| MD5 |
6323ccf2bcfccfd7985eb796e2b24304
|
|
| BLAKE2b-256 |
49100feff0db185b32d0d1ebafdae7ee315114d53e7051a457825a77858d208c
|
Provenance
The following attestation bundles were made for bw2kp-0.5.0-py3-none-any.whl:
Publisher:
release.yml on Lanjelin/bw2kp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bw2kp-0.5.0-py3-none-any.whl -
Subject digest:
fc6881254e99b26015ba29179dd9f868965717bbb42da94fa6b77162a60fa7d6 - Sigstore transparency entry: 2164969699
- Sigstore integration time:
-
Permalink:
Lanjelin/bw2kp@32c73fe57ac2dfada8c655220e0a3a0980274ee9 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/Lanjelin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@32c73fe57ac2dfada8c655220e0a3a0980274ee9 -
Trigger Event:
push
-
Statement type: