Inject API credentials into agent requests.
$ npx -y skills add imbue-ai/latchkey --agent claude-code
Inject API credentials into agent requests.
# User stores the credentials.
latchkey auth set slack -H "Authorization: Bearer xoxb-your-token"
# Agent makes http calls.
latchkey curl -X POST 'https://slack.com/api/conversations.create' \
-H 'Content-Type: application/json' \
-d '{"name":"something-urgent"}'
Latchkey is a command-line tool that injects credentials into curl commands. Its gateway mode and permission system can be used to keep tight control over sandboxed agents' usage of third-party services.
latchkey services list
latchkey services register can be used to add basic support for a new service at runtime.)latchkey curl <arguments>
latchkey auth set <service_name> <curl_arguments>
latchkey auth browser <service_name>
Latchkey is primarily designed for AI agents. By invoking Latchkey, agents can utilize user-provided credentials or prompt the user to authenticate, then continue interacting with HTTP APIs using standard curl syntax. No custom integrations or embedded credentials are required.
Unlike OAuth-based flows or typical MCP-style integrations,
Latchkey does not introduce an intermediary between the agent
and the service. When the browser command is used, requests are made
directly on the user’s behalf, which enables greater flexibility
at the cost of formal delegation: agents authenticate as the
user.
Latchkey integrates with Detent to let you define fine-grained HTTP permissions for agents.
If a service you need isn’t supported out of the box, the new service registering mechanism may help. Otherwise, contributions are welcome! See the development docs for details.
You can also leave us a note.
curl, node and npm need to be present on your system in reasonably recent versions.latchkey auth browser subcommand requires a graphical environment.npm install -g latchkey
# Optionally, if you intend to use `latchkey auth browser`:
latchkey ensure-browser
The ensure-browser command discovers and configures a browser
for Latchkey to use. It searches for Chrome, Chromium, or Edge
on your system. If none is found, it downloads Chromium via
Playwright.
Warning: giving AI agents access to your API credentials is
potentially dangerous, especially when using the auth browser
feature. They will be able to perform most of the actions you
can. Only do this if you're willing to accept the risks.
npx skills add imbue-ai/latchkey
npx clawhub install latchkey
pi install npm:latchkey
The exact steps will differ depending on the agent. Taking OpenCode as an example:
mkdir -p ~/.opencode/skills/latchkey
latchkey skill-md > ~/.opencode/skills/latchkey/SKILL.md
llm toolSee integrations/llm-latchkey/README.md. Also check out our llm-webchat web UI that can be used together with Latchkey!
Let's revisit the initial example:
latchkey curl -X POST 'https://slack.com/api/conversations.create' \
-H 'Content-Type: application/json' \
-d '{"name":"something-urgent"}'
Notice that -H 'Authorization: Bearer ...' is absent. This is
because Latchkey injects stored credentials automatically. To
set up credentials for a service (Slack in this example), run:
latchkey auth browser slack
This opens the browser with a login screen. After you log in, Latchkey extracts the necessary API credentials from the browser session, closes the browser, and stores the credentials so that they can be reused.
Alternatively, you can provide credentials manually:
latchkey auth set slack -H "Authorization: Bearer xoxb-your-token"
latchkey curl passes your arguments straight through to curl
so you can use the same interface you are used to. The return
code, stdout and stderr are passed back from curl to the caller
of latchkey.
Credentials for a service can be stored under several accounts.
An account is a string that uniquely identifies the account
behind the credentials - typically an e-mail, but for some
services it may be an id. Use the global --account option to
select one:
# Store credentials for a specific account.
latchkey --account bob@example.com auth set slack -H "Authorization: Bearer xoxb-..."
# Use them in a request.
latchkey --account bob@example.com curl https://slack.com/api/auth.test
When --account is omitted, the single stored account is used
automatically. If a service has more than one stored account,
--account becomes required. Credentials stored without an
account live under a "default" account (empty string, "").
Browser logins (latchkey auth browser) determine the account
automatically. The --account option here merely allows users
to specify which existing OAuth client configuration to use for
the login (selecting one associated with an existing account) if
needed.
The only exceptions are services that cannot determine the
account for the completed browser login. For those, --account
also names the account the new credentials are stored under. All
services registered at runtime (see "Entirely new services"
below) fall into this category. Whether a service falls into
this category is indicated by the detectsLoginAccount
capability flag in the output of latchkey services info.
For services that can be self-hosted, like GitLab, first make Latchkey aware of your service instance:
latchkey services register my-gitlab-instance --service-family=gitlab --base-api-url="https://gitlab.example.com/api/v4/"
Then continue as usual.
latchkey auth set my-gitlab-instance -H "PRIVATE-TOKEN: <token>"
# Agents can then call the API.
latchkey curl https://gitlab.example.com/api/v4/user
If you want to use Latchkey with a service that is not in the list of supported built-in services, you can still use the mechanism described above to register a new service at runtime:
latchkey services register mastodon --base-api-url="https://mastodon.social/api/v1/"
latchkey auth set mastodon -H "Authorization: Bearer <your_access_token>"
# Agents can then call the service:
latchkey curl https://mastodon.social/api/v1/timelines/public?limit=2
You can also configure browser login flows for registered services. For details,
see latchkey services register --help.
It is also possible to add support for a new service by
installing a plugin that implements it. A Latchkey plugin is
a git repository; installation is a matter of running git clone in ~/.latchkey/plugins/. For more details, see the
plugins docs.
Some services can't express their credentials as static curl arguments. For example:
In similar cases, when supported, you can use the latchkey auth set-nocurl command, e.g.
like this:
latchkey auth set-nocurl aws <access-key-id> <secret-access-key>
Latchkey will then modify subsequent latchkey curl requests as
needed. You can find more information (including the expected
signature) by calling latchkey services info <service_name>.
Your API credentials and browser state are encrypted and stored
by default under ~/.latchkey. They are never transmitted
anywhere beyond the endpoints specified by the actual curl
calls.
Calling latchkey services info <service_name> will show
information about the service, including a credentials object
keyed by account (the default account uses the empty string).
Each entry reports a credentials status of:
invalidvalidunknown (for user-registered services)When it is known that the credentials stop working after some
date the entry also carries a validUntil timestamp.
A service with no stored credentials shows an empty credentials
object.
Remembered API credentials can expire. The caller of latchkey curl will typically notice this because the calls will start returning
HTTP 401 or 403. To verify that, first call latchkey services info, e.g.:
latchkey services info discord
If the credentials status is invalid, it means the Unauthorized/Forbidden
responses are caused by invalid or expired credentials rather than insufficient
permissions. In that case, log in again:
latchkey auth browser discord
Or alternatively:
latchkey auth set discord -H "Authorization: ..."
In case you want to remove stored API credentials, use the auth clear subcommand.
latchkey auth clear discord
To clear all stored data (both the credential store and browser state file), run:
latchkey auth clear
If you want to export your stored credentials encrypted with
a different key or containing only some of the credentials (for
example to move them to another machine) , use the auth re-encrypt
subcommand. Use --services to limit the export to certain services
and the global --account option to export only the credentials of
a single account.
Optionally, you can specify rules for approving / rejecting
requests by creating the permissions.json file in the Latchkey
directory (~/.latchkey/permissions.json). For example:
{
"rules": [
{"google-gmail-api": ["google-gmail-read-all"]},
{"slack-api": ["slack-read-all"]}
]
}
This would mean that:
Rules can also depend on the used account which Latchkey injects as the
account custom metadata key. See the underlying library's docs for more details.
Ideally make the file read-only: chmod -w ~/.latchkey/permissions.json.
In the gateway mode, you can use permission overrides to let
different callers claim different permission policies.
For more details, check out the permission docs.
People sometimes run agents in isolated sandboxes for higher security. Using gateway mode lets you extend the isolation
latchkey is a Claude Code plugin with 1 hand-picked skill, indexed on Flowy in the Security category. Install it with the command on its page. It includes latchkey. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it