@lazehq/cli 0.1.26 → 0.1.27

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.
Files changed (2) hide show
  1. package/dist/laze.mjs +219 -39
  2. package/package.json +1 -1
package/dist/laze.mjs CHANGED
@@ -30997,6 +30997,41 @@ function isBasicAuthPayload(value) {
30997
30997
  }
30998
30998
  var CREDENTIAL_QUALIFIERS = "master|encryption|signing|private|access|api|auth|secret|refresh|session|bearer|verification|webhook|client|service|personal|root|admin";
30999
30999
  var CREDENTIAL_KEYWORD = `(?:x[_.\\- ]?)?(?:(?:${CREDENTIAL_QUALIFIERS})[_.\\- ]?(?:api[_.\\- ]?)?key|(?:${CREDENTIAL_QUALIFIERS})?[_.\\- ]?(?:api[_.\\- ]?)?(?:token|secret|password|passwd|pwd|credentials?|authorization|cookie))`;
31000
+ var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
31001
+ var GIT_SHA = /^[0-9a-f]{40}$/;
31002
+ var DOMAIN_PATH = /^[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}\//;
31003
+ var NAMED_KEY_MIN = 24;
31004
+ var NAMED_KEY_MAX = 256;
31005
+ function isSlug(value) {
31006
+ const parts = value.split(/[-_.]/);
31007
+ if (parts.length < 3) return false;
31008
+ const short = parts.every((part) => /^(?:[a-z0-9]{1,10}|[A-Z0-9]{1,10})$/.test(part));
31009
+ return short && parts.some((part) => /^[A-Za-z]{3,}$/.test(part));
31010
+ }
31011
+ var NOT_A_NAMED_KEY = [
31012
+ /^\/|\/\//,
31013
+ GIT_SHA,
31014
+ DOMAIN_PATH,
31015
+ PATH_LIKE,
31016
+ CODE_EXPRESSION,
31017
+ ENV_REFERENCE,
31018
+ VERSION_LIKE
31019
+ ];
31020
+ function isNamedKeyValue(value) {
31021
+ if (value.length < NAMED_KEY_MIN || value.length > NAMED_KEY_MAX) return false;
31022
+ if (UUID.test(value)) return true;
31023
+ if (isSlug(value)) return false;
31024
+ if (NOT_A_NAMED_KEY.some((shape) => shape.test(value))) return false;
31025
+ const prefix = /^([A-Za-z][A-Za-z0-9]{1,11})[_-]/.exec(value)?.[1];
31026
+ if (prefix && isNonCredentialPrefix(prefix)) return false;
31027
+ if (HEX.test(value)) return true;
31028
+ if (shannonEntropyBits(value) < 3.5) return false;
31029
+ const c = charClasses(value);
31030
+ return c.digit >= 2 && c.lower + c.upper >= 8 && (c.lower >= 2 || c.upper >= 2);
31031
+ }
31032
+ var KEY_WORD = String.raw`(?:api[_.\- ]?key|apikey|access[_.\- ]?key|key|token|secret|password|passwd|pwd)`;
31033
+ var QUOTE = "[\"'`]";
31034
+ var KEY_WORD_GAP = String.raw`(?:[ \t]{0,3}(?:is|was|here|it's|its|below|:|=|->|=>|-{1,2}))`;
31000
31035
  var TOKEN_START = "(?<![A-Za-z0-9_-])";
31001
31036
  var TOKEN_END = "(?![A-Za-z0-9_-])";
31002
31037
  var VENDOR_KEY_PATTERNS = [
@@ -31125,11 +31160,21 @@ var RULES = [
31125
31160
  "i"
31126
31161
  ),
31127
31162
  value: { kind: "group", group: 2 },
31163
+ dropsFullStop: true,
31128
31164
  accept: (match) => {
31129
31165
  const introduction = groupOf(match, 1);
31130
31166
  const value = groupOf(match, 2);
31131
31167
  return STRICT_INTRODUCTION.test(introduction) ? isCredentialValue(value) : isKeyMaterial(value);
31132
31168
  }
31169
+ },
31170
+ {
31171
+ id: "named_key",
31172
+ regex: rx(
31173
+ String.raw`\b(${KEY_WORD})\b(${KEY_WORD_GAP}{0,3}[ \t]*(?:\r?\n[ \t]*)?${QUOTE}?)` + String.raw`([A-Za-z0-9+/=_.-]{${NAMED_KEY_MIN - 1},${NAMED_KEY_MAX - 1}}[A-Za-z0-9+/=_-])` + String.raw`(?![A-Za-z0-9+/=_-]|\.[A-Za-z0-9])`,
31174
+ "i"
31175
+ ),
31176
+ value: { kind: "group", group: 3 },
31177
+ accept: (match) => /[\s:="'`]/.test(groupOf(match, 2)) && isNamedKeyValue(groupOf(match, 3))
31133
31178
  }
31134
31179
  ];
31135
31180
  var SECRET_RULE_IDS = RULES.map((rule) => rule.id);
@@ -31157,12 +31202,21 @@ function spanStartOf({ rule, text: text2, fullStart }) {
31157
31202
  const before = rule.precededBy.exec(text2.slice(from, fullStart));
31158
31203
  return before ? fullStart - before[0].length : fullStart;
31159
31204
  }
31205
+ function withoutFullStop({
31206
+ text: text2,
31207
+ span
31208
+ }) {
31209
+ let end = span.end;
31210
+ while (end > span.start && text2[end - 1] === "." && !/\S/.test(text2[end] ?? "")) end--;
31211
+ return end === span.end ? span : { start: span.start, end, spanEnd: Math.min(span.spanEnd, end) };
31212
+ }
31160
31213
  function rawMatches(rule, text2) {
31161
31214
  const out = [];
31162
31215
  rule.regex.lastIndex = 0;
31163
31216
  for (const match of text2.matchAll(rule.regex)) {
31164
31217
  if (rule.accept && !rule.accept(match)) continue;
31165
- const span = valueSpan(rule, match);
31218
+ const found = valueSpan(rule, match);
31219
+ const span = found && rule.dropsFullStop ? withoutFullStop({ text: text2, span: found }) : found;
31166
31220
  if (!span || span.end <= span.start) continue;
31167
31221
  const spanStart = spanStartOf({ rule, text: text2, fullStart: match.index });
31168
31222
  out.push({ ruleId: rule.id, spanStart, ...span });
@@ -31322,7 +31376,33 @@ function suggestedName({
31322
31376
  const line = lineBreak === -1 ? before : before.slice(lineBreak + 1);
31323
31377
  const assigned = ASSIGNMENT.exec(line)?.[1]?.toUpperCase();
31324
31378
  if (assigned && isValidSecretName(assigned)) return assigned;
31325
- return defaultName({ kind, value, before });
31379
+ const lead = before.replace(/\s+$/, "");
31380
+ const lastLine = lead.slice(lead.search(/[^\r\n]*$/));
31381
+ const named = KEY_WORD_KINDS.has(kind) ? keyWordName({ line: lastLine }) : null;
31382
+ return named ?? defaultName({ kind, value, before });
31383
+ }
31384
+ var KEY_WORD_KINDS = /* @__PURE__ */ new Set(["named_key", "sensitive_assignment"]);
31385
+ var VENDOR_KEY_WORD = /([A-Za-z][A-Za-z0-9]{1,30})[ _.-]+(?:(?:api|access)[ _.-]?)?(key|token|secret|password|passwd|pwd)\b/gi;
31386
+ var NOT_VENDOR_WORDS = new Set(
31387
+ "a an the my your our their his her its this that these new old here is of for with and or to my api access secret private public personal prod production live test dev staging master admin root bearer auth client service session refresh read write full main default".split(
31388
+ " "
31389
+ )
31390
+ );
31391
+ var KEY_WORD_SUFFIXES = {
31392
+ key: "_API_KEY",
31393
+ token: "_TOKEN",
31394
+ secret: "_SECRET",
31395
+ password: "_PASSWORD",
31396
+ passwd: "_PASSWORD",
31397
+ pwd: "_PASSWORD"
31398
+ };
31399
+ function keyWordName({ line }) {
31400
+ const last = [...line.slice(-80).matchAll(VENDOR_KEY_WORD)].at(-1);
31401
+ const vendor = last?.[1]?.toLowerCase();
31402
+ const word3 = last?.[2]?.toLowerCase();
31403
+ if (!vendor || !word3 || NOT_VENDOR_WORDS.has(vendor)) return null;
31404
+ const name2 = `${vendor.toUpperCase()}${KEY_WORD_SUFFIXES[word3] ?? "_KEY"}`;
31405
+ return isValidSecretName(name2) ? name2 : null;
31326
31406
  }
31327
31407
  var SAFE_CUT_LOOKAHEAD = 4096;
31328
31408
  var PEM_BEGIN = "-----BEGIN";
@@ -35625,7 +35705,7 @@ function flagText({
35625
35705
  }
35626
35706
 
35627
35707
  // src/rules/cli-version.rules.ts
35628
- var STAMPED = "0.1.26";
35708
+ var STAMPED = "0.1.27";
35629
35709
  function cliVersionOf({ stamped = STAMPED } = {}) {
35630
35710
  return stamped.startsWith("__") ? "dev" : stamped;
35631
35711
  }
@@ -57848,6 +57928,17 @@ var chatScrubReportSchemaDefinition = external_exports.object({
57848
57928
  channels: external_exports.array(chatScrubChannelSchemaDefinition)
57849
57929
  });
57850
57930
  var chatScrubReportSchema = chatScrubReportSchemaDefinition;
57931
+ var saveMessageSecretBodySchemaDefinition = external_exports.object({
57932
+ /** One token, as keys are: a value with spaces is text, not a key. */
57933
+ value: external_exports.string().min(8).max(4096).regex(/^\S+$/),
57934
+ name: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/),
57935
+ description: external_exports.string().trim().min(1).max(120)
57936
+ });
57937
+ var messageSecretSavedSchemaDefinition = external_exports.object({
57938
+ outcome: external_exports.enum(["named", "already_named"]),
57939
+ name: external_exports.string(),
57940
+ connectionId: external_exports.string()
57941
+ });
57851
57942
 
57852
57943
  // ../../modules/chat/contract/src/chat.sent.ts
57853
57944
  var SENT_PAGE_MAX = 50;
@@ -62603,6 +62694,16 @@ var savePendingSecretBodySchemaDefinition = external_exports.object({
62603
62694
  name: connectionName2,
62604
62695
  description: external_exports.string().trim().min(1).max(120)
62605
62696
  });
62697
+ var saveMessageSecretInputSchemaDefinition = external_exports.object({
62698
+ workspaceId: external_exports.string().min(1),
62699
+ channelId: external_exports.string().min(1),
62700
+ messageId: external_exports.string().min(1),
62701
+ /** The message's author, a person: the keychain the value goes to. */
62702
+ ownerUserId: external_exports.string().min(1),
62703
+ value: external_exports.string().min(8).max(4096).regex(/^\S+$/),
62704
+ name: connectionName2,
62705
+ description: external_exports.string().trim().min(1).max(120)
62706
+ });
62606
62707
  var vaultPendingSecretSavedSchemaDefinition = external_exports.object({
62607
62708
  outcome: external_exports.enum(["named", "already_named"]),
62608
62709
  name: connectionName2,
@@ -66817,14 +66918,20 @@ async function liveElsewhere({
66817
66918
  }
66818
66919
  return false;
66819
66920
  }
66820
- function notBoundText({ meta: meta3 }) {
66821
- return `Laze: this agent listens in another session${meta3.bound ? `: ${meta3.bound}` : ""}. Create a new Laze agent with this session: laze agent request. Or move this agent here: laze agent bind.`;
66921
+ function notBoundText({
66922
+ meta: meta3,
66923
+ agent: agent2,
66924
+ configPath
66925
+ }) {
66926
+ const who = `${agent2 ? `"${agent2}"` : "this agent"} (config ${configPath})`;
66927
+ return `Laze: ${who} listens in another session${meta3.bound ? `: ${meta3.bound}` : ""}. Create a new Laze agent with this session: laze agent request. Or move this agent here: laze agent bind.`;
66822
66928
  }
66823
66929
  async function notBoundNotice({
66824
66930
  context,
66825
66931
  client,
66826
66932
  session,
66827
- error: error62
66933
+ error: error62,
66934
+ profile
66828
66935
  }) {
66829
66936
  if (!(error62 instanceof LazeApiError) || error62.code !== "session_not_bound") return void 0;
66830
66937
  const meta3 = error62.meta ?? {};
@@ -66844,7 +66951,10 @@ async function notBoundNotice({
66844
66951
  if (told) return { notice: void 0 };
66845
66952
  await mkdir3(dirname3(path), { recursive: true, mode: 448 });
66846
66953
  await writeFile3(path, String(context.nowMs()), { mode: 384 });
66847
- return { notice: notBoundText({ meta: meta3 }) };
66954
+ const agent2 = (await context.store.read()).profiles[profile]?.name;
66955
+ return {
66956
+ notice: notBoundText({ meta: meta3, agent: agent2, configPath: context.environment.configPath })
66957
+ };
66848
66958
  }
66849
66959
 
66850
66960
  // src/services/plugin-hook.service.ts
@@ -67676,7 +67786,8 @@ async function settleRound(round) {
67676
67786
  context,
67677
67787
  client: forSession({ client, session }),
67678
67788
  session,
67679
- error: error62
67789
+ error: error62,
67790
+ profile: name2
67680
67791
  });
67681
67792
  if (!refused) throw error62;
67682
67793
  return refused;
@@ -69989,7 +70100,13 @@ async function handOver({ context, args }) {
69989
70100
  try {
69990
70101
  fresh = await receiveMessages({ context, client: claim3, waitSeconds: 0 });
69991
70102
  } catch (error62) {
69992
- const refused = await notBoundNotice({ context, client: claim3, session, error: error62 });
70103
+ const refused = await notBoundNotice({
70104
+ context,
70105
+ client: claim3,
70106
+ session,
70107
+ error: error62,
70108
+ profile: agent2
70109
+ });
69993
70110
  if (!refused) throw error62;
69994
70111
  if (refused.notice) stopContext({ context, text: refused.notice });
69995
70112
  return;
@@ -70723,6 +70840,7 @@ async function setAgentPool({
70723
70840
 
70724
70841
  // src/services/agent-session-commands.service.ts
70725
70842
  var NO_SESSION = "Run this inside the Claude Code or Codex session the agent should listen in, or pass --session <id>.";
70843
+ var NO_AGENT = "This session and its folder have no agent: name one with `laze agent bind --profile <name>`.";
70726
70844
  var DEFAULT_WAIT_SECONDS = 300;
70727
70845
  async function bindAgentSession({
70728
70846
  context,
@@ -70730,10 +70848,21 @@ async function bindAgentSession({
70730
70848
  }) {
70731
70849
  const session = await currentSessionOf({ context, args });
70732
70850
  if (!session) throw new CliUsageError(NO_SESSION);
70733
- const { client, name: name2 } = await signedIn({ context, args });
70851
+ const key = sessionKeyOf({ session });
70852
+ const config2 = await context.store.read();
70853
+ const held = config2.sessions?.[key];
70854
+ const own2 = held && config2.profiles[held] ? held : void 0;
70855
+ const explicit = flagText({ args, name: "profile" }) || void 0;
70856
+ const target = explicit ?? own2 ?? boundProfileOf({ bindings: config2.bindings, cwd: context.cwd });
70857
+ if (!target) throw new CliUsageError(NO_AGENT);
70858
+ const named = { ...args, flags: { ...args.flags, profile: target } };
70859
+ const { client, name: name2, profile } = await signedIn({ context, args: named });
70734
70860
  await forSession({ client, session }).post("/api/agents/me/bind", {});
70735
- await context.store.bindSession({ session: sessionKeyOf({ session }), profile: name2 });
70736
- context.out("This agent now listens in this session.\n");
70861
+ await context.store.bindSession({ session: key, profile: name2 });
70862
+ const where = `profile ${name2}, config ${context.environment.configPath}`;
70863
+ const from = own2 && own2 !== name2 ? ` It moved from "${config2.profiles[own2]?.name}".` : "";
70864
+ context.out(`"${profile.name}" now listens in this session (${where}).${from}
70865
+ `);
70737
70866
  }
70738
70867
  async function mintedRequestProfile({
70739
70868
  context,
@@ -76347,7 +76476,13 @@ async function monitorRound(turn) {
76347
76476
  const named = { ...turn.args, flags: { ...turn.args.flags, profile: turn.profile } };
76348
76477
  const { client } = await signedIn({ context, args: named });
76349
76478
  const claim3 = forSession({ client, session });
76350
- const refused = await notBoundNotice({ context, client: claim3, session, error: error62 });
76479
+ const refused = await notBoundNotice({
76480
+ context,
76481
+ client: claim3,
76482
+ session,
76483
+ error: error62,
76484
+ profile: turn.profile
76485
+ });
76351
76486
  if (refused?.rebound) return true;
76352
76487
  if (refused?.notice) context.out(`${refused.notice}
76353
76488
  `);
@@ -81431,6 +81566,7 @@ var MCP_REFUSED_COMMANDS = /* @__PURE__ */ new Set([
81431
81566
  "vault add",
81432
81567
  "vault replace",
81433
81568
  "vault compare",
81569
+ "vault save-from-message",
81434
81570
  "connect mcp-key",
81435
81571
  "connect card-key"
81436
81572
  ]);
@@ -83502,15 +83638,20 @@ async function update2({
83502
83638
  return 0;
83503
83639
  }
83504
83640
 
83505
- // src/services/vault-save-commands.service.ts
83506
- var USAGE18 = `Usage: laze vault save <pending> --name <name> --description "<what it is for>"
83507
- Names a key Laze held from a message you received, in the sender's vault.`;
83641
+ // src/services/vault-save-message-commands.service.ts
83642
+ var SAVE_USAGE = `Usage: laze vault save <pending> --name <name> --description "<what it is for>"
83643
+ Names a key Laze held from a message you received, in the sender's vault.
83644
+ or: laze vault save --from-message <message-id> --name <name> --description "<what>" <<'EOF'
83645
+ Saves a key a person sent in that message, which Laze did not hold, to their own vault: the key
83646
+ on stdin, exactly as it is in the message. The message then shows {{vault:<name>}}. Run it in
83647
+ your turn in the message's conversation; it needs no vault access. MCP cannot send stdin.`;
83508
83648
  var KEPT_IN_LAZE = "The key never left Laze: the chat, its history and your session hold only a reference, so there is nothing to rotate. Tell the person that.";
83509
- async function vaultSave({ context, args }) {
83510
- const pending = args.words[2];
83511
- const name2 = flagText({ args, name: "name" });
83512
- const description = flagText({ args, name: "description" });
83513
- if (!pending || !name2 || !description) throw new CliUsageError(USAGE18);
83649
+ async function postInTurn({
83650
+ context,
83651
+ args,
83652
+ path,
83653
+ body
83654
+ }) {
83514
83655
  const env = context.environment.inherited;
83515
83656
  const turn = await turnTokenOf4({
83516
83657
  env,
@@ -83518,11 +83659,13 @@ async function vaultSave({ context, args }) {
83518
83659
  command: "laze vault save"
83519
83660
  });
83520
83661
  const { client } = await signedIn({ context, args });
83521
- const saved3 = await client.withHeaders({ "x-laze-turn": turn }).post("/api/vault/pending-secrets/save", {
83522
- pending,
83523
- name: name2,
83524
- description
83525
- });
83662
+ return client.withHeaders({ "x-laze-turn": turn }).post(path, body);
83663
+ }
83664
+ function printSaved({
83665
+ context,
83666
+ args,
83667
+ saved: saved3
83668
+ }) {
83526
83669
  if (args.flags.json) return context.out(`${JSON.stringify(saved3, null, 2)}
83527
83670
  `);
83528
83671
  const done = saved3.outcome === "named" ? "Saved as" : "Already named";
@@ -83532,6 +83675,40 @@ ${KEPT_IN_LAZE}
83532
83675
  `
83533
83676
  );
83534
83677
  }
83678
+ async function vaultSaveFromMessage({
83679
+ context,
83680
+ args
83681
+ }) {
83682
+ const messageId = flagText({ args, name: "from-message" });
83683
+ const name2 = flagText({ args, name: "name" });
83684
+ const description = flagText({ args, name: "description" });
83685
+ if (!messageId || !name2 || !description) throw new CliUsageError(SAVE_USAGE);
83686
+ const value = (await context.readStdin()).trim();
83687
+ if (!value) throw new CliUsageError(SAVE_USAGE);
83688
+ const saved3 = await postInTurn({
83689
+ context,
83690
+ args,
83691
+ path: `/api/chat/messages/${encodeURIComponent(messageId)}/save-secret`,
83692
+ body: { value, name: name2, description }
83693
+ });
83694
+ printSaved({ context, args, saved: saved3 });
83695
+ }
83696
+
83697
+ // src/services/vault-save-commands.service.ts
83698
+ async function vaultSave({ context, args }) {
83699
+ if (flagText({ args, name: "from-message" })) return vaultSaveFromMessage({ context, args });
83700
+ const pending = args.words[2];
83701
+ const name2 = flagText({ args, name: "name" });
83702
+ const description = flagText({ args, name: "description" });
83703
+ if (!pending || !name2 || !description) throw new CliUsageError(SAVE_USAGE);
83704
+ const saved3 = await postInTurn({
83705
+ context,
83706
+ args,
83707
+ path: "/api/vault/pending-secrets/save",
83708
+ body: { pending, name: name2, description }
83709
+ });
83710
+ printSaved({ context, args, saved: saved3 });
83711
+ }
83535
83712
 
83536
83713
  // src/services/vault-scrub-commands.service.ts
83537
83714
  function lineOf3(channel) {
@@ -84265,7 +84442,7 @@ var PATHS3 = {
84265
84442
  var STATUS_WAIT_SECONDS2 = 50;
84266
84443
  var STATUS_CALLS2 = 2;
84267
84444
  var SETTLED = /* @__PURE__ */ new Set(["sent", "denied", "expired", "failed"]);
84268
- var USAGE19 = [
84445
+ var USAGE18 = [
84269
84446
  "Usage: laze whatsapp chats <machine> [--limit <n>] the chats on the machine, newest first",
84270
84447
  " laze whatsapp read <machine> <chat> [--limit <n>] a chat's last messages, oldest first",
84271
84448
  ' laze whatsapp send <machine> <chat> "<text>" send as the owner; an agent waits for their approval',
@@ -84275,14 +84452,14 @@ var USAGE19 = [
84275
84452
  ].join("\n");
84276
84453
  function word2({ args, at }) {
84277
84454
  const value = args.words[at];
84278
- if (!value) throw new CliUsageError(USAGE19);
84455
+ if (!value) throw new CliUsageError(USAGE18);
84279
84456
  return value;
84280
84457
  }
84281
84458
  function limitOf5({ args }) {
84282
84459
  const text2 = flagText({ args, name: "limit" });
84283
84460
  if (!text2) return {};
84284
84461
  const limit = Number(text2);
84285
- if (!Number.isInteger(limit) || limit < 1) throw new CliUsageError(USAGE19);
84462
+ if (!Number.isInteger(limit) || limit < 1) throw new CliUsageError(USAGE18);
84286
84463
  return { limit };
84287
84464
  }
84288
84465
  async function chats({ context, args }) {
@@ -84344,7 +84521,7 @@ Still waiting. Run \`laze whatsapp status ${send4.id}\` later to see the answer.
84344
84521
  }
84345
84522
  async function send3({ context, args }) {
84346
84523
  const text2 = args.words.slice(4).join(" ") || args.rest.join(" ");
84347
- if (!text2) throw new CliUsageError(USAGE19);
84524
+ if (!text2) throw new CliUsageError(USAGE18);
84348
84525
  const client = await computeClient({ context, args });
84349
84526
  const asked = await client.post(PATHS3.send, {
84350
84527
  machine: word2({ args, at: 2 }),
@@ -84374,11 +84551,11 @@ async function whatsapp({
84374
84551
  if (command === "status") return status7({ context, args });
84375
84552
  const linking = whatsappPairingCommand(command);
84376
84553
  if (linking) return linking({ context, args });
84377
- throw new CliUsageError(USAGE19);
84554
+ throw new CliUsageError(USAGE18);
84378
84555
  }
84379
84556
 
84380
84557
  // src/services/wiki-commands.service.ts
84381
- var USAGE20 = `Usage:
84558
+ var USAGE19 = `Usage:
84382
84559
  laze wiki list
84383
84560
  laze wiki get <path>
84384
84561
  laze wiki put <path> <markdown|@file|-> [--title <title>] [--channel <channel>] [--base <version>]
@@ -84398,7 +84575,7 @@ async function wikiList({ context, args }) {
84398
84575
  }
84399
84576
  async function wikiGet({ context, args }) {
84400
84577
  const path = args.words[2];
84401
- if (!path) throw new CliUsageError(USAGE20);
84578
+ if (!path) throw new CliUsageError(USAGE19);
84402
84579
  const { client } = await signedIn({ context, args });
84403
84580
  const page = await client.post("/api/wiki/get", { path });
84404
84581
  if (args.flags.json) return context.out(`${JSON.stringify(page, null, 2)}
@@ -84415,7 +84592,7 @@ Linked from: ${page.backlinks.map((link) => link.path).join(", ")}
84415
84592
  async function wikiPut({ context, args }) {
84416
84593
  const path = args.words[2];
84417
84594
  const value = args.words.slice(3).join(" ");
84418
- if (!path || !value) throw new CliUsageError(USAGE20);
84595
+ if (!path || !value) throw new CliUsageError(USAGE19);
84419
84596
  const body = await textArgument({ context, value });
84420
84597
  const title = flagText({ args, name: "title" });
84421
84598
  const channel = flagText({ args, name: "channel" });
@@ -84435,7 +84612,7 @@ async function wikiPut({ context, args }) {
84435
84612
  }
84436
84613
  async function wikiSearch({ context, args }) {
84437
84614
  const query = args.words.slice(2).join(" ").trim();
84438
- if (!query) throw new CliUsageError(USAGE20);
84615
+ if (!query) throw new CliUsageError(USAGE19);
84439
84616
  const { client } = await signedIn({ context, args });
84440
84617
  const hits = await client.post("/api/wiki/search", { query });
84441
84618
  if (args.flags.json) return context.out(`${JSON.stringify(hits, null, 2)}
@@ -84445,7 +84622,7 @@ async function wikiSearch({ context, args }) {
84445
84622
  }
84446
84623
  async function wikiHistory({ context, args }) {
84447
84624
  const path = args.words[2];
84448
- if (!path) throw new CliUsageError(USAGE20);
84625
+ if (!path) throw new CliUsageError(USAGE19);
84449
84626
  const { client } = await signedIn({ context, args });
84450
84627
  const revisions = await client.post("/api/wiki/history", { path });
84451
84628
  if (args.flags.json) return context.out(`${JSON.stringify(revisions, null, 2)}
@@ -84459,7 +84636,7 @@ async function wikiHistory({ context, args }) {
84459
84636
  }
84460
84637
  async function wikiMove({ context, args }) {
84461
84638
  const [, , path, to] = args.words;
84462
- if (!path || !to) throw new CliUsageError(USAGE20);
84639
+ if (!path || !to) throw new CliUsageError(USAGE19);
84463
84640
  const { client } = await signedIn({ context, args });
84464
84641
  const page = await client.post("/api/wiki/move", { path, to });
84465
84642
  if (args.flags.json) return context.out(`${JSON.stringify(page, null, 2)}
@@ -84469,7 +84646,7 @@ async function wikiMove({ context, args }) {
84469
84646
  }
84470
84647
  async function wikiRemove({ context, args }) {
84471
84648
  const path = args.words[2];
84472
- if (!path) throw new CliUsageError(USAGE20);
84649
+ if (!path) throw new CliUsageError(USAGE19);
84473
84650
  const { client } = await signedIn({ context, args });
84474
84651
  const removed = await client.post("/api/wiki/remove", { path });
84475
84652
  if (args.flags.json) return context.out(`${JSON.stringify(removed)}
@@ -84489,7 +84666,7 @@ var WIKI_COMMANDS = {
84489
84666
  async function wiki({ context, args }) {
84490
84667
  const name2 = args.words[1] ?? "";
84491
84668
  const command = Object.hasOwn(WIKI_COMMANDS, name2) ? WIKI_COMMANDS[name2] : void 0;
84492
- if (!command) throw new CliUsageError(USAGE20);
84669
+ if (!command) throw new CliUsageError(USAGE19);
84493
84670
  await command({ context, args });
84494
84671
  }
84495
84672
 
@@ -85107,6 +85284,8 @@ var HELP = `laze: work in a Laze workspace from your terminal or your agent.
85107
85284
  laze adopt codex --status | --stop the background adopt that laze agent link started
85108
85285
  laze vault run <name> --reason "<why>" -- <cmd> run a command with a vault connection (agents)
85109
85286
  laze vault save <pending> --name <name> --description "<text>" name a key Laze held from a message (agents)
85287
+ laze vault save --from-message <id> --name <name> --description "<text>" save a key a person sent,
85288
+ read from stdin, to their own vault; the message keeps {{vault:<name>}} (agents, no vault access)
85110
85289
  laze vault scrub [--dry-run] move secrets found in messages to the vault now (admins)
85111
85290
  laze vault list|add|update|replace|compare|rm|revoke|uses your keychains with your own key
85112
85291
  a value comes from stdin or --from-file, never a flag; no command prints a value
@@ -85262,6 +85441,7 @@ var COMMANDS3 = {
85262
85441
  app,
85263
85442
  "vault run": vaultRun,
85264
85443
  "vault save": vaultSave,
85444
+ "vault save-from-message": vaultSaveFromMessage,
85265
85445
  connect,
85266
85446
  slack,
85267
85447
  "connect providers": connectAsPerson,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazehq/cli",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "description": "The Laze command line: sign in, read and post in chat, and connect your own Claude Code or Codex session as an agent.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",