Metadata-Version: 2.5
Name: passvault-cli
Version: 0.1.2
Summary: A local, encrypted, offline password manager CLI.
Project-URL: Homepage, https://github.com/Ajeet2005/passvault
Project-URL: Repository, https://github.com/Ajeet2005/passvault
Project-URL: Issues, https://github.com/Ajeet2005/passvault/issues
Author: passvault contributors
License: MIT License
        
        Copyright (c) 2026 passvault contributors
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: cli,encryption,offline,password-manager,security,vault
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Requires-Dist: argon2-cffi>=23.1
Requires-Dist: cryptography>=42.0
Requires-Dist: inquirerpy>=0.3.4
Requires-Dist: platformdirs>=4.0
Requires-Dist: pyperclip>=1.8
Requires-Dist: rich>=13.0
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

# passvault

A local, encrypted, offline password manager CLI.

> **PyPI note:** the distribution is published as
> [`passvault-cli`](https://pypi.org/project/passvault-cli/) because the name
> `passvault` was already taken. The installed command and import name are
> still `passvault`.

- No network calls, no accounts, no telemetry.
- Everything lives in a single encrypted file on your machine.
- Your master password is required on **every** command. There is no session
  caching and no OS keychain integration — by design.

## How it works

Entries are stored as a JSON object and encrypted with
[Fernet](https://cryptography.io/en/latest/fernet/) (AES-128-CBC + HMAC-SHA256,
authenticated encryption).

The encryption key is derived from your master password with **Argon2id**
(memory-hard, 64 MiB, 3 passes) using a random 16-byte salt.

The vault file is laid out as:

```
salt (16 bytes) || Fernet token
```

The salt is generated once at vault creation and never rotated. Deriving the
key requires the master password, which is never stored, logged, or written
anywhere. A wrong master password fails loudly — authenticated decryption means
we never return garbage plaintext.

## Install

### Option 1 — pipx (recommended)

[pipx](https://pipx.pypa.io/) installs CLI tools in isolated environments and
puts their commands on your PATH. This is the best way to install `passvault`,
and it avoids the Windows "`passvault` is not recognized" problem entirely:

```bash
# install pipx if you don't have it
python -m pip install --user pipx
python -m pipx ensurepath   # adds pipx's bin dir to PATH; restart your terminal after

# then install passvault
pipx install passvault-cli
passvault init
```

### Option 2 — pip

```bash
pip install passvault-cli
```

> **Windows note:** with a plain `pip install`, the `passvault.exe` launcher
> lands in your Python `Scripts\` directory (e.g.
> `...\Python313\Scripts\`), which is often **not** on your PATH — so running
> `passvault` gives "command not found" / "is not recognized". Either:
>
> 1. add that `Scripts\` directory to your PATH, or
> 2. skip PATH entirely and run the CLI as a module:
>
>    ```bash
>    python -m passvault init
>    ```
>
>    The `-m` form works with every install method, on every OS.

### Option 3 — from source

```bash
git clone https://github.com/Ajeet2005/passvault.git
cd passvault
python -m venv .venv
# Windows: .venv\Scripts\activate
source .venv/bin/activate
pip install -e .
```

Requires Python 3.10+.

## Usage

All commands below also work as `python -m passvault <command>` if the
`passvault` command itself is not on your PATH.

### Create a vault

```bash
passvault init
```

Refuses to run if a vault already exists. You'll be asked for your master
password twice.

### Add an entry

```bash
passvault add github --generate --length 24 --username me@example.com
passvault add email                 # prompt for the password (hidden input)
```

Existing entries are only overwritten after a confirmation prompt. Passwords
are never echoed back to the terminal.

### List entries

```bash
passvault list
```

Shows names, usernames, and whether notes are set. **Never** prints stored
passwords.

### Retrieve a password

```bash
passvault get github               # print the password to stdout
passvault get github --clipboard   # copy to the clipboard, don't print it
```

The behavior is always explicit: you choose whether the secret is printed or
copied. There is no silent default.

### Delete an entry

```bash
passvault delete github
```

Asks for confirmation first.

### Generate a password without a vault

```bash
passvault generate --length 32
passvault generate --no-symbols
passvault generate --no-digits --clipboard
```

## Vault location

The vault lives in your OS's user data directory:

| OS      | Path                                              |
| ------- | ------------------------------------------------- |
| Windows | `%LOCALAPPDATA%\passvault\vault.dat`              |
| macOS   | `~/Library/Application Support/passvault/vault.dat` |
| Linux   | `~/.local/share/passvault/vault.dat`              |

## Development

```bash
pip install -e ".[dev]"
pytest --cov=passvault
```

Test layout:

- `tests/test_crypto.py` — key derivation determinism, round trips, wrong-password
  failure.
- `tests/test_storage.py` — create/load/save round trips, salt persistence,
  refusing writes on a wrong password.
- `tests/test_generator.py` — length and character-class guarantees.
- `tests/test_cli.py` — end-to-end command tests via Typer's `CliRunner`.

## Security notes

- The master password is never stored, in any form.
- Decrypted passwords are only printed when you explicitly run `get` without
  `--clipboard`.
- All randomness uses Python's `secrets` module, never `random`.
- A wrong master password always fails loudly.
- No session caching and no OS keychain support in this version.

## Disclaimer

This is a learning project. It has **not** been audited. For real secrets, use a
battle-tested password manager.

## License

MIT — see [LICENSE](https://github.com/Ajeet2005/passvault/blob/main/LICENSE).
