oathkey
Let your AI use your API keys through oathkey without ever holding them.
- The key sits in your computer's own keychain. When your AI needs an API, it asks oathkey to make the call.
- Replies are cleaned of the key. Anything other than a read (GET) waits for your click. Every call is logged.
- Plain Python, no extra packages. No account, no server, no cloud. MIT license. Beta: no independent security review yet.
- Not related to OATH/TOTP one-time codes.
Try it in 60 seconds
Need pipx? https://pipx.pypa.io
pipx install oathkey
oathkey doctor # is it working? checks the keychain and activity log, then attacks itself once
oathkey get github # opens the key page; you click Copy; oathkey tests it and saves it
oathkey call github GET /user # a window asks once to allow github reads: click Yes. Prints the answer, never the key
oathkey selftest # watch oathkey attack itself; prints how many attacks it stopped
oathkey install # plug it into Claude, Cursor or VS Code, then restart that app
When a key page asks which permissions to give, pick read-only or the minimum it offers.
Now ask your AI: "Who am I on GitHub?" It uses your key through oathkey and never holds it.
To see what it did: oathkey audit show.
No
pipx?pip install oathkeyworks too. Latest unreleased code:pipx install git+https://github.com/calasdan-sketch/oathkey. Needs Python 3.10 or newer. On Linux the keychain needssecret-tool(packagelibsecret-tools). If your computer saysoathkeyis not found, close the window and open a new one, or runpython -m oathkey.
Why not just put the key in a .env file?
AI coding tools read files in your project, and they paste what they read into a chat that someone else's computer sees. A key in a file, a chat or a config can leak in seconds. With oathkey your AI never receives the key: it stays in your computer's keychain and oathkey adds it to the request itself. oathkey get will not leave a key in a file in your project folder unless you agree to the fallback (it asks first, and only when no keychain works).
How it works
- You save a key once (
oathkey get <service>). It goes into the Windows, Mac or Linux keychain. oathkey tests it with a harmless call first. - Your AI asks for an action, not a key: "GET /user on GitHub". It can only name the service, the method, the path and the data.
- oathkey makes the call itself, to the service's real address only, adds the key, and hands back the answer with any trace of the key removed.
Reads are allowed after one "yes" per AI session (a window asks the first time). Anything that creates, changes or deletes pops up a window and waits for you. oathkey call is you making the same brokered call by hand, with no AI involved.
Check it yourself (don't trust us)
| Command | What it shows |
|---|---|
oathkey selftest |
Runs oathkey's rules against simulated attacks, using a made-up key and a pretend server: a server that echoes the key in disguise, tricky addresses, names that point inside your network, writes without permission, edits to the log. Prints how many it stopped (--verbose lists each) and exits with an error if any gets through. It does not test the live network layer, so treat it as a check of the rules, not a security audit. |
oathkey doctor |
One-paste health check: keychain, activity log, which AI tools it is plugged into, and a quick self-attack run. |
oathkey scan |
Finds API keys lying in your project files and AI-tool settings. It never prints a whole key. |
oathkey scan-git |
Looks through git history for keys; --staged checks only what is about to be committed, --install-hook blocks such commits. |
oathkey audit verify |
Checks the activity log was not edited, cut short or deleted. If it did not check out, audit reset starts a fresh log and keeps the old one. |
oathkey uses only Python's own standard library, and a test in the repository (tests/test_stdlib_only.py) fails if that ever changes.
Commands
Start
get <service>- one command: opens the key page, takes the key when you click Copy (then empties the clipboard), tests it, saves it in the keychain.--no-clipboarduses hidden typing instead.start- a short guided tour: what is connected and what to do next.install/uninstall- plug oathkey into (or remove it from) Claude Desktop, Cursor, Claude Code and VS Code.list- the services it knows.
Daily
call <service> <METHOD> <path>- make one brokered call yourself (--query name=value,--data '{...}',--json).overview- what is connected and whether the activity log is intact. (statusshows where each key lives and how old it is.)audit show- the last calls, with a warning if the log does not check out.rotate <service>- replace a stored key.forget <service>- remove a stored key.
Security
selftest,doctor,scan,scan-git,hook(stops Claude Code reading.envfiles and running oathkey commands that use a key; it blocks the call if it breaks, unless you install it withhook install --fail-open) as above.
Advanced
serve- a local web door for AI tools that cannot use MCP (OpenAI-style functions, Ollama, scripts).mcp- the MCP server your AI app starts for you. Besides brokered calls it hascapture_key: your AI opens the key page, you click Copy, and oathkey takes the key from the clipboard without the AI ever seeing it. You allow this per service withallow-agent <service>.init/setup- writeoathkey.jsonfor a project, then connect every service it needs.run <service> -- <command>- run a program with the key in its environment. For you, not for an AI with a shell: a program you start can print its own environment.remote,trust-server,deploy- use a key on your own server over ssh.add- make your own service recipe.find- look for free public APIs.
Coming from the old safeeasyapi name? 0.8.0 is a fresh start: nothing is migrated. Re-run oathkey get <service> and oathkey install, and remove any old safeeasyapi hook or MCP entry by hand.
Many commands accept --json (try list, overview, selftest, doctor, audit). Exit codes: 0 fine, 1 problem, 2 wrong usage, 3 service not found, 5 refused by policy, 7 network problem.
Services
36 services are built in, from GitHub and Stripe to OpenAI and AWS. oathkey list shows them all.
Not listed? oathkey add makes a recipe in a minute. A recipe cannot send a built-in service's key to a different server.
What oathkey does not stop
It reduces risk; it does not remove it, and no independent security review has been done yet.
- Malware, or an AI that can run programs as you. Anything running as you can read your keychain. Run risky agents in a separate account or container.
- Harmful things a key is allowed to do. Give each key only the permissions it needs, at the provider.
- The clipboard.
getempties it right away, but other programs or clipboard-history tools may see the key while it is there. - A log that can't be rewritten. The log shows accidents and casual edits. Someone running as you could rewrite it.
More known limits (a GET can read other secrets through a vendor's own endpoints, the log is only tamper-evident, and others) are listed under "Known limits" in [SECURITY.md]. The full list is in SECURITY.md. The longer user guide (every flag, where keys are stored, two-value keys, testing) is in docs/guide.md.
License
MIT. See LICENSE.
Metadata
Release files for oathkey 0.8.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 | Provenance | Actions |
|---|---|---|---|---|
| oathkey-0.8.0.tar.gz | 476.8 kB | With provenance | Details for oathkey-0.8.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| oathkey-0.8.0-py3-none-any.whl | Python 3 | none | any | Details for oathkey-0.8.0-py3-none-any.whl |
Total release size: 732.4 kB
Release files / oathkey-0.8.0.tar.gz
| Download URL | oathkey-0.8.0.tar.gz |
|---|---|
| Size | 476.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
49efc4fcb831d594bd08334a19106f3a768e1b902b7f729c09e4dff8e9696353
|
|
BLAKE2b-256 checksum How to use checksums |
b81898c3c2da58a417a98dbdc5a08ba3a8dc720a4b719dad9151cf4163e81d3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.
Transparency logRelease files / oathkey-0.8.0-py3-none-any.whl
| Download URL | oathkey-0.8.0-py3-none-any.whl |
|---|---|
| Size | 255.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
84769212ce0f4b3d7dbfa7b5d7cf54b672db5845b2b729d9cfc1c75293d2a4b4
|
|
BLAKE2b-256 checksum How to use checksums |
5b8bcd6a90eec296438eea8ffdb62b1308d9f76e7449fd5e4bd722496236bf8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.
Transparency logSecurity for oathkey 0.8.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for oathkey-0.8.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.