Bitwarden CLI Vault Cleanup Guide
A comprehensive guide for cleaning up your Bitwarden vault using the CLI, based on real troubleshooting sessions.
Prerequisites
- Bitwarden CLI installed in
C:\Tools\Bitwarden(or your chosen directory) - Windows PowerShell (works with PowerShell 5.x)
- Navigate to the Bitwarden directory in a Windows Terminal:
cd C:\Tools\Bitwarden
Initial Setup (Required for All Operations)
1. Login to Bitwarden
.\bw login
Enter your email, master password, and 2FA code when prompted.
2. Unlock the Vault and Store Your Session
You already logged in, but you still need to unlock and capture the session token.
Run this EXACT command:
$env:BW_SESSION = .\bw unlock --raw
You will be prompted for your master password again.
When it completes, your environment variable will be set.
3. Verify Session is Active
Check it:
$env:BW_SESSION
You should see a long base64-like token.
❗ If You See Nothing Printed
That means unlocking failed.
If unlocking failed, run:
.\bw unlock --raw
Copy the output token manually and set it:
$env:BW_SESSION = "PASTE_TOKEN_HERE"
Then verify again:
$env:BW_SESSION
Part 1: Remove Old Entries by Date
Step 1: Load All Items
$items = .\bw list items --session $env:BW_SESSION | ConvertFrom-Json
Step 2: Filter Items Older Than Specific Date
# Set your cutoff date (change as needed)
$cutoff = Get-Date '2023-01-01'
# Filter for login items (type 1) older than cutoff
$old = $items | Where-Object {
$_.type -eq 1 -and
([datetime]$_.revisionDate) -lt $cutoff
} | Select-Object name, username, revisionDate, id
One-line version (easier to paste):
$cutoff = Get-Date '2023-01-01'; $old = $items | Where-Object { $_.type -eq 1 -and ([datetime]$_.revisionDate) -lt $cutoff } | Select-Object name, username, revisionDate, id
Step 3: Review What Will Be Deleted
$old | Format-Table -AutoSize
$old.Count
Step 4: Delete Old Items (Moves to Trash)
⚠️ WARNING: Review the list carefully first!
$old.id | ForEach-Object {
.\bw delete item $_ --session $env:BW_SESSION
}
Part 2: Remove Duplicate Entries
Step 1: Load Items (if not already loaded)
$items = .\bw list items --session $env:BW_SESSION | ConvertFrom-Json
$logins = $items | Where-Object { $_.type -eq 1 }
Step 2: Find Duplicate Groups
Groups by username + item name to identify duplicates:
$dupeGroups = $logins | Group-Object -Property {
# username (lowercased, safe if null)
$u = ''
if ($_.login -and $null -ne $_.login.username) {
$u = $_.login.username.ToLower()
}
# item name (lowercased, safe if null)
$n = ''
if ($_.name) {
$n = $_.name.ToLower()
}
# key: username|name
"$u|$n"
} | Where-Object { $_.Count -gt 1 }
Step 3: Extract Older Duplicates (Keep Newest)
$dupes = @()
foreach ($g in $dupeGroups) {
# Sort newest → oldest by revisionDate
$sorted = $g.Group | Sort-Object @{ Expression = { [datetime]$_.revisionDate }; Descending = $true }
if ($sorted.Count -gt 1) {
# Skip index 0 (newest), keep the rest
$dupes += $sorted[1..($sorted.Count - 1)]
}
}
Step 4: Review Duplicates
$dupes | Select-Object `
name,
@{Name='username'; Expression = { if ($_.login) { $_.login.username } }},
revisionDate,
id | Format-Table -AutoSize
$dupes.Count
Step 5: Delete Duplicates (Moves to Trash)
$dupes.id | ForEach-Object {
.\bw delete item $_ --session $env:BW_SESSION
}
Part 3: Final Cleanup
Permanently Delete Items from Trash
⚠️ FINAL WARNING: This is permanent and cannot be undone!
Only after verifying in the Bitwarden UI that trash contains only items you want gone:
.\bw delete items --permanent --session $env:BW_SESSIONSync Your Vault
.\bw sync --session $env:BW_SESSION
Critical Notes & Troubleshooting
Always Use .\bw
- ❌ Wrong:
bw login - ✅ Correct:
.\bw login
PowerShell doesn't load commands from the current directory by default unless you use .\
Avoid Reserved Variable Names
- Never use
$hostin scripts (it's a PowerShell automatic variable) - The duplicate script uses
$uand$nto avoid this conflict
Item Types
$_.type -eq 1= Login items$_.type -eq 2= Secure notes$_.type -eq 3= Card items$_.type -eq 4= Identity items
Adjusting Cutoff Dates
Change the date in these examples as needed:
$cutoff = Get-Date '2022-01-01' # Older than 2022
$cutoff = Get-Date '2020-01-01' # Older than 2020
$cutoff = Get-Date '2024-06-01' # Older than mid-2024
Safety Best Practices
1. Export Before Bulk Deletion
.\bw export --format json --session $env:BW_SESSION > backup.json
2. Test with Small Batches First
# Test with first 5 items
$old = $old | Select-Object -First 5
3. Review Trash Before Permanent Delete
- Open Bitwarden web vault or desktop app
- Check the Trash folder
- Verify nothing important is there
- Then run the permanent delete command
4. Items Go to Trash First
Deleted items aren't gone immediately - they go to Trash where you can:
- Review them
- Restore if needed
- Permanently delete when ready
Quick Reference
Complete Old Item Cleanup (One Session)
# 1. Setup
cd C:\Tools\Bitwarden
$env:BW_SESSION = .\bw unlock --raw
# 2. Filter & Review
$items = .\bw list items --session $env:BW_SESSION | ConvertFrom-Json
$cutoff = Get-Date '2023-01-01'
$old = $items | Where-Object { $_.type -eq 1 -and ([datetime]$_.revisionDate) -lt $cutoff } | Select-Object name, username, revisionDate, id
$old | Format-Table -AutoSize
# 3. Delete (after review)
$old.id | ForEach-Object { .\bw delete item $_ --session $env:BW_SESSION }
Session Management
If your session expires during work:
$env:BW_SESSION = .\bw unlock --raw
To check if session is active:
$env:BW_SESSION # Should show a token
Common Issues & Solutions
"bw: The term 'bw' is not recognized"
Solution: Use .\bw instead of just bw
"error: option '--session <session>' argument missing"
Solution: Your session isn't set or has expired. Run:
$env:BW_SESSION = .\bw unlock --raw
"Cannot overwrite variable Host"
Solution: Script has been fixed to avoid using $host variable name
Session Expired
Solution: Run $env:BW_SESSION = .\bw unlock --raw again
Empty Results When Filtering
Solution: Check your date format and verify items exist in that date range:
$items | Select-Object name, revisionDate | Sort-Object revisionDate | Format-Table
Nothing Appears After $env:BW_SESSION
Solution: Unlock failed. Manually unlock and copy the token:
.\bw unlock --raw
# Copy the token output
$env:BW_SESSION = "PASTE_TOKEN_HERE"
Important Reminders
- Login vs Unlock: Login authenticates you; unlock creates a session. You need both.
- Session per PowerShell Window: Each new PowerShell window needs its own unlock.
- Trash is Your Friend: All deletes go to trash first - nothing is permanent until you explicitly purge.
- Test First: Always review with
Format-Tablebefore running delete commands. - Export for Safety: Create a backup export before any bulk cleanup operation.
Created & Maintained by Pacific Northwest Computers
📞 Pacific Northwest Computers offers Remote & Onsite Support Across:
SW Washington including Vancouver WA, Battle Ground WA, Camas WA, Washougal WA, Longview WA, Kelso WA, and Portland OR


No comments:
Post a Comment