patchcord 0.3.7 → 0.3.9

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 auto-inbox checking. Agents automatically respond to messages from other agents without human intervention.",
4
- "version": "0.3.7",
4
+ "version": "0.3.9",
5
5
  "author": {
6
6
  "name": "ppravdin"
7
7
  },
package/bin/patchcord.mjs CHANGED
@@ -41,12 +41,14 @@ if (cmd === "install") {
41
41
  const fullStatusline = flags.includes("--full");
42
42
  const { readFileSync, writeFileSync } = await import("fs");
43
43
 
44
+ console.log("Patchcord — setting up agent messaging\n");
45
+
44
46
  let installedSomething = false;
45
47
 
46
48
  // ── Claude Code ──
47
49
  const hasClaude = run("which claude");
48
50
  if (hasClaude) {
49
- console.log("Found Claude Code. Installing patchcord plugin...");
51
+ console.log(`\n🔧 Claude Code`);
50
52
 
51
53
  // Register npm package as a local marketplace (idempotent)
52
54
  const marketplaceExists = run(`claude plugin marketplace list`)?.includes("patchcord");
@@ -83,81 +85,110 @@ if (cmd === "install") {
83
85
  run(`bash "${enableScript}"${slArg}`);
84
86
  }
85
87
 
86
- console.log(`✓ Claude Code plugin installed.${fullStatusline ? " Full statusline enabled." : ""}`);
88
+ console.log(` ✓ Plugin installed${fullStatusline ? " (full statusline)" : ""}`);
89
+ console.log(` ✓ OAuth tool leakage blocked`);
87
90
  installedSomething = true;
88
91
  }
89
92
 
90
93
  // ── Codex CLI ──
91
94
  const codexConfig = join(process.env.HOME || "", ".codex", "config.toml");
92
95
  if (existsSync(codexConfig)) {
93
- console.log("Found Codex CLI config.");
94
-
95
- // Disable patchcord as ChatGPT app (prevents OAuth identity conflict)
96
96
  const content = readFileSync(codexConfig, "utf-8");
97
97
  if (!content.includes("[apps.patchcord]")) {
98
98
  writeFileSync(codexConfig, content.trimEnd() + "\n\n[apps.patchcord]\nenabled = false\n");
99
- console.log("✓ Disabled patchcord ChatGPT app in Codex (prevents identity conflict).");
100
99
  }
101
-
100
+ console.log(`\n🔧 Codex CLI`);
101
+ console.log(` ✓ ChatGPT app conflict prevented`);
102
102
  installedSomething = true;
103
103
  }
104
104
 
105
105
  if (!installedSomething) {
106
- console.log(`No Claude Code or Codex CLI detected.
106
+ console.log(`No Claude Code or Codex CLI found on this machine.
107
107
 
108
108
  Install one first:
109
- Claude Code: https://claude.ai/code
110
- Codex CLI: npm install -g @openai/codex
109
+ Claude Code https://claude.ai/code
110
+ Codex CLI npm install -g @openai/codex
111
111
 
112
112
  Then run: npx patchcord@latest install`);
113
113
  process.exit(1);
114
114
  }
115
115
 
116
- console.log(`\nRun "npx patchcord@latest agent" in each project to set up MCP.`);
116
+ console.log(`\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
117
+ console.log(`Next: cd into your project and run:`);
118
+ console.log(` npx patchcord@latest agent`);
117
119
  process.exit(0);
118
120
  }
119
121
 
120
- // ── agent: per-project MCP setup (auto-detects tool) ──────────
122
+ // ── agent: per-project MCP setup (interactive, auto-detects tool) ──
121
123
  if (cmd === "agent") {
122
124
  const cwd = process.cwd();
125
+ const { readFileSync, writeFileSync } = await import("fs");
126
+ const { createInterface } = await import("readline");
127
+
128
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
129
+ const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
130
+
131
+ // Ask for server URL with default
132
+ const serverUrl = (await ask("Server URL [https://mcp.patchcord.dev]: ")).trim() || "https://mcp.patchcord.dev";
133
+
134
+ // Ask for token
135
+ const token = (await ask("Paste your agent token: ")).trim();
136
+ rl.close();
137
+
138
+ if (!token) {
139
+ console.error("Token is required. Get one from your patchcord dashboard.");
140
+ process.exit(1);
141
+ }
123
142
 
124
143
  // Auto-detect: Codex project has .agents folder or .codex folder
125
144
  const isCodex = existsSync(join(cwd, ".agents")) || existsSync(join(cwd, ".codex"));
126
145
 
127
146
  if (isCodex) {
128
- // Codex: copy skill
147
+ // Codex: copy skill + write config
129
148
  const dest = join(cwd, ".agents", "skills", "patchcord");
130
149
  mkdirSync(dest, { recursive: true });
131
150
  cpSync(join(pluginRoot, "codex", "SKILL.md"), join(dest, "SKILL.md"));
132
- console.log(`✓ Codex skill installed: ${dest}/SKILL.md
133
-
134
- Add to .codex/config.toml in this project:
135
151
 
136
- [mcp_servers.patchcord]
137
- url = "https://YOUR_SERVER/mcp/bearer"
138
- http_headers = { "Authorization" = "Bearer YOUR_TOKEN", "X-Patchcord-Client-Type" = "codex" }`);
152
+ const codexDir = join(cwd, ".codex");
153
+ mkdirSync(codexDir, { recursive: true });
154
+ const configPath = join(codexDir, "config.toml");
155
+ let existing = existsSync(configPath) ? readFileSync(configPath, "utf-8") : "";
156
+ if (!existing.includes("[mcp_servers.patchcord]")) {
157
+ existing = existing.trimEnd() + `\n\n[mcp_servers.patchcord]\nurl = "${serverUrl}/mcp/bearer"\nhttp_headers = { "Authorization" = "Bearer ${token}", "X-Patchcord-Client-Type" = "codex" }\n`;
158
+ writeFileSync(configPath, existing);
159
+ }
160
+ console.log(`✓ Codex configured: ${configPath}\n✓ Skill installed: ${dest}/SKILL.md`);
139
161
  } else {
140
- // Claude Code: print .mcp.json template
141
- console.log(`Add .mcp.json to this project:
142
-
143
- {
144
- "mcpServers": {
145
- "patchcord": {
146
- "type": "http",
147
- "url": "https://YOUR_SERVER/mcp",
148
- "headers": {
149
- "Authorization": "Bearer YOUR_TOKEN"
150
- }
162
+ // Claude Code: write .mcp.json
163
+ const mcpPath = join(cwd, ".mcp.json");
164
+ const mcpConfig = {
165
+ mcpServers: {
166
+ patchcord: {
167
+ type: "http",
168
+ url: `${serverUrl}/mcp`,
169
+ headers: {
170
+ Authorization: `Bearer ${token}`,
171
+ },
172
+ },
173
+ },
174
+ };
175
+
176
+ if (existsSync(mcpPath)) {
177
+ try {
178
+ const existing = JSON.parse(readFileSync(mcpPath, "utf-8"));
179
+ existing.mcpServers = existing.mcpServers || {};
180
+ existing.mcpServers.patchcord = mcpConfig.mcpServers.patchcord;
181
+ writeFileSync(mcpPath, JSON.stringify(existing, null, 2) + "\n");
182
+ } catch {
183
+ writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2) + "\n");
151
184
  }
185
+ } else {
186
+ writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2) + "\n");
152
187
  }
188
+ console.log(`✓ Claude Code configured: ${mcpPath}`);
153
189
  }
154
190
 
155
- Or use the CLI:
156
-
157
- claude mcp add patchcord "https://YOUR_SERVER/mcp" \\
158
- --transport http -s project \\
159
- -H "Authorization: Bearer YOUR_TOKEN"`);
160
- }
191
+ console.log("\nRestart your session, then run: inbox()");
161
192
  process.exit(0);
162
193
  }
163
194
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchcord",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
4
4
  "description": "Cross-machine agent messaging for Claude Code and Codex",
5
5
  "author": "ppravdin",
6
6
  "license": "MIT",