proton-mail-bridge-client 2.7.3 → 2.8.1

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
@@ -24,7 +24,7 @@
24
24
 
25
25
  ---
26
26
 
27
- Give Claude Desktop (or Cline, or any MCP client) full access to your Proton Mail inbox: read, search, send, draft, triage threads, manage folders, save attachments, and more — 96 MCP tools in total. Most of the same capabilities are also available as a full CLI for scripting, cron, and piped automation — no Claude required.
27
+ Give Claude Desktop (or Cline, or any MCP client) full access to your Proton Mail inbox: read, search, send, draft, triage threads, manage folders, save attachments, and more — 100 MCP tools in total. Most of the same capabilities are also available as a full CLI for scripting, cron, and piped automation — no Claude required.
28
28
 
29
29
  > **Using Proton Drive too?** See [**proton-drive-mcp**](https://github.com/googlarz/proton-drive-mcp), the companion MCP server and CLI for Proton Drive (upload, download, share and manage your encrypted files from Claude). Run both side by side to handle mail and files in one conversation, for example save an attachment from here, then upload it to Drive. More in [Related projects](#related-projects).
30
30
 
@@ -42,14 +42,14 @@ Give Claude Desktop (or Cline, or any MCP client) full access to your Proton Mai
42
42
  - "Find the last email from `alice@example.com` and draft a reply for me to review." (nothing is sent until you say so)
43
43
  - "Which of my emails have attachments from this month?"
44
44
  - "Show me my drafts and tighten the oldest one."
45
- 5. **Optional:** `PROTONMAIL_READ_ONLY=true` to browse without being able to change anything, `PROTONMAIL_TOOL_TIER=core` for a smaller tool set (25 instead of 96), and more accounts under [Multi-account support](#multi-account-support-v210). More recipes below in [Try it](#try-it-example-claude-prompts).
45
+ 5. **Optional:** `PROTONMAIL_READ_ONLY=true` to browse without being able to change anything, `PROTONMAIL_TOOL_TIER=core` for a smaller tool set (25 instead of 100), and more accounts under [Multi-account support](#multi-account-support-v210). More recipes below in [Try it](#try-it-example-claude-prompts).
46
46
 
47
47
  ---
48
48
 
49
49
  ## What you get
50
50
 
51
51
  - **Claude reads and manages your Proton Mail** — triage, reply, draft, archive, search, move, batch-act on threads, pull attachments
52
- - **Full CLI** — a dedicated command for every one of the 96 tools (plus a generic `tool <name>` passthrough), scriptable and pipeable, works in cron and shell scripts
52
+ - **Full CLI** — a dedicated command for every one of the 100 tools (plus a generic `tool <name>` passthrough), scriptable and pipeable, works in cron and shell scripts
53
53
  - **Fast local search** — full-text search across your inbox without hitting IMAP on every query
54
54
  - **Safety controls** — read-only mode, send gate, destructive-action confirmation, per-action allowlist
55
55
  - **Privacy-native** — no third-party email service involved; your mail stays on your machine
@@ -326,6 +326,7 @@ First, enable **Split Addresses** in Proton Bridge and configure each address as
326
326
  - **Additional accounts:** each has an auto-generated slug (e.g., `alias`, `business`). Email IDs carry an account prefix: `alias::message-id`, `business::message-id`.
327
327
  - **Sending:** `send_email`, `reply_to_email`, etc. route through the account matching the `from` address. If no account matches, the primary connection is used with a header override (for non-configured aliases).
328
328
  - **Search and read:** all read tools (search, threads, analytics, digest) automatically fan out across all configured accounts and merge results, preserving the account prefix in returned IDs.
329
+ - **One account only:** the triage, statistics, draft and folder tools (`get_threads`, `get_inbox_digest`, `get_follow_up_candidates`, `get_labels`, `list_drafts`, `get_folders`, `top_senders`, ...) take an optional `account` (address or slug) to look at a single account instead of all of them; an unknown value is an error.
329
330
 
330
331
  ### Tools across accounts
331
332
 
@@ -381,6 +382,12 @@ Output:
381
382
  **Draft review**
382
383
  > "Show me my drafts, pick the oldest one, and suggest a better subject line and closing paragraph."
383
384
 
385
+ **Calendar invitations**
386
+ > "Do I have any unanswered meeting invitations this week? Accept the ones that don't clash with each other and show me the rest."
387
+
388
+ **Follow-up**
389
+ > "I just sent the proposal to Ann. If she hasn't answered in five days, remind me."
390
+
384
391
  > **Tip:** When creating folders, use `Folders/Name` (not just `Name`) — that's the Proton Bridge namespace for real folders vs. labels.
385
392
 
386
393
  More recipes — expanded triage prompts, cron scripts for scheduled digests, and a Claude Code `/mail-triage` slash command — are in [examples/](examples/).
@@ -421,7 +428,7 @@ All commands support `--json` for machine-readable output, and any MCP tool is d
421
428
 
422
429
  `<command> --help` prints that command's usage without running it. Flags accept `--flag value` or `--flag=value` (a value starting with `--` needs the `=` form, or must come after a bare `--`); unknown flags are an error. Exit codes: `0` success, `1` failure (including a failed `doctor` or `connection-status` check, or a failed item in a `batch`/`bulk-*` run), `2` usage error.
423
430
 
424
- **Full command reference: [docs/cli.md](docs/cli.md)** (a named command for every one of the 96 tools, across read, triage, compose, mailbox actions, folders, drafts, templates, analytics, and diagnostics).
431
+ **Full command reference: [docs/cli.md](docs/cli.md)** (a named command for every one of the 100 tools, across read, triage, compose, mailbox actions, folders, drafts, templates, analytics, and diagnostics).
425
432
 
426
433
  ---
427
434
 
@@ -430,7 +437,7 @@ All commands support `--json` for machine-readable output, and any MCP tool is d
430
437
  All flags work in both the MCP server and CLI:
431
438
 
432
439
  ```bash
433
- PROTONMAIL_TOOL_TIER=core # expose 25 core tools instead of all 96 — saves context window
440
+ PROTONMAIL_TOOL_TIER=core # expose 25 core tools instead of all 100 — saves context window
434
441
  PROTONMAIL_READ_ONLY=true # disable all write operations
435
442
  PROTONMAIL_ALLOW_SEND=false # disable SMTP sends only (other writes still work)
436
443
  PROTONMAIL_CONFIRM_DESTRUCTIVE=true # require confirmed:true on send, reply, forward, delete
@@ -474,7 +481,7 @@ PROTONMAIL_PASSWORD_COMMAND='pass proton/password'
474
481
  PROTONMAIL_DATA_DIR="$HOME/.proton-mail-bridge-client"
475
482
 
476
483
  # Tools
477
- PROTONMAIL_TOOL_TIER='full' # 'core' exposes 25 essential tools, incl. draft review/edit and list_accounts (saves context window); 'full' exposes all 96
484
+ PROTONMAIL_TOOL_TIER='full' # 'core' exposes 25 essential tools, incl. draft review/edit and list_accounts (saves context window); 'full' exposes all 100
478
485
 
479
486
  # Safety
480
487
  PROTONMAIL_READ_ONLY='false'
@@ -535,7 +542,7 @@ With several accounts or a signature, the server sends from whichever `from` the
535
542
  ## Tool surface
536
543
 
537
544
  ### Send
538
- `send_email` · `send_test_email` · `reply_to_email` · `reply_all_email` · `forward_email`
545
+ `send_email` · `send_test_email` · `reply_to_email` · `reply_all_email` · `forward_email` · `respond_to_invite` (answer a calendar invitation)
539
546
 
540
547
  ### Drafts
541
548
  `create_draft` · `create_reply_draft` · `create_forward_draft` · `create_thread_reply_draft` · `list_drafts` · `list_remote_drafts` · `get_draft` · `update_draft` · `sync_draft_to_remote` · `send_draft` · `delete_draft`
@@ -544,7 +551,7 @@ With several accounts or a signature, the server sends from whichever `from` the
544
551
  `get_emails` · `get_email_by_id` · `count_messages` · `search_emails` · `search_indexed_emails` · `list_attachments` · `get_attachment_content` · `save_attachment` · `save_attachments`
545
552
 
546
553
  ### Triage
547
- `get_folders` · `sync_folders` · `get_labels` · `get_threads` · `get_thread_by_id` · `get_thread_brief` · `get_actionable_threads` · `get_inbox_digest` · `get_follow_up_candidates` · `find_document_threads` · `prepare_meeting_context` · `delete_thread` · `flag_thread` · `move_thread`
554
+ `get_folders` · `sync_folders` · `get_labels` · `get_threads` · `get_thread_by_id` · `get_thread_brief` · `get_actionable_threads` · `get_inbox_digest` · `get_follow_up_candidates` · `set_reply_reminder` · `list_reply_reminders` · `cancel_reply_reminder` · `find_document_threads` · `prepare_meeting_context` · `delete_thread` · `flag_thread` · `move_thread`
548
555
 
549
556
  ### Actions
550
557
  `mark_email_read` · `star_email` · `move_email` · `archive_email` · `trash_email` · `restore_email` · `delete_email` · `batch_email_action` · `apply_thread_action` · `empty_folder` · `bulk_delete` · `bulk_move` · `bulk_update_flags` · `bulk_update_labels` · `update_message_flags` · `update_message_labels`
@@ -643,7 +650,7 @@ Measured in October 2026 (v2.7.0) on a copy of the same ~57,000-message index. "
643
650
  - Defaults are bounded: `search_emails`/`search_indexed_emails` return 50 (pass `limit` for more), `list_drafts` 20, `list_scheduled_sends` 50 newest first. Each reports `hasMore`; page with `offset`.
644
651
  - Draft and queued-message bodies are shortened to a preview in list and update responses (`bodyTruncated`, `bodyLength`); use `get_draft` for one full draft. Attachment content is never inlined in a listing.
645
652
  - Large attachments: set `PROTONMAIL_ALLOW_FILE_DOWNLOAD_DIR` and pass `saveTo`, rather than raising `PROTONMAIL_MAX_INLINE_BYTES`.
646
- - **`PROTONMAIL_TOOL_TIER=core`** exposes 25 tools instead of 96: about 7k tokens of tool definitions instead of about 20k (roughly 65% less, reference tokenizer), paid on every conversation that loads the server.
653
+ - **`PROTONMAIL_TOOL_TIER=core`** exposes 25 tools instead of 100: about 7k tokens of tool definitions instead of about 21k (roughly 67% less; the earlier measurement with a reference tokenizer, 7k against 20k for 96 tools, scaled by the 3.7% the four newest tool definitions add), paid on every conversation that loads the server.
647
654
  - Repeating an `update_draft` that changes nothing on a draft whose remote copy is already in sync does no store write and no IMAP upload. (A draft whose last sync failed, or that was edited with `syncToRemote:false`, still syncs.)
648
655
 
649
656
  **Working with drafts**
package/dist/cli.d.ts CHANGED
@@ -15,6 +15,13 @@ interface CommandSpec {
15
15
  flags: string[];
16
16
  }
17
17
  export declare const COMMAND_SPECS: Record<string, CommandSpec>;
18
+ export declare const COMPLETION_SHELLS: readonly ["zsh", "bash", "fish"];
19
+ export declare function completionCommands(): Array<{
20
+ name: string;
21
+ description: string;
22
+ flags: string[];
23
+ }>;
24
+ export declare function completionScript(shell: string): string;
18
25
  export declare function commandHelpText(command: string): string | undefined;
19
26
  export declare function toolResultExitCode(toolName: string, result: Record<string, unknown>): number;
20
27
  interface ToolOnlyCommand {
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA4BA,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAiBD,qBAAa,aAAc,SAAQ,KAAK;CAAG;AAM3C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAuD1D;AA0ID,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAOD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAkErD,CAAC;AAkBF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAcnE;AAyKD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAY5F;AAk0CD,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IAIb,SAAS,CAAC,EAAE,MAAM,CAAC;IAMnB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,eAAO,MAAM,kBAAkB,EAAE,eAAe,EA+D/C,CAAC;AA2EF,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA+N1C"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA4BA,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAiBD,qBAAa,aAAc,SAAQ,KAAK;CAAG;AAM3C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAuD1D;AA0ID,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAOD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAmErD,CAAC;AAoBF,eAAO,MAAM,iBAAiB,YAAI,KAAK,EAAE,MAAM,EAAE,MAAM,CAAU,CAAC;AAGlE,wBAAgB,kBAAkB,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAQlG;AAID,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA+DtD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAcnE;AAyKD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAY5F;AAk0CD,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IAIb,SAAS,CAAC,EAAE,MAAM,CAAC;IAMnB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,eAAO,MAAM,kBAAkB,EAAE,eAAe,EAmE/C,CAAC;AA2EF,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAkO1C"}
package/dist/cli.js CHANGED
@@ -226,6 +226,7 @@ const SEARCH_FLAGS = ["folder", "limit", "live", "sync", "label", "from", "to",
226
226
  const DRAFT_COPY_FLAGS = ["cc", "bcc", "notes"];
227
227
  const BULK_FILTER_FLAGS = ["from", "subject", "since", "before"];
228
228
  export const COMMAND_SPECS = {
229
+ completion: { usage: "completion <zsh|bash|fish>", description: "Print a shell completion script for the commands and their flags", flags: [] },
229
230
  help: { usage: "help [command]", description: "Show the command list, or the help for one command", flags: [] },
230
231
  version: { usage: "version", description: "Print the version and exit", flags: [] },
231
232
  "setup-claude-desktop": { usage: "setup-claude-desktop", description: "Run the Claude Desktop setup wizard (works from any install)", flags: [] },
@@ -308,6 +309,85 @@ function specForCommand(command) {
308
309
  flags: ["args", "args-file", ...fileFlag, ...(entry.boolFlags ?? [])],
309
310
  };
310
311
  }
312
+ // Tab completion for the commands and flags above. The scripts are generated from the same tables the parser and
313
+ // `--help` use, so they cannot drift from what the CLI accepts.
314
+ export const COMPLETION_SHELLS = ["zsh", "bash", "fish"];
315
+ const CLI_BINARIES = ["proton-mail-bridge-client", "proton-mail-bridge"];
316
+ export function completionCommands() {
317
+ const names = [...new Set([...Object.keys(COMMAND_SPECS), ...TOOL_ONLY_COMMANDS.map((entry) => entry.command)])].sort();
318
+ return names.flatMap((name) => {
319
+ const spec = specForCommand(name);
320
+ if (!spec)
321
+ return [];
322
+ const description = spec.description.replace(/\s*\(MCP tool [a-z_]+\)\s*$/, "").replace(/\s+/g, " ").trim();
323
+ return [{ name, description, flags: [...new Set([...spec.flags, "json", "help"])].sort() }];
324
+ });
325
+ }
326
+ const shellQuote = (value) => `'${value.replace(/'/g, "'\\''")}'`;
327
+ export function completionScript(shell) {
328
+ const commands = completionCommands();
329
+ if (shell === "bash") {
330
+ const cases = commands
331
+ .map((command) => ` ${command.name}) COMPREPLY=( $(compgen -W ${shellQuote(command.flags.map((flag) => `--${flag}`).join(" "))} -- "$cur") ) ;;`)
332
+ .join("\n");
333
+ return [
334
+ "# bash completion for proton-mail-bridge-client. Load it with:",
335
+ "# source <(proton-mail-bridge-client completion bash)",
336
+ "_proton_mail_bridge_client() {",
337
+ ' local cur="${COMP_WORDS[COMP_CWORD]}"',
338
+ " if [ \"$COMP_CWORD\" -eq 1 ]; then",
339
+ ` COMPREPLY=( $(compgen -W ${shellQuote(commands.map((command) => command.name).join(" "))} -- "$cur") )`,
340
+ " return",
341
+ " fi",
342
+ ' case "${COMP_WORDS[1]}" in',
343
+ cases,
344
+ " esac",
345
+ "}",
346
+ ...CLI_BINARIES.map((binary) => `complete -F _proton_mail_bridge_client ${binary}`),
347
+ "",
348
+ ].join("\n");
349
+ }
350
+ if (shell === "zsh") {
351
+ const list = commands.map((command) => ` ${shellQuote(`${command.name}:${command.description.replace(/:/g, " -")}`)}`).join("\n");
352
+ const cases = commands
353
+ .map((command) => ` ${command.name}) _arguments ${command.flags.map((flag) => shellQuote(`--${flag}`)).join(" ")} ;;`)
354
+ .join("\n");
355
+ return [
356
+ `#compdef ${CLI_BINARIES.join(" ")}`,
357
+ "# zsh completion for proton-mail-bridge-client. Load it with:",
358
+ "# source <(proton-mail-bridge-client completion zsh) (after compinit)",
359
+ "_proton_mail_bridge_client() {",
360
+ " local -a commands",
361
+ " commands=(",
362
+ list,
363
+ " )",
364
+ " if (( CURRENT == 2 )); then",
365
+ " _describe -t commands 'command' commands",
366
+ " return",
367
+ " fi",
368
+ ' case "$words[2]" in',
369
+ cases,
370
+ " esac",
371
+ "}",
372
+ `compdef _proton_mail_bridge_client ${CLI_BINARIES.join(" ")}`,
373
+ "",
374
+ ].join("\n");
375
+ }
376
+ if (shell === "fish") {
377
+ const lines = [];
378
+ for (const binary of CLI_BINARIES) {
379
+ lines.push(`complete -c ${binary} -f`);
380
+ for (const command of commands) {
381
+ lines.push(`complete -c ${binary} -n '__fish_use_subcommand' -a ${command.name} -d ${shellQuote(command.description)}`);
382
+ for (const flag of command.flags) {
383
+ lines.push(`complete -c ${binary} -n '__fish_seen_subcommand_from ${command.name}' -l ${flag}`);
384
+ }
385
+ }
386
+ }
387
+ return ["# fish completion for proton-mail-bridge-client. Load it with:", "# proton-mail-bridge-client completion fish | source", ...lines, ""].join("\n");
388
+ }
389
+ throw new CliUsageError(`completion needs a shell: ${COMPLETION_SHELLS.join(", ")}.`);
390
+ }
311
391
  export function commandHelpText(command) {
312
392
  const spec = specForCommand(command);
313
393
  if (!spec)
@@ -1733,6 +1813,10 @@ export const TOOL_ONLY_COMMANDS = [
1733
1813
  { command: "unsubscribe-info", tool: "get_unsubscribe_info", positionals: ["emailId"], help: "Read List-Unsubscribe details for a message" },
1734
1814
  { command: "unsubscribe-sender", tool: "unsubscribe_sender", positionals: ["emailId"], help: "Execute a mailto unsubscribe (--args '{\"confirmed\":true}' if required)" },
1735
1815
  { command: "reply-to-email", tool: "reply_to_email", positionals: ["emailId", "body"], help: "Immediately send a reply (full tool: attachments/dryRun via --args)" },
1816
+ { command: "set-reply-reminder", tool: "set_reply_reminder", positionals: ["emailId"], help: "Remind me if nobody answers this message (--args '{\"afterDays\":5}')" },
1817
+ { command: "list-reply-reminders", tool: "list_reply_reminders", positionals: [], help: "List reply reminders: waiting, due, answered" },
1818
+ { command: "cancel-reply-reminder", tool: "cancel_reply_reminder", positionals: ["id"], help: "Delete a reply reminder" },
1819
+ { command: "respond-to-invite", tool: "respond_to_invite", positionals: ["emailId", "response"], help: "Accept / decline / tentative a calendar invitation (--args '{\"dryRun\":true}' to preview)" },
1736
1820
  { command: "reply-all-email", tool: "reply_all_email", positionals: ["emailId", "body"], help: "Immediately reply to all recipients" },
1737
1821
  { command: "forward-email", tool: "forward_email", positionals: ["emailId", "to"], help: "Immediately forward a message, preserving attachments" },
1738
1822
  { command: "list-drafts", tool: "list_drafts", positionals: [], help: "List local drafts (tool form; see also `drafts`)" },
@@ -1875,6 +1959,9 @@ export async function main() {
1875
1959
  case "help":
1876
1960
  printCommandHelp(parsed.positionals[0]);
1877
1961
  return;
1962
+ case "completion":
1963
+ process.stdout.write(completionScript(parsed.positionals[0] ?? ""));
1964
+ return;
1878
1965
  case "-v":
1879
1966
  case "version":
1880
1967
  process.stdout.write(`proton-mail-bridge-client ${await getPkgVersion()}\n`);