> authsome manages credentials — nothing more. Every contribution should make that one job simpler, more secure, or more reliable. If a change expands scope beyond credential management, it probably belongs in a different tool.
These principles apply to all contributions — human and AI alike.
**YAGNI — You Aren't Gonna Need It.**
Implement only what the current task demands. Build for today's requirements; future requirements will arrive with future context.
**Use trusted libraries over reinventing.**
Reach for a well-maintained dependency before writing your own crypto, HTTP client, or token parser. The goal is a working credential manager, not a showcase of custom implementations. When a library exists and is maintained, use it.
**Deep modules over shallow ones.**
Prefer a module with a small surface area and rich internals over a sprawl of thin wrappers. A single `AuthClient` that handles everything cleanly beats a dozen one-method classes. More files is not more modular.
Prefer small collaborators wired together through explicit dependencies over inheritance hierarchies. Use inheritance only when there is a real subtype relationship and composition would make the design less clear.
**Single responsibility and separation of concerns.**
Auth authenticates. Vault stores credentials. The CLI presents output. These boundaries are not negotiable — a flow should not write to storage, and storage should not know about OAuth. If a function is hard to name, it's doing too many things.
**Premature optimization is evil.**
Don't add caching, batching, or concurrency before you have a measured performance problem. Simple code that's slow is fixable; complex code that's wrong is not.
**Don't do it just because you can.**
Clever is a cost, not a benefit. If a feature, abstraction, or refactor isn't directly solving a real problem that exists today, skip it.
**Leave it better than you found it.**
Every change is an opportunity to fix a nearby typo, remove a dead import, or clarify a confusing comment — not the whole file, just the immediate vicinity. Small improvements compound.
**Comment the why, not the what.**
Use Google-style docstrings for all public interfaces. Inline comments should explain non-obvious invariants, workarounds, or hidden constraints — not restate what the code already says clearly.
**Update docs alongside code.**
If you change behavior, update the relevant docstring, `README.md`, or this file in the same commit. Documentation debt accumulates faster than technical debt and is harder to pay down later.
---
## AI-assisted development
When using an AI coding assistant (Claude Code, Copilot, Codex, etc.), these additional practices apply.
**Verify before claiming done.**
Run `uv run pytest`, `uv run ruff check`, and `uv run ty check` and confirm they pass before stating work is complete. Never assume. Plausible-sounding output is not the same as passing output.
**Minimal blast radius.**
Fix only what you were asked to fix. Don't refactor surrounding code, rename variables, or reorganize imports while implementing a feature. Save cleanup for a dedicated commit so diffs stay reviewable.
**Surface uncertainty.**
If there are multiple valid approaches, say so and present the tradeoffs. Silently picking one and hiding the decision makes review harder and leads to avoidable rework.
**No hallucinated APIs.**
If you're unsure a method, parameter, or module exists, search for it in the codebase before using it. Plausible-sounding code that doesn't run wastes more time than asking first.
Do not hide missing imports or circular dependencies behind quoted annotations, `TYPE_CHECKING` imports, or postponed annotations. If an annotation names a class from another module, import it normally and let import-time failures reveal architectural cycles. Fix those cycles at the ownership boundary. Use `Self` for same-class return types.