patchcord 0.5.15 → 0.5.16

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.
Files changed (2) hide show
  1. package/bin/patchcord.mjs +174 -176
  2. package/package.json +1 -1
package/bin/patchcord.mjs CHANGED
@@ -97,6 +97,43 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
97
97
  } catch { return null; }
98
98
  }
99
99
 
100
+ // Read+merge+write a JSON config file. If the file exists but its contents
101
+ // can't be parsed, REFUSE to write — silently overwriting would erase
102
+ // unrelated MCP servers, settings, or hand-edits the user has in there.
103
+ // Returns true on success, false when skipped due to a parse failure (so
104
+ // the caller can suppress its "configured" message).
105
+ function updateJsonConfig(filePath, mutate) {
106
+ let parsed = {};
107
+ if (existsSync(filePath)) {
108
+ const raw = readFileSync(filePath, "utf-8");
109
+ try {
110
+ // JSONC-tolerant: Zed/Gemini settings allow //, /* */, trailing commas.
111
+ const cleaned = raw
112
+ .replace(/\/\/.*$/gm, "")
113
+ .replace(/\/\*[\s\S]*?\*\//g, "")
114
+ .replace(/,\s*([}\]])/g, "$1");
115
+ const result = cleaned.trim() ? JSON.parse(cleaned) : {};
116
+ // null / arrays / primitives aren't config objects we can merge into;
117
+ // refuse rather than blow them away.
118
+ if (result === null || typeof result !== "object" || Array.isArray(result)) {
119
+ console.log(`\n ${yellow}⚠${r} Skipped ${filePath} — existing file is not a JSON object.`);
120
+ console.log(` Replace it with a valid object ({...}) or remove it, then re-run.`);
121
+ return false;
122
+ }
123
+ parsed = result;
124
+ } catch {
125
+ console.log(`\n ${yellow}⚠${r} Skipped ${filePath} — could not parse existing JSON.`);
126
+ console.log(` Fix the file by hand and re-run the installer. We will not`);
127
+ console.log(` overwrite it: that would erase your other servers/settings.`);
128
+ return false;
129
+ }
130
+ }
131
+ mutate(parsed);
132
+ mkdirSync(dirname(filePath), { recursive: true });
133
+ writeFileSync(filePath, JSON.stringify(parsed, null, 2) + "\n");
134
+ return true;
135
+ }
136
+
100
137
  console.log(`
101
138
  ___ ____ ___ ____ _ _ ____ ____ ____ ___
102
139
  |__] |__| | | |__| | | | |__/ | \\
@@ -661,20 +698,14 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
661
698
  },
662
699
  };
663
700
 
664
- if (existsSync(cursorPath)) {
665
- try {
666
- const existing = JSON.parse(readFileSync(cursorPath, "utf-8"));
667
- existing.mcpServers = existing.mcpServers || {};
668
- existing.mcpServers.patchcord = cursorConfig.mcpServers.patchcord;
669
- writeFileSync(cursorPath, JSON.stringify(existing, null, 2) + "\n");
670
- } catch {
671
- writeFileSync(cursorPath, JSON.stringify(cursorConfig, null, 2) + "\n");
672
- }
673
- } else {
674
- writeFileSync(cursorPath, JSON.stringify(cursorConfig, null, 2) + "\n");
701
+ const cursorOk = updateJsonConfig(cursorPath, (obj) => {
702
+ obj.mcpServers = obj.mcpServers || {};
703
+ obj.mcpServers.patchcord = cursorConfig.mcpServers.patchcord;
704
+ });
705
+ if (cursorOk) {
706
+ console.log(`\n ${green}✓${r} Cursor configured: ${dim}${cursorPath}${r}`);
707
+ console.log(` ${dim}Per-project only — other projects won't see this agent.${r}`);
675
708
  }
676
- console.log(`\n ${green}✓${r} Cursor configured: ${dim}${cursorPath}${r}`);
677
- console.log(` ${dim}Per-project only — other projects won't see this agent.${r}`);
678
709
  } else if (isWindsurf) {
679
710
  // Windsurf: global only (~/.codeium/windsurf/mcp_config.json)
680
711
  const wsPath = join(HOME, ".codeium", "windsurf", "mcp_config.json");
@@ -690,84 +721,72 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
690
721
  },
691
722
  };
692
723
 
693
- if (existsSync(wsPath)) {
694
- try {
695
- const content = readFileSync(wsPath, "utf-8").trim();
696
- const existing = content ? JSON.parse(content) : {};
697
- existing.mcpServers = existing.mcpServers || {};
698
- existing.mcpServers.patchcord = wsConfig.mcpServers.patchcord;
699
- writeFileSync(wsPath, JSON.stringify(existing, null, 2) + "\n");
700
- } catch {
701
- writeFileSync(wsPath, JSON.stringify(wsConfig, null, 2) + "\n");
702
- }
703
- } else {
704
- mkdirSync(join(HOME, ".codeium", "windsurf"), { recursive: true });
705
- writeFileSync(wsPath, JSON.stringify(wsConfig, null, 2) + "\n");
724
+ const wsOk = updateJsonConfig(wsPath, (obj) => {
725
+ obj.mcpServers = obj.mcpServers || {};
726
+ obj.mcpServers.patchcord = wsConfig.mcpServers.patchcord;
727
+ });
728
+ if (wsOk) {
729
+ console.log(`\n ${green}✓${r} Windsurf configured: ${dim}${wsPath}${r}`);
730
+ console.log(` ${yellow}Global config all Windsurf projects share this agent.${r}`);
706
731
  }
707
- console.log(`\n ${green}✓${r} Windsurf configured: ${dim}${wsPath}${r}`);
708
- console.log(` ${yellow}Global config — all Windsurf projects share this agent.${r}`);
709
732
  } else if (isGemini) {
710
733
  // Gemini CLI: global only (~/.gemini/settings.json)
711
734
  const geminiPath = join(HOME, ".gemini", "settings.json");
712
- let geminiSettings = (existsSync(geminiPath) && safeReadJson(geminiPath)) || {};
713
- if (!geminiSettings.mcpServers) geminiSettings.mcpServers = {};
714
- geminiSettings.mcpServers.patchcord = {
715
- httpUrl: `${serverUrl}/mcp`,
716
- headers: {
717
- Authorization: `Bearer ${token}`,
718
- "X-Patchcord-Machine": hostname,
719
- },
720
- };
721
- // Clean up deprecated tools.allowed if present (removed in Gemini CLI 1.0)
722
- if (geminiSettings.tools?.allowed) {
723
- geminiSettings.tools.allowed = geminiSettings.tools.allowed.filter(t => !t.startsWith("mcp_patchcord_"));
724
- if (geminiSettings.tools.allowed.length === 0) delete geminiSettings.tools;
735
+ const geminiOk = updateJsonConfig(geminiPath, (obj) => {
736
+ obj.mcpServers = obj.mcpServers || {};
737
+ obj.mcpServers.patchcord = {
738
+ httpUrl: `${serverUrl}/mcp`,
739
+ headers: {
740
+ Authorization: `Bearer ${token}`,
741
+ "X-Patchcord-Machine": hostname,
742
+ },
743
+ };
744
+ // Clean up deprecated tools.allowed if present (removed in Gemini CLI 1.0)
745
+ if (obj.tools?.allowed) {
746
+ obj.tools.allowed = obj.tools.allowed.filter(t => !t.startsWith("mcp_patchcord_"));
747
+ if (obj.tools.allowed.length === 0) delete obj.tools;
748
+ }
749
+ });
750
+ if (geminiOk) {
751
+ console.log(`\n ${green}✓${r} Gemini CLI configured: ${dim}${geminiPath}${r}`);
752
+ console.log(` ${yellow}Global config — all Gemini CLI projects share this agent.${r}`);
725
753
  }
726
- mkdirSync(join(HOME, ".gemini"), { recursive: true });
727
- writeFileSync(geminiPath, JSON.stringify(geminiSettings, null, 2) + "\n");
728
- console.log(`\n ${green}✓${r} Gemini CLI configured: ${dim}${geminiPath}${r}`);
729
- console.log(` ${yellow}Global config — all Gemini CLI projects share this agent.${r}`);
730
754
  } else if (isZed) {
731
755
  // Zed: global settings.json → context_servers
732
756
  const zedPath = process.platform === "darwin"
733
757
  ? join(HOME, "Library", "Application Support", "Zed", "settings.json")
734
758
  : join(HOME, ".config", "zed", "settings.json");
735
- let zedSettings = (existsSync(zedPath) && safeReadJson(zedPath)) || {};
736
- if (!zedSettings.context_servers) zedSettings.context_servers = {};
737
- zedSettings.context_servers.patchcord = {
738
- url: `${serverUrl}/mcp`,
739
- headers: {
740
- Authorization: `Bearer ${token}`,
741
- "X-Patchcord-Machine": hostname,
742
- },
743
- };
744
- const zedDir = process.platform === "darwin"
745
- ? join(HOME, "Library", "Application Support", "Zed")
746
- : join(HOME, ".config", "zed");
747
- mkdirSync(zedDir, { recursive: true });
748
- writeFileSync(zedPath, JSON.stringify(zedSettings, null, 2) + "\n");
749
- console.log(`\n ${green}✓${r} Zed configured: ${dim}${zedPath}${r}`);
750
- console.log(` ${yellow}Global config — all Zed projects share this agent.${r}`);
759
+ const zedOk = updateJsonConfig(zedPath, (obj) => {
760
+ obj.context_servers = obj.context_servers || {};
761
+ obj.context_servers.patchcord = {
762
+ url: `${serverUrl}/mcp`,
763
+ headers: {
764
+ Authorization: `Bearer ${token}`,
765
+ "X-Patchcord-Machine": hostname,
766
+ },
767
+ };
768
+ });
769
+ if (zedOk) {
770
+ console.log(`\n ${green}✓${r} Zed configured: ${dim}${zedPath}${r}`);
771
+ console.log(` ${yellow}Global config all Zed projects share this agent.${r}`);
772
+ }
751
773
  } else if (isOpenCode) {
752
774
  // OpenCode: per-project opencode.json → mcp
753
775
  const ocPath = join(cwd, "opencode.json");
754
- let ocConfig = {};
755
- if (existsSync(ocPath)) {
756
- try {
757
- ocConfig = JSON.parse(readFileSync(ocPath, "utf-8"));
758
- } catch {}
776
+ const ocOk = updateJsonConfig(ocPath, (obj) => {
777
+ obj.mcp = obj.mcp || {};
778
+ obj.mcp.patchcord = {
779
+ type: "remote",
780
+ url: `${serverUrl}/mcp`,
781
+ headers: {
782
+ Authorization: `Bearer ${token}`,
783
+ "X-Patchcord-Machine": hostname,
784
+ },
785
+ };
786
+ });
787
+ if (ocOk) {
788
+ console.log(`\n ${green}✓${r} OpenCode configured: ${dim}${ocPath}${r}`);
759
789
  }
760
- if (!ocConfig.mcp) ocConfig.mcp = {};
761
- ocConfig.mcp.patchcord = {
762
- type: "remote",
763
- url: `${serverUrl}/mcp`,
764
- headers: {
765
- Authorization: `Bearer ${token}`,
766
- "X-Patchcord-Machine": hostname,
767
- },
768
- };
769
- writeFileSync(ocPath, JSON.stringify(ocConfig, null, 2) + "\n");
770
- console.log(`\n ${green}✓${r} OpenCode configured: ${dim}${ocPath}${r}`);
771
790
  } else if (isOpenClaw) {
772
791
  // OpenClaw: global ~/.openclaw/openclaw.json → mcp.servers
773
792
  // Try CLI first, fall back to direct file write
@@ -785,28 +804,23 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
785
804
  console.log(`\n ${green}✓${r} OpenClaw configured via CLI: ${dim}openclaw mcp set${r}`);
786
805
  } else {
787
806
  // CLI not available — write config directly
788
- const openclawDir = join(HOME, ".openclaw");
789
- const openclawPath = join(openclawDir, "openclaw.json");
790
- let openclawConfig = {};
791
- if (existsSync(openclawPath)) {
792
- try {
793
- openclawConfig = JSON.parse(readFileSync(openclawPath, "utf-8"));
794
- } catch {}
807
+ const openclawPath = join(HOME, ".openclaw", "openclaw.json");
808
+ const openclawOk = updateJsonConfig(openclawPath, (obj) => {
809
+ obj.mcp = obj.mcp || {};
810
+ obj.mcp.servers = obj.mcp.servers || {};
811
+ obj.mcp.servers.patchcord = {
812
+ url: `${serverUrl}/mcp`,
813
+ transport: "streamable-http",
814
+ headers: {
815
+ Authorization: `Bearer ${token}`,
816
+ "X-Patchcord-Machine": hostname,
817
+ },
818
+ connectionTimeoutMs: 300000,
819
+ };
820
+ });
821
+ if (openclawOk) {
822
+ console.log(`\n ${green}✓${r} OpenClaw configured: ${dim}${openclawPath}${r}`);
795
823
  }
796
- if (!openclawConfig.mcp) openclawConfig.mcp = {};
797
- if (!openclawConfig.mcp.servers) openclawConfig.mcp.servers = {};
798
- openclawConfig.mcp.servers.patchcord = {
799
- url: `${serverUrl}/mcp`,
800
- transport: "streamable-http",
801
- headers: {
802
- Authorization: `Bearer ${token}`,
803
- "X-Patchcord-Machine": hostname,
804
- },
805
- connectionTimeoutMs: 300000,
806
- };
807
- mkdirSync(openclawDir, { recursive: true });
808
- writeFileSync(openclawPath, JSON.stringify(openclawConfig, null, 2) + "\n");
809
- console.log(`\n ${green}✓${r} OpenClaw configured: ${dim}${openclawPath}${r}`);
810
824
  }
811
825
  console.log(` ${yellow}Global config — all OpenClaw channels share this agent.${r}`);
812
826
  console.log(` ${dim}Run: openclaw gateway restart${r}`);
@@ -818,32 +832,28 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
818
832
  // Antigravity: global ~/.gemini/antigravity/mcp_config.json → mcpServers
819
833
  const agDir = join(HOME, ".gemini", "antigravity");
820
834
  const agPath = join(agDir, "mcp_config.json");
821
- let agConfig = {};
822
- if (existsSync(agPath)) {
823
- try {
824
- agConfig = JSON.parse(readFileSync(agPath, "utf-8"));
825
- } catch {}
835
+ const agOk = updateJsonConfig(agPath, (obj) => {
836
+ obj.mcpServers = obj.mcpServers || {};
837
+ obj.mcpServers.patchcord = {
838
+ serverUrl: `${serverUrl}/mcp`,
839
+ headers: {
840
+ Authorization: `Bearer ${token}`,
841
+ "X-Patchcord-Machine": hostname,
842
+ },
843
+ };
844
+ });
845
+ if (agOk) {
846
+ console.log(`\n ${green}✓${r} Antigravity configured: ${dim}${agPath}${r}`);
847
+ // Install global skills
848
+ const agSkillDir = join(agDir, "skills", "patchcord");
849
+ const agWaitDir = join(agDir, "skills", "patchcord-wait");
850
+ mkdirSync(agSkillDir, { recursive: true });
851
+ mkdirSync(agWaitDir, { recursive: true });
852
+ cpSync(join(pluginRoot, "skills", "inbox", "SKILL.md"), join(agSkillDir, "SKILL.md"));
853
+ cpSync(join(pluginRoot, "skills", "wait", "SKILL.md"), join(agWaitDir, "SKILL.md"));
854
+ console.log(` ${green}✓${r} Skills installed: ${dim}patchcord${r}, ${dim}patchcord-wait${r}`);
855
+ console.log(` ${yellow}Global config — all Antigravity projects share this agent.${r}`);
826
856
  }
827
- if (!agConfig.mcpServers) agConfig.mcpServers = {};
828
- agConfig.mcpServers.patchcord = {
829
- serverUrl: `${serverUrl}/mcp`,
830
- headers: {
831
- Authorization: `Bearer ${token}`,
832
- "X-Patchcord-Machine": hostname,
833
- },
834
- };
835
- mkdirSync(agDir, { recursive: true });
836
- writeFileSync(agPath, JSON.stringify(agConfig, null, 2) + "\n");
837
- console.log(`\n ${green}✓${r} Antigravity configured: ${dim}${agPath}${r}`);
838
- // Install global skills
839
- const agSkillDir = join(agDir, "skills", "patchcord");
840
- const agWaitDir = join(agDir, "skills", "patchcord-wait");
841
- mkdirSync(agSkillDir, { recursive: true });
842
- mkdirSync(agWaitDir, { recursive: true });
843
- cpSync(join(pluginRoot, "skills", "inbox", "SKILL.md"), join(agSkillDir, "SKILL.md"));
844
- cpSync(join(pluginRoot, "skills", "wait", "SKILL.md"), join(agWaitDir, "SKILL.md"));
845
- console.log(` ${green}✓${r} Skills installed: ${dim}patchcord${r}, ${dim}patchcord-wait${r}`);
846
- console.log(` ${yellow}Global config — all Antigravity projects share this agent.${r}`);
847
857
  } else if (isCline) {
848
858
  // Cline VS Code extension: global cline_mcp_settings.json
849
859
  // Config lives in VS Code's globalStorage for saoudrizwan.claude-dev
@@ -884,24 +894,22 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
884
894
  }
885
895
 
886
896
  const clinePath = join(clineSettingsDir, "cline_mcp_settings.json");
887
- let clineConfig = {};
888
- if (existsSync(clinePath)) {
889
- try { clineConfig = JSON.parse(readFileSync(clinePath, "utf-8")); } catch {}
897
+ const clineOk = updateJsonConfig(clinePath, (obj) => {
898
+ obj.mcpServers = obj.mcpServers || {};
899
+ obj.mcpServers.patchcord = {
900
+ url: `${serverUrl}/mcp`,
901
+ headers: {
902
+ Authorization: `Bearer ${token}`,
903
+ "X-Patchcord-Machine": hostname,
904
+ },
905
+ disabled: false,
906
+ alwaysAllow: [],
907
+ };
908
+ });
909
+ if (clineOk) {
910
+ console.log(`\n ${green}✓${r} Cline configured: ${dim}${clinePath}${r}`);
911
+ console.log(` ${yellow}Global config — all Cline projects share this agent.${r}`);
890
912
  }
891
- if (!clineConfig.mcpServers) clineConfig.mcpServers = {};
892
- clineConfig.mcpServers.patchcord = {
893
- url: `${serverUrl}/mcp`,
894
- headers: {
895
- Authorization: `Bearer ${token}`,
896
- "X-Patchcord-Machine": hostname,
897
- },
898
- disabled: false,
899
- alwaysAllow: [],
900
- };
901
- mkdirSync(clineSettingsDir, { recursive: true });
902
- writeFileSync(clinePath, JSON.stringify(clineConfig, null, 2) + "\n");
903
- console.log(`\n ${green}✓${r} Cline configured: ${dim}${clinePath}${r}`);
904
- console.log(` ${yellow}Global config — all Cline projects share this agent.${r}`);
905
913
  } else if (isVSCode) {
906
914
  // VS Code: write .vscode/mcp.json (per-project)
907
915
  const vscodeDir = join(cwd, ".vscode");
@@ -920,20 +928,14 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
920
928
  },
921
929
  };
922
930
 
923
- if (existsSync(vscodePath)) {
924
- try {
925
- const existing = JSON.parse(readFileSync(vscodePath, "utf-8"));
926
- existing.servers = existing.servers || {};
927
- existing.servers.patchcord = vscodeConfig.servers.patchcord;
928
- writeFileSync(vscodePath, JSON.stringify(existing, null, 2) + "\n");
929
- } catch {
930
- writeFileSync(vscodePath, JSON.stringify(vscodeConfig, null, 2) + "\n");
931
- }
932
- } else {
933
- writeFileSync(vscodePath, JSON.stringify(vscodeConfig, null, 2) + "\n");
931
+ const vscodeOk = updateJsonConfig(vscodePath, (obj) => {
932
+ obj.servers = obj.servers || {};
933
+ obj.servers.patchcord = vscodeConfig.servers.patchcord;
934
+ });
935
+ if (vscodeOk) {
936
+ console.log(`\n ${green}✓${r} VS Code configured: ${dim}${vscodePath}${r}`);
937
+ console.log(` ${dim}Requires GitHub Copilot extension with agent mode enabled.${r}`);
934
938
  }
935
- console.log(`\n ${green}✓${r} VS Code configured: ${dim}${vscodePath}${r}`);
936
- console.log(` ${dim}Requires GitHub Copilot extension with agent mode enabled.${r}`);
937
939
  } else if (isCodex) {
938
940
  // Codex: write MCP config + per-project skills + global plugin
939
941
  // Per-project skills (working @patchcord in Codex v0.117)
@@ -1010,19 +1012,17 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
1010
1012
 
1011
1013
  // Personal marketplace entry (relative path from marketplace root)
1012
1014
  const marketplacePath = join(marketplaceDir, "marketplace.json");
1013
- let marketplace = { name: "patchcord", interface: { displayName: "Patchcord" }, plugins: [] };
1014
- if (existsSync(marketplacePath)) {
1015
- try { marketplace = JSON.parse(readFileSync(marketplacePath, "utf-8")); } catch {}
1016
- }
1017
- if (!marketplace.plugins) marketplace.plugins = [];
1018
- marketplace.plugins = marketplace.plugins.filter(p => p.name !== "patchcord");
1019
- marketplace.plugins.push({
1020
- name: "patchcord",
1021
- source: { source: "local", path: "./patchcord" },
1022
- policy: { installation: "INSTALLED_BY_DEFAULT", authentication: "ON_INSTALL" },
1023
- category: "Productivity",
1015
+ updateJsonConfig(marketplacePath, (obj) => {
1016
+ if (!obj.name) obj.name = "patchcord";
1017
+ if (!obj.interface) obj.interface = { displayName: "Patchcord" };
1018
+ obj.plugins = (obj.plugins || []).filter(p => p.name !== "patchcord");
1019
+ obj.plugins.push({
1020
+ name: "patchcord",
1021
+ source: { source: "local", path: "./patchcord" },
1022
+ policy: { installation: "INSTALLED_BY_DEFAULT", authentication: "ON_INSTALL" },
1023
+ category: "Productivity",
1024
+ });
1024
1025
  });
1025
- writeFileSync(marketplacePath, JSON.stringify(marketplace, null, 2) + "\n");
1026
1026
 
1027
1027
  // Also install global skills (working @patchcord — plugin/read broken in Codex v0.117)
1028
1028
  const globalSkillDir = join(homedir(), ".agents", "skills", "patchcord");
@@ -1052,17 +1052,15 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
1052
1052
  },
1053
1053
  };
1054
1054
 
1055
- if (existsSync(mcpPath)) {
1056
- try {
1057
- const existing = JSON.parse(readFileSync(mcpPath, "utf-8"));
1058
- existing.mcpServers = existing.mcpServers || {};
1059
- existing.mcpServers.patchcord = mcpConfig.mcpServers.patchcord;
1060
- writeFileSync(mcpPath, JSON.stringify(existing, null, 2) + "\n");
1061
- } catch {
1062
- writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2) + "\n");
1063
- }
1064
- } else {
1065
- writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2) + "\n");
1055
+ const mcpOk = updateJsonConfig(mcpPath, (obj) => {
1056
+ obj.mcpServers = obj.mcpServers || {};
1057
+ obj.mcpServers.patchcord = mcpConfig.mcpServers.patchcord;
1058
+ });
1059
+ if (!mcpOk) {
1060
+ // Existing .mcp.json was malformed helper already explained.
1061
+ // Bail with non-zero so wrapper scripts notice; the user fixes
1062
+ // their JSON and re-runs.
1063
+ process.exit(1);
1066
1064
  }
1067
1065
  console.log(`\n ${green}✓${r} Claude Code configured: ${dim}${mcpPath}${r}`);
1068
1066
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchcord",
3
- "version": "0.5.15",
3
+ "version": "0.5.16",
4
4
  "description": "Cross-machine agent messaging for Claude Code and Codex",
5
5
  "author": "ppravdin",
6
6
  "license": "MIT",