@holdyourvoice/hyv 2.9.24 → 2.9.25
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/CHANGELOG.md +7 -0
- package/dist/index.js +43 -23
- package/package.json +1 -1
- package/scripts/postinstall-lib.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable CLI changes. Also mirrored to [holdyourvoice.com/changelog](https://holdyourvoice.com/changelog) for user-facing releases.
|
|
4
4
|
|
|
5
|
+
## [2.9.25] — 2026-07-04
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **MCP stdio pollution** — `hyv mcp` no longer prints setup banners to stdout when spawned by Cursor/Claude/ChatGPT (fixes "Unexpected token … is not valid JSON" toast spam on app open)
|
|
9
|
+
- Auto-detects piped stdout (`!isTTY`) or explicit `--stdio` flag; MCP configs now use `mcp --stdio`
|
|
10
|
+
- Interactive terminal runs still show setup on stderr before the JSON-RPC server starts
|
|
11
|
+
|
|
5
12
|
## [2.9.15] — 2026-06-18
|
|
6
13
|
|
|
7
14
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -5413,7 +5413,7 @@ function printFreePaidMatrix(opts = {}) {
|
|
|
5413
5413
|
First month $1 \u2192 ${PRICING_URL}`));
|
|
5414
5414
|
console.log(import_chalk.default.dim(" hyv init | hyv plan --upgrade\n"));
|
|
5415
5415
|
}
|
|
5416
|
-
var import_chalk, NPX_EXAMPLES, FREE_CLI_COMMANDS, PAID_FEATURES, FREE_WEB_TOOLS, COMMUNITY_URL, PRICING_URL, DASHBOARD_BILLING_URL;
|
|
5416
|
+
var import_chalk, NPX_EXAMPLES, FREE_CLI_COMMANDS, PAID_FEATURES, FREE_WEB_TOOLS, COMMUNITY_URL, X_URL, PRICING_URL, DASHBOARD_BILLING_URL;
|
|
5417
5417
|
var init_free_paid = __esm({
|
|
5418
5418
|
"src/lib/free-paid.ts"() {
|
|
5419
5419
|
"use strict";
|
|
@@ -5460,6 +5460,7 @@ var init_free_paid = __esm({
|
|
|
5460
5460
|
{ name: "Blog", url: "https://holdyourvoice.com/blog" }
|
|
5461
5461
|
];
|
|
5462
5462
|
COMMUNITY_URL = "https://holdyourvoice.com/community";
|
|
5463
|
+
X_URL = "https://x.com/istupidpreneur";
|
|
5463
5464
|
PRICING_URL = "https://holdyourvoice.com/#pricing";
|
|
5464
5465
|
DASHBOARD_BILLING_URL = "https://holdyourvoice.com/dashboard?tab=billing";
|
|
5465
5466
|
}
|
|
@@ -17766,6 +17767,18 @@ var import_child_process4 = require("child_process");
|
|
|
17766
17767
|
// src/lib/cli-entry.ts
|
|
17767
17768
|
var fs18 = __toESM(require("fs"));
|
|
17768
17769
|
var path17 = __toESM(require("path"));
|
|
17770
|
+
|
|
17771
|
+
// src/lib/mcp-stdio.ts
|
|
17772
|
+
function isMcpStdioMode(opts) {
|
|
17773
|
+
if (opts?.stdio)
|
|
17774
|
+
return true;
|
|
17775
|
+
if (process.env.HYV_MCP_STDIO === "1" || process.env.HYV_MCP_STDIO === "true")
|
|
17776
|
+
return true;
|
|
17777
|
+
return !process.stdout.isTTY;
|
|
17778
|
+
}
|
|
17779
|
+
var MCP_SERVER_ARGS = ["mcp", "--stdio"];
|
|
17780
|
+
|
|
17781
|
+
// src/lib/cli-entry.ts
|
|
17769
17782
|
function resolveCliEntry() {
|
|
17770
17783
|
const candidates = [
|
|
17771
17784
|
path17.resolve(process.argv[1] || ""),
|
|
@@ -17777,9 +17790,9 @@ function resolveCliEntry() {
|
|
|
17777
17790
|
function mcpServerCommand() {
|
|
17778
17791
|
const entry = resolveCliEntry();
|
|
17779
17792
|
if (entry) {
|
|
17780
|
-
return { command: process.execPath, args: [entry,
|
|
17793
|
+
return { command: process.execPath, args: [entry, ...MCP_SERVER_ARGS] };
|
|
17781
17794
|
}
|
|
17782
|
-
return { command: "hyv", args: [
|
|
17795
|
+
return { command: "hyv", args: [...MCP_SERVER_ARGS] };
|
|
17783
17796
|
}
|
|
17784
17797
|
function mcpServerSnippet() {
|
|
17785
17798
|
const { command, args: args2 } = mcpServerCommand();
|
|
@@ -17792,9 +17805,9 @@ async function testMcpStdioSubprocess() {
|
|
|
17792
17805
|
if (!entry)
|
|
17793
17806
|
return { ok: false };
|
|
17794
17807
|
return new Promise((resolve18) => {
|
|
17795
|
-
const child = (0, import_child_process4.spawn)(process.execPath, [entry, "mcp"], {
|
|
17808
|
+
const child = (0, import_child_process4.spawn)(process.execPath, [entry, "mcp", "--stdio"], {
|
|
17796
17809
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17797
|
-
env: { ...process.env, HYV_POSTINSTALL_QUIET: "1" }
|
|
17810
|
+
env: { ...process.env, HYV_POSTINSTALL_QUIET: "1", HYV_MCP_STDIO: "1" }
|
|
17798
17811
|
});
|
|
17799
17812
|
let buffer = "";
|
|
17800
17813
|
let settled = false;
|
|
@@ -19159,16 +19172,17 @@ More: hyv content ci`
|
|
|
19159
19172
|
},
|
|
19160
19173
|
share: {
|
|
19161
19174
|
title: "Share your voice fingerprint",
|
|
19162
|
-
body: `Social post template:
|
|
19175
|
+
body: `Social post template (X / LinkedIn):
|
|
19163
19176
|
|
|
19164
19177
|
I run my AI drafts through @holdyourvoice/hyv before they ship.
|
|
19165
19178
|
|
|
19166
|
-
Free local scan caught
|
|
19179
|
+
Free local scan caught 34 patterns in 2 seconds \u2014 score 0/100. no API, offline.
|
|
19167
19180
|
|
|
19168
19181
|
Cursor/Claude agents can call hyv mcp tools directly.
|
|
19169
19182
|
|
|
19170
19183
|
Try: npx @holdyourvoice/hyv welcome
|
|
19171
19184
|
|
|
19185
|
+
${X_URL}
|
|
19172
19186
|
${COMMUNITY_URL}`
|
|
19173
19187
|
}
|
|
19174
19188
|
};
|
|
@@ -19448,7 +19462,7 @@ function formatChatGptConnectorGuide() {
|
|
|
19448
19462
|
"2. Settings \u2192 Connectors \u2192 Add connector",
|
|
19449
19463
|
"3. Name: **hold your voice**",
|
|
19450
19464
|
"4. Command: **hyv** (or absolute path below if connector fails)",
|
|
19451
|
-
"5. Arguments: **mcp**",
|
|
19465
|
+
"5. Arguments: **mcp --stdio**",
|
|
19452
19466
|
"",
|
|
19453
19467
|
"If the connector fails to start, use absolute paths:",
|
|
19454
19468
|
` command: ${mcpCmd.command}`,
|
|
@@ -20334,7 +20348,7 @@ function printMcpSetup() {
|
|
|
20334
20348
|
console.log(import_chalk35.default.dim(" Skill: ~/.commandcode/skills/hyv/SKILL.md\n"));
|
|
20335
20349
|
console.log(import_chalk35.default.bold("ChatGPT Desktop (manual connector)"));
|
|
20336
20350
|
console.log(import_chalk35.default.dim(" Settings \u2192 Connectors \u2192 add connector"));
|
|
20337
|
-
console.log(import_chalk35.default.dim(" Name: hold your voice | Command: hyv | Arguments: mcp"));
|
|
20351
|
+
console.log(import_chalk35.default.dim(" Name: hold your voice | Command: hyv | Arguments: mcp --stdio"));
|
|
20338
20352
|
console.log(import_chalk35.default.dim(" Guide: ~/.chatgpt/hyv-mcp-connector.txt (after hyv doctor --fix-agents)"));
|
|
20339
20353
|
console.log(import_chalk35.default.dim(" hyv mcp --setup-chatgpt"));
|
|
20340
20354
|
if (IS_WIN2) {
|
|
@@ -20638,7 +20652,7 @@ registerWelcomeCommand(program2);
|
|
|
20638
20652
|
registerContentCommand(program2);
|
|
20639
20653
|
registerUpgradeCommand(program2);
|
|
20640
20654
|
registerShareCommand(program2);
|
|
20641
|
-
program2.command("mcp").description("Detect installed apps, configure MCP, and start the MCP server").option("--setup", "Show MCP setup for Claude Desktop, Cursor, Windsurf, Codex").option("--test", "Run MCP health check (tools, profile, stdio)").option("--setup-chatgpt", "Show ChatGPT connector setup instructions").option("--force", "Force re-configure MCP even if already integrated").action(async (opts) => {
|
|
20655
|
+
program2.command("mcp").description("Detect installed apps, configure MCP, and start the MCP server").option("--setup", "Show MCP setup for Claude Desktop, Cursor, Windsurf, Codex").option("--test", "Run MCP health check (tools, profile, stdio)").option("--setup-chatgpt", "Show ChatGPT connector setup instructions").option("--force", "Force re-configure MCP even if already integrated").option("--stdio", "Stdio MCP mode \u2014 no stdout banners (auto when stdout is piped)").action(async (opts) => {
|
|
20642
20656
|
if (opts.setup) {
|
|
20643
20657
|
printMcpSetup();
|
|
20644
20658
|
return;
|
|
@@ -20675,7 +20689,7 @@ program2.command("mcp").description("Detect installed apps, configure MCP, and s
|
|
|
20675
20689
|
console.log(import_chalk36.default.dim(" 3. Add connector:"));
|
|
20676
20690
|
console.log(import_chalk36.default.dim(" Name: ") + import_chalk36.default.cyan("hold your voice"));
|
|
20677
20691
|
console.log(import_chalk36.default.dim(" Command: ") + import_chalk36.default.cyan("hyv") + import_chalk36.default.dim(" (full path on Windows if needed)"));
|
|
20678
|
-
console.log(import_chalk36.default.dim(" Arguments: ") + import_chalk36.default.cyan("mcp"));
|
|
20692
|
+
console.log(import_chalk36.default.dim(" Arguments: ") + import_chalk36.default.cyan("mcp --stdio"));
|
|
20679
20693
|
console.log(import_chalk36.default.dim(" 4. Save, restart ChatGPT Desktop"));
|
|
20680
20694
|
console.log(import_chalk36.default.dim(' 5. Test: "scan this with hold your voice"\n'));
|
|
20681
20695
|
console.log(import_chalk36.default.dim(" If connector fails to start, use full paths from:"));
|
|
@@ -20697,20 +20711,26 @@ program2.command("mcp").description("Detect installed apps, configure MCP, and s
|
|
|
20697
20711
|
console.log("");
|
|
20698
20712
|
return;
|
|
20699
20713
|
}
|
|
20700
|
-
|
|
20714
|
+
if (isMcpStdioMode(opts)) {
|
|
20715
|
+
await startMcpServer();
|
|
20716
|
+
return;
|
|
20717
|
+
}
|
|
20718
|
+
const err = (msg) => process.stderr.write(msg + "\n");
|
|
20719
|
+
err(import_chalk36.default.bold("\nhold your voice \u2014 detecting and configuring mcp...\n"));
|
|
20701
20720
|
const result = runMcpAutoIntegrate({ force: Boolean(opts.force) });
|
|
20721
|
+
const reportLines = [];
|
|
20722
|
+
const origLog = console.log;
|
|
20723
|
+
console.log = (...args2) => {
|
|
20724
|
+
reportLines.push(args2.map(String).join(" "));
|
|
20725
|
+
};
|
|
20702
20726
|
printMcpIntegrateReport(result, { force: Boolean(opts.force) });
|
|
20703
|
-
console.log
|
|
20704
|
-
|
|
20705
|
-
|
|
20706
|
-
|
|
20707
|
-
|
|
20708
|
-
|
|
20709
|
-
|
|
20710
|
-
console.log(import_chalk36.default.dim(" It auto-detects installed apps, configures MCP servers, and is ready"));
|
|
20711
|
-
console.log(import_chalk36.default.dim(" for scanning, rewriting, and voice-profile validation in any tool.\n"));
|
|
20712
|
-
console.log(import_chalk36.default.dim("\nstarting MCP server (press Ctrl+C to stop)...\n"));
|
|
20713
|
-
startMcpServer();
|
|
20727
|
+
console.log = origLog;
|
|
20728
|
+
for (const line of reportLines)
|
|
20729
|
+
err(line);
|
|
20730
|
+
err(import_chalk36.default.green.bold("\n\u2713 hold your voice \u2014 mcp setup complete\n"));
|
|
20731
|
+
err(import_chalk36.default.dim(" restart cursor / claude desktop if they were open during setup"));
|
|
20732
|
+
err(import_chalk36.default.dim("\nstarting MCP server (press Ctrl+C to stop) \u2014 JSON-RPC on stdout...\n"));
|
|
20733
|
+
await startMcpServer();
|
|
20714
20734
|
});
|
|
20715
20735
|
program2.command("export").description("Export voice profile for LLMs").argument("[format]", "Export format (claude, chatgpt, generic, cursor)", "claude").option("--output <file>", "Write to file instead of stdout").option("--json", "Output as JSON").action(async (format, opts) => {
|
|
20716
20736
|
await exportCommand(format, opts);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holdyourvoice/hyv",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.25",
|
|
4
4
|
"description": "Free local AI writing scan for cursor & claude. MCP server, 220+ pattern detection, voice profiles. npx @holdyourvoice/hyv welcome",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -78,9 +78,9 @@ function markOnboardingComplete(hyvDir, pkgVersion) {
|
|
|
78
78
|
function resolveHyvMcpCommand(pkgDir) {
|
|
79
79
|
const entry = path.join(pkgDir, 'dist', 'index.js');
|
|
80
80
|
if (fs.existsSync(entry)) {
|
|
81
|
-
return { command: process.execPath, args: [entry, 'mcp'] };
|
|
81
|
+
return { command: process.execPath, args: [entry, 'mcp', '--stdio'] };
|
|
82
82
|
}
|
|
83
|
-
return { command: 'hyv', args: ['mcp'] };
|
|
83
|
+
return { command: 'hyv', args: ['mcp', '--stdio'] };
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/** OpenCode local MCP uses a command array: [node, entry, mcp] */
|