llm-1password
An llm plugin that keeps model API keys in 1Password.
I wrote this so llm can resolve keys from op:// references at call time. The durable store holds the reference only.
$ llm 1password doctor
op: /usr/local/bin/op
auth: SERVICE_ACCOUNT
$ llm 1password check
openai OK
refs.json is mode 0600 in a 0700 directory. The wrap that owns resolution is _wrapped_get_key in llm_1password.py.
Install
Requires Python 3.10+, llm 0.32 or newer, and the 1Password CLI.
llm install llm-1password
From a checkout:
git clone https://github.com/dallascrilley/llm-1password.git
cd llm-1password
llm install -e .
If llm itself fails with No module named 'httpx' before any plugin loads, that is an llm 0.32 packaging gap:
pipx inject llm httpx
Confirm the plugin loaded:
llm plugins
llm 1password doctor
llm 1password check
doctor prints the chosen op binary and its user_type. check prints No references registered. until you set one.
Use
llm 1password set openai 'op://Vault/Item/credential'
llm 1password check
llm 1password doctor
llm prompt 'hello'
llm 1password unset openai
set writes the reference under llm's user directory at 1password/refs.json. It does not write keys.json. The llm prompt line needs a reference op read can resolve. Run check first and look for OK.
If you previously stored a plaintext key for the same alias, remove that alias (llm keys path) so this plugin owns the name.
check exits 1 if any registered reference fails to resolve.
How resolution works
- If
$HOME/.local/bin/opexists, is executable, and is a non-world-writable regular file, the plugin uses it. That lets a local wrapper sit in front of the official CLI. - Otherwise it uses
oponPATH, with the same file checks. - It runs
op read -- <ref>. A missing binary, a non-zero exit, a timeout, empty output, or a non-UTF-8 payload aborts the model call.
llm 1password doctor prints the chosen binary and the op whoami user_type field (SERVICE_ACCOUNT, or whatever op reports).
An explicit --key / input= value is not replaced by a registered alias unless that value itself is the alias. Unregistered op:// strings in keys.json or the environment are rejected rather than fetched or sent to the provider (_reject_bare_op_uri).
Security model
| Surface | Holds |
|---|---|
refs.json |
op:// references only, mode 0600 in a 0700 directory |
| Process memory | Secret value for the life of that llm process |
check / doctor / errors |
Alias and OK/FAIL or binary/auth mode. Never the secret, never the reference path |
If op read fails, the plugin raises an error and does not call the model.
What this package does not do
- Resolve
op://inside prompts, templates, or fragments. - Hide the
op://URI frompswhileop readis running. - Wrap assignments such as
model.key = "op://...". Those bypassllm.get_key. - Uninstall leftover plaintext keys from
keys.json.
See SECURITY.md for reporting and the guarantees the package aims for.
License
Apache-2.0
Metadata
Release files for llm-1password 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 | |
|---|---|---|---|
| llm_1password-0.1.0.tar.gz | 13.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| llm_1password-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.1 kB
Release files / llm_1password-0.1.0.tar.gz
| Download URL | llm_1password-0.1.0.tar.gz |
|---|---|
| Size | 13.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2de74881b485fefbec1d3cc94169f955dd73c4f0ead46aea02769498f38ff0bb
|
|
BLAKE2b-256 checksum How to use checksums |
5ff0a1e520f59664ea24a98370cd9c74e5a7cfa2f42869c35a4ccc0638c92e30
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / llm_1password-0.1.0-py3-none-any.whl
| Download URL | llm_1password-0.1.0-py3-none-any.whl |
|---|---|
| Size | 10.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e37d91900e26793846c3adeb846ab210d38268f735d629ab7e85c4c710dad4f2
|
|
BLAKE2b-256 checksum How to use checksums |
a0335ce4a8c8c524d0704013ed49115b213370fb3988b4bceaf0c03139744faf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|