A local private document vault CLI with a polished interactive shell.
Project description
vault-cli
vault-cli is a local, private, terminal-first vault for ideas, notes, and project documents. It keeps the interactive shell and polished CLI flow of the original base project, but swaps the domain entirely to an encrypted document library designed for single-user local use.
PyPI package: secure-vault-cli
Quick links: Contributing · Contributors · License
Public command:
vault
Highlights
- Local-only encrypted vault backed by SQLite
- Functional metadata encrypted at rest
- Integrated shell with
help,man, and command completion - Integrated multiline editor by default
- Optional export, clipboard copy, and external editor with explicit privacy warnings
- Cross-platform target: Windows and Linux
- Ready for
pipx
Installation
Recommended:
pipx install secure-vault-cli
Development install:
python -m pip install -e .[dev]
python -m pytest
PyPI publishing
The repository includes a GitHub Actions workflow for PyPI publishing via Trusted Publishing.
It is designed to:
- build the distributions in a dedicated job
- run
twine checkbefore upload - pass the built artifacts to a separate publish job
- publish to PyPI using GitHub OIDC instead of a long-lived API token
Before the workflow can upload anything, configure secure-vault-cli on PyPI with this repository as a Trusted Publisher and use the pypi environment in GitHub.
Commands
vault initvault unlockvault lockvault new <id>vault edit <id>vault view <id>vault listvault delete <id>vault export <id> <path>vault copy <id>vault purgevault helpvault manvault shell
Running vault with no subcommand starts the interactive shell.
Data paths
Default per-user paths are resolved with platformdirs.
- Vault config:
config_dir / vault.json - Vault database:
data_dir / vault.db
For tests or custom local runs you can override the root with:
VAULT_CLI_HOME=/custom/root
Inside that root, the app uses:
config/vault.jsondata/vault.db
Security model
What is encrypted
The full functional payload of every document is encrypted:
idtitlecreated_atupdated_atfoldertagstemplate_namebody
Outside the encrypted payload, the database stores only:
lookup_keypayload_versionencrypted_payload- technical metadata that is not functionally sensitive
IDs are never stored in cleartext.
Cryptography v1
- Passphrase KDF:
Argon2id master_key: 32 bytesindex_key: 32 bytes derived frommaster_keyusingHKDF- Per-document cipher:
AESGCM - Nonce size: 12 bytes
encrypted_payloadformat:nonce(12 bytes) || ciphertext+tag- Authenticated additional data includes:
payload_version- stable type identifier
document-v1
lookup_key is defined exactly as:
HMAC-SHA256(index_key, normalized_id.encode("utf-8"))
The full binary digest is stored as fixed-length BLOB and indexed uniquely. It is not reversible.
vault.json schema
vault.json contains only technical material:
{
"schema_version": 1,
"kdf": {
"algorithm": "argon2id",
"time_cost": 3,
"memory_cost": 65536,
"parallelism": 4,
"hash_len": 32,
"salt_b64": "..."
},
"wrapping": {
"algorithm": "AESGCM",
"nonce_b64": "...",
"wrapped_master_key_b64": "..."
}
}
Units and semantics:
memory_costis expressed inKiBtime_cost,parallelism, andhash_lenare integers
No functional metadata is stored in vault.json.
SQLite behavior
In v1 the SQLite connection uses:
PRAGMA journal_mode=DELETEPRAGMA temp_store=MEMORY
This reduces auxiliary artifacts compared with WAL, but it does not replace the cryptographic erase model or guarantee absence of filesystem traces.
Query UX
vault list
Default columns:
idtitleupdated_at
Verbose mode:
vault list --verbose
Adds:
foldertags
Stable JSON output:
vault list --json
Public stable shape:
{
"items": [
{
"id": "example-id",
"title": "Example",
"updated_at": "2026-04-13T12:00:00Z",
"folder": "inbox",
"tags": ["one", "two"]
}
]
}
This JSON format is treated as stable for v1. Timestamps are emitted in ISO 8601 UTC.
vault view
view, export by default, and copy --full all share the same canonical full render with this fixed order:
IDTitleCreated AtUpdated AtFolderTags- body
Editing
The integrated editor is the default. It supports:
.save.cancel.print.help
The app always controls:
idcreated_atupdated_attemplate_name
The editor is intended for:
titlefoldertagsbody
Privacy warnings
Export
vault export writes plaintext outside the encrypted perimeter.
- Default output: canonical full render
--body-only: only the body- No overwrite without
--force
Clipboard
vault copy is best-effort and intentionally avoids extra dependencies.
- Default: copy
body --full: copy canonical full render- Windows:
clip - Linux:
wl-copy,xclip, orxsel
Clipboard contents are outside the encrypted perimeter and may be visible to other local processes.
External editor
vault edit --external-editor is opt-in only. It may create plaintext artifacts such as temp files, swap, MRU entries, or editor history.
IDs and normalization
IDs are normalized predictably:
- trimmed
- lowercased
- internal whitespace converted to
- - only
[a-z0-9._-]allowed after normalization
Examples:
My Idea->my-ideaProject_1->project_1
If normalization changes the ID, the CLI reports it before persistence. Empty IDs after normalization are rejected. Collisions after normalization are rejected.
Exit codes
0success1generic error2invalid usage3locked vault / auth required4not found5already exists6destructive action aborted
Examples
vault init
vault unlock
vault new idea-one
vault view idea-one
vault list --verbose
vault export idea-one ./idea-one.txt
vault copy idea-one --full
vault delete idea-one
vault purge
Threats and limits
- The session key lives only in process memory, but Python memory cleanup is best-effort and not a forensic guarantee.
listand filters decrypt documents in memory in v1; this is an explicit privacy/functionality trade-off.- No full-text search is implemented in v1.
- No passphrase by CLI argument or environment variable in v1.
purgedestroys key/config material and app-managed files as application-level cryptographic erase, but cannot guarantee physical erasure on modern SSDs or all filesystems.
Manual
Use the built-in manual:
vault man
vault man new
vault man purge
Contributors
- Luis Romero (Luis696969) — creator and maintainer
See also CONTRIBUTORS.md.
License
This project is licensed under the MIT License. See LICENSE.
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 secure_vault_cli-0.1.3.tar.gz.
File metadata
- Download URL: secure_vault_cli-0.1.3.tar.gz
- Upload date:
- Size: 23.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1350ae409adfdac4fa4ead5d07890cf83f4c5c9649d9b08bdc4317ad8b1b3efb
|
|
| MD5 |
de840543b5a2eee1c40ac49a7fe05eb3
|
|
| BLAKE2b-256 |
2e8e52d7c5e459390ee894cfb494d06311c144ec4de2cbcdb8a944c9ac21d412
|
Provenance
The following attestation bundles were made for secure_vault_cli-0.1.3.tar.gz:
Publisher:
publish-pypi.yml on Luis696969/vault-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
secure_vault_cli-0.1.3.tar.gz -
Subject digest:
1350ae409adfdac4fa4ead5d07890cf83f4c5c9649d9b08bdc4317ad8b1b3efb - Sigstore transparency entry: 1288847287
- Sigstore integration time:
-
Permalink:
Luis696969/vault-cli@16712c42f429021e857de3a681ffd66e7591e954 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/Luis696969
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@16712c42f429021e857de3a681ffd66e7591e954 -
Trigger Event:
release
-
Statement type:
File details
Details for the file secure_vault_cli-0.1.3-py3-none-any.whl.
File metadata
- Download URL: secure_vault_cli-0.1.3-py3-none-any.whl
- Upload date:
- Size: 25.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d9f3235d41261cce11d32e0df06494d9564d44e45aa3cf74b2b5d3c9a9fa11b1
|
|
| MD5 |
e91c9a3898f9a095da626fec778bba6b
|
|
| BLAKE2b-256 |
5a26b2e2f5109e53945825d673b57c6baf2351c666f27d69b2c63cd9aa655d57
|
Provenance
The following attestation bundles were made for secure_vault_cli-0.1.3-py3-none-any.whl:
Publisher:
publish-pypi.yml on Luis696969/vault-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
secure_vault_cli-0.1.3-py3-none-any.whl -
Subject digest:
d9f3235d41261cce11d32e0df06494d9564d44e45aa3cf74b2b5d3c9a9fa11b1 - Sigstore transparency entry: 1288847413
- Sigstore integration time:
-
Permalink:
Luis696969/vault-cli@16712c42f429021e857de3a681ffd66e7591e954 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/Luis696969
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@16712c42f429021e857de3a681ffd66e7591e954 -
Trigger Event:
release
-
Statement type: