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.4.tar.gz (24.4 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.4-py3-none-any.whl (26.2 kB view details)

Uploaded Python 3

File details

Details for the file secure_vault_cli-0.1.4.tar.gz.

File metadata

  • Download URL: secure_vault_cli-0.1.4.tar.gz
  • Upload date:
  • Size: 24.4 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.4.tar.gz
Algorithm Hash digest
SHA256 1d0b508fc02fcf76d32fcc6a87a5a430ac3525b7ce7ca3b55269aacd5d777ada
MD5 df255ac11930d5bda22197f8becb88bb
BLAKE2b-256 d9c8674cb13fbb37005ccd56059cc1a5f3df7d22b355de66e9419208644da7cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for secure_vault_cli-0.1.4.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.4-py3-none-any.whl.

File metadata

File hashes

Hashes for secure_vault_cli-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 164b59982e1e546dfbb5b8acc8962983abd027f7191280b7cdb43bc5de70c492
MD5 a514bb274862b96e6a594d42948abd91
BLAKE2b-256 0c8a5fda1c3532bc94c71097c03a273b0696a931686a9572a38da4b11f0e807d

See more details on using hashes here.

Provenance

The following attestation bundles were made for secure_vault_cli-0.1.4-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