patchcord 0.3.95 → 0.3.96

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "patchcord",
3
3
  "description": "Cross-machine agent messaging with push delivery. Messages from other agents arrive as native channel notifications.",
4
- "version": "0.4.0",
4
+ "version": "0.3.96",
5
5
  "author": {
6
6
  "name": "ppravdin"
7
7
  },
package/bin/patchcord.mjs CHANGED
@@ -173,12 +173,12 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
173
173
  let cursorChanged = false;
174
174
  if (!existsSync(cursorSkillDir)) {
175
175
  mkdirSync(cursorSkillDir, { recursive: true });
176
- cpSync(join(pluginRoot, "skills", "inbox", "SKILL.md"), join(cursorSkillDir, "SKILL.md"));
176
+ cpSync(join(pluginRoot, "skills", "patchcord", "SKILL.md"), join(cursorSkillDir, "SKILL.md"));
177
177
  cursorChanged = true;
178
178
  }
179
179
  if (!existsSync(cursorWaitDir)) {
180
180
  mkdirSync(cursorWaitDir, { recursive: true });
181
- cpSync(join(pluginRoot, "skills", "wait", "SKILL.md"), join(cursorWaitDir, "SKILL.md"));
181
+ cpSync(join(pluginRoot, "skills", "patchcord-wait", "SKILL.md"), join(cursorWaitDir, "SKILL.md"));
182
182
  cursorChanged = true;
183
183
  }
184
184
  if (cursorChanged) globalChanges.push("Cursor skills installed");
@@ -191,12 +191,12 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
191
191
  let windsurfChanged = false;
192
192
  if (!existsSync(windsurfSkillDir)) {
193
193
  mkdirSync(windsurfSkillDir, { recursive: true });
194
- cpSync(join(pluginRoot, "skills", "inbox", "SKILL.md"), join(windsurfSkillDir, "SKILL.md"));
194
+ cpSync(join(pluginRoot, "skills", "patchcord", "SKILL.md"), join(windsurfSkillDir, "SKILL.md"));
195
195
  windsurfChanged = true;
196
196
  }
197
197
  if (!existsSync(windsurfWaitDir)) {
198
198
  mkdirSync(windsurfWaitDir, { recursive: true });
199
- cpSync(join(pluginRoot, "skills", "wait", "SKILL.md"), join(windsurfWaitDir, "SKILL.md"));
199
+ cpSync(join(pluginRoot, "skills", "patchcord-wait", "SKILL.md"), join(windsurfWaitDir, "SKILL.md"));
200
200
  windsurfChanged = true;
201
201
  }
202
202
  if (windsurfChanged) globalChanges.push("Windsurf skills installed");
@@ -210,12 +210,12 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
210
210
  let geminiChanged = false;
211
211
  if (!existsSync(geminiSkillDir)) {
212
212
  mkdirSync(geminiSkillDir, { recursive: true });
213
- cpSync(join(pluginRoot, "skills", "inbox", "SKILL.md"), join(geminiSkillDir, "SKILL.md"));
213
+ cpSync(join(pluginRoot, "skills", "patchcord", "SKILL.md"), join(geminiSkillDir, "SKILL.md"));
214
214
  geminiChanged = true;
215
215
  }
216
216
  if (!existsSync(geminiWaitDir)) {
217
217
  mkdirSync(geminiWaitDir, { recursive: true });
218
- cpSync(join(pluginRoot, "skills", "wait", "SKILL.md"), join(geminiWaitDir, "SKILL.md"));
218
+ cpSync(join(pluginRoot, "skills", "patchcord-wait", "SKILL.md"), join(geminiWaitDir, "SKILL.md"));
219
219
  geminiChanged = true;
220
220
  }
221
221
  if (!existsSync(join(geminiCmdDir, "patchcord.toml"))) {
@@ -264,6 +264,7 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
264
264
  const CLIENT_TYPE_MAP = {
265
265
  "claude_code": "1", "codex": "2", "cursor": "3", "windsurf": "4",
266
266
  "gemini": "5", "vscode": "6", "zed": "7", "opencode": "8", "openclaw": "9", "antigravity": "10",
267
+ "cline": "11",
267
268
  };
268
269
 
269
270
 
@@ -298,9 +299,9 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
298
299
  console.log(` ${cyan}2.${r} Codex CLI ${cyan}6.${r} VS Code`);
299
300
  console.log(` ${cyan}3.${r} Cursor ${cyan}7.${r} Zed`);
300
301
  console.log(` ${cyan}4.${r} Windsurf ${cyan}8.${r} OpenCode`);
301
- console.log(` ${cyan}9.${r} OpenClaw\n`);
302
- choice = (await ask(`${dim}Choose (1-9):${r} `)).trim();
303
- if (!["1","2","3","4","5","6","7","8","9"].includes(choice)) {
302
+ console.log(` ${cyan}11.${r} Cline ${cyan}9.${r} OpenClaw\n`);
303
+ choice = (await ask(`${dim}Choose (1-9, 11):${r} `)).trim();
304
+ if (!["1","2","3","4","5","6","7","8","9","11"].includes(choice)) {
304
305
  console.error("Invalid choice.");
305
306
  rl.close();
306
307
  process.exit(1);
@@ -566,6 +567,7 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
566
567
  const isOpenCode = choice === "8";
567
568
  const isOpenClaw = choice === "9";
568
569
  const isAntigravity = choice === "10";
570
+ const isCline = choice === "11";
569
571
 
570
572
  const hostname = run("hostname -s") || run("hostname") || "unknown";
571
573
 
@@ -765,10 +767,68 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
765
767
  const agWaitDir = join(agDir, "skills", "patchcord-wait");
766
768
  mkdirSync(agSkillDir, { recursive: true });
767
769
  mkdirSync(agWaitDir, { recursive: true });
768
- cpSync(join(pluginRoot, "skills", "inbox", "SKILL.md"), join(agSkillDir, "SKILL.md"));
769
- cpSync(join(pluginRoot, "skills", "wait", "SKILL.md"), join(agWaitDir, "SKILL.md"));
770
+ cpSync(join(pluginRoot, "skills", "patchcord", "SKILL.md"), join(agSkillDir, "SKILL.md"));
771
+ cpSync(join(pluginRoot, "skills", "patchcord-wait", "SKILL.md"), join(agWaitDir, "SKILL.md"));
770
772
  console.log(` ${green}✓${r} Skills installed: ${dim}patchcord${r}, ${dim}patchcord-wait${r}`);
771
773
  console.log(` ${yellow}Global config — all Antigravity projects share this agent.${r}`);
774
+ } else if (isCline) {
775
+ // Cline VS Code extension: global cline_mcp_settings.json
776
+ // Config lives in VS Code's globalStorage for saoudrizwan.claude-dev
777
+ // Try stable VS Code first, then Insiders, then Cursor
778
+ const vsCodeVariants = process.platform === "darwin"
779
+ ? [
780
+ join(HOME, "Library", "Application Support", "Code", "User", "globalStorage"),
781
+ join(HOME, "Library", "Application Support", "Code - Insiders", "User", "globalStorage"),
782
+ join(HOME, "Library", "Application Support", "Cursor", "User", "globalStorage"),
783
+ ]
784
+ : process.platform === "win32"
785
+ ? [
786
+ join(process.env.APPDATA || join(HOME, "AppData", "Roaming"), "Code", "User", "globalStorage"),
787
+ join(process.env.APPDATA || join(HOME, "AppData", "Roaming"), "Code - Insiders", "User", "globalStorage"),
788
+ join(process.env.APPDATA || join(HOME, "AppData", "Roaming"), "Cursor", "User", "globalStorage"),
789
+ ]
790
+ : [
791
+ join(HOME, ".config", "Code", "User", "globalStorage"),
792
+ join(HOME, ".config", "Code - Insiders", "User", "globalStorage"),
793
+ join(HOME, ".config", "Cursor", "User", "globalStorage"),
794
+ ];
795
+
796
+ // Find the first variant that has Cline's globalStorage directory (or exists at all)
797
+ const clineExtDir = "saoudrizwan.claude-dev";
798
+ let clineSettingsDir = null;
799
+ for (const base of vsCodeVariants) {
800
+ const candidate = join(base, clineExtDir, "settings");
801
+ const extDir = join(base, clineExtDir);
802
+ if (existsSync(extDir)) {
803
+ clineSettingsDir = candidate;
804
+ break;
805
+ }
806
+ }
807
+ // Fall back to stable VS Code path even if it doesn't exist yet
808
+ if (!clineSettingsDir) {
809
+ const fallbackBase = vsCodeVariants[0];
810
+ clineSettingsDir = join(fallbackBase, clineExtDir, "settings");
811
+ }
812
+
813
+ const clinePath = join(clineSettingsDir, "cline_mcp_settings.json");
814
+ let clineConfig = {};
815
+ if (existsSync(clinePath)) {
816
+ try { clineConfig = JSON.parse(readFileSync(clinePath, "utf-8")); } catch {}
817
+ }
818
+ if (!clineConfig.mcpServers) clineConfig.mcpServers = {};
819
+ clineConfig.mcpServers.patchcord = {
820
+ url: `${serverUrl}/mcp`,
821
+ headers: {
822
+ Authorization: `Bearer ${token}`,
823
+ "X-Patchcord-Machine": hostname,
824
+ },
825
+ disabled: false,
826
+ alwaysAllow: [],
827
+ };
828
+ mkdirSync(clineSettingsDir, { recursive: true });
829
+ writeFileSync(clinePath, JSON.stringify(clineConfig, null, 2) + "\n");
830
+ console.log(`\n ${green}✓${r} Cline configured: ${dim}${clinePath}${r}`);
831
+ console.log(` ${yellow}Global config — all Cline projects share this agent.${r}`);
772
832
  } else if (isVSCode) {
773
833
  // VS Code: write .vscode/mcp.json (per-project)
774
834
  const vscodeDir = join(cwd, ".vscode");
@@ -811,7 +871,7 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
811
871
  const waitDest = join(cwd, ".agents", "skills", "patchcord-wait");
812
872
  mkdirSync(waitDest, { recursive: true });
813
873
  writeFileSync(join(waitDest, "SKILL.md"),
814
- readFileSync(join(pluginRoot, "skills", "wait", "SKILL.md"), "utf-8"));
874
+ readFileSync(join(pluginRoot, "skills", "patchcord-wait", "SKILL.md"), "utf-8"));
815
875
 
816
876
  const codexDir = join(cwd, ".codex");
817
877
  mkdirSync(codexDir, { recursive: true });
@@ -873,7 +933,7 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
873
933
  writeFileSync(join(pluginDir, "skills", "patchcord", "SKILL.md"),
874
934
  readFileSync(join(pluginRoot, "per-project-skills", "codex", "SKILL.md"), "utf-8"));
875
935
  writeFileSync(join(pluginDir, "skills", "patchcord-wait", "SKILL.md"),
876
- readFileSync(join(pluginRoot, "skills", "wait", "SKILL.md"), "utf-8"));
936
+ readFileSync(join(pluginRoot, "skills", "patchcord-wait", "SKILL.md"), "utf-8"));
877
937
 
878
938
  // Personal marketplace entry (relative path from marketplace root)
879
939
  const marketplacePath = join(marketplaceDir, "marketplace.json");
@@ -899,7 +959,7 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
899
959
  const globalWaitDir = join(homedir(), ".agents", "skills", "patchcord-wait");
900
960
  mkdirSync(globalWaitDir, { recursive: true });
901
961
  writeFileSync(join(globalWaitDir, "SKILL.md"),
902
- readFileSync(join(pluginRoot, "skills", "wait", "SKILL.md"), "utf-8"));
962
+ readFileSync(join(pluginRoot, "skills", "patchcord-wait", "SKILL.md"), "utf-8"));
903
963
 
904
964
  console.log(`\n ${green}✓${r} Codex configured: ${dim}${configPath}${r}`);
905
965
  console.log(` ${green}✓${r} Plugin installed: ${dim}@patchcord${r}, ${dim}@patchcord-wait${r}`);
@@ -944,24 +1004,27 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
944
1004
  }
945
1005
 
946
1006
  // Warn about gitignore for per-project configs with tokens
947
- if (!isWindsurf && !isGemini && !isZed && !isOpenClaw && !isAntigravity) {
1007
+ if (!isWindsurf && !isGemini && !isZed && !isOpenClaw && !isAntigravity && !isCline) {
948
1008
  const gitignorePath = join(cwd, ".gitignore");
949
1009
  const configFile = isCodex ? ".codex/config.toml" : isCursor ? ".cursor/mcp.json" : isVSCode ? ".vscode/mcp.json" : isOpenCode ? "opencode.json" : ".mcp.json";
950
1010
  let needsWarning = true;
951
1011
  if (existsSync(gitignorePath)) {
952
1012
  const gi = readFileSync(gitignorePath, "utf-8");
953
- if (gi.includes(configFile) || gi.includes(".mcp.json") || gi.includes(".codex/") || gi.includes(".cursor/")) {
954
- needsWarning = false;
955
- }
1013
+ // Only check patterns relevant to this agent's config file
1014
+ const patterns = [configFile];
1015
+ if (isCodex) patterns.push(".codex/");
1016
+ else if (isCursor) patterns.push(".cursor/");
1017
+ else if (isVSCode) patterns.push(".vscode/");
1018
+ if (patterns.some(p => gi.includes(p))) needsWarning = false;
956
1019
  }
957
1020
  if (needsWarning) {
958
1021
  console.log(`\n ${yellow}⚠ Add ${configFile} to .gitignore — it contains your token${r}`);
959
1022
  }
960
1023
  }
961
1024
 
962
- const toolName = isAntigravity ? "Antigravity" : isOpenClaw ? "OpenClaw" : isOpenCode ? "OpenCode" : isZed ? "Zed" : isVSCode ? "VS Code" : isGemini ? "Gemini CLI" : isWindsurf ? "Windsurf" : isCursor ? "Cursor" : isCodex ? "Codex" : "Claude Code";
1025
+ const toolName = isAntigravity ? "Antigravity" : isCline ? "Cline" : isOpenClaw ? "OpenClaw" : isOpenCode ? "OpenCode" : isZed ? "Zed" : isVSCode ? "VS Code" : isGemini ? "Gemini CLI" : isWindsurf ? "Windsurf" : isCursor ? "Cursor" : isCodex ? "Codex" : "Claude Code";
963
1026
 
964
- if (!isWindsurf && !isGemini && !isZed && !isOpenClaw && !isAntigravity) {
1027
+ if (!isWindsurf && !isGemini && !isZed && !isOpenClaw && !isAntigravity && !isCline) {
965
1028
  console.log(`\n ${dim}To connect a second agent:${r}`);
966
1029
  console.log(` ${dim}cd into another project and run${r} ${bold}npx patchcord@latest${r} ${dim}there.${r}`);
967
1030
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchcord",
3
- "version": "0.3.95",
3
+ "version": "0.3.96",
4
4
  "description": "Cross-machine agent messaging for Claude Code and Codex",
5
5
  "author": "ppravdin",
6
6
  "license": "MIT",
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: "patchcord:wait"
2
+ name: patchcord-wait
3
3
  description: >
4
4
  Enter listening mode - wait for incoming patchcord messages. Use when user
5
5
  says "wait", "listen", "stand by", or wants the agent to stay responsive
File without changes