Latchkey
Credentials for unattended AI agents. Password managers assume a human is present; Latchkey exists because yours isn't.
Install and use
pip install latchkey
latchkey bootstrap
latchkey serve
# In any agent script:
from latchkey.client import get_credential
gh = get_credential("github.com")
print(gh["password"])
Why this exists
Cron jobs, background tasks, and scheduled agents sometimes need API keys or passwords. Interactive password managers such as 1Password expect a person to approve access; Latchkey deliberately does not provide that interaction. Cron jobs don't have fingers.
Latchkey stores credentials locally and serves them to local processes through a Unix socket.
Who it's for / not for
For local, unattended processes that need credentials: scheduled agents, cron jobs, and background tasks.
Not for interactive-only use, shared or public machines, enterprise compliance requirements, or password-management workflows. Any process running as your user can read the socket — that's the design; don't run it on shared machines.
Security facts
| Property | Detail |
|---|---|
| Encryption | Fernet (AES-128-CBC + HMAC-SHA256) at rest |
| Socket | Unix socket chmod 600 — only your user connects |
| Master key | 44 bytes, chmod 600, generated on first init |
| Network | Zero — socket is local only |
| Attestation | No remote attestation, no audit log, no SOC2 |
CLI reference
latchkey init # Generate key + DB
latchkey bootstrap # init + import Chrome + verify
latchkey add <service> <user> <pass> # Store a credential
latchkey get <service> # Retrieve (JSON)
latchkey list [--prefix PREFIX] # List services
latchkey delete <service> # Delete
latchkey serve # Start daemon
latchkey stats # Store statistics
latchkey migrate # Import from old credential-proxy path
Python API
from latchkey.client import get_credential, list_services, ping
from latchkey.launcher import ensure_daemon
ensure_daemon() # Auto-start daemon
gh = get_credential("github.com") # → {"username": "...", "password": "..."}
svcs = list_services(prefix="git") # → {"services": [...], "count": 2}
status = ping() # → {"status": "ok", "credentials": N}
Optional: Chrome bulk import
Export passwords from Chrome to Google Passwords.csv, then import the file:
latchkey import-chrome path/to.csv
Migration from credential-proxy
If you used the old version:
latchkey migrate
This moves files from ~/.hermes/credential_proxy/ to ~/.latchkey/.
Part of Works With Agents. See also ORA (task orchestrator) and Memory OS (persistent agent memory).
License
MIT
Release files for latchkey 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| latchkey-0.1.0.tar.gz | 14.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| latchkey-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.0 kB
Release files / latchkey-0.1.0.tar.gz
| Download URL | latchkey-0.1.0.tar.gz |
|---|---|
| Size | 14.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
570395e4a941f2714a5af20bd0776e7d563e80b751c8b96c525747325f2d3544
|
|
BLAKE2b-256 checksum How to use checksums |
7ad54c36033490751be930fb36fee14ea6c1bc10aee7e0c38aebdf1909bdd3da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / latchkey-0.1.0-py3-none-any.whl
| Download URL | latchkey-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4e04701f55c44738ddd186580b7692bba348ae6d8d5b18d140c1af1c74cb6b5c
|
|
BLAKE2b-256 checksum How to use checksums |
6d2e9f062bdb0ef4d66e07057de6ab9e48ae5e93cafd632a4d22b5d6220878d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|