Secure local password manager CLI with terminal
Project description
pm — Password Manager CLI
A secure, local password manager for developers. Runs entirely on your laptop — no cloud, no sync service, no account required.
Python 3.10 · 3.11 · 3.12 · 3.13
Features
- 4 entry types: Login, Database, API Credential, Secure Note
- AES-256-GCM encryption — every secret encrypted individually at rest
- Folder organisation with typo-safe folder creation
- Interactive wizard — no flags to memorise
- Session caching —
pm unlockonce, skip the password prompt for 15 minutes - TOTP / 2FA — store authenticator secrets, live 6-digit codes in
pm get - Camera-safe display —
ccopy ·tcopy TOTP ·sreveal · clipboard auto-clears in 45s - Password history — last 5 rotations archived per entry (
pm history <name>) - Vault health report — detects reused/weak passwords, missing 2FA, never-rotated credentials
- Import from Chrome CSV, Bitwarden CSV, and 1Password 1PUX
- Custom fields — attach arbitrary key-value pairs to any entry
- Shell tab completion —
pm get git<TAB>completes to entry names --output table | json | rawfor scripting and piping- Encrypted export/restore for laptop migration
Requirements
- Python 3.10+
- macOS / Linux / Windows
Installation
git clone <repo>
cd password-manager
pip install -e .
Verify:
pm --version
Quick Start
pm init # create vault (~/.pm/vault.db)
pm unlock # cache session (skip password for 15 min)
pm create # interactive wizard
pm list # list all entries
pm get github # view entry
pm status # vault summary + stale report
pm status --health # full security audit
Commands
pm init
Initialise a new vault. Run once. Vault is stored at ~/.pm/vault.db.
pm init
pm unlock / pm lock
Cache the master password derivation so subsequent commands skip the prompt.
pm unlock # cache for 15 minutes (default)
pm unlock --timeout 60 # cache for 1 hour
pm lock # clear the session immediately
Session is stored in the OS keychain (macOS Keychain / Linux SecretService). Each command that prompts for a password also starts a session automatically.
pm create
Interactive wizard. Prompts for entry type then relevant fields.
pm create
→ Type [login/database/api/note]: database
→ Name: prod-postgres
→ Kind [mysql/postgres/redis/mongodb/sqlite/other]: postgres
→ Host: db.example.com
→ Port [5432]:
→ Database: myapp
→ Username: admin
→ Generate Password? [y/n]: y → Generated: Xk9#...
→ Notes:
→ Folder [personal]: company-a
Folder 'company-a' doesn't exist. Existing folders: personal
Create new folder 'company-a'? [y/n]: y
✓ prod-postgres (Database) saved in folder company-a.
Entry types and their fields:
| Type | Fields |
|---|---|
login |
username, password, website, TOTP secret, custom fields, notes |
database |
kind, host, port, database, username, password, notes |
api |
service, api key, api secret, endpoint, environment, notes |
note |
title, content |
Login entries support optional TOTP secrets and custom fields (e.g. account ID, recovery email).
pm get <name>
View an entry. Secrets are masked by default.
pm get github # masked
pm get github --show # reveal secrets
pm get github --copy # copy primary secret to clipboard silently
Camera-safe interactive mode — after displaying the masked entry:
↳ c copy password t copy totp s reveal q/any key to quit
c— copies password/api key silently; auto-clears clipboard in 45st— copies the live TOTP code (only shown when entry has a 2FA secret)s— reveals masked fields inline + warns to clear terminalq/ any other key — dismisses
If the entry has markdown notes or long notes, they are rendered below the table with syntax highlighting.
pm edit <name>
Interactive wizard pre-filled with current values.
pm edit github # full interactive edit
pm edit github --folder company-a # move to different folder only
pm rename <old> <new>
Rename an entry without recreating it.
pm rename github github-personal
pm duplicate <source> <new-name>
Clone an entry — copies all fields, metadata, TOTP secret, and custom fields.
pm duplicate prod-postgres staging-postgres
pm history <name>
Show the last 5 password rotations for an entry.
pm history github # masked
pm history github --show # reveal previous passwords
History is recorded automatically on every pm edit that changes the password.
pm list
List all entries grouped by folder.
pm list # all entries
pm list --folder company-a # one folder
pm list --folders # folder summary with counts
pm list --search postgres # search across all folders
pm find <query>
Deep search across all fields including encrypted metadata (host, database name, service, environment, custom fields, etc.).
pm find postgres # matches name, host, or database name
pm find stripe # matches service field in api entries
pm find production # matches environment in api entries
pm find company-a # matches folder name
pm delete <name>
pm delete github # prompts for confirmation
pm delete github --yes # skip confirmation
pm status
Vault summary and stale credential report.
pm status # default 90-day threshold
pm status --days 30 # stricter threshold
pm status --health # full health audit
--health adds:
- Reused passwords — entries that share the same password
- Weak passwords — too short or no digits/symbols
- Never rotated — password has never been changed since creation
- Missing 2FA — login entries without a TOTP secret
pm import
Import passwords from external password managers.
# Chrome / Edge CSV export
pm import ~/chrome-passwords.csv --format chrome
# Bitwarden unencrypted CSV export
pm import ~/bitwarden-export.csv --format bitwarden
# 1Password 1PUX export
pm import ~/1password-export.1pux --format 1password
# Override destination folder for all imported entries
pm import ~/bitwarden-export.csv --folder work
Format is auto-detected from the file extension and header when --format is omitted. A preview table is shown before import is confirmed.
pm export / pm restore
Portable backup for laptop migration.
# Export (encrypted — safe to store in cloud/USB)
pm export backup.enc
# Export plain JSON (keep secure — contains raw secrets)
pm export backup.json --format json
# Restore on new laptop
pm init
pm restore backup.enc
pm open <name>
Open the saved URL in the default browser.
pm open github
pm generate
Generate a password without saving it.
pm generate # 20 chars, letters + digits + symbols
pm generate --length 32
pm generate --no-symbols
pm generate --count 5 # generate 5 options
pm completion
Enable shell tab completion for entry names (pm get git<TAB>).
# Zsh
pm completion --shell zsh
# → follow the printed instructions to add to ~/.zshrc
# Bash
pm completion --shell bash
# Fish
pm completion --shell fish
Entry names complete when a vault session is active (pm unlock first).
Output Formats
All read commands (get, list, find, status) support --output / -o:
| Format | Description |
|---|---|
table |
Rich terminal display (default) |
json |
Full JSON — secrets masked unless --show |
raw |
Primary secret only, suitable for piping |
pm get github -o raw # password only
pm get prod-postgres -o raw # postgresql://user:pass@host/db
pm get stripe-prod -o raw # api key only
pm get github -o json --show # full JSON with plaintext secrets
pm list -o json | jq '.[].name' # extract names
pm status --days 30 -o json | jq '.stale[].name'
pm find production -o raw # one entry name per line
Folders
Entries are grouped by folder (personal by default). Folders are created implicitly — no setup needed. A confirmation prompt protects against typos when a new folder name is used.
pm create # wizard asks for folder
pm edit github --folder work # move entry to a different folder
pm list --folders # see all folders
TOTP / 2FA
Store an authenticator secret alongside any login entry. The live 6-digit code appears automatically in pm get and can be copied with t.
Name github
Password ••••••••
TOTP 847291 (12s)
↳ c copy password t copy totp s reveal q/any key to quit
Add or update via pm create or pm edit — the wizard prompts for a TOTP secret (base32 format, e.g. from a QR code scanner).
Custom Fields
Attach arbitrary key-value pairs to any entry during pm create or pm edit:
Add/edit custom fields? [y/n]: y
Custom field (label=value): Account ID=GH-123456
Custom field (label=value): Recovery email=backup@email.com
Custom field (label=value): ← empty to finish
Custom fields are encrypted at rest alongside other metadata.
Laptop Migration
# On old laptop
pm export ~/backup.enc # prompts for a backup password
# Copy backup.enc to new laptop (USB, AirDrop, encrypted cloud, etc.)
# On new laptop
pip install -e .
pm init
pm restore ~/backup.enc # prompts for the backup password
The backup password is independent of your master password.
Security
| Property | Detail |
|---|---|
| Encryption | AES-256-GCM per field |
| Key derivation | PBKDF2-HMAC-SHA256, 600 000 iterations |
| Master password | Never stored — derived key verified via token |
| Storage | SQLite at ~/.pm/vault.db |
| Session cache | Derived key stored in OS keychain (macOS Keychain / Linux SecretService) |
| Clipboard | Auto-cleared after 45s; only cleared if clipboard still holds the copied value |
| Export | Re-encrypted with a separate backup password + fresh salt |
Override vault location: export PM_VAULT_PATH=/path/to/vault.db
Skip password prompt in scripts: export PM_MASTER_PASSWORD=...
Environment Variables
| Variable | Default | Description |
|---|---|---|
PM_VAULT_PATH |
~/.pm/vault.db |
Path to vault file |
PM_MASTER_PASSWORD |
— | Skip interactive password prompt |
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 password_manager_vault-1.0.0.tar.gz.
File metadata
- Download URL: password_manager_vault-1.0.0.tar.gz
- Upload date:
- Size: 27.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64124b286790854564117b50ff497d0b5e1149a3a6b7d366e60906296b98eabb
|
|
| MD5 |
f05506282d634e0d3c6dc6a2e4ff1747
|
|
| BLAKE2b-256 |
3c9c09fedcb878a0d970b78957f370a5e4e97245bee1837d148733719559ae2d
|
File details
Details for the file password_manager_vault-1.0.0-py3-none-any.whl.
File metadata
- Download URL: password_manager_vault-1.0.0-py3-none-any.whl
- Upload date:
- Size: 28.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a803377cae9a218a1b85ee2d0974e49e432170cc9bc91f566a24931094349f09
|
|
| MD5 |
bb1b7907a11f6596419ac1b5a531f935
|
|
| BLAKE2b-256 |
9be1c5933fda32b8661f380ef92e51c1adf66d7f7610ddb12cd61a55a03fd9c5
|