shinjuku-shield 0.3.88 → 0.3.89

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,13 +6,13 @@ 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.88. The npm packages `shinjuku-shield` and
9
+ This is version 0.3.89. The npm packages `shinjuku-shield` and
10
10
  `shinjuku-shielded` hold the same files; `shinjuku` is the short command.
11
11
 
12
12
  ## Set up
13
13
 
14
14
  ```sh
15
- npx -y --no-audit --no-fund shinjuku-shield@0.3.88 setup
15
+ npx -y --no-audit --no-fund shinjuku-shield@0.3.89 setup
16
16
  ```
17
17
 
18
18
  Setup makes the wallet on this machine, a private passphrase file, and the
@@ -24,7 +24,7 @@ server to that host's config.
24
24
  ## The `shinjuku` command
25
25
 
26
26
  ```sh
27
- npm install -g shinjuku@0.3.88
27
+ npm install -g shinjuku@0.3.89
28
28
  shinjuku help
29
29
  ```
30
30
 
@@ -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-shielded -- npx -y --no-audit --no-fund shinjuku-shield@0.3.88 mcp
39
+ claude mcp add --scope user shinjuku-shielded -- npx -y --no-audit --no-fund shinjuku-shield@0.3.89 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-shielded": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.88", "mcp"] } } }
45
+ { "mcpServers": { "shinjuku-shielded": { "command": "npx", "args": ["-y", "--no-audit", "--no-fund", "shinjuku-shield@0.3.89", "mcp"] } } }
46
46
  ```
47
47
 
48
48
  On native Windows, if the host cannot find `npx`, use `"command": "cmd"` and
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": "17d8275d7939ba1783b53b5839277d88fdb473fd4e1cfb1e59e6f0226e13d8fb",
5
- "bytes": 12524840,
6
- "sourceCommit": "a964944a76529fa5b5f834e16a1e279df6b4e7cf",
4
+ "sha256": "9af59797297cdea3750a86cc8bc6287cab8952e4a8fc5da4bdb8d3e48ab2bd67",
5
+ "bytes": 12528864,
6
+ "sourceCommit": "5a32786bd0096a2a45135944a10dd1944ee4012d",
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",
@@ -1282,5 +1282,5 @@
1282
1282
  "version": "1.8.0"
1283
1283
  }
1284
1284
  ],
1285
- "publishedAt": "2026-10-23T23:37:34.040Z"
1285
+ "publishedAt": "2026-10-24T00:07:43.778Z"
1286
1286
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "shinjuku-shield",
3
- "version": "0.3.88",
3
+ "version": "0.3.89",
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": "17d8275d",
7
- "shinjukuSha256": "17d8275d7939ba1783b53b5839277d88fdb473fd4e1cfb1e59e6f0226e13d8fb",
6
+ "shinjukuRelease": "9af59797",
7
+ "shinjukuSha256": "9af59797297cdea3750a86cc8bc6287cab8952e4a8fc5da4bdb8d3e48ab2bd67",
8
8
  "license": "SEE LICENSE IN LICENSE.txt",
9
9
  "author": "Shinjuku Shielded",
10
10
  "homepage": "https://github.com/ShinjukuStaition/shinjuku-mcp#readme",
@@ -47011,6 +47011,14 @@ async function proveProxy(mode, proxy) {
47011
47011
  throw new Error(`proxy_not_answering: ${address5} did not carry a request to ${TOR_CHECK}, so nothing was sent. Check the proxy and rerun`);
47012
47012
  }
47013
47013
  }
47014
+ function plainTorTrouble(text3, said = TOR_TROUBLE_SAID) {
47015
+ const line = String(text3).replace(/\r?\n$/, "");
47016
+ if (!/^(?:tor|rpc|history|memo service): /.test(line) || !TOR_TROUBLE_LINE.test(line) || /\bWARNING\b/.test(line)) return void 0;
47017
+ const plain = TOR_TROUBLE_PLAIN.find(([kind]) => kind.test(line))?.[1] ?? TOR_WAIT_PLAIN;
47018
+ if (said.has(plain)) return "";
47019
+ said.add(plain);
47020
+ return plain;
47021
+ }
47014
47022
  function childRunProxy(env = process.env) {
47015
47023
  const marked = String(env[MARK] ?? "");
47016
47024
  if (!marked) return { args: [], env: { ...env } };
@@ -47306,7 +47314,7 @@ async function proxyEntry(argv2, run5, { err = (text3) => process.stderr.write(t
47306
47314
  }
47307
47315
  return reexec(options.args, options.mode, options.proxy);
47308
47316
  }
47309
- var TOR_HTTP_TUNNEL, TOR_CHECK, PROOF_TIMEOUT_MS, LOCAL_PROOF_TIMEOUT_MS, LOCAL_PROOF_MAX_BYTES, torProvenAt, proxyProvenAt, MARK, TOR_RUN_STARTED_ENV, ownProxyRefused, ONION_V3, RETRY_AFTER_CAP_MS, RETRY_AFTER_FLOOR_MS, RETRY_AFTER_DEFAULT_MS, RPC_NO_ANSWER_LIMIT_MS, RPC_PACING_CAP_MS, PACING_NOTICE_EVERY_MS, PACING_RATE_WINDOW_MS, TOR_MAX_ROTATIONS, runStartedAt, rpcNotBefore, pacingWaiters, pacingSince, pacedMs, rpcAnswered, lastAnswerAt, readSteps, pacingNoticeAt, pacingSamples, torMoves, torCircuitId, torMovesRefused, pendingMove, inTorRun, runNetworkMode, isOnionOrigin, ProxyUsageError, isOnionHost, TOR_EXPERT_BUNDLE, TUNNEL_LINE, TOR_INSTALL, OS_NAMES, osKey, torNotRunningMessage, NOTICE, QUIET_RUN_MARK, QUIET_NOTICE, quietRun, TOR_TROUBLE_LINE, quietTorErr, withRunTag, proxyEnv, pacedSoFar, RESENDABLE_METHOD, torCircuit, GLOBAL_DISPATCHER2, laneDispatchers, paymentWarmStop, PROXY_WARNING_FLAG, proxiedExecArgv, proxiedNodeOptions, TOR_FROM_CONFIG_ENV, TOR_FROM_CONFIG_HINT;
47317
+ var TOR_HTTP_TUNNEL, TOR_CHECK, PROOF_TIMEOUT_MS, LOCAL_PROOF_TIMEOUT_MS, LOCAL_PROOF_MAX_BYTES, torProvenAt, proxyProvenAt, MARK, TOR_RUN_STARTED_ENV, ownProxyRefused, ONION_V3, RETRY_AFTER_CAP_MS, RETRY_AFTER_FLOOR_MS, RETRY_AFTER_DEFAULT_MS, RPC_NO_ANSWER_LIMIT_MS, RPC_PACING_CAP_MS, PACING_NOTICE_EVERY_MS, PACING_RATE_WINDOW_MS, TOR_MAX_ROTATIONS, runStartedAt, rpcNotBefore, pacingWaiters, pacingSince, pacedMs, rpcAnswered, lastAnswerAt, readSteps, pacingNoticeAt, pacingSamples, torMoves, torCircuitId, torMovesRefused, pendingMove, inTorRun, runNetworkMode, isOnionOrigin, ProxyUsageError, isOnionHost, TOR_EXPERT_BUNDLE, TUNNEL_LINE, TOR_INSTALL, OS_NAMES, osKey, torNotRunningMessage, NOTICE, QUIET_RUN_MARK, QUIET_NOTICE, QUIET_TERMINAL_COMMANDS, INFER_SUBCOMMANDS, quietRun, TOR_TROUBLE_LINE, TOR_WAIT_PLAIN, TOR_TROUBLE_PLAIN, TOR_TROUBLE_SAID, quietTorErr, withRunTag, proxyEnv, pacedSoFar, RESENDABLE_METHOD, torCircuit, GLOBAL_DISPATCHER2, laneDispatchers, paymentWarmStop, PROXY_WARNING_FLAG, proxiedExecArgv, proxiedNodeOptions, TOR_FROM_CONFIG_ENV, TOR_FROM_CONFIG_HINT;
47310
47318
  var init_proxy = __esm({
47311
47319
  "wallet/src/net/proxy.mjs"() {
47312
47320
  "use strict";
@@ -47371,14 +47379,31 @@ var init_proxy = __esm({
47371
47379
  chat: { tor: "Private: this chat goes through Tor.", proxy: "Private: this chat goes through your proxy." },
47372
47380
  funds: { tor: "Private: every request of this run goes through Tor.", proxy: "Private: every request of this run goes through your proxy." }
47373
47381
  };
47382
+ QUIET_TERMINAL_COMMANDS = /* @__PURE__ */ new Set(["add-funds", "funds-status", "balance", "unshield"]);
47383
+ INFER_SUBCOMMANDS = /* @__PURE__ */ new Set(["models", "serve", "start", "status", "stop"]);
47374
47384
  quietRun = (args) => {
47375
47385
  if (args.includes("--verbose")) return void 0;
47376
47386
  if (args[0] === "chat") return "chat";
47377
- return ["add-funds", "funds-status"].includes(args[0]) && process.stdout.isTTY && !args.includes("--json") ? "funds" : void 0;
47387
+ const quietCommand = QUIET_TERMINAL_COMMANDS.has(args[0]) || args[0] === "infer" && !INFER_SUBCOMMANDS.has(args[1]);
47388
+ return quietCommand && process.stdout.isTTY && !args.includes("--json") ? "funds" : void 0;
47378
47389
  };
47379
47390
  TOR_TROUBLE_LINE = /\bno (?:other )?(?:history-proxy )?onion\b|\bgave no answer\b|\bstalled\b|\bHTTP 429\b|\bcannot move\b/;
47391
+ TOR_WAIT_PLAIN = "Tor is slow right now, so the wallet waits for it and tries again. This can take longer than usual.";
47392
+ TOR_TROUBLE_PLAIN = [
47393
+ [/\bpublishes no onion\b/, "One server of this run has no Tor-only address, so the last Tor relay sees that server's name, but not what the wallet sends."],
47394
+ [/\bHTTP 429\b/, "A server asked the wallet to slow down, so the wallet waits as the server asks. This can add some time."],
47395
+ [/\bkeeps its circuit\b|\bcannot move\b|\bretries there\b|\bwait for (?:it|them)\b|\bno (?:other )?(?:history-proxy )?onion\b/, TOR_WAIT_PLAIN],
47396
+ [/\bmoved to a new Tor circuit\b|\bgave no answer\b/, "Tor was slow, so the wallet switched to another Tor route. This can add a few seconds."]
47397
+ ];
47398
+ TOR_TROUBLE_SAID = /* @__PURE__ */ new Set();
47380
47399
  quietTorErr = (err) => (text3) => {
47381
- if (/^tor: /.test(text3) && !TOR_TROUBLE_LINE.test(text3) && !/\bWARNING\b/.test(text3)) return;
47400
+ const plain = plainTorTrouble(text3);
47401
+ if (plain !== void 0) {
47402
+ if (plain) err(`${plain}
47403
+ `);
47404
+ return;
47405
+ }
47406
+ if (/^tor: /.test(text3) && !/\bWARNING\b/.test(text3)) return;
47382
47407
  err(text3);
47383
47408
  };
47384
47409
  withRunTag = (mode, proxy) => {
@@ -130561,9 +130586,16 @@ function readConfig(env) {
130561
130586
  }
130562
130587
  function hideProgressLines(stream = process.stderr) {
130563
130588
  const original = stream.write;
130589
+ const shown = (line) => {
130590
+ if (!line.endsWith("\n")) return line;
130591
+ const plain = plainTorTrouble(line);
130592
+ if (plain !== void 0) return plain ? `${plain}
130593
+ ` : "";
130594
+ return isProgressLine(line) ? "" : line;
130595
+ };
130564
130596
  stream.write = function write(chunk, encoding, callback) {
130565
130597
  const text3 = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString(typeof encoding === "string" ? encoding : "utf8");
130566
- const kept = text3.split(/(?<=\n)/).filter((line) => !(line.endsWith("\n") && isProgressLine(line))).join("");
130598
+ const kept = text3.split(/(?<=\n)/).map(shown).join("");
130567
130599
  if (kept === text3) return original.call(stream, chunk, encoding, callback);
130568
130600
  const done = typeof encoding === "function" ? encoding : callback;
130569
130601
  if (kept) return original.call(stream, kept, done);
@@ -130850,7 +130882,7 @@ var init_chat = __esm({
130850
130882
  NO_ANSWER_CODES = /^inference_(upstream_failed|response_invalid)$/;
130851
130883
  NOTHING_PAID = /\bnothing was (?:sent or )?paid\b|\bnothing was paid or signed\b/i;
130852
130884
  CAP_FROM = { line: "from this command line", setup: "set in setup", default: "the default" };
130853
- PROGRESS_LINE = /^(?:tor|rpc|history|memo service): |^reading \d+ memos? from the memo service/;
130885
+ PROGRESS_LINE = /^(?:tor|rpc|history|memo service): |^reading \d+ memos? from the memo service|^reading your private balance again\b|^merge \S+: self-paying\b/;
130854
130886
  SHOWN_PROGRESS = /\bWARNING\b|\bminutes?\b/;
130855
130887
  isProgressLine = (line) => PROGRESS_LINE.test(line) && !SHOWN_PROGRESS.test(line) && !TOR_TROUBLE_LINE.test(line);
130856
130888
  fail46 = (deps, message) => typeof deps.publicFailure === "function" ? deps.publicFailure(message) : new Error(message);
@@ -157414,6 +157446,7 @@ function withProofToolsRefresh(options, fromConfig) {
157414
157446
  return { ...options, proofToolsRefresh: { home: fromConfig.home } };
157415
157447
  }
157416
157448
  var inProxiedRun = (env) => childRunProxy(env).args.length > 0;
157449
+ var terminalQuiet = (values, deps) => deps.stdoutIsTTY?.() === true && !values.has("--json") && !values.has("--verbose");
157417
157450
  var TOR_RUN_STARTED_ENV2 = "SHINJUKU_WALLET_TOR_RUN_STARTED_FILE";
157418
157451
  var TOR_DOWN_DETAIL = "Your private connection (Tor) is not running, so no payment was made. Start Tor, then restart this MCP server in your agent host and try again.";
157419
157452
  var recordedTunnelHost = (configPath2) => {
@@ -158498,7 +158531,8 @@ var COMMANDS = [
158498
158531
  bool2("--refresh", "run the same chain walk as recover first (network)"),
158499
158532
  // --digests narrows recover's printed output; a balance needs the whole history.
158500
158533
  ...recoverFlags({ refreshOnly: true }).filter((entry) => entry.name !== "--digests"),
158501
- bool2("--json", "print the whole report as JSON in a terminal too (a file or a program gets JSON without this flag)")
158534
+ bool2("--json", "print the whole report as JSON in a terminal too (a file or a program gets JSON without this flag)"),
158535
+ bool2("--verbose", "in a terminal, also show the wallet's own progress lines (Tor, the RPC relay, the pool history, the memo reads); without it a terminal shows only the result")
158502
158536
  ],
158503
158537
  examples: [
158504
158538
  `${CLI2} balance --pool ${GUIDE.pool}`,
@@ -158509,7 +158543,7 @@ var COMMANDS = [
158509
158543
  "shinjukuShielded is what you can spend: unspent accounts and notes minus the ones in-flight payments or unshields will use.",
158510
158544
  "Without --refresh, balance reads only local files: the last walk (recover or balance --refresh) and the wallet log. It makes no network call.",
158511
158545
  "shinjukuShielded is null when the last walk is missing, stale, or incomplete. reasons says why; next shows the command to run.",
158512
- "In a terminal it prints one plain line: the private balance in USDC, and a short reason when it is not current (then the command to run). A program, or --json, gets the whole report as JSON (total, shinjukuShielded, status, reasons, next, detail).",
158546
+ "In a terminal it prints one plain line: the private balance in USDC, and a short reason when it is not current (then the command to run). The wallet's own progress lines (Tor, the RPC relay, the pool history walk, the memo reads) show only with --verbose; warnings and failures always show. A program, or --json, gets the whole report as JSON (total, shinjukuShielded, status, reasons, next, detail).",
158513
158547
  "Payments that others send to this wallet appear only after a refresh.",
158514
158548
  "With --refresh it also reads the one-time deposit addresses of this home's earlier pools (one address per request). USDC found there goes into this pool by itself (the facilitator pays the fee), and earlierDeposits lists each one with a notice.",
158515
158549
  "paymentsWithoutWaiting (and detail.fundedAccounts): your funded accounts that no in-flight work holds. A payment spends one account, and its change pays only after the next pool anchor (up to 5 minutes; about 30 s on some pools), so this many payments can run before the next anchor without waiting (an account made since the last anchor, such as a change, waits for the next one). add-funds --split makes more of them."
@@ -158523,10 +158557,12 @@ var COMMANDS = [
158523
158557
  }
158524
158558
  return;
158525
158559
  }
158526
- const extra = [...values.keys()].find((name) => name !== "--pool" && name !== "--json");
158560
+ const extra = [...values.keys()].find((name) => !["--pool", "--json", "--verbose"].includes(name));
158527
158561
  if (extra) throw new UsageError(`${extra} is used only with --refresh`);
158528
158562
  },
158529
158563
  rpcWhen: (values) => values.has("--refresh"),
158564
+ // In a terminal its progress lines show only with --verbose (inference/chat.mjs hideProgressLines; fault 6 of the pin 0.3.86).
158565
+ quietProgress: (values, deps) => terminalQuiet(values, deps),
158530
158566
  run: (args, values, deps, io) => runBalance(args, values, deps, io)
158531
158567
  },
158532
158568
  {
@@ -158616,6 +158652,7 @@ var COMMANDS = [
158616
158652
  flag2("--max-session", "<usdc>", "the most this run may pay in total, in USDC; at least --max-payment. Default: the cap setup recorded, else 1", { check: "atomic", usdc: true }),
158617
158653
  flag2("--request-id", "<id>", "your stable name for this request; default infer-<random>, printed on stderr before any payment. Rerun with the same id to resume a stopped run: it never pays twice"),
158618
158654
  bool2("--json", "print one JSON line (answer, model, usage, paidAtomic, requestId, receipt) instead of the answer text"),
158655
+ bool2("--verbose", "in a terminal, also show the wallet's own progress lines (Tor, the RPC relay, the pool history, the memo reads); without it a terminal shows only the cost line, the answer, and what it paid"),
158619
158656
  // After setup config.json gives every wallet flag; they stay for a wallet in another place.
158620
158657
  ...payerSessionFlags().map((spec) => ({ ...spec, required: false }))
158621
158658
  ],
@@ -158629,7 +158666,7 @@ var COMMANDS = [
158629
158666
  `Private form (recommended): pipe the prompt in and write - in its place, so it is not in the process list or your shell history: ${INFER_STDIN_EXAMPLE}. stdin is read until it ends (UTF-8, at most 1 MiB); an empty one is refused before anything is paid.`,
158630
158667
  "It runs only through Tor (or --proxy <url>), never a direct connection: usePod would see your IP address next to your prompt, so the command refuses before anything is sent.",
158631
158668
  `${INFER_COST_LINE}. stderr says this before the payment, with the most the request can cost.`,
158632
- "stdout holds the answer; stderr says paid <amount> USDC request-id <id>. An answer cut short by --max-tokens says so.",
158669
+ "stdout holds the answer; stderr says paid <amount> USDC request-id <id>. An answer cut short by --max-tokens says so. In a terminal the wallet's own progress lines (Tor, the RPC relay, the pool history walk, the memo reads) show only with --verbose; warnings and failures always show.",
158633
158670
  "Exit codes: 0 answered; 1 refused or failed (one line says why, and a hint says what works); 2 the command line is wrong."
158634
158671
  ],
158635
158672
  next: `chat in this terminal: ${CLI2} chat; the local AI address for an agent app: ${CLI2} infer start; the models and prices: ${CLI2} infer models`,
@@ -158639,6 +158676,8 @@ var COMMANDS = [
158639
158676
  // Outside a Tor run (or without a wallet) infer runs again behind Tor or refuses: it reads nothing itself (as chat).
158640
158677
  skipFamilyRoots: (values, env) => !inferPaysHere(values, env),
158641
158678
  rpcWhen: (values, env) => inferPaysHere(values, env),
158679
+ // The Tor run, the one that pays, in a terminal: its progress lines show only with --verbose (as chat; fault 6 of the pin 0.3.86).
158680
+ quietProgress: (values, deps) => inProxiedRun(deps.env) && terminalQuiet(values, deps),
158642
158681
  run: (args, values, deps, io) => deps.inferMain(values, { ...deps, io })
158643
158682
  },
158644
158683
  {
@@ -158973,7 +159012,8 @@ var COMMANDS = [
158973
159012
  HISTORY_RPC_FLAG,
158974
159013
  flag2("--parts", "<1-8>", "optional, default 1: send the amount as this many separate exits of unequal size (a private send); each part carries at least 0.01 USDC; above 1 it needs --max-delay-minutes 1-60, and --unshield-id may then be at most 45 characters", { check: "count" }),
158975
159014
  flag2("--max-delay-minutes", "<0-60>", "optional, default 0: each part, part 1 included, is sent after a random wait of up to this many minutes; a part that is late (the command was stopped) waits a new random time", { check: "count" }),
158976
- bool2("--json", "end with the result as JSON in a terminal too (a file or a program gets JSON without this flag)")
159015
+ bool2("--json", "end with the result as JSON in a terminal too (a file or a program gets JSON without this flag)"),
159016
+ bool2("--verbose", "in a terminal, also show the wallet's own progress lines (Tor, the RPC relay, the pool history, the memo reads, the join's steps); without it a terminal shows only the steps you act on and the result")
158977
159017
  ],
158978
159018
  // T9 (live run 2026-10-23 18:44 UTC, npm 0.3.83): the old two examples looked the same and neither had --amount or a
158979
159019
  // plain --to; after setup these two work as typed (config.json gives every file flag).
@@ -158984,12 +159024,14 @@ var COMMANDS = [
158984
159024
  "The recipient must already hold USDC (a Solana address with a USDC account, for example a Phantom address that received USDC); the command checks it first and sends nothing to an address without one. It refuses this wallet's own address: an exit there would show on chain that the money is yours. Best: an address that never sent USDC into this wallet.",
158985
159025
  "--amount all sends the whole private balance. When the balance is in more than one part, the same command joins the parts first (a private move inside this wallet, no fee; nothing leaves it; about 2 minutes per extra part, after a random wait of up to 60 s), then sends all of it. Ctrl+C stops it; the same command again goes on and never sends twice.",
158986
159026
  "The command prints the unshield id first. If it stops, run the same command with --unshield-id <that id> added: it finishes that unshield and never sends twice.",
158987
- "In a terminal it ends with one plain line (what was sent, to whom, the exit transaction) and the new private balance: after an exit the wallet reads the balance again itself (the same walk as balance --refresh, over the same connection; Tor when setup recorded it). A program, or --json, gets the result as JSON.",
159027
+ "In a terminal it ends with one plain line (what was sent, to whom, the exit transaction) and the new private balance: after an exit the wallet reads the balance again itself (the same walk as balance --refresh, over the same connection; Tor when setup recorded it). A program, or --json, gets the result as JSON. The wallet's own progress lines (Tor, the RPC relay, the pool history walk, the memo reads, the join's steps) show only with --verbose; warnings and failures always show.",
158988
159028
  `--parts and --max-delay-minutes make a private send (${CLI2} unshield --amount 3 --parts 3 --max-delay-minutes 20 --to <your wallet address>): the plan (part sizes, part ids <unshield-id>-p1.., earliest times) is saved in the wallet before part 1, each part is one unshield, and a stopped run continues at the first part not yet exited when the same command with its --unshield-id runs again. The wallet is free for other commands while a part waits. Keep the command running until it prints its result.`,
158989
159029
  `Stop the parts of a private send not sent yet: ${CLI2} unshield-cancel --unshield-id <id>.`,
158990
159030
  "Privacy limit of a private send: every part goes to the same --to, so anyone who adds up that account's incoming transfers sees the total. The parts hide the time and the single amount of the exit, not the sum the account received."
158991
159031
  ],
158992
159032
  next: `back up the wallet (${CLI2} help backup-export); ${CLI2} balance shows the private balance`,
159033
+ // In a terminal its progress lines show only with --verbose (inference/chat.mjs hideProgressLines; fault 6 of the pin 0.3.86).
159034
+ quietProgress: (values, deps) => terminalQuiet(values, deps),
158993
159035
  run: (args, values, deps, io) => runUnshieldCommand(args, values, deps, io)
158994
159036
  },
158995
159037
  {
@@ -159779,7 +159821,7 @@ async function recipientHoldsUsdc({ connection, mint, owner }) {
159779
159821
  }
159780
159822
  async function runUnshieldCommand(args, values, deps, io) {
159781
159823
  const terminal = deps.stdoutIsTTY?.() === true && !values.has("--json");
159782
- let callArgs = args.filter((word) => word !== "--json");
159824
+ let callArgs = args.filter((word) => word !== "--json" && word !== "--verbose");
159783
159825
  const setArg = (name, value) => {
159784
159826
  const at = callArgs.indexOf(name);
159785
159827
  callArgs = at >= 0 ? callArgs.map((word, index) => index === at + 1 ? value : word) : [...callArgs, name, value];
@@ -159837,6 +159879,7 @@ async function runUnshieldCommand(args, values, deps, io) {
159837
159879
  if (values.get("--amount") === "all") setArg("--amount", await sendAllAtomic(values, deps, io, openStore, ensureId));
159838
159880
  ensureId();
159839
159881
  const gated = await spendGate(callArgs, values, deps, io, { amountAtomic: values.get("--amount"), again: ` with --unshield-id ${id}` });
159882
+ if (terminal && isSingleSend(values.get("--parts") ?? 1, values.get("--max-delay-minutes") ?? 0)) io.err("sending privately now; this takes about a minute\n");
159840
159883
  let answer;
159841
159884
  const returned = await deps.unshieldMain(gated, { output: (result) => {
159842
159885
  answer = result;
@@ -160564,7 +160607,7 @@ async function runBalance(args, values, deps, io) {
160564
160607
  let store;
160565
160608
  let earlierDeposits = [];
160566
160609
  if (values.has("--refresh")) {
160567
- const refreshed = await refreshSnapshot(args.filter((word) => word !== "--json"), values, deps);
160610
+ const refreshed = await refreshSnapshot(args.filter((word) => word !== "--json" && word !== "--verbose"), values, deps);
160568
160611
  warnUnsavedSync(refreshed.result, io);
160569
160612
  refreshed.save();
160570
160613
  await refreshed.prune();