patchcord 0.5.123 → 0.5.124

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. Messages from other agents land in the inbox and wake the agent to reply.",
4
- "version": "0.5.123",
4
+ "version": "0.5.124",
5
5
  "author": {
6
6
  "name": "ppravdin"
7
7
  },
package/bin/patchcord.mjs CHANGED
@@ -349,18 +349,19 @@ async function _resolveBearer(options = {}) {
349
349
  );
350
350
  })();
351
351
 
352
- // NO global kimi/kimi-code reader. Kimi is a PER-PROJECT identity
353
- // (.kimi-code/mcp.json in the worktree); a global ~/.kimi(-code)/mcp.json would
354
- // make a leftover token hijack every kimi session everywhere. A kimi outside a
352
+ // NO global reader for PER-PROJECT tools. Kimi (.kimi-code/mcp.json) and
353
+ // Antigravity (.agents/mcp_config.json) are per-project identities: a leftover
354
+ // token in a global config (~/.kimi(-code)/mcp.json, ~/.gemini/antigravity/
355
+ // mcp_config.json) would hijack every session everywhere and make the agent
356
+ // "check inbox" in projects it has nothing to do with. Such a tool outside a
355
357
  // patchcord worktree is simply not an agent. (The tools below are global-ONLY
356
- // by nature — Windsurf/Gemini/Zed/etc. store MCP config globally — so they keep
357
- // their global readers.)
358
+ // by nature — Windsurf/Gemini CLI/Zed/etc. store MCP config globally — so they
359
+ // keep their global readers.)
358
360
  const defaultGlobalCandidates = [
359
361
  () => readJsonAt(join(HOME, ".codeium", "windsurf", "mcp_config.json"), ["mcpServers", "patchcord"], "windsurf"),
360
362
  () => readJsonAt(join(HOME, ".gemini", "settings.json"), ["mcpServers", "patchcord"], "gemini"),
361
363
  () => readJsonAt(zedPath, ["context_servers", "patchcord"], "zed"),
362
364
  () => readJsonAt(join(HOME, ".openclaw", "openclaw.json"), ["mcp", "servers", "patchcord"], "openclaw"),
363
- () => readJsonAt(join(HOME, ".gemini", "antigravity", "mcp_config.json"), ["mcpServers", "patchcord"], "antigravity"),
364
365
  () => readHermesShape(join(HOME, ".hermes", "config.yaml")),
365
366
  ...clinePaths.map((p) => () => readJsonAt(p, ["mcpServers", "patchcord"], "cline")),
366
367
  ];
@@ -1669,13 +1670,33 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
1669
1670
  if (windsurfChanged) globalChanges.push("Windsurf skills installed");
1670
1671
  }
1671
1672
 
1672
- // Gemini CLI + Antigravity (they SHARE ~/.gemini/skills and ~/.gemini/commands).
1673
- // Seed the patchcord skill ONLY when patchcord MCP is actually configured for
1674
- // one of these surfaces. Otherwise a bare session (esp. Antigravity, which
1675
- // inherits this dir) reads a skill with no backing MCP tool and improvises
1676
- // destructively scavenging other agents' bearer tokens off disk and curling
1677
- // the API. Invariant: skill present patchcord MCP present under ~/.gemini.
1673
+ // Gemini CLI + Antigravity SHARE ~/.gemini/skills and ~/.gemini/commands, but
1674
+ // their MCP config is NOT shared: Gemini CLI stores patchcord globally
1675
+ // (~/.gemini/settings.json) while Antigravity is PER-PROJECT
1676
+ // (<project>/.agents/mcp_config.json). So the shared global skill must be
1677
+ // seeded ONLY off Gemini CLI's global config — never off an Antigravity config.
1678
+ // A patchcord entry in the global ~/.gemini/antigravity(-cli)/mcp_config.json is
1679
+ // a leaked per-project token: it makes agy load the patchcord MCP (and its
1680
+ // "check inbox first" instruction) in EVERY project, and it kept this skill
1681
+ // seeded everywhere. We strip that leak below and gate the skill on Gemini only.
1678
1682
  if (existsSync(join(HOME, ".gemini"))) {
1683
+ // Remove any leaked patchcord server from Antigravity's GLOBAL configs so a
1684
+ // per-project token stops hijacking every agy session. Preserve other MCP
1685
+ // servers; only drop patchcord.
1686
+ for (const agGlobal of [
1687
+ join(HOME, ".gemini", "antigravity", "mcp_config.json"),
1688
+ join(HOME, ".gemini", "antigravity-cli", "mcp_config.json"),
1689
+ ]) {
1690
+ if (!existsSync(agGlobal)) continue;
1691
+ try {
1692
+ const j = JSON.parse(readFileSync(agGlobal, "utf-8"));
1693
+ if (j?.mcpServers?.patchcord) {
1694
+ delete j.mcpServers.patchcord;
1695
+ writeFileSync(agGlobal, JSON.stringify(j, null, 2) + "\n");
1696
+ globalChanges.push("Removed leaked global Antigravity patchcord MCP (agy is per-project)");
1697
+ }
1698
+ } catch {}
1699
+ }
1679
1700
  // true = configured, false = file absent (definitely not), null = unparseable (unknown)
1680
1701
  const hasPatchcordMcp = (p, keyPath) => {
1681
1702
  if (!existsSync(p)) return false;
@@ -1684,8 +1705,6 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
1684
1705
  };
1685
1706
  const checks = [
1686
1707
  hasPatchcordMcp(join(HOME, ".gemini", "settings.json"), ["mcpServers", "patchcord"]),
1687
- hasPatchcordMcp(join(HOME, ".gemini", "antigravity", "mcp_config.json"), ["mcpServers", "patchcord"]),
1688
- hasPatchcordMcp(join(HOME, ".gemini", "antigravity-cli", "mcp_config.json"), ["mcpServers", "patchcord"]),
1689
1708
  ];
1690
1709
  const mcpConfigured = checks.some((c) => c === true);
1691
1710
  const mcpUnknown = checks.some((c) => c === null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchcord",
3
- "version": "0.5.123",
3
+ "version": "0.5.124",
4
4
  "description": "Cross-machine agent messaging for Claude Code and Codex",
5
5
  "scripts": {
6
6
  "version": "node scripts/sync-plugin-version.mjs && git add .claude-plugin/plugin.json"