@totalreclaw/totalreclaw 1.0.3 → 1.0.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
@@ -46,6 +46,7 @@ TotalReclaw also ships a standalone MCP server for Claude Desktop, Cursor, and o
46
46
  | `totalreclaw_forget` | Delete a specific memory (on-chain tombstone) |
47
47
  | `totalreclaw_export` | Export all memories as plaintext |
48
48
  | `totalreclaw_status` | Check subscription tier and quota |
49
+ | `totalreclaw_generate_recovery_phrase` | Generate a secure 12-word BIP-39 mnemonic (onboarding) |
49
50
 
50
51
  ## Lifecycle hooks
51
52
 
package/SKILL.md CHANGED
@@ -208,6 +208,28 @@ Check subscription status and usage quota.
208
208
 
209
209
  ---
210
210
 
211
+ ### totalreclaw_generate_recovery_phrase
212
+
213
+ Generate a cryptographically secure 12-word BIP-39 recovery phrase for new users. **Always use this tool** — never generate mnemonic words yourself.
214
+
215
+ **Parameters:** None
216
+
217
+ **Example:**
218
+ ```json
219
+ {}
220
+ ```
221
+
222
+ **Returns:**
223
+ ```json
224
+ {
225
+ "mnemonic": "abandon ability able about above absent absorb abstract absurd abuse access accident",
226
+ "wordCount": 12,
227
+ "instructions": ["Display this phrase prominently to the user.", "..."]
228
+ }
229
+ ```
230
+
231
+ ---
232
+
211
233
  ## Post-Install Setup
212
234
 
213
235
  After installing TotalReclaw, the agent MUST complete setup automatically. **Do NOT ask the user to set environment variables manually.**
@@ -227,7 +249,7 @@ The master password is a **12-word BIP-39 mnemonic** — like a crypto wallet se
227
249
  Ask the user:
228
250
  > "Do you have an existing TotalReclaw recovery phrase you'd like to restore, or should I generate a new one?"
229
251
 
230
- - **New user:** Generate a random 12-word BIP-39 mnemonic and set it as `TOTALRECLAW_MASTER_PASSWORD`. Then display it prominently with a warning:
252
+ - **New user:** Call the `totalreclaw_generate_recovery_phrase` tool to generate a cryptographically secure 12-word BIP-39 mnemonic. **NEVER generate mnemonic words yourself** — always use this tool. Then set it as `TOTALRECLAW_MASTER_PASSWORD` and display it prominently with a warning:
231
253
  > "⚠️ SAVE YOUR RECOVERY PHRASE — it's the only way to recover your memories if you switch devices: `[phrase]`"
232
254
  - **Returning user:** Ask them to provide their existing 12-word phrase, then set it as `TOTALRECLAW_MASTER_PASSWORD`.
233
255
 
package/dist/index.js CHANGED
@@ -9758,6 +9758,12 @@ function createHasher(hashCons, info = {}) {
9758
9758
  Object.assign(hashC, info);
9759
9759
  return Object.freeze(hashC);
9760
9760
  }
9761
+ function randomBytes(bytesLength = 32) {
9762
+ const cr = typeof globalThis === "object" ? globalThis.crypto : null;
9763
+ if (typeof cr?.getRandomValues !== "function")
9764
+ throw new Error("crypto.getRandomValues must be defined");
9765
+ return cr.getRandomValues(new Uint8Array(bytesLength));
9766
+ }
9761
9767
  var oidNist = (suffix) => ({
9762
9768
  oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
9763
9769
  });
@@ -11512,6 +11518,7 @@ var utils = {
11512
11518
  };
11513
11519
 
11514
11520
  // node_modules/@scure/bip39/index.js
11521
+ var isJapanese = (wordlist2) => wordlist2[0] === "\u3042\u3044\u3053\u304F\u3057\u3093";
11515
11522
  function nfkd(str) {
11516
11523
  if (typeof str !== "string")
11517
11524
  throw new TypeError("invalid mnemonic type: " + typeof str);
@@ -11529,6 +11536,12 @@ function aentropy(ent) {
11529
11536
  if (![16, 20, 24, 28, 32].includes(ent.length))
11530
11537
  throw new Error("invalid entropy length");
11531
11538
  }
11539
+ function generateMnemonic(wordlist2, strength = 128) {
11540
+ anumber(strength);
11541
+ if (strength % 32 !== 0 || strength > 256)
11542
+ throw new TypeError("Invalid entropy");
11543
+ return entropyToMnemonic(randomBytes(strength / 8), wordlist2);
11544
+ }
11532
11545
  var calcChecksum = (entropy) => {
11533
11546
  const bitsLeft = 8 - entropy.length / 4;
11534
11547
  return new Uint8Array([sha256(entropy)[0] >> bitsLeft << bitsLeft]);
@@ -11548,6 +11561,11 @@ function mnemonicToEntropy(mnemonic, wordlist2) {
11548
11561
  aentropy(entropy);
11549
11562
  return entropy;
11550
11563
  }
11564
+ function entropyToMnemonic(entropy, wordlist2) {
11565
+ aentropy(entropy);
11566
+ const words = getCoder(wordlist2).encode(entropy);
11567
+ return words.join(isJapanese(wordlist2) ? "\u3000" : " ");
11568
+ }
11551
11569
  function validateMnemonic(mnemonic, wordlist2) {
11552
11570
  try {
11553
11571
  mnemonicToEntropy(mnemonic, wordlist2);
@@ -13629,6 +13647,9 @@ function isBip39Mnemonic(input) {
13629
13647
  if (words.length !== 12 && words.length !== 24) return false;
13630
13648
  return validateMnemonic(input.trim(), wordlist);
13631
13649
  }
13650
+ function generateSecureMnemonic() {
13651
+ return generateMnemonic(wordlist, 128);
13652
+ }
13632
13653
  function deriveKeysFromMnemonic(mnemonic) {
13633
13654
  const seed = mnemonicToSeedSync(mnemonic.trim());
13634
13655
  const salt = Buffer.from(seed.slice(0, 32));
@@ -30952,7 +30973,7 @@ async function initialize(logger) {
30952
30973
  }
30953
30974
  }
30954
30975
  }
30955
- var SETUP_ERROR_MSG = 'TotalReclaw setup required. Follow the "Post-Install Setup" steps in SKILL.md:\n1. Set TOTALRECLAW_MASTER_PASSWORD \u2014 ask the user if they have an existing recovery phrase or generate a new 12-word BIP-39 mnemonic.\n2. Set TOTALRECLAW_SUBGRAPH_MODE=true\n3. Restart the gateway to apply changes.';
30976
+ var SETUP_ERROR_MSG = 'TotalReclaw setup required. Follow the "Post-Install Setup" steps in SKILL.md:\n1. Set TOTALRECLAW_MASTER_PASSWORD \u2014 ask the user if they have an existing recovery phrase, or call totalreclaw_generate_recovery_phrase to generate a secure one.\n2. Set TOTALRECLAW_SUBGRAPH_MODE=true\n3. Restart the gateway to apply changes.';
30956
30977
  async function ensureInitialized(logger) {
30957
30978
  if (!initPromise) {
30958
30979
  initPromise = initialize(logger);
@@ -31688,6 +31709,40 @@ ${lines.join("\n")}`;
31688
31709
  },
31689
31710
  { name: "totalreclaw_status" }
31690
31711
  );
31712
+ api.registerTool(
31713
+ {
31714
+ name: "totalreclaw_generate_recovery_phrase",
31715
+ label: "Generate Recovery Phrase",
31716
+ description: "Generate a cryptographically secure 12-word BIP-39 recovery phrase. Call this during onboarding when the user needs a new recovery phrase. NEVER generate mnemonics yourself \u2014 always use this tool.",
31717
+ parameters: {
31718
+ type: "object",
31719
+ properties: {},
31720
+ additionalProperties: false
31721
+ },
31722
+ execute() {
31723
+ const mnemonic = generateSecureMnemonic();
31724
+ return {
31725
+ content: [
31726
+ {
31727
+ type: "text",
31728
+ text: JSON.stringify({
31729
+ mnemonic,
31730
+ wordCount: 12,
31731
+ instructions: [
31732
+ "Display this phrase prominently to the user.",
31733
+ "Warn them to save it \u2014 it is the ONLY way to recover their memories.",
31734
+ "Set it as TOTALRECLAW_MASTER_PASSWORD in the OpenClaw config.",
31735
+ "Set TOTALRECLAW_SUBGRAPH_MODE=true.",
31736
+ "Restart the gateway to apply changes."
31737
+ ]
31738
+ })
31739
+ }
31740
+ ]
31741
+ };
31742
+ }
31743
+ },
31744
+ { name: "totalreclaw_generate_recovery_phrase" }
31745
+ );
31691
31746
  api.on(
31692
31747
  "before_agent_start",
31693
31748
  async (event) => {
@@ -31700,7 +31755,7 @@ ${lines.join("\n")}`;
31700
31755
  await ensureInitialized(api.logger);
31701
31756
  if (needsSetup) {
31702
31757
  return {
31703
- prependContext: '## TotalReclaw Setup Required\n\nTotalReclaw is installed but needs configuration. Follow the "Post-Install Setup" steps in SKILL.md to complete setup.\nAsk the user: "Do you have an existing TotalReclaw recovery phrase, or should I generate a new one?"'
31758
+ prependContext: '## TotalReclaw Setup Required\n\nTotalReclaw is installed but needs configuration. Follow the "Post-Install Setup" steps in SKILL.md to complete setup.\nAsk the user: "Do you have an existing TotalReclaw recovery phrase, or should I generate a new one?"\nIf they want a new one, call the `totalreclaw_generate_recovery_phrase` tool \u2014 NEVER generate mnemonic words yourself.'
31704
31759
  };
31705
31760
  }
31706
31761
  let billingWarning = "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totalreclaw/totalreclaw",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Zero-knowledge encrypted memory vault for AI agents — the password manager for AI memory.",
5
5
  "type": "module",
6
6
  "license": "MIT",