latchkey

A CLI tool that injects API credentials into curl requests to third-party services

Package details

skill

Install latchkey from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:latchkey
Package
latchkey
Version
2.7.3
Published
Apr 30, 2026
Downloads
1,705/mo · 451/wk
Author
hynek-urban
License
MIT
Types
skill
Size
1.1 MB
Dependencies
5 dependencies · 0 peers
Pi manifest JSON
{
  "skills": [
    "./dist/skills/generic"
  ],
  "video": "https://github.com/imbue-ai/latchkey/releases/download/2.5.4/demo.mp4"
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

Latchkey

npm CI license downloads

Inject API credentials into local agent requests.

Full documentation

Quick example

# 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"}'

Overview

Latchkey is a command-line tool that injects credentials into curl commands.

  • latchkey services list
    • List third-party services (Slack, Google Workspace, Linear, GitHub, etc.) that are supported out-of-the-box.
    • (In simple cases, latchkey services register can be used to add basic support for a new service at runtime.)
  • latchkey curl <arguments>
    • Automatically inject credentials into your otherwise standard curl calls to HTTP APIs.
    • Credentials must already exist (see below).
  • latchkey auth set <service_name> <curl_arguments>
    • Manually store credentials for a service as arbitrary curl arguments.
  • latchkey auth browser <service_name>
    • Open a browser login pop-up window and store the resulting API credentials.
    • This also allows agents to prompt users for credentials.
    • Only some services support this option.

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.

Installation

Prerequisites

  • curl, node and npm need to be present on your system in reasonably recent versions.
  • The latchkey auth browser subcommand requires a graphical environment.

Steps

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.

Agent integrations

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.

Using skills.sh

npx skills add imbue-ai/latchkey

From ClawHub

npx clawhub install latchkey

As a Pi package

pi install npm:latchkey

Manually

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

Using the Python llm tool

See integrations/llm-latchkey/README.md. Also check out our llm-webchat web UI that can be used together with Latchkey!

Demo

Image

Direct usage

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.

Self-hosted services

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

Entirely new services

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

User-registered services only support authentication via static curl arguments provided through latchkey auth set.

Indirect credentials

Some services can't express their credentials as static curl arguments. For example:

  • AWS requires a signature that changes with each request.
  • Telegram expects bot tokens to be directly part of the URL.

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>.

Remembering API credentials

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.

Inspecting the status of stored credentials

Calling latchkey services info <service_name> will show information about the service, including the credentials status. The credentials status line will show one of:

  • missing
  • invalid
  • valid
  • unknown (for user-registered services)

Clearing credentials

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: ..."

Clearing credentials and logins

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

Permissions

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:

  • When accessing the Gmail or the Slack API, only read actions are allowed.
  • No requests are allowed to any other domains.

Ideally make the file read-only: chmod -w ~/.latchkey/permissions.json. For more details, check out the permission docs.

Gateway mode

People sometimes run agents in isolated sandboxes for higher security. Using gateway mode lets you extend the isolation to Latchkey itself. Run this to start a Latchkey server on the machine where your main configuration lives:

# Listens on localhost:1989 by default.
# You can override this using the LATCHKEY_GATEWAY_LISTEN_HOST
# and LATCHKEY_GATEWAY_LISTEN_PORT environment variables.
latchkey gateway

Suppose you run an agent inside a container on the same machine, with the gateway port mapped into the container. Then setting LATCHKEY_GATEWAY=http://localhost:1989 in your container will route your agent's latchkey calls to the host Latchkey (limited to a selected safe subset of commands). That way the agent won't be able to tamper with your Latchkey configuration while still being able to use Latchkey itself as intended.

Other configuration

You can set these environment variables to override certain defaults:

  • LATCHKEY_DIRECTORY: path to the directory where Latchkey stores its data (defaults to ~/.latchkey)
  • LATCHKEY_CURL: path to the curl binary
  • LATCHKEY_KEYRING_SERVICE_NAME, LATCHKEY_KEYRING_ACCOUNT_NAME: identifiers that are used to store the encryption password in your keyring
  • LATCHKEY_ENCRYPTION_KEY: override the encryption key, e.g. when a keyring is not available. Example: export LATCHKEY_ENCRYPTION_KEY="$(openssl rand -base64 32)"
  • LATCHKEY_DISABLE_BROWSER: when set to a non-empty value, disables the browser login flow; commands that would trigger a browser login (auth browser, auth browser-prepare) will fail with an error instead
  • LATCHKEY_DISABLE_COUNTING: when set to a non-empty value, disables daily usage counting.
  • LATCHKEY_PERMISSIONS_CONFIG: override the permissions.json location.
  • LATCHKEY_PERMISSIONS_DO_NOT_USE_BUILTIN_SCHEMAS: do not use the built-in permission definitions.
  • LATCHKEY_PASSTHROUGH_UNKNOWN: if set, Latchkey will forward requests (via latchkey curl or gateway) even if no credentials are injected.
  • LATCHKEY_GATEWAY: when set to a base URL (e.g. http://localhost:1989), the CLI delegates commands to a remote Latchkey gateway instead of running them locally. Commands that change local state (auth set, auth clear, services register, ensure-browser, gateway) cannot run in this mode.
  • LATCHKEY_GATEWAY_LISTEN_HOST, LATCHKEY_GATEWAY_LISTEN_PORT: default address and port the local latchkey gateway command binds to when --host / --port are not supplied (defaults: localhost, 1989). Distinct from LATCHKEY_GATEWAY, which configures a remote gateway URL.

All of the above settings, except for LATCHKEY_DIRECTORY and LATCHKEY_ENCRYPTION_KEY, can alternatively be specified in the settings section of config.json inside the Latchkey directory. In case of a clash, environment variables override config.json values.

{
  "settings": {
    "curlCommand": "/usr/local/bin/curl",
    "keyringServiceName": "latchkey",
    "keyringAccountName": "encryption-key",
    "browserDisabled": false,
    "countingDisabled": true,
    "permissionsConfig": "/etc/latchkey/permissions.json",
    "permissionsDoNotUseBuiltinSchemas": false,
    "passthroughUnknown": false,
    "gateway": "http://localhost:1989",
    "gatewayListenHost": "localhost",
    "gatewayListenPort": 1989
  }
}

Disclaimers

  • This is still a work in progress.
  • Latchkey has been created with the help of AI-assisted coding tools with careful human curation.
  • Invoking latchkey auth browser ... can sometimes have side effects in the form of new API keys being created in your accounts (through browser automation).
  • Using agents for automated access may be prohibited by some services' ToS.
  • Unless LATCHKEY_DISABLE_COUNTING is set, once a day, when invoking latchkey, a GET request is sent to goatcounter.com. We don't store any sort of private information and don't track anything beyond a simple daily count of active users.
  • We reserve the right to change the license of future releases of Latchkey.
  • Latchkey was not tested on Windows.

Currently supported services

Latchkey currently offers varying levels of support for the following services: AWS, Calendly, Discord, Dropbox, Figma, GitHub, GitLab, Gmail, Google Analytics, Google Calendar, Google Docs, Google Drive, Google Sheets, Linear, Mailchimp, Notion, Sentry, Slack, Stripe, Telegram, Yelp, Zoom, and more.