Metadata-Version: 2.4
Name: bw2kp
Version: 0.5.0
Summary: Convert Bitwarden vaults into KeePass databases
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pykeepass<5,>=4.1
Dynamic: license-file

# bw2kp

Export Bitwarden vault data into a KeePass database.

## Python CLI

Install from PyPI:

```bash
pip install bw2kp
```

Then run:

```bash
bw2kp --help
```

To get `BW_SESSION`, log in with `bw login` and then run:

```bash
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-session`
- `DATABASE_PATH` / `--database-path`
- `DATABASE_PASSWORD` / `--database-password`
- `DATABASE_KEYFILE` / `--database-keyfile`
- `BW_PATH` / `--bw-path`
- `ROOT_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.totp` is stored in KeePass `otp`.
- 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_PASSWORD`
- `BW_CLIENTID`
- `BW_CLIENTSECRET`
- `BW_PASSWORD`

Optional container vars:
- `DATABASE_PATH` (default: `/exports/bitwarden-export.kdbx`)
- `DATABASE_KEYFILE`
- `ROOT_GROUP`
- `ARCHIVED_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/.config`
If Docker creates either bind mount path for you, chown it to `1000:1000` before the first run so the container user can write to it.
Keep the `./bw-config` mount 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:1000` by default; override with `docker run --user` when needed.

Run:

```bash
docker compose up
```

Example secret-based values:

```bash
-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
```
