@daslabhq/kern

中文文档
0.2.0发布于 2026/05/28MITTypeScriptES Module近 30 天下载 2799

The agent wallet. Hold credentials — agents use them without seeing them.

原始使用文档
文档目录16 节
  1. The problem
  2. How kern works
  3. Quick start
  4. Agent integration (MCP)
  5. MCP tools
  6. Vault layout
  7. Scoping rules
  8. Nodes
  9. Add a teammate
  10. Add CI
  11. Revoke access
  12. Machine payments
  13. CLI
  14. Environment
  15. How it compares
  16. License

kern

tests

The agent wallet. Hold credentials — agents use them without seeing them.

npm install @daslabhq/kern

Works with Node.js 18+ and Bun. CLI requires Bun.

The problem

Agents need API keys. Today those live in env vars — plaintext, unscoped, every process sees everything. The agent calling Stripe has your production secret key in its context window. Every credential is one prompt injection away from exfiltration.

How kern works

Kern is a credential wallet backed by age encryption. Credentials are encrypted files, organized in folders, committed to git. The wallet holds them. Agents use them two ways:

Proxy — the credential never leaves the wallet. The agent asks kern to make the API call; kern injects the auth and returns the response.

import { openWallet, loadIdentityFromHost } from "@daslabhq/kern";

const wallet = openWallet({ identity: await loadIdentityFromHost() });

// wallet injects the Bearer token — agent never sees it
const resp = await wallet.fetch("tokens/github", "https://api.github.com/user/repos");
const repos = await resp.json();

Direct — for SDKs and non-HTTP protocols where you need the raw credential.

const key = await wallet.get("tokens/openai");
const client = new OpenAI({ apiKey: key });

Both read from the same encrypted vault. You choose per credential.

Quick start

# create your identity (age keypair)
kern identity init

# create the vault
mkdir -p secrets
kern identity pubkey >> secrets/.recipients

# add credentials
kern secret add tokens/github
kern secret add tokens/openai

# proxy request — credential stays in the wallet
kern fetch tokens/github https://api.github.com/user

Agent integration (MCP)

Add kern as an MCP server. The agent talks to the wallet — never holds the keys.

{
  "mcpServers": {
    "kern": {
      "command": "npx",
      "args": ["@daslabhq/kern", "mcp"]
    }
  }
}
Agent: "Fetch my GitHub repos"

→ kern_fetch(secret: "tokens/github", url: "https://api.github.com/user/repos")
→ wallet decrypts tokens/github, injects Bearer token, makes the request
→ returns JSON response to agent

Agent got the data. Never saw the token.
Agent: "Add my Stripe test key"

→ kern_add(name: "testing/stripe")
→ browser opens kern's local form
→ you paste the key
→ encrypted into secrets/testing/stripe.age

Credential went: browser → wallet → encrypted file. Agent never saw it.

MCP tools

ToolModeDescription
kern_fetchproxyAuthenticated HTTP request. Credential stays in the wallet.
kern_getdirectDecrypt and return a credential value.
kern_add—Add a credential via browser form. Agent never sees it.
kern_rotate—Replace a credential via browser form.
kern_remove—Delete a credential.
kern_list—List credential names (never values).
kern_status—Wallet health check.
kern_recipients—List recipients (public keys).

Vault layout

Credentials are age-encrypted files in folders. Each folder has a .recipients file controlling who can decrypt. Commit the whole thing to git — it's ciphertext without the private key.

secrets/
├── .recipients              # all nodes
│
├── tokens/                  # API credentials
│   ├── github.age
│   ├── openai.age
│   └── stripe.age
│
├── infra/                   # production infrastructure
│   ├── database_url.age
│   └── redis_url.age
│
└── testing/                 # dev + CI only
    ├── .recipients          # narrower: Alice + CI (not prod)
    ├── stripe_test.age
    └── llm.age

Scoping rules

  • Each folder can have its own .recipients
  • No .recipients? Inherits from parent
  • Prod server decrypts tokens/ and infra/ — never sees test keys
  • CI decrypts testing/ — never touches prod credentials

Nodes

A node is any machine with an age keypair — your laptop, CI, a production server.

Add a teammate

# Bob generates his identity
kern identity init && kern identity pubkey
# → age1xyz...

echo "age1xyz..." >> secrets/.recipients
echo "age1xyz..." >> secrets/testing/.recipients
kern secret rewrap
git commit -am "add Bob"

Add CI

kern identity init --save /tmp/ci-key
echo "$(kern identity pubkey)" >> secrets/.recipients
echo "$(kern identity pubkey)" >> secrets/testing/.recipients
kern secret rewrap
gh secret set KERN_AGE_KEY < /tmp/ci-key
rm /tmp/ci-key

One secret in CI. Everything else decrypts from git.

Revoke access

kern recipients remove age1xyz...
kern secret rewrap
kern secret rotate tokens/github  # rotate what they had access to

Machine payments

The same proxy that protects API keys protects payment credentials. An agent that purchases compute, calls paid APIs, or manages subscriptions needs payment keys — but shouldn't hold them.

// agent charges a customer — never sees sk_live_*
const resp = await wallet.fetch("tokens/stripe", "https://api.stripe.com/v1/payment_intents", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: "amount=2000&currency=usd&automatic_payment_methods[enabled]=true",
});

Works with Stripe MPP for machine-to-machine payments and any API that takes Bearer auth. x402 support — auto-negotiating 402 Payment Required responses — is on the roadmap.

CLI

kern identity init [--save PATH]   # create age keypair
kern identity pubkey               # print public key

kern secret add [FOLDER/]NAME      # encrypt and store
kern secret get [FOLDER/]NAME      # decrypt to stdout
kern secret list                   # show all names
kern secret rotate [FOLDER/]NAME   # replace a value
kern secret delete [FOLDER/]NAME   # remove
kern secret rewrap                 # re-encrypt for current recipients

kern fetch SECRET URL [OPTIONS]    # proxy request (credential stays in wallet)
  --method POST                    # HTTP method (default GET)
  --body '{"key": "val"}'          # request body

kern recipients                    # list all recipients
kern recipients remove KEY         # remove from all folders

kern mcp                           # start MCP server
kern serve                         # start local credential form

Environment

VariablePurposeDefault
KERN_AGE_KEYage private key~/.kern/key
KERN_VAULT_DIRvault directory./secrets

How it compares

.envSOPSVaultkern
Encrypted at rest✓✓✓
Lives in git✓✓
Folder scoping✓✓
No server✓✓✓
Proxy mode✓
Agent-native (MCP)✓
TypeScript SDK✓

License

MIT

版本与发布记录

@daslabhq/kern 共发布 1 个版本,首次发布于 2026/05/28;过去 12 个月发布了 1 个版本。

版本发布日期距今
0.2.0latest2026/05/285 个月前

关于 @daslabhq/kern 的常见问题

@daslabhq/kern 是什么?

The agent wallet. Hold credentials — agents use them without seeing them.

如何安装 @daslabhq/kern?

在项目目录运行 npm install @daslabhq/kern,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 kern,可以用 npx kern 直接运行。

@daslabhq/kern 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@daslabhq/kern 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@daslabhq/kern 可以商用吗?

@daslabhq/kern 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@daslabhq/kern 的下载量有多少?

根据 npm 官方下载统计,@daslabhq/kern 在 2026/10/12 – 2026/11/10 这 30 天内被下载 2,799 次,日均约 93 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@daslabhq/kern 还在维护吗?

最新版本 0.2.0 发布于 2026/05/28(5 个月前);至今共发布 1 个版本,其中过去 12 个月发布了 1 个;首次发布于 2026/05/28。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。