Skip to main content

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 check before 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 init
  • vault unlock
  • vault lock
  • vault new <id>
  • vault edit <id>
  • vault view <id>
  • vault list
  • vault delete <id>
  • vault export <id> <path>
  • vault copy <id>
  • vault purge
  • vault help
  • vault man
  • vault 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.json
  • data/vault.db

Security model

What is encrypted

The full functional payload of every document is encrypted:

  • id
  • title
  • created_at
  • updated_at
  • folder
  • tags
  • template_name
  • body

Outside the encrypted payload, the database stores only:

  • lookup_key
  • payload_version
  • encrypted_payload
  • technical metadata that is not functionally sensitive

IDs are never stored in cleartext.

Cryptography v1

  • Passphrase KDF: Argon2id
  • master_key: 32 bytes
  • index_key: 32 bytes derived from master_key using HKDF
  • Per-document cipher: AESGCM
  • Nonce size: 12 bytes
  • encrypted_payload format: 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_cost is expressed in KiB
  • time_cost, parallelism, and hash_len are integers

No functional metadata is stored in vault.json.

SQLite behavior

In v1 the SQLite connection uses:

  • PRAGMA journal_mode=DELETE
  • PRAGMA 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:

  • id
  • title
  • updated_at

Verbose mode:

vault list --verbose

Adds:

  • folder
  • tags

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:

  1. ID
  2. Title
  3. Created At
  4. Updated At
  5. Folder
  6. Tags
  7. body

Editing

The integrated editor is the default. It supports:

  • .save
  • .cancel
  • .print
  • .help

The app always controls:

  • id
  • created_at
  • updated_at
  • template_name

The editor is intended for:

  • title
  • folder
  • tags
  • body

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, or xsel

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-idea
  • Project_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

  • 0 success
  • 1 generic error
  • 2 invalid usage
  • 3 locked vault / auth required
  • 4 not found
  • 5 already exists
  • 6 destructive 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.
  • list and 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.
  • purge destroys 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

secure_vault_cli-0.1.3.tar.gz (23.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

secure_vault_cli-0.1.3-py3-none-any.whl (25.6 kB view details)

Uploaded Python 3

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

Hashes for secure_vault_cli-0.1.3.tar.gz
Algorithm Hash digest
SHA256 1350ae409adfdac4fa4ead5d07890cf83f4c5c9649d9b08bdc4317ad8b1b3efb
MD5 de840543b5a2eee1c40ac49a7fe05eb3
BLAKE2b-256 2e8e52d7c5e459390ee894cfb494d06311c144ec4de2cbcdb8a944c9ac21d412

See more details on using hashes here.

Provenance

The following attestation bundles were made for secure_vault_cli-0.1.3.tar.gz:

Publisher: publish-pypi.yml on Luis696969/vault-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file secure_vault_cli-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for secure_vault_cli-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 d9f3235d41261cce11d32e0df06494d9564d44e45aa3cf74b2b5d3c9a9fa11b1
MD5 e91c9a3898f9a095da626fec778bba6b
BLAKE2b-256 5a26b2e2f5109e53945825d673b57c6baf2351c666f27d69b2c63cd9aa655d57

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page