shinjuku-shielded 0.3.166 → 0.3.168

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
@@ -6,19 +6,19 @@ answers privately, in a terminal chat or for your agent app. Its `mcp`
6
6
  command runs a local MCP server (stdio) for your agent. Your keys never
7
7
  leave your machine.
8
8
 
9
- This is version 0.3.166. The npm packages `shinjuku-shield` and
9
+ This is version 0.3.168. The npm packages `shinjuku-shield` and
10
10
  `shinjuku-shielded` hold the same files. The command is `shinjuku`.
11
11
 
12
12
  ## Set up
13
13
 
14
14
  ```sh
15
- npm install -g shinjuku@0.3.166
15
+ npm install -g shinjuku@0.3.168
16
16
  shinjuku setup
17
17
  ```
18
18
 
19
19
  Type the two lines as they are. `npx install shinjuku` does not work: npx
20
20
  reads `install` as the name of another npm package. To set up without
21
- installing, type `npx shinjuku@0.3.166 setup`.
21
+ installing, type `npx shinjuku@0.3.168 setup`.
22
22
 
23
23
  Setup makes the wallet on this machine, a private passphrase file, and the
24
24
  checked proof tools (about 191 MB), and writes `config.json`. It also writes
@@ -36,13 +36,13 @@ Every wallet command works after `shinjuku`, for example `shinjuku balance`,
36
36
  Claude Code:
37
37
 
38
38
  ```sh
39
- claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.166 mcp
39
+ claude mcp add --scope user shinjuku -- npx -y --no-audit --no-fund shinjuku-shield@0.3.168 mcp
40
40
  ```
41
41
 
42
42
  Claude Desktop (`claude_desktop_config.json`) or Cursor (`~/.cursor/mcp.json`):
43
43
 
44
44
  ```json
45
- { "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.166", "mcp"] } } }
45
+ { "mcpServers": { "shinjuku": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.168", "mcp"] } } }
46
46
  ```
47
47
 
48
48
  On native Windows, if the host cannot find `npx`, use `"command": "cmd"` and
@@ -55,7 +55,7 @@ Codex (the Codex app and Codex CLI read the same file, `~/.codex/config.toml`):
55
55
  ```toml
56
56
  [mcp_servers.shinjuku]
57
57
  command = "npx"
58
- args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.166", "mcp"]
58
+ args = ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.168", "mcp"]
59
59
  startup_timeout_sec = 120
60
60
  tool_timeout_sec = 300
61
61
  ```
package/manifest.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schema": "carbon-shielded-wallet/bundle-manifest/v1",
3
3
  "file": "shinjuku-wallet.mjs",
4
- "sha256": "162d3a005e0491faedec0df58d95385a183a68993d209faa54e51dbdc2c81afb",
5
- "bytes": 9298964,
6
- "sourceCommit": "4d37fd634d7539d6289106ed611016d77dd7249f",
4
+ "sha256": "7320b9c07d69b0d94e0ee25c1821e1f674dde5964c65e84fe3de3be6c1ff7170",
5
+ "bytes": 9306006,
6
+ "sourceCommit": "f3e7665265b2adae937b45163fff7116c6c7bd00",
7
7
  "sourceDirty": false,
8
8
  "installRecordMatchesLockfile": true,
9
9
  "releaseRule": "valid only when two fresh npm ci --ignore-scripts builds on different OSes give the same sha256; installRecordMatchesLockfile true means every entry npm installed equals its package-lock.json entry and every entry not marked optional, devOptional included, is installed: an optional entry (a package for another platform) may be absent",
@@ -1038,5 +1038,5 @@
1038
1038
  "version": "1.8.0"
1039
1039
  }
1040
1040
  ],
1041
- "publishedAt": "2026-11-05T02:48:05.006Z"
1041
+ "publishedAt": "2026-11-05T04:16:16.938Z"
1042
1042
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "shinjuku-shielded",
3
- "version": "0.3.166",
3
+ "version": "0.3.168",
4
4
  "mcpName": "io.github.ShinjukuStaition/shinjuku-mcp",
5
5
  "description": "Shinjuku Shielded, the private x402 facilitator on Solana: the self-custody wallet CLI and its MCP server. Shield, pay, and unshield USDC from any MCP agent, under caps you set.",
6
- "shinjukuRelease": "162d3a00",
7
- "shinjukuSha256": "162d3a005e0491faedec0df58d95385a183a68993d209faa54e51dbdc2c81afb",
6
+ "shinjukuRelease": "7320b9c0",
7
+ "shinjukuSha256": "7320b9c07d69b0d94e0ee25c1821e1f674dde5964c65e84fe3de3be6c1ff7170",
8
8
  "license": "SEE LICENSE IN LICENSE.txt",
9
9
  "author": "Shinjuku Shielded",
10
10
  "homepage": "https://github.com/ShinjukuStaition/shinjuku-shield#readme",
@@ -53952,28 +53952,175 @@ var init_processLock = __esm({
53952
53952
  }
53953
53953
  });
53954
53954
 
53955
+ // wallet/src/setup/userPath.mjs
53956
+ import { spawnSync as spawnSync2 } from "node:child_process";
53957
+ import { basename as basename3, join as join8 } from "node:path";
53958
+ function commandFolder({ env = process.env, platform = process.platform } = {}) {
53959
+ const prefix = env.npm_config_global_prefix || env.npm_config_prefix;
53960
+ if (platform === "win32") return prefix || (env.APPDATA ? join8(env.APPDATA, "npm") : void 0);
53961
+ return prefix ? `${String(prefix).replace(/\/+$/, "")}/bin` : void 0;
53962
+ }
53963
+ function commandFileIn(folder, platform = process.platform) {
53964
+ if (!folder) return void 0;
53965
+ const file = join8(folder, platform === "win32" ? `${COMMAND_PACKAGE}.cmd` : COMMAND_PACKAGE);
53966
+ try {
53967
+ if (!statSync(file).isFile()) return void 0;
53968
+ if (platform !== "win32") accessSync(file, constants.X_OK);
53969
+ return file;
53970
+ } catch {
53971
+ return void 0;
53972
+ }
53973
+ }
53974
+ function shellPathEntries({ env = process.env, platform = process.platform } = {}) {
53975
+ const pathValue = env.PATH ?? env.Path ?? env.path ?? "";
53976
+ const entries = String(pathValue).split(platform === "win32" ? ";" : ":");
53977
+ let last = -1;
53978
+ entries.forEach((each, index) => {
53979
+ if (/[\\/]node-gyp-bin[\\/]*$/i.test(each.trim())) last = index;
53980
+ });
53981
+ return entries.slice(last + 1);
53982
+ }
53983
+ function folderOnPath(folder, { env = process.env, platform = process.platform } = {}) {
53984
+ const key = folderKey(folder, platform);
53985
+ return shellPathEntries({ env, platform }).some((each) => each.trim() && folderKey(each, platform) === key);
53986
+ }
53987
+ function addFolderToUserPath(folder, { run: run2 = spawnSync2, env = process.env } = {}) {
53988
+ let result;
53989
+ try {
53990
+ result = run2(
53991
+ "powershell.exe",
53992
+ [
53993
+ "-NoProfile",
53994
+ "-NonInteractive",
53995
+ "-ExecutionPolicy",
53996
+ "Bypass",
53997
+ "-EncodedCommand",
53998
+ Buffer.from(ADD_SCRIPT, "utf16le").toString("base64")
53999
+ ],
54000
+ { windowsHide: true, encoding: "utf8", timeout: 6e4, env: { ...env, SHINJUKU_PATH_FOLDER: folder } }
54001
+ );
54002
+ } catch {
54003
+ return { state: "failed", reason: "Windows PowerShell did not start" };
54004
+ }
54005
+ const line = String(result?.stdout ?? "").trim().split(/\r?\n/).reverse().find((each) => each.startsWith("{"));
54006
+ try {
54007
+ const answer = JSON.parse(line ?? "");
54008
+ if (["present", "added", "failed"].includes(answer?.state)) return answer;
54009
+ } catch {
54010
+ }
54011
+ return { state: "failed", reason: "Windows PowerShell gave no answer" };
54012
+ }
54013
+ function shellProfileLine(folder, { env = process.env, platform = process.platform } = {}) {
54014
+ const shell = basename3(String(env.SHELL ?? ""));
54015
+ if (shell === "fish") return { file: "~/.config/fish/config.fish", line: `fish_add_path '${String(folder).replace(/[\\']/g, "\\$&")}'` };
54016
+ const file = shell === "zsh" ? "~/.zshrc" : shell === "bash" ? platform === "darwin" ? "~/.bash_profile" : "~/.bashrc" : "~/.profile";
54017
+ return { file, line: `export PATH='${String(folder).replace(/'/g, "'\\''")}':"$PATH"` };
54018
+ }
54019
+ function commandPathStep({ env = process.env, platform = process.platform, run: run2 = spawnSync2 } = {}) {
54020
+ const folder = commandFolder({ env, platform });
54021
+ if (!commandFileIn(folder, platform)) return { state: "no-command", folder };
54022
+ if (platform !== "win32") {
54023
+ return folderOnPath(folder, { env, platform }) ? { state: "on-path", folder } : { state: "profile", folder, ...shellProfileLine(folder, { env, platform }) };
54024
+ }
54025
+ return { folder, ...addFolderToUserPath(folder, { run: run2, env }), thisWindow: folderOnPath(folder, { env, platform }) };
54026
+ }
54027
+ function pathStepSays(step) {
54028
+ return ["added", "failed", "profile"].includes(step?.state) || step?.state === "present" && step.thisWindow === false;
54029
+ }
54030
+ function commandPathLines(step, hereLine) {
54031
+ const here3 = ["In this window, type the longer command, for example:", ` ${hereLine}`];
54032
+ if (step?.state === "added") {
54033
+ return [step.broadcast === false ? "Added Shinjuku to your PATH. Sign out of Windows and in again, then type shinjuku in a new window." : "Added Shinjuku to your PATH. Open a new window to type shinjuku.", ...here3];
54034
+ }
54035
+ if (step?.state === "present") return ["Shinjuku is on your PATH. Open a new window to type shinjuku.", ...here3];
54036
+ if (step?.state === "failed") {
54037
+ return [
54038
+ `Setup could not add Shinjuku to your PATH (${step.reason}). To add it yourself: open Start, type environment variables, open "Edit environment variables for your account", pick Path, choose Edit, then New, and paste this folder:`,
54039
+ ` ${step.folder}`,
54040
+ "Then open a new window to type shinjuku.",
54041
+ ...here3
54042
+ ];
54043
+ }
54044
+ if (step?.state === "profile") {
54045
+ return [
54046
+ `Your terminal does not look in the folder where npm put the shinjuku command. Add this line to the end of ${step.file}, then open a new terminal to type shinjuku:`,
54047
+ ` ${step.line}`,
54048
+ ...here3
54049
+ ];
54050
+ }
54051
+ return [];
54052
+ }
54053
+ var folderKey, ADD_SCRIPT;
54054
+ var init_userPath = __esm({
54055
+ "wallet/src/setup/userPath.mjs"() {
54056
+ "use strict";
54057
+ init_fs();
54058
+ init_config();
54059
+ folderKey = (folder, platform) => {
54060
+ const key = String(folder).trim().replace(/^"(.*)"$/, "$1").replace(/[\\/]+$/, "");
54061
+ return platform === "win32" || platform === "darwin" ? key.toLowerCase() : key;
54062
+ };
54063
+ ADD_SCRIPT = String.raw`
54064
+ $ErrorActionPreference = 'Stop'
54065
+ $ProgressPreference = 'SilentlyContinue'
54066
+ $folder = $env:SHINJUKU_PATH_FOLDER
54067
+ function Key([string]$p) { ([Environment]::ExpandEnvironmentVariables($p.Trim().Trim('"'))).TrimEnd('\', '/').ToLowerInvariant() }
54068
+ try {
54069
+ $raw = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
54070
+ $want = Key $folder
54071
+ $machineKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SYSTEM\CurrentControlSet\Control\Session Manager\Environment')
54072
+ $machine = if ($machineKey) { [string]$machineKey.GetValue('Path', '', $raw) } else { '' }
54073
+ $key = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey('Environment')
54074
+ $user = $key.GetValue('Path', $null, $raw)
54075
+ $kind = if ($null -ne $user) { $key.GetValueKind('Path') } else { [Microsoft.Win32.RegistryValueKind]::ExpandString }
54076
+ $entries = @(([string]$user).Split(';')) + @($machine.Split(';'))
54077
+ if (@($entries | Where-Object { $_.Trim() -and (Key $_) -eq $want }).Count -gt 0) {
54078
+ '{"state":"present"}'; exit 0
54079
+ }
54080
+ if ($kind -ne [Microsoft.Win32.RegistryValueKind]::ExpandString -and $kind -ne [Microsoft.Win32.RegistryValueKind]::String) {
54081
+ '{"state":"failed","reason":"your PATH setting has a type setup does not change"}'; exit 0
54082
+ }
54083
+ $old = [string]$user
54084
+ $new = if ($old -eq '') { $folder } elseif ($old.EndsWith(';')) { $old + $folder } else { $old + ';' + $folder }
54085
+ if ($new.Length -ge 32767) { '{"state":"failed","reason":"your PATH setting is full"}'; exit 0 }
54086
+ $key.SetValue('Path', $new, $kind)
54087
+ if ([string]$key.GetValue('Path', '', $raw) -ne $new) { '{"state":"failed","reason":"the new PATH did not read back"}'; exit 0 }
54088
+ $broadcast = $false
54089
+ try {
54090
+ Add-Type -Namespace ShinjukuPath -Name Native -MemberDefinition '[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);'
54091
+ $result = [UIntPtr]::Zero
54092
+ $broadcast = [ShinjukuPath.Native]::SendMessageTimeout([IntPtr]0xffff, 0x1A, [UIntPtr]::Zero, 'Environment', 2, 5000, [ref]$result) -ne [IntPtr]::Zero
54093
+ } catch { $broadcast = $false }
54094
+ '{"state":"added","kind":"' + $kind + '","broadcast":' + $(if ($broadcast) { 'true' } else { 'false' }) + '}'
54095
+ } catch {
54096
+ '{"state":"failed","reason":"Windows did not let setup change your PATH setting"}'
54097
+ }
54098
+ `;
54099
+ }
54100
+ });
54101
+
53955
54102
  // wallet/src/setup/config.mjs
53956
54103
  import { execFileSync as execFileSync2 } from "node:child_process";
53957
54104
  import { randomBytes as randomBytes7 } from "node:crypto";
53958
54105
  import { homedir } from "node:os";
53959
- import { dirname as dirname6, isAbsolute as isAbsolute2, join as join8, resolve as resolve6 } from "node:path";
54106
+ import { dirname as dirname6, isAbsolute as isAbsolute2, join as join9, resolve as resolve6 } from "node:path";
53960
54107
  function retiredPoolText(pool2, npmVersion) {
53961
54108
  const next = RETIRED_POOLS[pool2];
53962
54109
  if (!next) return void 0;
53963
54110
  return `pool ${pool2} is retired: Shinjuku runs a newer pool now, and nothing serves the old pool. It held no user balance when it was retired. Your old wallet file stays where it is; run ${oneTimeCommandLine("setup", npmVersion)} to make a wallet for the new pool`;
53964
54111
  }
53965
54112
  function holdsWallet(dir) {
53966
- if (existsSync(join8(dir, CONFIG_FILE))) return true;
54113
+ if (existsSync(join9(dir, CONFIG_FILE))) return true;
53967
54114
  try {
53968
- return readdirSync(dir, { withFileTypes: true }).some((entry) => entry.isDirectory() && existsSync(join8(dir, entry.name, "wallet.json")));
54115
+ return readdirSync(dir, { withFileTypes: true }).some((entry) => entry.isDirectory() && existsSync(join9(dir, entry.name, "wallet.json")));
53969
54116
  } catch {
53970
54117
  return false;
53971
54118
  }
53972
54119
  }
53973
54120
  function setupHome(env = process.env, home = homedir()) {
53974
54121
  if (env.SHIELDED_WALLET_HOME) return resolve6(env.SHIELDED_WALLET_HOME);
53975
- const current = join8(home, HOME_FOLDER);
53976
- const older = join8(home, OLDER_HOME_FOLDER);
54122
+ const current = join9(home, HOME_FOLDER);
54123
+ const older = join9(home, OLDER_HOME_FOLDER);
53977
54124
  return !holdsWallet(current) && holdsWallet(older) ? older : current;
53978
54125
  }
53979
54126
  function checkConfig(value2) {
@@ -54067,7 +54214,7 @@ async function setAsideInvalidConfig(home, now = /* @__PURE__ */ new Date()) {
54067
54214
  function setAsideNow(home, now) {
54068
54215
  const path = configPath(home);
54069
54216
  const text3 = readFileSync(path, "utf8");
54070
- const keptAs = join8(home, `config.invalid-${now.toISOString().replace(/[:.]/g, "-")}.json`);
54217
+ const keptAs = join9(home, `config.invalid-${now.toISOString().replace(/[:.]/g, "-")}.json`);
54071
54218
  copyFileSync(path, keptAs, constants.COPYFILE_EXCL);
54072
54219
  rmSync(path);
54073
54220
  let loose;
@@ -54275,11 +54422,57 @@ function claudeCodeCommand(options = {}) {
54275
54422
  const platform = options.platform ?? process.platform;
54276
54423
  const gitBash = options.gitBash ?? inGitBash(options);
54277
54424
  const words2 = claudeCodeArgs(options).map((word, index, all) => gitBash && platform === "win32" && word === "/c" && all[index - 1] === "cmd" ? "//c" : word);
54278
- return ["claude", ...words2].map((word) => hostShellWord(word, platform)).join(" ");
54425
+ const program = claudeProgramWord(programOf(options), platform, options.shell ?? (gitBash ? "bash" : "cmd"));
54426
+ return program === void 0 ? void 0 : [program, ...words2.map((word) => hostShellWord(word, platform))].join(" ");
54427
+ }
54428
+ function claudeCodeProgram({ env = process.env, platform = process.platform, userHome = homedir(), isProgram = programFileAt } = {}) {
54429
+ const windows = platform === "win32";
54430
+ const pathValue = String(env.PATH ?? env.Path ?? "");
54431
+ if (windows) {
54432
+ const endings = String(env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").map((each) => each.trim()).filter(Boolean);
54433
+ for (const folder of pathValue.split(";").map((each) => each.trim().replace(/^"(.*)"$/, "$1")).filter(Boolean)) {
54434
+ if (endings.some((ending) => isProgram(join9(folder, `claude${ending.toLowerCase()}`), platform))) return "claude";
54435
+ }
54436
+ } else {
54437
+ for (const folder of pathValue.split(":")) {
54438
+ if (isProgram(join9(folder === "" ? "." : folder, "claude"), platform)) return "claude";
54439
+ }
54440
+ }
54441
+ const npmFolder = commandFolder({ env, platform });
54442
+ const places = windows ? [join9(env.USERPROFILE || userHome, ".local", "bin", "claude.exe"), ...npmFolder ? [join9(npmFolder, "claude.cmd")] : []] : [join9(userHome, ".local", "bin", "claude"), ...npmFolder ? [join9(npmFolder, "claude")] : []];
54443
+ return places.find((file) => isProgram(file, platform));
54444
+ }
54445
+ function programFileAt(file, platform = process.platform) {
54446
+ try {
54447
+ if (!statSync(file).isFile()) return false;
54448
+ if (platform !== "win32") accessSync(file, constants.X_OK);
54449
+ return true;
54450
+ } catch {
54451
+ return false;
54452
+ }
54453
+ }
54454
+ function claudeProgramWord(program, platform, shell = "cmd") {
54455
+ if (!program || program === "claude") return "claude";
54456
+ if (platform !== "win32") return hostShellWord(program, platform);
54457
+ const slashed = program.replace(/\\/g, "/");
54458
+ if (/^[A-Za-z0-9_./:=@-]+$/.test(slashed)) return slashed;
54459
+ if (shell === "bash") return hostShellWord(slashed, "linux");
54460
+ if (shell === "powershell") return `& '${program.replace(/'/g, "''")}'`;
54461
+ return CMD_UNSAFE.test(program) ? void 0 : `"${program}"`;
54462
+ }
54463
+ function claudeProgramRunWhy(program, platform = process.platform) {
54464
+ if (platform !== "win32" || !program || program === "claude" || /\.exe$/i.test(program) || !CMD_UNSAFE.test(program)) return null;
54465
+ return `its folder path (${program}) holds a character that cmd reads as code, so setup cannot start it`;
54279
54466
  }
54280
54467
  function claudeCodeLines(options = {}) {
54281
54468
  if ((options.platform ?? process.platform) !== "win32") return ["Claude Code (run once):", ` ${claudeCodeCommand(options)}`];
54282
- const powershell = ["Claude Code (run once; in PowerShell or cmd):", ` ${claudeCodeCommand({ ...options, gitBash: false })}`];
54469
+ const split4 = claudeLineDiffers(options);
54470
+ const cmdLine = claudeCodeCommand({ ...options, gitBash: false, shell: "cmd" });
54471
+ const powershell = split4 ? [
54472
+ "Claude Code (run once; in PowerShell):",
54473
+ ` ${claudeCodeCommand({ ...options, gitBash: false, shell: "powershell" })}`,
54474
+ ...cmdLine ? ["Claude Code (run once; in cmd):", ` ${cmdLine}`] : ["Claude Code in cmd: its folder path holds %, which cmd reads as code; use the PowerShell or Git Bash line."]
54475
+ ] : ["Claude Code (run once; in PowerShell or cmd):", ` ${cmdLine}`];
54283
54476
  const gitBash = ["Claude Code (run once; in Git Bash):", ` ${claudeCodeCommand({ ...options, gitBash: true })}`];
54284
54477
  return inGitBash(options) ? [...gitBash, ...powershell] : [...powershell, ...gitBash];
54285
54478
  }
@@ -54298,28 +54491,45 @@ function hostShellWord(word, platform = process.platform) {
54298
54491
  }
54299
54492
  function hostConfigFile(target, { platform = process.platform, env = process.env, home = homedir() } = {}) {
54300
54493
  const set = (name) => typeof env[name] === "string" && env[name].trim() ? env[name].trim() : void 0;
54301
- if (target === "cursor") return join8(home, ".cursor", "mcp.json");
54302
- if (target === "codex") return join8(env.CODEX_HOME || join8(home, ".codex"), "config.toml");
54494
+ if (target === "cursor") return join9(home, ".cursor", "mcp.json");
54495
+ if (target === "codex") return join9(env.CODEX_HOME || join9(home, ".codex"), "config.toml");
54303
54496
  if (target === "vscode") {
54304
- const appData = platform === "win32" ? env.APPDATA || join8(home, "AppData", "Roaming") : platform === "darwin" ? join8(home, "Library", "Application Support") : env.XDG_CONFIG_HOME || join8(home, ".config");
54305
- return join8(appData, "Code", "User", "mcp.json");
54497
+ const appData = platform === "win32" ? env.APPDATA || join9(home, "AppData", "Roaming") : platform === "darwin" ? join9(home, "Library", "Application Support") : env.XDG_CONFIG_HOME || join9(home, ".config");
54498
+ return join9(appData, "Code", "User", "mcp.json");
54306
54499
  }
54307
54500
  if (target === "devin") {
54308
- return join8(platform === "win32" ? join8(home, "AppData", "Roaming", "devin") : join8(env.XDG_CONFIG_HOME || join8(home, ".config"), "devin"), "mcp_config.json");
54501
+ return join9(platform === "win32" ? join9(home, "AppData", "Roaming", "devin") : join9(env.XDG_CONFIG_HOME || join9(home, ".config"), "devin"), "mcp_config.json");
54309
54502
  }
54310
54503
  if (target === "cline") {
54311
- return set("CLINE_MCP_SETTINGS_PATH") ?? join8(set("CLINE_DATA_DIR") ?? join8(set("CLINE_DIR") ?? join8(home, ".cline"), "data"), "settings", "cline_mcp_settings.json");
54504
+ return set("CLINE_MCP_SETTINGS_PATH") ?? join9(set("CLINE_DATA_DIR") ?? join9(set("CLINE_DIR") ?? join9(home, ".cline"), "data"), "settings", "cline_mcp_settings.json");
54312
54505
  }
54313
- if (target === "continue") return join8(set("CONTINUE_GLOBAL_DIR") ? resolve6(set("CONTINUE_GLOBAL_DIR")) : join8(home, ".continue"), "mcpServers", `${MCP_SERVER_NAME}.yaml`);
54314
- if (target === "gemini") return join8(set("GEMINI_CLI_HOME") ?? home, ".gemini", "settings.json");
54315
- if (target === "antigravity") return join8(home, ".gemini", "config", "mcp_config.json");
54506
+ if (target === "continue") return join9(set("CONTINUE_GLOBAL_DIR") ? resolve6(set("CONTINUE_GLOBAL_DIR")) : join9(home, ".continue"), "mcpServers", `${MCP_SERVER_NAME}.yaml`);
54507
+ if (target === "gemini") return join9(set("GEMINI_CLI_HOME") ?? home, ".gemini", "settings.json");
54508
+ if (target === "antigravity") return join9(home, ".gemini", "config", "mcp_config.json");
54316
54509
  if (target === "claude-desktop") {
54317
- if (platform === "win32") return join8(env.APPDATA || join8(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
54318
- if (platform === "darwin") return join8(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
54319
- return join8(env.XDG_CONFIG_HOME || join8(home, ".config"), "Claude", "claude_desktop_config.json");
54510
+ if (platform === "win32") return packagedClaudeDesktopFile(env, home) ?? join9(env.APPDATA || join9(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
54511
+ if (platform === "darwin") return join9(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
54512
+ return join9(env.XDG_CONFIG_HOME || join9(home, ".config"), "Claude", "claude_desktop_config.json");
54320
54513
  }
54321
54514
  return void 0;
54322
54515
  }
54516
+ function packagedClaudeDesktopFile(env, home) {
54517
+ const packages = join9(env.LOCALAPPDATA || join9(home, "AppData", "Local"), "Packages");
54518
+ let names;
54519
+ try {
54520
+ names = readdirSync(packages);
54521
+ } catch {
54522
+ return void 0;
54523
+ }
54524
+ const files = names.filter((each) => /^Claude_[a-z0-9]+$/i.test(each)).map((name) => join9(packages, name, "LocalCache", "Roaming", "Claude", "claude_desktop_config.json")).filter((file) => existsSync(file));
54525
+ if (files.length > 1) {
54526
+ throw Object.assign(
54527
+ new Error(`setup_host_config_ambiguous: this computer has ${files.length} Claude Desktop settings files (${files.join("; ")}), so the wallet did not pick one`),
54528
+ { files }
54529
+ );
54530
+ }
54531
+ return files[0];
54532
+ }
54323
54533
  function hostConfigText({ home, env = process.env, platform = process.platform, npmVersion, skip = /* @__PURE__ */ new Set(), userHome = homedir() } = {}) {
54324
54534
  const entry = mcpServerEntry({ home, platform, npmVersion });
54325
54535
  const more = ["vscode", "devin", "cline", "continue", "gemini", "antigravity"].filter((target) => !skip.has(target)).flatMap((target) => {
@@ -54332,7 +54542,10 @@ function hostConfigText({ home, env = process.env, platform = process.platform,
54332
54542
  ];
54333
54543
  });
54334
54544
  const member = `${JSON.stringify(MCP_SERVER_NAME)}: ${JSON.stringify(entry, null, 2)}`;
54335
- const files = [["claude-desktop", "Claude Desktop (claude_desktop_config.json)"], ["cursor", "Cursor (~/.cursor/mcp.json)"]].filter(([target]) => !skip.has(target)).map(([, label]) => label);
54545
+ const files = [
54546
+ ["claude-desktop", "Claude Desktop (claude_desktop_config.json: in Claude Desktop, Settings > Developer > Edit Config opens it)"],
54547
+ ["cursor", "Cursor (~/.cursor/mcp.json)"]
54548
+ ].filter(([target]) => !skip.has(target)).map(([, label]) => label);
54336
54549
  return [
54337
54550
  ...skip.has("claude-code") ? [] : claudeCodeShellWhy({ home, env, platform }) ? ["Claude Code:", ` ${claudeCodeShellWhy({ home, env, platform })}`] : claudeCodeLines({ home, env, platform, npmVersion }),
54338
54551
  ...files.length ? [
@@ -54340,7 +54553,7 @@ function hostConfigText({ home, env = process.env, platform = process.platform,
54340
54553
  ...member.split("\n").map((line) => ` ${line}`)
54341
54554
  ] : [],
54342
54555
  ...skip.has("codex") ? [] : [
54343
- "Codex (the Codex app and Codex CLI), at the end of ~/.codex/config.toml:",
54556
+ "Codex (the Codex side of the ChatGPT desktop app, and Codex CLI), at the end of ~/.codex/config.toml:",
54344
54557
  ...codexTomlBlock(entry).trimEnd().split("\n").map((line) => ` ${line}`)
54345
54558
  ],
54346
54559
  ...more
@@ -54658,12 +54871,12 @@ function isSameClaudeCodeEntry(existing, options = {}) {
54658
54871
  return entry !== void 0 && sameJson(entry, mcpServerEntry(options));
54659
54872
  }
54660
54873
  function restrictToOwnerWindows(file, { run: run2 = execFileSync2 } = {}) {
54661
- const system32 = join8(process.env.SystemRoot || "C:/Windows", "System32");
54874
+ const system32 = join9(process.env.SystemRoot || "C:/Windows", "System32");
54662
54875
  try {
54663
- const line = String(run2(join8(system32, "whoami.exe"), ["/user", "/fo", "csv", "/nh"], { encoding: "utf8", windowsHide: true }));
54876
+ const line = String(run2(join9(system32, "whoami.exe"), ["/user", "/fo", "csv", "/nh"], { encoding: "utf8", windowsHide: true }));
54664
54877
  const sid = line.match(/"(S-1-[0-9-]+)"/)?.[1];
54665
54878
  if (!sid) throw new Error("no sid");
54666
- run2(join8(system32, "icacls.exe"), [file, "/inheritance:r", "/grant:r", `*${sid}:F`], { stdio: "ignore", windowsHide: true });
54879
+ run2(join9(system32, "icacls.exe"), [file, "/inheritance:r", "/grant:r", `*${sid}:F`], { stdio: "ignore", windowsHide: true });
54667
54880
  } catch {
54668
54881
  throw new Error("setup_host_config_acl_failed: setup could not limit the file to only you on this computer (icacls), so it did not write it; add the printed entry by hand");
54669
54882
  }
@@ -54936,7 +55149,7 @@ function changeFileOnce(file, change, { now, platform, restrict, codec = JSON_CO
54936
55149
  }
54937
55150
  return { changed: true, ...backup ? { backup } : {} };
54938
55151
  }
54939
- var import_web396, CONFIG_SCHEMA, CONFIG_FILE, NPM_PACKAGE_NAMES, COMMAND_PACKAGE, NPX_PACKAGE, NPX_INSTALL_FLAGS, MCP_SERVER_NAME, OLD_MCP_SERVER_NAMES, P03_BINDING, PRODUCTION, RETIRED_POOLS, NO_LIMIT_ATOMIC, DEFAULT_CAPS, OLD_DEFAULT_SETUP_CAPS, OLD_DEFAULT_WALLET_BUDGETS, capText, POSITIVE_ATOMIC, HOME_FOLDER, OLDER_HOME_FOLDER, defaultHomeWords, configPath, homeWalletPath, invalid, isPubkey, MAX_OWN_ADDRESSES, isOwnAddressText, salvagePath, clearConfigSalvage, HOST_TARGETS, HOST_NAMES, hostServersKey, hostEntry, CODEX_STARTUP_TIMEOUT_SEC, CODEX_TOOL_TIMEOUT_SEC, PINNED_PACKAGE, LAUNCHER_PACKAGE, NPM_VERSION, knownNpmVersion, RECOVERY_WORDS, NPX_WALLET_LINE, RELEASES_URL, npmStartEnvironment, NPM_START_KEYS, defaultWalletHome, WINDOWS_SHELL_CODE, CONTINUE_HEADER, tomlString, tomlKey, codexEntryOf, isPlainObject, sameJson, claudeCodeEntry, READ_ONLY_TOOL_NAMES, claudeCodeAllowRules, claudeCodeSettingsFile, UNREADABLE_JSON, JSON_CODEC, indentAt, TEXT_CODEC, RACED;
55152
+ var import_web396, CONFIG_SCHEMA, CONFIG_FILE, NPM_PACKAGE_NAMES, COMMAND_PACKAGE, NPX_PACKAGE, NPX_INSTALL_FLAGS, MCP_SERVER_NAME, OLD_MCP_SERVER_NAMES, P03_BINDING, PRODUCTION, RETIRED_POOLS, NO_LIMIT_ATOMIC, DEFAULT_CAPS, OLD_DEFAULT_SETUP_CAPS, OLD_DEFAULT_WALLET_BUDGETS, capText, POSITIVE_ATOMIC, HOME_FOLDER, OLDER_HOME_FOLDER, defaultHomeWords, configPath, homeWalletPath, invalid, isPubkey, MAX_OWN_ADDRESSES, isOwnAddressText, salvagePath, clearConfigSalvage, HOST_TARGETS, HOST_NAMES, hostServersKey, hostEntry, CODEX_STARTUP_TIMEOUT_SEC, CODEX_TOOL_TIMEOUT_SEC, PINNED_PACKAGE, LAUNCHER_PACKAGE, NPM_VERSION, knownNpmVersion, RECOVERY_WORDS, NPX_WALLET_LINE, RELEASES_URL, npmStartEnvironment, NPM_START_KEYS, defaultWalletHome, CMD_UNSAFE, programOf, claudeLineDiffers, WINDOWS_SHELL_CODE, CONTINUE_HEADER, tomlString, tomlKey, codexEntryOf, isPlainObject, sameJson, claudeCodeEntry, READ_ONLY_TOOL_NAMES, claudeCodeAllowRules, claudeCodeSettingsFile, UNREADABLE_JSON, JSON_CODEC, indentAt, TEXT_CODEC, RACED;
54940
55153
  var init_config = __esm({
54941
55154
  "wallet/src/setup/config.mjs"() {
54942
55155
  "use strict";
@@ -54944,6 +55157,7 @@ var init_config = __esm({
54944
55157
  import_web396 = __toESM(require_index_cjs(), 1);
54945
55158
  init_rpcDefault();
54946
55159
  init_processLock();
55160
+ init_userPath();
54947
55161
  CONFIG_SCHEMA = "shinjuku-shielded/config/v1";
54948
55162
  CONFIG_FILE = "config.json";
54949
55163
  NPM_PACKAGE_NAMES = Object.freeze(["shinjuku-shield", "shinjuku-shielded"]);
@@ -54981,9 +55195,9 @@ var init_config = __esm({
54981
55195
  POSITIVE_ATOMIC = /^[1-9][0-9]{0,30}$/;
54982
55196
  HOME_FOLDER = ".shinjuku-shield";
54983
55197
  OLDER_HOME_FOLDER = ".carbon-shielded-wallet";
54984
- defaultHomeWords = (home = homedir()) => `~/${setupHome({}, home) === join8(home, HOME_FOLDER) ? HOME_FOLDER : OLDER_HOME_FOLDER}`;
54985
- configPath = (home) => join8(home, CONFIG_FILE);
54986
- homeWalletPath = (home, pool2) => join8(home, pool2, "wallet.json");
55198
+ defaultHomeWords = (home = homedir()) => `~/${setupHome({}, home) === join9(home, HOME_FOLDER) ? HOME_FOLDER : OLDER_HOME_FOLDER}`;
55199
+ configPath = (home) => join9(home, CONFIG_FILE);
55200
+ homeWalletPath = (home, pool2) => join9(home, pool2, "wallet.json");
54987
55201
  invalid = (why) => new Error(`setup_config_invalid: config.json ${why}; rerun shinjuku setup (it keeps the wallet) or fix the file`);
54988
55202
  isPubkey = (value2) => {
54989
55203
  try {
@@ -54994,7 +55208,7 @@ var init_config = __esm({
54994
55208
  };
54995
55209
  MAX_OWN_ADDRESSES = 8;
54996
55210
  isOwnAddressText = (value2) => isPubkey(value2);
54997
- salvagePath = (home) => join8(home, "config.salvage.json");
55211
+ salvagePath = (home) => join9(home, "config.salvage.json");
54998
55212
  clearConfigSalvage = (home) => rmSync(salvagePath(home), { force: true });
54999
55213
  HOST_TARGETS = Object.freeze(["claude-code", "claude-desktop", "cursor", "codex", "vscode", "devin", "cline", "continue", "gemini", "antigravity"]);
55000
55214
  HOST_NAMES = Object.freeze({
@@ -55023,6 +55237,9 @@ var init_config = __esm({
55023
55237
  npmStartEnvironment = (tor) => tor ? { npm_config_offline: "true" } : { npm_config_prefer_offline: "true" };
55024
55238
  NPM_START_KEYS = ["npm_config_offline", "npm_config_prefer_offline"];
55025
55239
  defaultWalletHome = (home = homedir()) => setupHome({}, home);
55240
+ CMD_UNSAFE = /[%"\r\n]/;
55241
+ programOf = (options) => "claudeProgram" in options ? options.claudeProgram : claudeCodeProgram(options);
55242
+ claudeLineDiffers = (options) => claudeProgramWord(programOf(options), "win32", "cmd") !== claudeProgramWord(programOf(options), "win32", "powershell");
55026
55243
  WINDOWS_SHELL_CODE = /[%$`"\r\n]/;
55027
55244
  CONTINUE_HEADER = Object.freeze(["name: Shinjuku Shield", "version: 0.0.1", "schema: v1", "mcpServers:"]);
55028
55245
  tomlString = (value2) => `"${String(value2).replace(/[\\"]/g, (c) => `\\${c}`).replace(/[\u0000-\u001f\u007f]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`)}"`;
@@ -55047,7 +55264,7 @@ var init_config = __esm({
55047
55264
  "inference_models"
55048
55265
  ]);
55049
55266
  claudeCodeAllowRules = () => READ_ONLY_TOOL_NAMES.map((name) => `mcp__${MCP_SERVER_NAME}__${name}`);
55050
- claudeCodeSettingsFile = ({ env = process.env, home = homedir() } = {}) => join8(env.CLAUDE_CONFIG_DIR || join8(home, ".claude"), "settings.json");
55267
+ claudeCodeSettingsFile = ({ env = process.env, home = homedir() } = {}) => join9(env.CLAUDE_CONFIG_DIR || join9(home, ".claude"), "settings.json");
55051
55268
  UNREADABLE_JSON = "setup_host_config_unreadable: the host's config file is not a JSON object, so setup left it alone; add the printed entry by hand";
55052
55269
  JSON_CODEC = Object.freeze({
55053
55270
  empty: () => ({}),
@@ -55085,7 +55302,7 @@ var init_config = __esm({
55085
55302
 
55086
55303
  // wallet/src/setup/channel.mjs
55087
55304
  import { createPublicKey as createPublicKey2, randomBytes as randomBytes8, verify } from "node:crypto";
55088
- import { join as join9 } from "node:path";
55305
+ import { join as join10 } from "node:path";
55089
55306
  function canonicalJson(value2) {
55090
55307
  if (value2 === null || typeof value2 !== "object") {
55091
55308
  if (typeof value2 === "number" && !Number.isFinite(value2)) throw fail7("wallet_channel_invalid", "the channel body holds a number JSON cannot carry");
@@ -55170,7 +55387,7 @@ function verifyChannelDocument(document2, { publicKeyHex = CHANNEL_PUBLIC_KEY_HE
55170
55387
  return checkBody(document2.body);
55171
55388
  }
55172
55389
  function readSeq(home) {
55173
- const path = join9(home, CHANNEL_SEQ_FILE);
55390
+ const path = join10(home, CHANNEL_SEQ_FILE);
55174
55391
  if (!existsSync(path)) return -1;
55175
55392
  let value2;
55176
55393
  try {
@@ -55198,9 +55415,9 @@ function acceptSeq(home, body, documentBytes) {
55198
55415
  throw fail7("wallet_channel_rollback", `Shinjuku serves channel ${body.seq}, older than channel ${seen} this wallet already saw; nothing was installed and the old setup files stay`);
55199
55416
  }
55200
55417
  mkdirSync(home, { recursive: true, mode: 448 });
55201
- if (body.seq > seen) writeAtomic(join9(home, CHANNEL_SEQ_FILE), `${JSON.stringify({ seq: body.seq })}
55418
+ if (body.seq > seen) writeAtomic(join10(home, CHANNEL_SEQ_FILE), `${JSON.stringify({ seq: body.seq })}
55202
55419
  `);
55203
- if (documentBytes) writeAtomic(join9(home, CHANNEL_FILE), documentBytes);
55420
+ if (documentBytes) writeAtomic(join10(home, CHANNEL_FILE), documentBytes);
55204
55421
  }
55205
55422
  function onChannelRegistered(listener) {
55206
55423
  registrationListeners.add(listener);
@@ -55275,7 +55492,7 @@ function applyStoredChannel({ home, publicKeyHex = CHANNEL_PUBLIC_KEY_HEX }) {
55275
55492
  } catch {
55276
55493
  return void 0;
55277
55494
  }
55278
- const path = join9(home, CHANNEL_FILE);
55495
+ const path = join10(home, CHANNEL_FILE);
55279
55496
  if (!existsSync(path)) return void 0;
55280
55497
  let document2;
55281
55498
  try {
@@ -61655,16 +61872,16 @@ var init_incremental = __esm({
61655
61872
  // wallet/src/history/walletHistory.mjs
61656
61873
  import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
61657
61874
  import { createHmac as createHmac5 } from "node:crypto";
61658
- import { dirname as dirname8, join as join10, resolve as resolve7 } from "node:path";
61875
+ import { dirname as dirname8, join as join11, resolve as resolve7 } from "node:path";
61659
61876
  function walletHistoryCache(store) {
61660
- return createHistoryCacheStore({ path: join10(dirname8(store.path), "history-cache.json"), hmacKey: historyCacheKey(store) });
61877
+ return createHistoryCacheStore({ path: join11(dirname8(store.path), "history-cache.json"), hmacKey: historyCacheKey(store) });
61661
61878
  }
61662
61879
  function walletSuccessorHistoryCache(store, pool2) {
61663
61880
  if (!/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(String(pool2))) throw new Error("wallet_succession_chain_invalid");
61664
- return createHistoryCacheStore({ path: join10(dirname8(store.path), `history-cache-successor-${pool2}.json`), hmacKey: historyCacheKey(store) });
61881
+ return createHistoryCacheStore({ path: join11(dirname8(store.path), `history-cache-successor-${pool2}.json`), hmacKey: historyCacheKey(store) });
61665
61882
  }
61666
61883
  function walletCompactHistoryCache(store) {
61667
- return createCompactHistoryCacheStore({ path: join10(dirname8(store.path), "history-compact-cache.json"), hmacKey: historyCacheKey(store) });
61884
+ return createCompactHistoryCacheStore({ path: join11(dirname8(store.path), "history-compact-cache.json"), hmacKey: historyCacheKey(store) });
61668
61885
  }
61669
61886
  async function loadWalletP03History(args) {
61670
61887
  const runKey = lastRunReportKey(args.store, args.programId, args.pool, args.deploymentIdentity, args.cache);
@@ -63210,7 +63427,7 @@ var init_production_proof_bundle = __esm({
63210
63427
  // wallet/src/prove/recoveredPayment.mjs
63211
63428
  import { spawn as spawn2 } from "node:child_process";
63212
63429
  import { createHash as createHash15 } from "node:crypto";
63213
- import { dirname as dirname10, isAbsolute as isAbsolute4, join as join11, relative as relative4, resolve as resolve10 } from "node:path";
63430
+ import { dirname as dirname10, isAbsolute as isAbsolute4, join as join12, relative as relative4, resolve as resolve10 } from "node:path";
63214
63431
  import { tmpdir as tmpdir2 } from "node:os";
63215
63432
  function fail9(reason) {
63216
63433
  throw new Error(`p03_recovered_payment_${reason}`);
@@ -63597,7 +63814,7 @@ async function proveRecoveredP03Payment({ request, tools, onMemoBundle }) {
63597
63814
  const bundle = loadBundle(tools);
63598
63815
  markPhase("bundle");
63599
63816
  const started = await takeEarlyTools(tools);
63600
- const scratch = started?.scratch ?? mkdtempSync(join11(tmpdir2(), "sx402-wallet-payment-"));
63817
+ const scratch = started?.scratch ?? mkdtempSync(join12(tmpdir2(), "sx402-wallet-payment-"));
63601
63818
  try {
63602
63819
  const { vectors, primaryProofs } = scratchDirectories(scratch);
63603
63820
  if (!started) {
@@ -63653,7 +63870,7 @@ async function proveRecoveredP03Payment({ request, tools, onMemoBundle }) {
63653
63870
  } catch {
63654
63871
  }
63655
63872
  markPhase("payment-prover", Number.isSafeInteger(ownMs) && ownMs >= 0 ? `proof_ms${ownMs}` : void 0);
63656
- const primary = JSON.parse(readFileSync(join11(primaryProofs, "shielded-exact-v2.json"), "utf8"));
63873
+ const primary = JSON.parse(readFileSync(join12(primaryProofs, "shielded-exact-v2.json"), "utf8"));
63657
63874
  if (JSON.stringify(primary.publicInputBytesHex) !== JSON.stringify(output2.primaryWitness.publicInputBytesHex)) {
63658
63875
  fail9("proof_public_inputs_mismatch");
63659
63876
  }
@@ -63689,7 +63906,7 @@ function startRecoveredPaymentTools(tools, { maxAgeMs = EARLY_TOOLS_MAX_AGE_MS }
63689
63906
  }
63690
63907
  async function launchEarlyTools(tools) {
63691
63908
  const bundle = loadBundle(tools);
63692
- const scratch = mkdtempSync(join11(tmpdir2(), "sx402-wallet-payment-"));
63909
+ const scratch = mkdtempSync(join12(tmpdir2(), "sx402-wallet-payment-"));
63693
63910
  const runs = [];
63694
63911
  const stop3 = async () => {
63695
63912
  for (const run2 of runs) run2.send("");
@@ -63744,10 +63961,10 @@ async function proveP03Vector({ tools, relation, vector }) {
63744
63961
  const [toolName, outputName] = RELATION_PROVERS[relation] ?? fail9("relation_invalid");
63745
63962
  const tool = tools[toolName] ?? fail9(`${toolName}_missing`);
63746
63963
  const bundle = loadBundle(tools);
63747
- const scratch = mkdtempSync(join11(tmpdir2(), "sx402-wallet-vector-"));
63964
+ const scratch = mkdtempSync(join12(tmpdir2(), "sx402-wallet-vector-"));
63748
63965
  try {
63749
- const vectorPath = join11(scratch, "vector.json");
63750
- const proofs = join11(scratch, "proof");
63966
+ const vectorPath = join12(scratch, "vector.json");
63967
+ const proofs = join12(scratch, "proof");
63751
63968
  mkdirSync(proofs, { mode: 448 });
63752
63969
  writeFileSync(vectorPath, jsonBytes(vector), { mode: 384 });
63753
63970
  try {
@@ -63760,7 +63977,7 @@ async function proveP03Vector({ tools, relation, vector }) {
63760
63977
  } catch (error) {
63761
63978
  throw new Error(`p03_recovered_payment_${relation.replaceAll("-", "_")}_prover_failed`, { cause: error });
63762
63979
  }
63763
- const proof = JSON.parse(readFileSync(join11(proofs, outputName), "utf8"));
63980
+ const proof = JSON.parse(readFileSync(join12(proofs, outputName), "utf8"));
63764
63981
  return Object.freeze({ proofBytesHex: proof.proofBytesHex, publicInputBytesHex: proof.publicInputBytesHex });
63765
63982
  } finally {
63766
63983
  removeScratch(scratch);
@@ -63789,9 +64006,9 @@ var init_recoveredPayment = __esm({
63789
64006
  ${stamp}`;
63790
64007
  bundleStamps = (files) => files.map((file) => fileStamp(file)).join("\n");
63791
64008
  OPTIONAL_TOOL_KEYS = /* @__PURE__ */ new Set(["depositProver", "solanaCli", "moveWitness", "moveProver"]);
63792
- scratchDirectories = (scratch) => ({ vectors: join11(scratch, "vectors"), primaryProofs: join11(scratch, "payment-proof") });
64009
+ scratchDirectories = (scratch) => ({ vectors: join12(scratch, "vectors"), primaryProofs: join12(scratch, "payment-proof") });
63793
64010
  paymentProverEnvironment = (bundle, vectors, primaryProofs) => ({
63794
- SHIELDED_X402_VECTOR_PATH: join11(vectors, "shielded-exact-v2.json"),
64011
+ SHIELDED_X402_VECTOR_PATH: join12(vectors, "shielded-exact-v2.json"),
63795
64012
  SHIELDED_X402_PRODUCTION_PROOF_DIR: primaryProofs,
63796
64013
  SHIELDED_X402_PARAMETER_MANIFEST_SHA256: bundle.manifestSha256,
63797
64014
  SHIELDED_X402_PARAMETER_PATH: bundle.relations["shielded-exact-v2"].parameterPath
@@ -65945,10 +66162,10 @@ var init_deposit = __esm({
65945
66162
 
65946
66163
  // wallet/src/store/sealedCache.mjs
65947
66164
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, createHmac as createHmac7, randomBytes as randomBytes11 } from "node:crypto";
65948
- import { dirname as dirname12, join as join12 } from "node:path";
66165
+ import { dirname as dirname12, join as join13 } from "node:path";
65949
66166
  function sealedCacheFile(store, { file, schema, keyLabel }) {
65950
66167
  if (typeof store?.path !== "string" || !/^[0-9a-f]{64}$/i.test(store?.state?.seedHex ?? "")) return void 0;
65951
- const path = join12(dirname12(store.path), file);
66168
+ const path = join13(dirname12(store.path), file);
65952
66169
  const key = createHmac7("sha256", Buffer.from(store.state.seedHex, "hex")).update(keyLabel).digest();
65953
66170
  const aad = Buffer.from(schema, "utf8");
65954
66171
  return Object.freeze({
@@ -66570,14 +66787,14 @@ var init_successorHistories = __esm({
66570
66787
 
66571
66788
  // wallet/src/recovery/recover.mjs
66572
66789
  import { createHash as createHash16 } from "node:crypto";
66573
- import { join as join13, resolve as resolve11 } from "node:path";
66790
+ import { join as join14, resolve as resolve11 } from "node:path";
66574
66791
  import { performance as performance4 } from "node:perf_hooks";
66575
66792
  import { fileURLToPath as fileURLToPath5 } from "node:url";
66576
66793
  function pinnedGenerator2(profileVector) {
66577
66794
  if (profileVector?.payerKeys?.generator) return profileVector.payerKeys.generator;
66578
66795
  if (!committedGenerator) {
66579
66796
  const committed2 = JSON.parse(readFileSync(
66580
- join13(MODEL_DIR, "vectors", "rust-vectors.json"),
66797
+ join14(MODEL_DIR, "vectors", "rust-vectors.json"),
66581
66798
  "utf8"
66582
66799
  ));
66583
66800
  committedGenerator = Object.freeze(committed2.payerKeys.generator);
@@ -75621,7 +75838,7 @@ var init_production_proof_bundle2 = __esm({
75621
75838
  // spikes/shielded-x402-wallet/lib/p03-recovered-exit.mjs
75622
75839
  import { spawn as spawn3 } from "node:child_process";
75623
75840
  import { createHash as createHash18 } from "node:crypto";
75624
- import { dirname as dirname14, isAbsolute as isAbsolute6, join as join14, relative as relative6, resolve as resolve14 } from "node:path";
75841
+ import { dirname as dirname14, isAbsolute as isAbsolute6, join as join15, relative as relative6, resolve as resolve14 } from "node:path";
75625
75842
  import { tmpdir as tmpdir3 } from "node:os";
75626
75843
  function fail15(reason) {
75627
75844
  throw new Error(`p03_recovered_exit_${reason}`);
@@ -75909,11 +76126,11 @@ function proveRecoveredP03Exit({ request, tools }) {
75909
76126
  return proveLoadedExit({ request, tools, kind, primaryProver, bundle });
75910
76127
  }
75911
76128
  async function proveLoadedExit({ request, tools, kind, primaryProver, bundle }) {
75912
- const scratch = mkdtempSync(join14(tmpdir3(), kind.scratchPrefix));
76129
+ const scratch = mkdtempSync(join15(tmpdir3(), kind.scratchPrefix));
75913
76130
  try {
75914
- const vectors = join14(scratch, "vectors");
75915
- const primaryProofs = join14(scratch, "primary-proof");
75916
- const appendProofs = join14(scratch, "append-proof");
76131
+ const vectors = join15(scratch, "vectors");
76132
+ const primaryProofs = join15(scratch, "primary-proof");
76133
+ const appendProofs = join15(scratch, "append-proof");
75917
76134
  mkdirSync(vectors, { recursive: true, mode: 448 });
75918
76135
  mkdirSync(primaryProofs, { recursive: true, mode: 448 });
75919
76136
  mkdirSync(appendProofs, { recursive: true, mode: 448 });
@@ -75931,10 +76148,10 @@ async function proveLoadedExit({ request, tools, kind, primaryProver, bundle })
75931
76148
  if (output2?.schema !== "carbon-shielded-x402/p03-recovered-exit-witness/v1" || output2.relation !== request.exitKind || output2.ownerRole !== kind.ownerRole) {
75932
76149
  fail15("witness_output_invalid");
75933
76150
  }
75934
- const primaryVector = join14(vectors, kind.vectorName);
76151
+ const primaryVector = join15(vectors, kind.vectorName);
75935
76152
  const appendVector = oneItemAppendVector(
75936
- join14(vectors, "tree-append-v1.json"),
75937
- join14(vectors, "tree-append-sequence.json")
76153
+ join15(vectors, "tree-append-v1.json"),
76154
+ join15(vectors, "tree-append-sequence.json")
75938
76155
  );
75939
76156
  try {
75940
76157
  await runTool2(primaryProver, [kind.command], {
@@ -75956,8 +76173,8 @@ async function proveLoadedExit({ request, tools, kind, primaryProver, bundle })
75956
76173
  } catch (error) {
75957
76174
  throw new Error("p03_recovered_exit_append_prover_phase_failed", { cause: error });
75958
76175
  }
75959
- const primary = JSON.parse(readFileSync(join14(primaryProofs, kind.proofName), "utf8"));
75960
- const append = JSON.parse(readFileSync(join14(appendProofs, "tree-append-v1-deposit.json"), "utf8"));
76176
+ const primary = JSON.parse(readFileSync(join15(primaryProofs, kind.proofName), "utf8"));
76177
+ const append = JSON.parse(readFileSync(join15(appendProofs, "tree-append-v1-deposit.json"), "utf8"));
75961
76178
  if (JSON.stringify(primary.publicInputBytesHex) !== JSON.stringify(output2.primaryWitness.publicInputBytesHex) || JSON.stringify(append.publicInputBytesHex) !== JSON.stringify(output2.treeAppendWitness.publicInputBytesHex)) {
75962
76179
  fail15("proof_public_inputs_mismatch");
75963
76180
  }
@@ -76018,13 +76235,13 @@ var init_p03_recovered_exit = __esm({
76018
76235
 
76019
76236
  // spikes/shielded-x402-wallet/bin/shielded-wallet.mjs
76020
76237
  import { createHash as createHash19 } from "node:crypto";
76021
- import { join as join15, resolve as resolve15 } from "node:path";
76238
+ import { join as join16, resolve as resolve15 } from "node:path";
76022
76239
  import { fileURLToPath as fileURLToPath7 } from "node:url";
76023
76240
  function walletHome() {
76024
76241
  return setupHome(process.env);
76025
76242
  }
76026
76243
  function walletPath(pool2) {
76027
- return join15(walletHome(), pool2, "wallet.json");
76244
+ return join16(walletHome(), pool2, "wallet.json");
76028
76245
  }
76029
76246
  function initialWalletState({ pool: pool2, network, asset, decimals, binding, config, keys: keys3, memoStart }) {
76030
76247
  const seedHex = keys3?.seedHex ?? Buffer.from(generateSeed()).toString("hex");
@@ -76082,16 +76299,16 @@ function readCallerJson(path, code2) {
76082
76299
  }
76083
76300
  function loadProfileDirectory(profileDir) {
76084
76301
  const directory = resolve15(profileDir);
76085
- const profile = readCallerJson(join15(directory, "profile.json"), "profile_json_invalid");
76086
- const vector = readCallerJson(join15(directory, "rust-vectors.json"), "profile_vectors_json_invalid");
76302
+ const profile = readCallerJson(join16(directory, "profile.json"), "profile_json_invalid");
76303
+ const vector = readCallerJson(join16(directory, "rust-vectors.json"), "profile_vectors_json_invalid");
76087
76304
  const production = profile.schema === "carbon-shielded-exact/svm-mainnet-bounded-alpha-profile/v4";
76088
- const artifactDir = join15(directory, production ? "proofs" : "artifacts");
76305
+ const artifactDir = join16(directory, production ? "proofs" : "artifacts");
76089
76306
  return { directory, profile, vector, production, artifactDir };
76090
76307
  }
76091
76308
  function pinnedGenerator3(profileVector) {
76092
76309
  if (profileVector?.payerKeys?.generator) return profileVector.payerKeys.generator;
76093
76310
  const committed2 = JSON.parse(readFileSync(
76094
- join15(MODEL_DIR2, "vectors", "rust-vectors.json"),
76311
+ join16(MODEL_DIR2, "vectors", "rust-vectors.json"),
76095
76312
  "utf8"
76096
76313
  ));
76097
76314
  return committed2.payerKeys.generator;
@@ -76251,7 +76468,7 @@ function proveFromProfile({ binding, profileDir }) {
76251
76468
  const proved = provePayment({
76252
76469
  binding,
76253
76470
  modelDir: MODEL_DIR2,
76254
- vectorPath: join15(resolve15(profileDir), "rust-vectors.json"),
76471
+ vectorPath: join16(resolve15(profileDir), "rust-vectors.json"),
76255
76472
  artifactDir,
76256
76473
  production: production ? {
76257
76474
  parameterPathByRelation: profile.parameterBundle?.parameterPathByRelation,
@@ -77549,7 +77766,7 @@ async function main(argv2 = process.argv.slice(2)) {
77549
77766
  case "backup-verify": {
77550
77767
  const pool2 = flag(args, "--pool") ?? requiredPoolFromHome();
77551
77768
  const backupDir = flag(args, "--backup-dir");
77552
- const path = backupDir ? join15(backupDir, "wallet.json") : walletPath(pool2);
77769
+ const path = backupDir ? join16(backupDir, "wallet.json") : walletPath(pool2);
77553
77770
  const store = openWalletStore(path, passphrase());
77554
77771
  if (store.state.pool !== pool2) throw new Error("backup-verify pool does not match wallet");
77555
77772
  const bundle = backupDir ? verifyWalletRecoveryBundle(backupDir, passphrase()) : void 0;
@@ -77715,7 +77932,7 @@ async function runValueMove(command, args) {
77715
77932
  const vault = vaultAddress(programId, pool2, mint);
77716
77933
  const poolState2 = await readPoolState(connection, pool2);
77717
77934
  if (!poolState2) throw new Error("pool account not found");
77718
- const readProof = (name) => JSON.parse(readFileSync(join15(artifactDir, name), "utf8"));
77935
+ const readProof = (name) => JSON.parse(readFileSync(join16(artifactDir, name), "utf8"));
77719
77936
  if (command === "deposit") {
77720
77937
  const proofName = production ? "deposit-v1.json" : "UNSAFE_TEST_ONLY-deposit-v1-proof.json";
77721
77938
  const appendName2 = production ? "tree-append-v1-deposit.json" : "UNSAFE_TEST_ONLY-tree-append-v1-deposit-proof.json";
@@ -78103,153 +78320,6 @@ var init_secretFile = __esm({
78103
78320
  }
78104
78321
  });
78105
78322
 
78106
- // wallet/src/setup/userPath.mjs
78107
- import { spawnSync as spawnSync2 } from "node:child_process";
78108
- import { basename as basename3, join as join16 } from "node:path";
78109
- function commandFolder({ env = process.env, platform = process.platform } = {}) {
78110
- const prefix = env.npm_config_global_prefix || env.npm_config_prefix;
78111
- if (platform === "win32") return prefix || (env.APPDATA ? join16(env.APPDATA, "npm") : void 0);
78112
- return prefix ? `${String(prefix).replace(/\/+$/, "")}/bin` : void 0;
78113
- }
78114
- function commandFileIn(folder, platform = process.platform) {
78115
- if (!folder) return void 0;
78116
- const file = join16(folder, platform === "win32" ? `${COMMAND_PACKAGE}.cmd` : COMMAND_PACKAGE);
78117
- try {
78118
- if (!statSync(file).isFile()) return void 0;
78119
- if (platform !== "win32") accessSync(file, constants.X_OK);
78120
- return file;
78121
- } catch {
78122
- return void 0;
78123
- }
78124
- }
78125
- function shellPathEntries({ env = process.env, platform = process.platform } = {}) {
78126
- const pathValue = env.PATH ?? env.Path ?? env.path ?? "";
78127
- const entries = String(pathValue).split(platform === "win32" ? ";" : ":");
78128
- let last = -1;
78129
- entries.forEach((each, index) => {
78130
- if (/[\\/]node-gyp-bin[\\/]*$/i.test(each.trim())) last = index;
78131
- });
78132
- return entries.slice(last + 1);
78133
- }
78134
- function folderOnPath(folder, { env = process.env, platform = process.platform } = {}) {
78135
- const key = folderKey(folder, platform);
78136
- return shellPathEntries({ env, platform }).some((each) => each.trim() && folderKey(each, platform) === key);
78137
- }
78138
- function addFolderToUserPath(folder, { run: run2 = spawnSync2, env = process.env } = {}) {
78139
- let result;
78140
- try {
78141
- result = run2(
78142
- "powershell.exe",
78143
- [
78144
- "-NoProfile",
78145
- "-NonInteractive",
78146
- "-ExecutionPolicy",
78147
- "Bypass",
78148
- "-EncodedCommand",
78149
- Buffer.from(ADD_SCRIPT, "utf16le").toString("base64")
78150
- ],
78151
- { windowsHide: true, encoding: "utf8", timeout: 6e4, env: { ...env, SHINJUKU_PATH_FOLDER: folder } }
78152
- );
78153
- } catch {
78154
- return { state: "failed", reason: "Windows PowerShell did not start" };
78155
- }
78156
- const line = String(result?.stdout ?? "").trim().split(/\r?\n/).reverse().find((each) => each.startsWith("{"));
78157
- try {
78158
- const answer = JSON.parse(line ?? "");
78159
- if (["present", "added", "failed"].includes(answer?.state)) return answer;
78160
- } catch {
78161
- }
78162
- return { state: "failed", reason: "Windows PowerShell gave no answer" };
78163
- }
78164
- function shellProfileLine(folder, { env = process.env, platform = process.platform } = {}) {
78165
- const shell = basename3(String(env.SHELL ?? ""));
78166
- if (shell === "fish") return { file: "~/.config/fish/config.fish", line: `fish_add_path '${String(folder).replace(/[\\']/g, "\\$&")}'` };
78167
- const file = shell === "zsh" ? "~/.zshrc" : shell === "bash" ? platform === "darwin" ? "~/.bash_profile" : "~/.bashrc" : "~/.profile";
78168
- return { file, line: `export PATH='${String(folder).replace(/'/g, "'\\''")}':"$PATH"` };
78169
- }
78170
- function commandPathStep({ env = process.env, platform = process.platform, run: run2 = spawnSync2 } = {}) {
78171
- const folder = commandFolder({ env, platform });
78172
- if (!commandFileIn(folder, platform)) return { state: "no-command", folder };
78173
- if (platform !== "win32") {
78174
- return folderOnPath(folder, { env, platform }) ? { state: "on-path", folder } : { state: "profile", folder, ...shellProfileLine(folder, { env, platform }) };
78175
- }
78176
- return { folder, ...addFolderToUserPath(folder, { run: run2, env }), thisWindow: folderOnPath(folder, { env, platform }) };
78177
- }
78178
- function pathStepSays(step) {
78179
- return ["added", "failed", "profile"].includes(step?.state) || step?.state === "present" && step.thisWindow === false;
78180
- }
78181
- function commandPathLines(step, hereLine) {
78182
- const here3 = ["In this window, type the longer command, for example:", ` ${hereLine}`];
78183
- if (step?.state === "added") {
78184
- return [step.broadcast === false ? "Added Shinjuku to your PATH. Sign out of Windows and in again, then type shinjuku in a new window." : "Added Shinjuku to your PATH. Open a new window to type shinjuku.", ...here3];
78185
- }
78186
- if (step?.state === "present") return ["Shinjuku is on your PATH. Open a new window to type shinjuku.", ...here3];
78187
- if (step?.state === "failed") {
78188
- return [
78189
- `Setup could not add Shinjuku to your PATH (${step.reason}). To add it yourself: open Start, type environment variables, open "Edit environment variables for your account", pick Path, choose Edit, then New, and paste this folder:`,
78190
- ` ${step.folder}`,
78191
- "Then open a new window to type shinjuku.",
78192
- ...here3
78193
- ];
78194
- }
78195
- if (step?.state === "profile") {
78196
- return [
78197
- `Your terminal does not look in the folder where npm put the shinjuku command. Add this line to the end of ${step.file}, then open a new terminal to type shinjuku:`,
78198
- ` ${step.line}`,
78199
- ...here3
78200
- ];
78201
- }
78202
- return [];
78203
- }
78204
- var folderKey, ADD_SCRIPT;
78205
- var init_userPath = __esm({
78206
- "wallet/src/setup/userPath.mjs"() {
78207
- "use strict";
78208
- init_fs();
78209
- init_config();
78210
- folderKey = (folder, platform) => {
78211
- const key = String(folder).trim().replace(/^"(.*)"$/, "$1").replace(/[\\/]+$/, "");
78212
- return platform === "win32" || platform === "darwin" ? key.toLowerCase() : key;
78213
- };
78214
- ADD_SCRIPT = String.raw`
78215
- $ErrorActionPreference = 'Stop'
78216
- $ProgressPreference = 'SilentlyContinue'
78217
- $folder = $env:SHINJUKU_PATH_FOLDER
78218
- function Key([string]$p) { ([Environment]::ExpandEnvironmentVariables($p.Trim().Trim('"'))).TrimEnd('\', '/').ToLowerInvariant() }
78219
- try {
78220
- $raw = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
78221
- $want = Key $folder
78222
- $machineKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SYSTEM\CurrentControlSet\Control\Session Manager\Environment')
78223
- $machine = if ($machineKey) { [string]$machineKey.GetValue('Path', '', $raw) } else { '' }
78224
- $key = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey('Environment')
78225
- $user = $key.GetValue('Path', $null, $raw)
78226
- $kind = if ($null -ne $user) { $key.GetValueKind('Path') } else { [Microsoft.Win32.RegistryValueKind]::ExpandString }
78227
- $entries = @(([string]$user).Split(';')) + @($machine.Split(';'))
78228
- if (@($entries | Where-Object { $_.Trim() -and (Key $_) -eq $want }).Count -gt 0) {
78229
- '{"state":"present"}'; exit 0
78230
- }
78231
- if ($kind -ne [Microsoft.Win32.RegistryValueKind]::ExpandString -and $kind -ne [Microsoft.Win32.RegistryValueKind]::String) {
78232
- '{"state":"failed","reason":"your PATH setting has a type setup does not change"}'; exit 0
78233
- }
78234
- $old = [string]$user
78235
- $new = if ($old -eq '') { $folder } elseif ($old.EndsWith(';')) { $old + $folder } else { $old + ';' + $folder }
78236
- if ($new.Length -ge 32767) { '{"state":"failed","reason":"your PATH setting is full"}'; exit 0 }
78237
- $key.SetValue('Path', $new, $kind)
78238
- if ([string]$key.GetValue('Path', '', $raw) -ne $new) { '{"state":"failed","reason":"the new PATH did not read back"}'; exit 0 }
78239
- $broadcast = $false
78240
- try {
78241
- Add-Type -Namespace ShinjukuPath -Name Native -MemberDefinition '[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);'
78242
- $result = [UIntPtr]::Zero
78243
- $broadcast = [ShinjukuPath.Native]::SendMessageTimeout([IntPtr]0xffff, 0x1A, [UIntPtr]::Zero, 'Environment', 2, 5000, [ref]$result) -ne [IntPtr]::Zero
78244
- } catch { $broadcast = $false }
78245
- '{"state":"added","kind":"' + $kind + '","broadcast":' + $(if ($broadcast) { 'true' } else { 'false' }) + '}'
78246
- } catch {
78247
- '{"state":"failed","reason":"Windows did not let setup change your PATH setting"}'
78248
- }
78249
- `;
78250
- }
78251
- });
78252
-
78253
78323
  // wallet/src/cli/commandName.mjs
78254
78324
  import { spawnSync as spawnSync3 } from "node:child_process";
78255
78325
  import { basename as basename4, dirname as dirname15, join as join17 } from "node:path";
@@ -142299,7 +142369,7 @@ var init_tools = __esm({
142299
142369
  "--max-shield / --max-unshield": "shield and unshield limits"
142300
142370
  };
142301
142371
  capName = (flag3) => CAP_NAMES[flag3] ?? "spending limit";
142302
- entryPlaces = (change) => `Where the entry is: Claude Desktop: claude_desktop_config.json; Cursor: ~/.cursor/mcp.json; Claude Code: claude mcp get ${MCP_SERVER_NAME} shows the entry (an entry added by hand can have another name: claude mcp list shows it), then claude mcp remove ${MCP_SERVER_NAME} and claude mcp add it again ${change}; Hermes: config.yaml.`;
142372
+ entryPlaces = (change) => `Where the entry is: Claude Desktop: claude_desktop_config.json (Settings > Developer > Edit Config opens it); Cursor: ~/.cursor/mcp.json; Claude Code: claude mcp get ${MCP_SERVER_NAME} shows the entry (an entry added by hand can have another name: claude mcp list shows it), then claude mcp remove ${MCP_SERVER_NAME} and claude mcp add it again ${change}; Hermes: config.yaml.`;
142303
142373
  capRaiseText = (flag3) => {
142304
142374
  if (capFlagFromLaunchLine(flag3)) {
142305
142375
  const both = flag3 === "--max-payment" ? " (raise the 24-hour payment limit there too when it is below the new amount: the wallet does not start with it lower)" : "";
@@ -156835,7 +156905,13 @@ function claudeCodeState(env, home) {
156835
156905
  }
156836
156906
  function agentHostsOf(env, home) {
156837
156907
  const jsonHost = (target) => {
156838
- const config = readJsonFile(hostConfigFile(target, { env, home: homedir3() }));
156908
+ let file;
156909
+ try {
156910
+ file = hostConfigFile(target, { env, home: homedir3() });
156911
+ } catch {
156912
+ return null;
156913
+ }
156914
+ const config = readJsonFile(file);
156839
156915
  return config === void 0 ? false : config === null ? null : runsThisWallet(config[hostServersKey(target)], home);
156840
156916
  };
156841
156917
  const continueHost = () => {
@@ -159631,7 +159707,7 @@ function agentAppLines({ skip = /* @__PURE__ */ new Set() }) {
159631
159707
  function hostLines(targets) {
159632
159708
  const commands = targets.map((target) => `${setupCli2()} setup --add-to ${target}`);
159633
159709
  const width = Math.max(...commands.map((command) => command.length));
159634
- const label = { codex: "Codex (the Codex app or Codex CLI)", devin: "Devin Desktop (the app that was Windsurf)", vscode: "VS Code (GitHub Copilot)" };
159710
+ const label = { codex: "Codex (the ChatGPT desktop app's Codex side, or Codex CLI)", devin: "Devin Desktop (the app that was Windsurf)", vscode: "VS Code (GitHub Copilot)" };
159635
159711
  return targets.map((target, index) => ` ${commands[index].padEnd(width)} ${label[target] ?? HOST_NAMES[target]}`);
159636
159712
  }
159637
159713
  function setupNextText({ home, deps, npmVersion, config, fundAsked, rerun, targets = [], added = /* @__PURE__ */ new Set() }) {
@@ -160056,7 +160132,33 @@ function claudeCodeEntryOf(deps) {
160056
160132
  return void 0;
160057
160133
  }
160058
160134
  }
160135
+ function runClaude(args, program = "claude", stdio = "inherit") {
160136
+ const options = { stdio, windowsHide: true, timeout: 12e4 };
160137
+ const programWord = program === "claude" ? program : `"${program}"`;
160138
+ const result = process.platform === "win32" && !/\.exe$/i.test(program) ? spawnSync10([programWord, ...args.map((word) => hostShellWord(word, "win32"))].join(" "), { ...options, shell: true }) : spawnSync10(program, args, options);
160139
+ return result.status ?? 1;
160140
+ }
160141
+ function claudeRemoveLines(program, platform) {
160142
+ const tail = `mcp remove --scope user ${MCP_SERVER_NAME}`;
160143
+ const shells = platform === "win32" ? ["powershell", "cmd", "bash"] : ["bash"];
160144
+ const words2 = shells.map((shell) => claudeProgramWord(program, platform, shell));
160145
+ if (new Set(words2).size === 1) return ` ${words2[0]} ${tail}`;
160146
+ const names = { powershell: "PowerShell", cmd: "cmd", bash: "Git Bash" };
160147
+ return shells.map((shell, index) => words2[index] === void 0 ? void 0 : ` In ${names[shell]}:
160148
+ ${words2[index]} ${tail}`).filter((line) => line !== void 0).join("\n");
160149
+ }
160059
160150
  var RESTART_APP = (app) => `If ${app} is open now, quit it and start it again.`;
160151
+ function hostAddedNext(target, app, platform) {
160152
+ const ask = 'then ask in plain words, for example "what is my Shinjuku balance".';
160153
+ if (target === "claude-desktop") {
160154
+ const quit = platform === "win32" ? "If Claude Desktop is open now, quit it: right-click its icon by the clock and choose Quit (closing its window does not quit it). Then open it again" : platform === "darwin" ? "If Claude Desktop is open now, quit it (Claude > Quit Claude, or Command+Q) and open it again" : `${RESTART_APP(app).slice(0, -1)}`;
160155
+ return `${quit}. In a new chat, click + and choose Connectors to see Shinjuku there, ${ask}`;
160156
+ }
160157
+ if (target === "codex") {
160158
+ return `If the ChatGPT desktop app or Codex CLI is open now, quit it and start it again. In the app, use its Codex side (ChatGPT's own chat cannot start a server on this computer). In Codex, type /mcp to see the wallet's tools, ${ask}`;
160159
+ }
160160
+ return RESTART_APP(app);
160161
+ }
160060
160162
  function allowWalletChecks(deps) {
160061
160163
  const file = claudeCodeSettingsFile({ env: deps.env, home: deps.homedir() });
160062
160164
  try {
@@ -160150,7 +160252,23 @@ async function addToHosts(targets, home, deps, { force = false, npmVersion, ask,
160150
160252
  `);
160151
160253
  continue;
160152
160254
  }
160153
- const quiet = deps.runClaudeCliQuiet ?? deps.runClaudeCli;
160255
+ const claudeProgram = claudeCodeProgram({ env: deps.env ?? process.env, platform: options.platform, userHome: deps.homedir() });
160256
+ const claudeOptions = { ...options, userHome: deps.homedir() };
160257
+ if (claudeProgram === void 0) {
160258
+ io.out(`Not added to Claude Code: its command, claude, is not on this computer's PATH and not in the folders where Claude Code's installers put it (${options.platform === "win32" ? "%USERPROFILE%\\.local\\bin, or npm's folder" : "~/.local/bin"}). If Claude Code is not installed, install it (https://code.claude.com/docs/en/setup), then do this step again. If it is in another folder, run this line in a window where claude works:
160259
+ ${claudeCodeCommand({ ...claudeOptions, claudeProgram: "claude" })}
160260
+ `);
160261
+ continue;
160262
+ }
160263
+ const runWhy = claudeProgramRunWhy(claudeProgram, options.platform);
160264
+ if (runWhy) {
160265
+ io.out(`Not added to Claude Code: ${runWhy}. Run this yourself:
160266
+ ${claudeCodeLines({ ...claudeOptions, claudeProgram }).map((line) => ` ${line}`).join("\n")}
160267
+ `);
160268
+ continue;
160269
+ }
160270
+ const quiet = (args) => (deps.runClaudeCliQuiet ?? deps.runClaudeCli)(args, claudeProgram);
160271
+ const runClaudeCli = (args) => deps.runClaudeCli(args, claudeProgram);
160154
160272
  for (const old of OLD_MCP_SERVER_NAMES) {
160155
160273
  if (quiet(["mcp", "remove", "--scope", "user", old]) === 0) io.out(`Replaced the old ${old} entry in Claude Code.
160156
160274
  `);
@@ -160173,9 +160291,9 @@ async function addToHosts(targets, home, deps, { force = false, npmVersion, ask,
160173
160291
  continue;
160174
160292
  }
160175
160293
  const replacedOther = replace === true && quiet(["mcp", "remove", "--scope", "user", MCP_SERVER_NAME]) === 0;
160176
- let status = deps.runClaudeCli(claudeCodeArgs(options));
160294
+ let status = runClaudeCli(claudeCodeArgs(options));
160177
160295
  const removed = olderOwn || replacedOther || status !== 0 && force && quiet(["mcp", "remove", "--scope", "user", MCP_SERVER_NAME]) === 0;
160178
- if (removed && status !== 0) status = deps.runClaudeCli(claudeCodeArgs(options));
160296
+ if (removed && status !== 0) status = runClaudeCli(claudeCodeArgs(options));
160179
160297
  if (status === 0) done.add(target);
160180
160298
  const check = status === 0 ? await hostStartCheck("Claude Code", options, deps, { terminal: true, noTor }) : void 0;
160181
160299
  if (check && !check.ok) io.out(`${hostCheckWords("Claude Code", check)}
@@ -160183,15 +160301,23 @@ async function addToHosts(targets, home, deps, { force = false, npmVersion, ask,
160183
160301
  const homeNow = replacedOther ? ` Claude Code now uses the wallet in ${home}; the wallet in ${otherHome} is unchanged.` : "";
160184
160302
  io.out(status === 0 ? `${removed ? "Replaced the wallet in" : "Added the wallet to"} Claude Code, for all your folders.${homeNow} ${allowWalletChecks(deps).say} ${RESTART_APP("Claude Code")}
160185
160303
  ` : `Claude Code did not take the server; its message is above. Run this yourself:
160186
- ${claudeCodeCommand(options)}
160304
+ ${claudeCodeLines({ ...claudeOptions, claudeProgram }).map((line) => ` ${line}`).join("\n")}
160187
160305
  ` + (removed ? `Setup removed the old ${MCP_SERVER_NAME} entry first, so Claude Code has none until that line runs.
160188
160306
  ` : `If it says the server already exists, remove that entry with this command, then run the line above:
160189
- claude mcp remove --scope user ${MCP_SERVER_NAME}
160307
+ ${claudeRemoveLines(claudeProgram, options.platform)}
160190
160308
  `));
160191
160309
  continue;
160192
160310
  }
160193
- const file = hostConfigFile(target, { ...options, home: deps.homedir() });
160194
160311
  const app = HOST_NAMES[target];
160312
+ let file;
160313
+ try {
160314
+ file = hostConfigFile(target, { ...options, home: deps.homedir() });
160315
+ } catch (error) {
160316
+ if (!String(error?.message).startsWith("setup_host_config_ambiguous:")) throw error;
160317
+ io.out(`Not added to ${app}: this computer has more than one ${app} settings file (${error.files.join("; ")}), so the wallet did not pick one. In ${app}, Settings > Developer > Edit Config opens the file it reads: add the entry below to it by hand.
160318
+ `);
160319
+ continue;
160320
+ }
160195
160321
  const first = torOn ? await hostStartCheck(app, options, deps, { terminal: false, noTor }) : void 0;
160196
160322
  if (first && !first.ok) {
160197
160323
  io.out(`Not added to ${app}: ${hostCheckWords(app, first)}
@@ -160205,8 +160331,8 @@ async function addToHosts(targets, home, deps, { force = false, npmVersion, ask,
160205
160331
  `);
160206
160332
  const check = await hostStartCheck(app, options, deps, { terminal: false, noTor });
160207
160333
  if (check.path) added = { ...write(mcpServerEntry({ ...options, path: check.path }), false), changed: true };
160208
- io.out(!added.changed ? `${app} already has the wallet: ${file} (nothing changed).${check.ok ? ` ${app} starts it (checked).` : ""}
160209
- ` : `Added the wallet to ${app}: ${file}${added.backup ? ` (the old file was copied to ${added.backup}, readable by you alone)` : ""}.${check.ok ? ` ${app} starts it (checked).` : ""} ${RESTART_APP(target === "codex" ? "the Codex app or Codex CLI" : app)}${target === "codex" ? ` In Codex, type /mcp to see the wallet's tools, then ask in plain words, for example "what is my Shinjuku balance".` : ""}
160334
+ io.out(!added.changed ? `${app} already has the wallet: ${file} (nothing changed).${check.ok ? ` ${app} starts it (checked).` : ""} If ${app} does not show the wallet yet: ${hostAddedNext(target, app, options.platform)}
160335
+ ` : `Added the wallet to ${app}: ${file}${added.backup ? ` (the old file was copied to ${added.backup}, readable by you alone)` : ""}.${check.ok ? ` ${app} starts it (checked).` : ""} ${hostAddedNext(target, app, options.platform)}
160210
160336
  `);
160211
160337
  if (!check.ok) io.out(`${hostCheckWords(app, check)}
160212
160338
  `);
@@ -161593,7 +161719,7 @@ var COMMANDS = [
161593
161719
  "Your own --passphrase-file must be private: on Linux and macOS setup refuses a file that group or other may read or write, or that another user owns (setup_passphrase_file_insecure: chmod 600 <file>). On Windows setup cannot read the access list; it accepts the file with a warning.",
161594
161720
  `--add-to writes each app's own user file: vscode (VS Code with Copilot) mcp.json in VS Code's User folder, under "servers"; devin (Devin Desktop, the app that was Windsurf) mcp_config.json in AppData\\Roaming\\devin on Windows, else ~/.config/devin; cline ~/.cline/data/settings/cline_mcp_settings.json (or CLINE_MCP_SETTINGS_PATH, CLINE_DATA_DIR, CLINE_DIR); continue its own block file ~/.continue/mcpServers/shinjuku.yaml (or in CONTINUE_GLOBAL_DIR); gemini (Gemini CLI) ~/.gemini/settings.json (or in GEMINI_CLI_HOME); antigravity (Antigravity) ~/.gemini/config/mcp_config.json. Every other key and server in a file stays as it is.`,
161595
161721
  `--add-to for a JSON file (Claude Desktop, Cursor and the apps above): a host config whose server list is not a JSON object, or that has a different ${MCP_SERVER_NAME} entry (without --force), is left alone. Otherwise the old file is copied to <file>.bak-<time> (mode 0600 on Linux and macOS; on Windows the folder's access list) and the new file replaces it in one rename. An entry an older setup wrote (no version, another version, or an old package name, shinjuku or shinjuku-shielded; the same home) is replaced without --force, in a JSON host and in Claude Code. An entry under an old key (${OLD_MCP_SERVER_NAMES.join(" or ")}) is replaced by itself, in every host, so the host never starts two wallet servers. For Claude Code, a different ${MCP_SERVER_NAME} server (not an older entry of this wallet) needs --force.`,
161596
- `--add-to codex: the Codex app and Codex CLI read one file, config.toml in CODEX_HOME (else ~/.codex). Setup writes the [mcp_servers.${MCP_SERVER_NAME}] tables at its end with startup_timeout_sec = 120 (a first start downloads the wallet) and tool_timeout_sec = 300, and keeps every other line; the same rules as a JSON host (a different entry stays without --force; the old file is backed up first). Then type /mcp in Codex to see the tools.`,
161722
+ `--add-to codex: the ChatGPT desktop app (its Codex side) and Codex CLI read one file, config.toml in CODEX_HOME (else ~/.codex). Setup writes the [mcp_servers.${MCP_SERVER_NAME}] tables at its end with startup_timeout_sec = 120 (a first start downloads the wallet) and tool_timeout_sec = 300, and keeps every other line; the same rules as a JSON host (a different entry stays without --force; the old file is backed up first). Then type /mcp in Codex to see the tools.`,
161597
161723
  "The proof programs run natively: Windows x64, Linux x64 and Linux arm64 each download their own set (no WSL). Setup downloads the programs first and starts each one once before it makes a key; when Windows app control or an antivirus blocks one, setup stops and says which. macOS and other systems: not supported yet; setup says so and creates nothing.",
161598
161724
  "Run it again at any time: it never changes an existing wallet, keeps the recorded caps unless you pass new ones, checks every setup file again, downloads what is missing or newer, and rewrites config.json.",
161599
161725
  `A wallet that ${SETUP_CLI_WORD} restore made and did not read back yet (the restore stopped): setup reads its money back from the chain in place of the add-money question, so setup finishes that restore.`,
@@ -165386,16 +165512,8 @@ function defaultDependencies() {
165386
165512
  });
165387
165513
  }),
165388
165514
  /** claude with no output on the terminal (setup's probe of an old entry, and its remove); the exit status. */
165389
- runClaudeCliQuiet: (args) => {
165390
- const windows = process.platform === "win32";
165391
- const result = windows ? spawnSync10(["claude", ...args].map((word) => hostShellWord(word, "win32")).join(" "), { stdio: "ignore", shell: true, windowsHide: true, timeout: 12e4 }) : spawnSync10("claude", args, { stdio: "ignore", windowsHide: true, timeout: 12e4 });
165392
- return result.status ?? 1;
165393
- },
165394
- runClaudeCli: (args) => {
165395
- const windows = process.platform === "win32";
165396
- const result = windows ? spawnSync10(["claude", ...args].map((word) => hostShellWord(word, "win32")).join(" "), { stdio: "inherit", shell: true, windowsHide: true, timeout: 12e4 }) : spawnSync10("claude", args, { stdio: "inherit", windowsHide: true, timeout: 12e4 });
165397
- return result.status ?? 1;
165398
- },
165515
+ runClaudeCliQuiet: (args, program) => runClaude(args, program, "ignore"),
165516
+ runClaudeCli: (args, program) => runClaude(args, program, "inherit"),
165399
165517
  /**
165400
165518
  * The --tor entry of this CLI: re-execute `args` behind Tor (proxy.mjs proves Tor first). `startedFile`
165401
165519
  * (torRunOf) reaches the Tor run in its environment, which proxy.mjs copies from this process at the spawn.