enclave-link 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  </picture>
6
6
  </h1>
7
7
 
8
- Your AI agent needs your Netflix password. Instead of asking in chat, it sends you a link. You open it, type the password (or let your password manager fill it) and tap **Send**. It's locked in your browser before it leaves, so only your agent can open it. The agent keeps it in a vault of its own and uses it later without ever seeing it.
8
+ Your AI agent needs your Netflix password. Instead of asking in chat, it sends you a link. You type the password (or your password manager fills it) and tap **Send**. It's locked in your browser before it leaves, so only your agent can open it. The agent keeps it in a vault of its own, next to 2FA codes and passkeys, and uses it later without seeing it.
9
9
 
10
10
  <p>
11
11
  <picture>
@@ -34,7 +34,7 @@ It works out of the box with a hosted relay. No accounts, no keys to set up, not
34
34
  npx skills add AVGVSTVS96/enclave
35
35
  ```
36
36
 
37
- The skill teaches the agent to send a link instead of asking in chat, and runs enclave with `npx`, so there's nothing else to install.
37
+ It runs enclave with `npx`, so there's nothing else to install.
38
38
 
39
39
  **Agents that use MCP** get the same thing as tools. Add the server below, and add this line to the agent's instructions, because tools alone don't stop a model from asking in chat:
40
40
 
@@ -63,7 +63,7 @@ claude mcp add enclave -- npx -y enclave-link mcp
63
63
  codex mcp add enclave -- npx -y enclave-link mcp
64
64
  ```
65
65
 
66
- Codex stops a tool after 60 seconds by default. `wait_for_secret` waits up to 25 minutes a call (the agent calls it again if the person needs longer), so add this under `[mcp_servers.enclave]` in `~/.codex/config.toml`:
66
+ Codex stops a tool after 60 seconds by default, and `wait_for_secret` can wait 25 minutes, so add this under `[mcp_servers.enclave]` in `~/.codex/config.toml`:
67
67
 
68
68
  ```toml
69
69
  tool_timeout_sec = 1800
@@ -188,7 +188,7 @@ Run `goose configure`, choose **Add Extension → Command-line Extension**, ente
188
188
 
189
189
  </details>
190
190
 
191
- **ChatGPT, Claude.ai and the Gemini and Grok apps** can't use enclave yet. They run in the cloud with no computer of yours behind them, and enclave keeps the vault on the computer where the agent runs. What would make them work is an enclave server you run yourself that the app reaches over remote MCP; it doesn't exist yet. Their desktop and coding-agent versions above work today.
191
+ **ChatGPT, Claude.ai and the Gemini and Grok apps** can't use enclave yet: they run in the cloud, and the vault lives on the computer where the agent runs. Their desktop and coding-agent versions above work.
192
192
 
193
193
  **Your own code** can use the TypeScript SDK; see [SDK](#sdk).
194
194
 
@@ -232,11 +232,9 @@ A field named `passkey` holds a passkey, and the agent signs in with it in Chrom
232
232
  enclave passkey GitHub # then click the site's passkey sign-in
233
233
  ```
234
234
 
235
- `enclave passkey` arms the passkey for one sign-in, for up to 5 minutes. When the site asks for a passkey, enclave's Chrome extension hands the request to `enclave sign`, which signs it inside the vault and disarms the passkey. The private key never enters Chrome.
235
+ `enclave passkey` arms the passkey for one sign-in, for up to 5 minutes. When the site asks for a passkey, enclave's Chrome extension hands the request to `enclave sign`, which signs it inside the vault and disarms the passkey. The private key never leaves the vault: `enclave get` and `enclave run` refuse passkey fields.
236
236
 
237
- enclave signs the way Proton Pass does, with a signature counter of 0 every time. Sites read 0 as "this authenticator doesn't count", so a passkey keeps working from Proton and from enclave side by side.
238
-
239
- A passkey's private key never comes out: `enclave get` and `enclave run` refuse passkey fields, and only `enclave sign` uses them.
237
+ A passkey keeps working in Proton Pass and enclave side by side.
240
238
 
241
239
  Install the extension once per machine, from a clone of this repo, with Google Chrome on Linux. It's force-installed through Chrome's policy, so it loads in every profile:
242
240
 
@@ -252,9 +250,9 @@ enclave import proton # every vault
252
250
  enclave import proton Work # or just the ones you name
253
251
  ```
254
252
 
255
- copies [Proton Pass](https://proton.me/pass) in through [pass-cli](https://github.com/protonpass/pass-cli): logins, 2FA, passkeys, notes, cards, SSH keys and custom fields, one item per Proton item, named by its title (two items with the same title get the account or a number after it). Proton keeps everything. Run it again to bring in what changed: each Proton item keeps its name across imports, a renamed one follows its new title, one you deleted in Proton leaves enclave too, and items saved by link are left alone. `~/.enclave/proton.json` remembers which item is which, by Proton's IDs and names only.
253
+ copies [Proton Pass](https://proton.me/pass) in through [pass-cli](https://github.com/protonpass/pass-cli): logins, 2FA, passkeys, notes, cards, SSH keys and custom fields, one item per Proton item, named by its title. Proton keeps everything. Run it again to bring in what changed: names stay the same, renames follow, items deleted in Proton leave enclave too, and anything you saved yourself is kept.
256
254
 
257
- 2FA comes in as a `totp` field, so `enclave get <name> totp` gives the current code. Passkeys come in as a `passkey` field: Proton keeps each passkey's private key in the item, and enclave unpacks it the way Proton's own [export code](https://github.com/protonpass/proton-pass-common/blob/main/proton-pass-common/src/cxf/credentials/passkey.rs) does.
255
+ 2FA comes in as a `totp` field, so `enclave get <name> totp` gives the current code, and passkeys as a `passkey` field.
258
256
 
259
257
  ## CLI
260
258
 
@@ -329,7 +327,7 @@ The vault keeps each item encrypted in `~/.enclave/items`, sealed to the vault's
329
327
 
330
328
  What enclave can't protect against:
331
329
 
332
- - **Whoever runs the relay sends you the page.** Your browser downloads the page, including the code that locks your password, from the relay each time you open a link. What the relay stores can't be read, but if someone took over the relay's Convex account, they could change the page to copy what you type before locking it. Every website that encrypts in your browser works this way. The page's script is 128 lines in [`page/page.ts`](page/page.ts) plus the encryption in [`src/hpke.ts`](src/hpke.ts), served as one file with a strict Content Security Policy, so you can read exactly what it runs. If you'd rather trust nobody's relay, [host your own](#host-your-own).
330
+ - **Whoever runs the relay sends you the page.** Your browser downloads the page, including the code that locks your password, from the relay each time you open a link. What the relay stores can't be read, but if someone took over the relay's Convex account, they could change the page to copy what you type before locking it. The page's script is 128 lines in [`page/page.ts`](page/page.ts) plus the encryption in [`src/hpke.ts`](src/hpke.ts), served as one file with a strict Content Security Policy, so you can read exactly what it runs. If you'd rather trust nobody's relay, [host your own](#host-your-own).
333
331
  - **Anyone with the link can answer it first.** They still can't read anything, but they could send a fake answer. If that happens, the page says "This link doesn't work anymore" when you open it.
334
332
  - **Phishing.** A link can say anyone is asking. Only send secrets to agents you asked for help.
335
333
  - **An agent that wants to see a secret can.** enclave keeps secrets out of the chat and out of tool results, and `run` hides their exact values in output. But an agent with a shell on the same computer could still read its own vault. enclave stops secrets from leaking by accident, not a model that's trying.
@@ -28,7 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  mod
29
29
  ));
30
30
 
31
- // node_modules/zod/v4/core/util.js
31
+ // ../../../Developer/enclave/node_modules/zod/v4/core/util.js
32
32
  var util_exports = {};
33
33
  __export(util_exports, {
34
34
  BIGINT_FORMAT_RANGES: () => BIGINT_FORMAT_RANGES,
@@ -871,7 +871,7 @@ function constantCatch(value) {
871
871
  return fn;
872
872
  }
873
873
 
874
- // node_modules/zod/v4/core/core.js
874
+ // ../../../Developer/enclave/node_modules/zod/v4/core/core.js
875
875
  var _a;
876
876
  var _zodDesc = { value: void 0, enumerable: false };
877
877
  var _E = "captureStackTrace" in Error ? Error : null;
@@ -989,7 +989,7 @@ function config(newConfig) {
989
989
  return globalConfig;
990
990
  }
991
991
 
992
- // node_modules/zod/v4/core/errors.js
992
+ // ../../../Developer/enclave/node_modules/zod/v4/core/errors.js
993
993
  function _getMessage() {
994
994
  const internals = this._zod;
995
995
  internals.message ?? (internals.message = JSON.stringify(internals.def, jsonStringifyReplacer, 2));
@@ -1104,7 +1104,7 @@ function formatError(error2, mapper = (issue2) => issue2.message) {
1104
1104
  return fieldErrors;
1105
1105
  }
1106
1106
 
1107
- // node_modules/zod/v4/core/parse.js
1107
+ // ../../../Developer/enclave/node_modules/zod/v4/core/parse.js
1108
1108
  function finalizeParams(callee, params) {
1109
1109
  return { callee: params?.callee ?? callee, Err: params?.Err };
1110
1110
  }
@@ -1256,7 +1256,7 @@ var _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
1256
1256
  return _safeParseAsync(_Err)(schema, value, _ctx);
1257
1257
  };
1258
1258
 
1259
- // node_modules/zod/v4/core/regexes.js
1259
+ // ../../../Developer/enclave/node_modules/zod/v4/core/regexes.js
1260
1260
  var cuid = /^[cC][0-9a-z]{6,}$/;
1261
1261
  var cuid2 = /^[0-9a-z]+$/;
1262
1262
  var ulid = /^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$/;
@@ -1315,7 +1315,7 @@ var _null = /^null$/i;
1315
1315
  var lowercase = /^[^A-Z]*$/;
1316
1316
  var uppercase = /^[^a-z]*$/;
1317
1317
 
1318
- // node_modules/zod/v4/core/checks.js
1318
+ // ../../../Developer/enclave/node_modules/zod/v4/core/checks.js
1319
1319
  var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
1320
1320
  var _a3;
1321
1321
  inst._zod ?? (inst._zod = {});
@@ -1635,7 +1635,7 @@ var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (ins
1635
1635
  };
1636
1636
  });
1637
1637
 
1638
- // node_modules/zod/v4/core/doc.js
1638
+ // ../../../Developer/enclave/node_modules/zod/v4/core/doc.js
1639
1639
  var Doc = class {
1640
1640
  constructor(args = [], closed = {}) {
1641
1641
  this.content = [];
@@ -1676,14 +1676,14 @@ ${content.join("\n")}
1676
1676
  }
1677
1677
  };
1678
1678
 
1679
- // node_modules/zod/v4/core/versions.js
1679
+ // ../../../Developer/enclave/node_modules/zod/v4/core/versions.js
1680
1680
  var version = {
1681
1681
  major: 4,
1682
1682
  minor: 6,
1683
1683
  patch: 5
1684
1684
  };
1685
1685
 
1686
- // node_modules/zod/v4/core/schemas.js
1686
+ // ../../../Developer/enclave/node_modules/zod/v4/core/schemas.js
1687
1687
  var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
1688
1688
  var _a3;
1689
1689
  inst ?? (inst = {});
@@ -3449,7 +3449,7 @@ function handleRefineResult(result, payload, input, inst) {
3449
3449
  }
3450
3450
  }
3451
3451
 
3452
- // node_modules/zod/v4/core/memoizer.js
3452
+ // ../../../Developer/enclave/node_modules/zod/v4/core/memoizer.js
3453
3453
  var $ZodCyclicError = class extends Error {
3454
3454
  constructor() {
3455
3455
  super(`Cannot parse a reference cycle that closes through a transform`);
@@ -3723,7 +3723,7 @@ function isBackEdge(ctx, value) {
3723
3723
  return backEdges !== void 0 && isRef(value) && backEdges.has(value);
3724
3724
  }
3725
3725
 
3726
- // node_modules/zod/v4/locales/en.js
3726
+ // ../../../Developer/enclave/node_modules/zod/v4/locales/en.js
3727
3727
  var error = () => {
3728
3728
  const Sizable = {
3729
3729
  string: { unit: "characters", verb: "to have" },
@@ -3848,7 +3848,7 @@ function en_default() {
3848
3848
  };
3849
3849
  }
3850
3850
 
3851
- // node_modules/zod/v4/core/registries.js
3851
+ // ../../../Developer/enclave/node_modules/zod/v4/core/registries.js
3852
3852
  var _a2;
3853
3853
  var $ZodRegistry = class {
3854
3854
  constructor() {
@@ -3896,7 +3896,7 @@ function registry() {
3896
3896
  (_a2 = globalThis).__zod_globalRegistry ?? (_a2.__zod_globalRegistry = registry());
3897
3897
  var globalRegistry = globalThis.__zod_globalRegistry;
3898
3898
 
3899
- // node_modules/zod/v4/core/api.js
3899
+ // ../../../Developer/enclave/node_modules/zod/v4/core/api.js
3900
3900
  function snapshotChecks(def) {
3901
3901
  if (def.checks)
3902
3902
  def.checks = [...def.checks];
@@ -4423,7 +4423,7 @@ function _check(fn, params) {
4423
4423
  return ch;
4424
4424
  }
4425
4425
 
4426
- // node_modules/zod/v4/core/to-json-schema.js
4426
+ // ../../../Developer/enclave/node_modules/zod/v4/core/to-json-schema.js
4427
4427
  function assignProps(target, ...sources) {
4428
4428
  for (const source of sources) {
4429
4429
  for (const key of Reflect.ownKeys(source)) {
@@ -4953,7 +4953,7 @@ var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) =
4953
4953
  return finalize(ctx, schema);
4954
4954
  };
4955
4955
 
4956
- // node_modules/zod/v4/core/json-schema-processors.js
4956
+ // ../../../Developer/enclave/node_modules/zod/v4/core/json-schema-processors.js
4957
4957
  var narrowMin = (agg, key, value) => {
4958
4958
  if (agg[key] === void 0 || value > agg[key])
4959
4959
  agg[key] = value;
@@ -5701,7 +5701,7 @@ function toJSONSchema(input, params) {
5701
5701
  return finalize(ctx, input);
5702
5702
  }
5703
5703
 
5704
- // node_modules/zod/v4/classic/errors.js
5704
+ // ../../../Developer/enclave/node_modules/zod/v4/classic/errors.js
5705
5705
  var _installedErrorProtos = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]);
5706
5706
  function _lazyMethod(proto, key, make) {
5707
5707
  Object.defineProperty(proto, key, {
@@ -5746,7 +5746,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, void 0
5746
5746
  Parent: Error
5747
5747
  });
5748
5748
 
5749
- // node_modules/zod/v4/classic/parse.js
5749
+ // ../../../Developer/enclave/node_modules/zod/v4/classic/parse.js
5750
5750
  var parse2 = /* @__PURE__ */ _parse(ZodRealError);
5751
5751
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
5752
5752
  var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
@@ -5760,7 +5760,7 @@ var safeDecode = /* @__PURE__ */ _safeDecode(ZodRealError);
5760
5760
  var safeEncodeAsync = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
5761
5761
  var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
5762
5762
 
5763
- // node_modules/zod/v4/classic/schemas.js
5763
+ // ../../../Developer/enclave/node_modules/zod/v4/classic/schemas.js
5764
5764
  function _ensureDefaultLocale() {
5765
5765
  if (!globalConfig.localeError)
5766
5766
  config(en_default());