New:Microsoft Teams Notifications Are Now Available in Socket.Learn more →
Get Started

keychains

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

keychains

CLI for Keychains.dev — register machines, manage permissions, and make proxied API calls

npmnpm
Version
0.0.12
Version published
Weekly downloads
3
-75%
Maintainers
1
Weekly downloads
 
Created
Source

keychains

CLI for Keychains.dev — secure credential delegation for AI agents.

Install

npm install -g keychains

Quick Start

# Just run it — no setup needed
keychains curl https://api.lifx.com/v1/lights/all \
  -X GET \
  -H "Authorization: Bearer {{LIFX_PERSONAL_ACCESS_TOKEN}}"

That's it. On first run, Keychains automatically:

  • Registers your machine (using your hostname)
  • Creates a default wildcard permission
  • Returns an authorization URL

Click the URL, sign in, connect your credentials, and re-run the command. After that, every call just works.

You never put real tokens in the command. Use template variables like {{OAUTH2_ACCESS_TOKEN}} or {{LIFX_PERSONAL_ACCESS_TOKEN}} and Keychains swaps them for real credentials at proxy time.

How it works

keychains curl <url>
   │
   ├── Machine not registered? → auto-register using hostname
   ├── No permission? → auto-create wildcard (active immediately)
   ├── Make proxied API call
   │
   └── 403: credentials missing
       └── "Authorize at: https://keychains.dev/add-permissions?machineId=...&scopes=..."
           └── User clicks → signs in → machine linked → credentials connected
               └── Re-run → works!

Output Formats

Every command supports three output formats:

FlagFormatUse case
--humanColored table (default)Reading in terminal
--jsonRaw JSONPiping to jq, scripts, CI
--envKEY=VALUEAppending to .env files
# Create a permission and append directly to .env
keychains permissions create --name "Dev" --env >> .env

# List permissions as JSON
keychains permissions ls --json

# Get your identity as env vars
keychains whoami --env >> .env

Input Variables (Piped JSON)

Use {{$varname}} patterns in your URL, headers, or body to inject values from piped JSON input. This is different from Keychains credential templates ({{OAUTH2_ACCESS_TOKEN}}) which are resolved server-side.

# Pipe JSON into curl — variables get substituted before the request
echo '{"user": "alice", "email": "alice@example.com"}' \
  | keychains curl https://api.com/users/{{$user}} \
    -X POST \
    -d '{"user": "{{$user}}", "email": "{{$email}}"}'

Supported accessor syntax

SyntaxResolves to
{{$user}}params.user
{{$user.name}}params.user.name
{{$items[0].id}}params.items[0].id
{{$items[0]['key']}}params.items[0]["key"]
{{$items[0]["key"]}}params.items[0]["key"]
{{$a.b[2].c['d']}}params.a.b[2].c["d"]

How it works

  • Keychains detects {{$...}} patterns in the URL, headers, and body
  • If variables are found, it reads JSON from stdin (Unix pipe)
  • Each {{$path}} is replaced with the resolved value from the piped JSON
  • The original command (with {{$...}} patterns) is saved to history
  • When exported, the generated code is a function accepting params
# Complex nested data
echo '{"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}' \
  | keychains curl https://api.com/users/{{$users[0].id}} \
    -X PATCH \
    -d '{"name": "{{$users[0].name}}"}'

# Credential templates (server-side) can mix with input variables (client-side)
echo '{"repo": "my-org/my-repo"}' \
  | keychains curl https://api.github.com/repos/{{$repo}}/issues \
    -X POST \
    -H "Authorization: Bearer {{OAUTH2_ACCESS_TOKEN}}" \
    -d '{"title": "Bug in {{$repo}}"}'

Commands

keychains machine — Machine Identity

Manage your machine's cryptographic identity (Ed25519 SSH keypair).

Most users don't need to register manually — machines are auto-registered on first use. Use these commands for explicit registration or management.

keychains machine register --name "my-laptop"   # Register with a custom name
keychains machine register --name "ci" --server https://custom.keychains.dev
keychains machine status                         # Show machine status & permissions
keychains machine ls                             # List all machines on your account
keychains machine update --name "new-name"       # Rename this machine
keychains machine rotate-keys                    # Rotate SSH keypair
keychains machine rm <machineId>                 # Remove a machine from your account
keychains machine rm <machineId> -f              # Remove without confirmation

keychains permissions — Permission Requests

Create, list, revoke, and suspend permissions. Use -a to see all permissions across your account (like git branch -a).

# Create a wildcard permission (default)
keychains permissions create --name "Dev machine"
keychains permissions create --name "Dev" --env >> .env   # Append to .env

# Create a scoped permission
keychains permissions create --name "GitHub read-only" \
  --scopes "github::repo:read,github::read:org"

# List permissions
keychains permissions ls                    # This machine only
keychains permissions ls -a                 # All permissions on your account
keychains permissions ls --json             # JSON output
keychains permissions ls --status active    # Filter by status

# Revoke / suspend
keychains permissions rm <id>               # Revoke a permission
keychains permissions rm <id> -f            # Skip confirmation
keychains permissions suspend <id>          # Suspend (requires re-auth)

Aliases: keychains perm create, keychains perm ls, etc.

keychains delegates — Delegate Identities

Give remote systems (sandboxed agents, CI runners) limited access without sharing your machine keys.

# Create a wildcard delegate from a permission
keychains delegates add <permissionId> --wildcard --ttl 3600

# Create a scoped delegate
keychains delegates add <permissionId> --scopes "github::repo"

# List delegate-enabled permissions
keychains delegates ls
keychains delegates ls -a                   # All on account
keychains delegates ls <permissionId>       # For a specific permission

# Revoke a delegate
keychains delegates rm <delegateId>
keychains delegates rm <delegateId> -f      # Skip confirmation

# Get delegate credentials as env vars
keychains delegates add <permissionId> --wildcard --env >> .env

Aliases: keychains delegate add, keychains delegate ls, etc.

keychains connections — OAuth & API Key Connections

List and manage your connected services (OAuth providers and API keys). Interactive and non-interactive modes.

# List connections
keychains connections ls                    # Active connections
keychains connections ls --status all       # All connections
keychains connections ls --provider github  # Filter by provider
keychains connections ls --json             # JSON output
keychains connections ls -i                 # Interactive mode

# Remove a connection
keychains connections rm github             # By provider name
keychains connections rm <connectionId>     # By connection ID
keychains connections rm -i                 # Interactive mode (select from list)
keychains connections rm github -f          # Skip confirmation

Aliases: keychains conn ls, keychains conn rm, etc.

keychains curl — Proxied API Calls

Make API calls through the Keychains proxy. Credentials are injected automatically.

# Basic GET request
keychains curl https://api.github.com/user \
  -H "Authorization: Bearer {{OAUTH2_ACCESS_TOKEN}}"

# POST with body
keychains curl https://slack.com/api/chat.postMessage \
  -X POST \
  -H "Authorization: Bearer {{SLACK_BOT_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{"channel": "#general", "text": "Hello from keychains!"}'

# Use a specific permission
keychains curl https://api.stripe.com/v1/customers?limit=5 \
  --permission pr_abc123 \
  -H "Authorization: Bearer {{STRIPE_SECRET_KEY}}"

Permission resolution order:

  • --permission <id> flag
  • KEYCHAINS_PERMISSION_ID in .env (cwd)
  • KEYCHAINS_PERMISSION_ID environment variable
  • First active wildcard permission on this machine
  • Auto-create a default wildcard permission

Every curl command is automatically saved to local history.

keychains whoami — Identity Check

keychains whoami                  # Human-readable
keychains whoami --json           # JSON output
keychains whoami --env >> .env    # Append to .env

keychains history — Curl Command History

Browse, search, and manage your past keychains curl commands. History is stored locally in ~/.keychains/history.json (default: 100 entries).

# List recent history
keychains history

# Search history
keychains history "github"
keychains history "stripe" --limit 50

# Interactive browse (select entries to export/re-run)
keychains history -i
keychains history -i "gmail"

# Save a history entry as a template
keychains history save hist_abc123 --name "List GitHub repos"

# Clear history
keychains history clear
keychains history clear -f          # Skip confirmation

keychains templates — Request Templates

Save frequently-used requests as named templates for quick re-use and code export.

# List templates
keychains templates ls
keychains templates ls "github"     # Search templates
keychains templates ls --json       # JSON output

# Show template details
keychains templates show "my-template"
keychains templates show tpl_abc123

# Delete a template
keychains templates rm tpl_abc123
keychains templates rm "my-template" -f   # By name, skip confirmation

Aliases: keychains tpl ls, keychains tpl show, etc.

keychains export — Code Generation

Export any history entry or template as runnable code in your language of choice.

When the command contains input variables ({{$...}}), the generated code is a function that accepts a params dict. Use --name to set the function name.

# Export a standalone script (no input variables)
keychains export hist_abc123 --nodejs > index.js
keychains export hist_abc123 --ts > index.ts
keychains export hist_abc123 --python > script.py
keychains export hist_abc123 --go > main.go
keychains export hist_abc123 --curl > request.sh

# Export a function (when input variables are present)
keychains export hist_abc123 --ts --name fetchUser > fetchUser.ts
keychains export tpl_abc123 --python --name fetch_user > fetch_user.py
keychains export hist_abc123 --go --name FetchUser > fetch_user.go

# Export from template (by ID or name)
keychains export tpl_abc123 --nodejs > index.js
keychains export "my-template" --python > script.py

# Use --lang flag
keychains export hist_abc123 --lang typescript > index.ts

Generated function example (TypeScript):

// keychains export hist_xxx --ts --name fetchUser > fetchUser.ts

interface InputParams {
  user: any;
  email: any;
}

export async function fetchUser(params: InputParams): Promise<{ status: number; data: any }> {
  const url = `https://api.com/users/${params.user}`;
  const headers: Record<string, string> = {};
  headers["Content-Type"] = "application/json";
  const body = `{"user": "${params.user}", "email": "${params.email}"}`;

  const response = await fetch(url, { method: "POST", headers, body });
  const text = await response.text();
  let data: any;
  try { data = JSON.parse(text); } catch { data = text; }
  return { status: response.status, data };
}

Supported languages:

FlagLanguageFile
--nodejs / --node / --js / --javascriptNode.js (CommonJS).js
--typescript / --tsTypeScript (fetch).ts
--python / --pyPython (requests).py
--go / --golangGo (net/http).go
--curlcurl / bash function.sh

Credential Templates

You don't pass real secrets. Use {{VARIABLE_NAME}} placeholders in your headers. Keychains resolves them at the proxy level — the actual token never touches your machine.

OAuth Tokens

TemplateResolves to
{{OAUTH2_ACCESS_TOKEN}}OAuth 2.0 access token (auto-refreshed)
{{OAUTH2_REFRESH_TOKEN}}OAuth 2.0 refresh token
{{OAUTH1_TOKEN}}OAuth 1.0 token
{{OAUTH1_TOKEN_SECRET}}OAuth 1.0 token secret

API Keys

Named API keys stored in the Keychains dashboard:

TemplateExample service
{{STRIPE_SECRET_KEY}}Stripe
{{OPENAI_API_KEY}}OpenAI
{{SENDGRID_API_KEY}}SendGrid
{{LIFX_PERSONAL_ACCESS_TOKEN}}LIFX

Examples

# Toggle LIFX lights
keychains curl https://api.lifx.com/v1/lights/all/toggle \
  -X POST \
  -H "Authorization: Bearer {{LIFX_PERSONAL_ACCESS_TOKEN}}"

# List Stripe customers
keychains curl https://api.stripe.com/v1/customers?limit=5 \
  -H "Authorization: Bearer {{STRIPE_SECRET_KEY}}"

# Send a Slack message
keychains curl https://slack.com/api/chat.postMessage \
  -X POST \
  -H "Authorization: Bearer {{SLACK_BOT_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{"channel": "#general", "text": "Hello from keychains!"}'

# Create a GitHub issue
keychains curl https://api.github.com/repos/octocat/hello-world/issues \
  -X POST \
  -H "Authorization: Bearer {{OAUTH2_ACCESS_TOKEN}}" \
  -H "Content-Type: application/json" \
  -d '{"title": "Found a bug", "body": "Something is broken"}'

Workflow Example

# 1. Register machine
keychains machine register --name "dev-laptop"

# 2. Create a scoped permission for a project
keychains permissions create --name "My Project" \
  --scopes "github::repo,slack::chat:write" \
  --env >> .env

# 3. Make API calls (permission auto-detected from .env)
keychains curl https://api.github.com/user \
  -H "Authorization: Bearer {{OAUTH2_ACCESS_TOKEN}}"

# 4. Use input variables with piped JSON
echo '{"owner":"octocat","repo":"hello-world"}' \
  | keychains curl https://api.github.com/repos/{{$owner}}/{{$repo}}/issues \
    -X POST \
    -H "Authorization: Bearer {{OAUTH2_ACCESS_TOKEN}}" \
    -d '{"title":"Bug in {{$repo}}"}'

# 5. Export the command as a TypeScript function
keychains export hist_abc123 --ts --name createIssue > createIssue.ts

# 6. Give a CI runner limited access
keychains delegates add pr_abc123 --wildcard --ttl 3600 --env >> ci.env

# 7. Check your connections
keychains connections ls
keychains connections ls --json | jq '.[] | .provider'

Using .env for Projects

Drop a .env in your project root:

KEYCHAINS_PERMISSION_ID=pr_abc123

Every keychains curl in that directory will use it automatically.

Or create a permission directly into .env:

keychains permissions create --name "My Project" --env >> .env

Local Storage

All local data is stored in ~/.keychains/:

FileContents
credentials.jsonMachine ID, server URL, key paths
history.jsonCurl command history (default limit: 100)
templates.jsonSaved request templates
config.jsonCLI configuration (history limit, etc.)
id_ed25519Ed25519 private key
id_ed25519.pubEd25519 public key

All Commands Reference

CommandDescription
Machine
machine register --name <n>Register this machine
machine statusShow machine status
machine lsList machines on account
machine update --name <n>Update machine name
machine rotate-keysRotate SSH keypair
machine rm <id>Remove a machine
Permissions
permissions create --name <n>Create permission (wildcard default)
permissions lsList machine permissions
permissions ls -aList all account permissions
permissions rm <id>Revoke a permission
permissions suspend <id>Suspend a permission
Delegates
delegates add <permId>Create a delegate identity
delegates lsList delegate-enabled permissions
delegates rm <id>Revoke a delegate
Connections
connections lsList connections
connections rm <provider>Remove a connection
Curl & History
curl <url>Proxied API call
history [query]Browse curl history
history save <id> --name <n>Save history as template
history clearClear history
Templates
templates ls [query]List templates
templates show <id>Show template details
templates rm <id>Delete a template
Export
export <id> --nodejsExport as Node.js
export <id> --tsExport as TypeScript
export <id> --pythonExport as Python
export <id> --goExport as Go
export <id> --curlExport as curl
Identity
whoamiShow current identity

Build from Source

npm run build
node dist/index.js --help

FAQs

Package last updated on 17 Feb 2026

Related posts