First Pass
Type the damn thing step by step
I'm continuing with the idea of typing or transcribing the script βI do feel this is good practice to get some muscle memory, and it also helps me a lot in understanding what the code does, gives me familiarity with structures and vocabularyβ, but do it step by step in a more "realistic" workflow... it's all still simulated, obviously, but baby steps, getting closer to the real thing.
BUT... for this project, Claude.AI decided to spit out 388 lines, so just to make that part smoother, I asked it to give me the step-by-step of what the "real" workflow would look like; this is what it gave me:
ποΈ Build Order - Password Manager
Phase 1: Basic Structure (Get something running)
Goal: Create a working loop that does nothing
-
Start with the skeleton:
main()function with welcome message- Simple
while Trueloop withinput() quitcommand to exitif __name__ == "__main__":block
-
Test it: Should be able to type
quitand exit
Phase 2: Help & Commands (Navigation)
Goal: Show available commands
-
Add:
show_help()functionhelpcommand in main loop- Handle unknown commands with else clause
-
Test it: Type
help, see commands, type garbage, see error message
Phase 3: In-Memory Storage (No files yet)
Goal: Store passwords temporarily (they disappear when you quit)
-
Add:
vault = {}dictionary at top ofmain()add_account()function (simplified - no encryption, no file save)- Just get account name, username, password
- Store in
vault[account_name] = {...} - Print success message
- Wire up
addcommand in main loop
-
Test it: Add a few accounts, they exist during session
-
Add:
list_accounts()function- Wire up
listcommand
-
Test it: Add accounts, list them, see them appear
-
Add:
view_account()function- Wire up
viewcommand
-
Test it: Add account, view it, see details
Phase 4: File Persistence (Save/Load - NO encryption yet)
Goal: Data survives program restarts
-
Add:
VAULT_FILE = "password_vault.json"constant at topsave_vault()function (simple version - no encryption)- Use
json.dump()
- Use
- Update
add_account()to callsave_vault()at the end
-
Test it: Add account, quit, restart program - file exists but can't load yet
-
Add:
load_vault()function (simple version - no encryption)- Check if file exists with
os.path.exists() - Use
json.load() - Return empty dict if file doesn't exist
- Check if file exists with
- Call
load_vault()inmain()before the loop - Pass
vaultto functions that need it
-
Test it: Add accounts, quit, restart, list - accounts persist! π
Phase 5: Encryption (Make it secure-ish)
Goal: Encrypt stored passwords
-
Add:
- Master password prompt in
main()(usegetpass.getpass()) simple_encrypt()functionsimple_decrypt()function
- Master password prompt in
-
Update:
save_vault()to encrypt username/password before savingload_vault()to decrypt after loading- Add try/except for wrong master password
-
Test it:
- Add account with master password "test123"
- Quit, restart with "test123" - works!
- Quit, restart with "wrong" - fails!
- Look at
password_vault.json- gibberish! β
Phase 6: Polish & Features
Goal: Nice-to-haves
-
Add:
delete_account()functionsearch_accounts()function- Timestamps (
datetimeimport, add toadd_account()) - Better input validation (empty checks, confirmation prompts)
- Error handling (try/except blocks)
-
Test each feature individually
Phase 7: UX Polish
Goal: Make it feel professional
- Add:
- Emoji decorations (π, β, β, β οΈ)
- Formatting (borders, spacing)
- Confirm password when adding
- Optional fields (URL, notes)
π Development Tips:
For each phase:
- β Write the function
- β
Wire it into
main()loop - β Test it immediately
- β Break stuff, fix it
Use print statements liberally:
def load_vault():
print(f"DEBUG: Looking for {VAULT_FILE}") # Remove later
if not os.path.exists(VAULT_FILE):
print("DEBUG: File doesn't exist yet")
return {}
# ...
Start simple, add complexity:
- Phase 3: No password confirmation, no validation
- Phase 6: Add all the checks and confirmations
This way you'll have a working program at EVERY step, not just at the end! Much more satisfying.