ospeak
ospeak copied to clipboard
Safe and pragmatic way to use API key
I am concerned about setting my openai API key as global env. WIl other packages be able to use it without my confirmation?
I like how llm manages it with "llm keys set openai". It would be great to have here the same.
WIl other packages be able to use it without my confirmation?
They could do this with llm
as well since the key is just stored in plain text json
file on disk. You could wrap llm
and ospeak
with an alias that also pulls in the API key from a password manager if you're that concerned. Here's an example of how this can work with 1password
Having said all that...
It would be great to have here the same.
Agreed. Here's where llm
implements the keys
command: https://github.com/simonw/llm/blob/main/llm/cli.py#L470. I've not got any spare time to fork and add but it shouldn't be that difficult for somebody with a spare hour or two.
Yeah I'm not a huge fan of the environment variable thing either.
I'd like to make this double as an LLM plugin - if you install both this and LLM in the same environment you could run llm ospeak
- at which point it would make sense for it to
optionally use the LLM API key as well.
This tool uses a different incompatible version of the OpenAI Python library though so I'd need to fix that first:
- https://github.com/simonw/llm/issues/325
With something like 1password-cli, or basically anything that allows fetching a credential from the command line, there is a simple workaround for interactive shells: making a function wrapper.
ospeak() {
local token="${OPENAI_API_KEY:-}"
if [[ -z $token && $1 != "--help" && $1 != "--version" ]]; then
token="$(op read 'op://Personal/OpenAI API Key/api key')" || return 1
fi
OPENAI_API_KEY="$token" command ospeak "$@"
}
Explanation: the op
command (1password-cli) reads the 'api key' field from the item named "OpenAI API Key" in my Personal vault.
With this approach, OPENAI_API_KEY is only ever 1) fetched on-demand, and 2) exported to the ospeak
command and nothing else. This is essentially the same mechanism that enables 1Password shell plugins, with a small difference that their plugins work by defining shell aliases instead of functions. 1Password shell plugins, however, are only available for a predefined set of tools that specific plugins exist for, so they are useless for a small, newer utility like ospeak
.
The downside, of course, is that every ospeak
invocation will now have a small overhead. On my machine, the op
command takes about 0.75s to fetch an API key from a vault.
With macOS Keychain instead of 1Password, for example, the command to fetch the credential could be as following:
security find-generic-password -s api.openai.com -w