Skip to main content

Move secrets from credential providers without printing them

Project description

ainv

ainv is a small, provider-neutral CLI for moving secrets without printing them. It is intended for humans and shell-capable coding agents that need to:

  • add credentials to an existing provider through hidden human input;
  • search credential stores using non-sensitive metadata;
  • write a selected credential directly into an environment file; and
  • inject selected credentials into one child process.

ainv is not a vault, daemon, cloud service, or MCP server. Credential providers remain the source of truth.

[!IMPORTANT] This project is an early development preview. The current release supports non-synchronizable generic passwords in the default macOS Keychain only.

The proposed product and security contract is documented in SPEC.md.

Installation

[!WARNING] Version 0.1.0 is a pre-alpha name-reservation and evaluation release. In the current uv tool distribution, macOS Keychain trusts the uv-managed Python interpreter, not the ainv command. Do not treat it as a stable, least-privilege identity for unattended high-value credentials. See SECURITY.md before choosing Keychain approval.

Install the published package with:

uv tool install ainv

For development from a local checkout:

uv tool install .

Usage

Add a native Keychain credential through one hidden input prompt:

ainv add OPENAI_API_KEY --provider keychain --account personal

--label is optional. Existing credentials are never overwritten. A human may paste a newly issued credential from a browser into the hidden prompt. Agents must never read, inspect, or manipulate the clipboard. On success, the full opaque reference is labeled Reference (non-secret identifier) so it is not mistaken for a credential value.

Search Keychain metadata without retrieving secret values:

ainv find openai
ainv find openai --json

Use the opaque reference returned by find to set one dotenv entry:

ainv set 'keychain://v1/item/REFERENCE' --as OPENAI_API_KEY --file .env

Or inject it into one child process without touching disk:

ainv run 'OPENAI_API_KEY=keychain://v1/item/REFERENCE' -- command

set refuses tracked or non-ignored Git destinations unless explicitly overridden. Run ainv <command> --help for all options.

[!WARNING] ainv run keeps resolved values out of its normal arguments and output, but it gives them to the selected process. That process, its descendants, dependencies, crash reporters, telemetry, and anything it invokes can read, retain, transmit, or expose them. Use it only for an intended, trusted consumer and avoid debug or environment-dumping modes. This is guidance, not an enforcement boundary: ainv does not make untrusted agents, repositories, dependencies, or commands safe.

The command surface will not include a generic operation that prints a resolved secret.

References and cleanup

A Keychain reference is an opaque local locator, not portable project configuration or a unique identifier for one immutable credential incarnation. It may become stale after identity metadata changes or deletion. If it no longer resolves, search again rather than reconstructing it from metadata.

For private dogfood, remove an ainv-created Keychain item manually in Keychain Access by its service, account, and label. Remove a materialized dotenv entry manually without asking an agent to read the file. If a credential is exposed, revoke or rotate it with its remote issuer first. Removing the local Keychain item does not revoke it remotely.

Agent skill

The repository includes an optional agent skill at skills/ainv. Install it into the canonical shared skills directory with:

mkdir -p ~/.agents/skills
ditto skills/ainv ~/.agents/skills/ainv

Claude Code additionally needs a discovery symlink:

ln -s ~/.agents/skills/ainv ~/.claude/skills/ainv

Development

Requires Python 3.13 and uv.

uv sync
uv run pytest
uv run ruff check .
uv run ruff format --check .

Security model

ainv reduces accidental credential exposure by keeping resolved values out of its normal arguments and output. Once a secret is written to a file or injected into a child process, it can be read, retained, printed, transmitted, or exposed by that process, its descendants, dependencies, crash reporters, telemetry, or anything it invokes. Child stdout and stderr pass through unchanged. ainv does not make untrusted agents, repositories, dependencies, or commands safe.

License

No license has been granted yet. The published pre-alpha package is available for evaluation, but permission to copy, modify, or redistribute it has not been granted.

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

ainv-0.1.0.tar.gz (18.4 kB view details)

Uploaded Source

Built Distribution

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

ainv-0.1.0-py3-none-any.whl (22.9 kB view details)

Uploaded Python 3

File details

Details for the file ainv-0.1.0.tar.gz.

File metadata

  • Download URL: ainv-0.1.0.tar.gz
  • Upload date:
  • Size: 18.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ainv-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6a5b9fdf7d1255729b002bd162b4497b5c9e6e15a3b86b6148e33e994991a7fe
MD5 43b44a9834cc25f87f2097bd2a91f3fb
BLAKE2b-256 285cc270429cfb279929b767af7eff94db7627da37a114dfd9541c8fbe5a7a8a

See more details on using hashes here.

File details

Details for the file ainv-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ainv-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 22.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ainv-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fafa92924f10ce96b1b65e6262b03ae31c5109bdd2b8aceac894d2a06742684d
MD5 eb515a17e778845c6f095758e73e7d72
BLAKE2b-256 22daaf5302890942f7455071654f03ed954e75bec6e4898d5b2001336b8e30e1

See more details on using hashes here.

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