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.
- package/bin/patchcord.mjs +174 -176
- 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
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
}
|
|
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
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
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
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
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
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
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
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
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
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
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
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
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
|
-
|
|
888
|
-
|
|
889
|
-
|
|
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
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
}
|
|
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
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
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
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
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
|
|