patchcord 0.3.19 → 0.3.21

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.19",
4
+ "version": "0.3.21",
5
5
  "author": {
6
6
  "name": "ppravdin"
7
7
  },
package/bin/patchcord.mjs CHANGED
@@ -17,16 +17,15 @@ function run(cmd) {
17
17
  }
18
18
  }
19
19
 
20
- if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
21
- console.log(`patchcord — agent messaging for Claude Code & Codex
20
+ if (cmd === "help" || cmd === "--help" || cmd === "-h") {
21
+ console.log(`patchcord — agent messaging for AI coding agents
22
22
 
23
- Commands:
24
- patchcord install One-time global setup (auto-detects Claude Code + Codex)
25
- patchcord install --full Same + enable full statusline (model, context%, git)
26
- patchcord agent Set up MCP config for this project (auto-detects tool)
27
- patchcord skill apply Fetch custom skill from web console
23
+ Usage:
24
+ npx patchcord@latest Full setup (global + project) run in your project folder
25
+ npx patchcord@latest --full Same + full statusline (model, context%, git)
26
+ npx patchcord@latest skill apply Fetch custom skill from web console
28
27
 
29
- Run "patchcord install" once. Run "patchcord agent" in each project.`);
28
+ That's it. One command does everything.`);
30
29
  process.exit(0);
31
30
  }
32
31
 
@@ -35,8 +34,8 @@ if (cmd === "plugin-path") {
35
34
  process.exit(0);
36
35
  }
37
36
 
38
- // ── install: global setup for all detected tools (idempotent) ──
39
- if (cmd === "install") {
37
+ // ── main flow: global setup + project setup (or just install/agent for back-compat) ──
38
+ if (!cmd || cmd === "install" || cmd === "agent") {
40
39
  const flags = process.argv.slice(3);
41
40
  const fullStatusline = flags.includes("--full");
42
41
  const { readFileSync, writeFileSync } = await import("fs");
@@ -49,28 +48,21 @@ if (cmd === "install") {
49
48
  Messenger for AI agents.
50
49
  `);
51
50
 
52
- let installedSomething = false;
51
+ // ── Global setup (silent if nothing changed) ──
52
+ let globalChanges = [];
53
53
 
54
- // ── Claude Code ──
54
+ // Claude Code
55
55
  const hasClaude = run("which claude");
56
56
  if (hasClaude) {
57
- console.log(`\n🔧 Claude Code`);
58
-
59
- // Register npm package as a local marketplace (idempotent)
60
57
  const marketplaceExists = run(`claude plugin marketplace list`)?.includes("patchcord");
61
58
  if (!marketplaceExists) {
62
59
  run(`claude plugin marketplace add "${pluginRoot}"`);
60
+ const installed = run(`claude plugin list`)?.includes("patchcord");
61
+ installed ? run(`claude plugin update patchcord`) : run(`claude plugin install patchcord`);
62
+ globalChanges.push("Claude Code plugin installed");
63
63
  }
64
64
 
65
- // Install or update the plugin from the marketplace
66
- const installed = run(`claude plugin list`)?.includes("patchcord");
67
- installed ? run(`claude plugin update patchcord`) : run(`claude plugin install patchcord`);
68
-
69
- console.log(` ✓ Plugin installed`);
70
-
71
- // Block OAuth tool leakage from claude.ai web connector
72
65
  const claudeSettings = join(process.env.HOME || "", ".claude", "settings.json");
73
- let settingsOk = false;
74
66
  if (existsSync(claudeSettings)) {
75
67
  try {
76
68
  const settings = JSON.parse(readFileSync(claudeSettings, "utf-8"));
@@ -90,61 +82,48 @@ if (cmd === "install") {
90
82
  }
91
83
  if (changed) {
92
84
  writeFileSync(claudeSettings, JSON.stringify(settings, null, 2) + "\n");
85
+ globalChanges.push("Permissions configured");
93
86
  }
94
- settingsOk = true;
95
- console.log(` ✓ Permissions configured`);
96
87
  } catch (e) {
97
- console.log(` ✗ Settings update failed — invalid JSON in ${claudeSettings}`);
98
- console.log(` ${e.message}`);
99
- console.log(` Fix the JSON and re-run: npx patchcord@latest install`);
88
+ globalChanges.push(`✗ Settings error: ${e.message}`);
100
89
  }
101
90
  }
102
91
 
103
- // Enable statusline
104
- if (settingsOk) {
105
- const enableScript = join(pluginRoot, "scripts", "enable-statusline.sh");
106
- if (existsSync(enableScript)) {
107
- const slArg = fullStatusline ? " --full" : "";
108
- run(`bash "${enableScript}"${slArg}`);
109
- console.log(` ✓ Statusline${fullStatusline ? " (full)" : ""} enabled`);
92
+ const enableScript = join(pluginRoot, "scripts", "enable-statusline.sh");
93
+ if (existsSync(enableScript)) {
94
+ const slArg = fullStatusline ? " --full" : "";
95
+ const slResult = run(`bash "${enableScript}"${slArg}`);
96
+ if (slResult !== null && slResult.includes("statusline")) {
97
+ globalChanges.push(`Statusline${fullStatusline ? " (full)" : ""} enabled`);
110
98
  }
111
99
  }
112
- installedSomething = true;
113
100
  }
114
101
 
115
- // ── Codex CLI ──
102
+ // Codex CLI
116
103
  const codexConfig = join(process.env.HOME || "", ".codex", "config.toml");
117
104
  if (existsSync(codexConfig)) {
118
105
  const content = readFileSync(codexConfig, "utf-8");
119
106
  if (!content.includes("[apps.patchcord]")) {
120
107
  writeFileSync(codexConfig, content.trimEnd() + "\n\n[apps.patchcord]\nenabled = false\n");
108
+ globalChanges.push("Codex ChatGPT app conflict prevented");
121
109
  }
122
- console.log(`\n🔧 Codex CLI`);
123
- console.log(` ✓ ChatGPT app conflict prevented`);
124
- installedSomething = true;
125
110
  }
126
111
 
127
- if (!installedSomething) {
128
- console.log(`No Claude Code or Codex CLI found on this machine.
129
-
130
- Install one first:
131
- Claude Code https://claude.ai/code
132
- Codex CLI → npm install -g @openai/codex
133
-
134
- Then run: npx patchcord@latest install`);
135
- process.exit(1);
112
+ // Only show global changes if something actually changed
113
+ if (globalChanges.length > 0) {
114
+ console.log(`${dim}Global setup:${r}`);
115
+ for (const change of globalChanges) {
116
+ const icon = change.startsWith("✗") ? "" : " ✓ ";
117
+ console.log(`${icon}${change}`);
118
+ }
136
119
  }
137
120
 
138
- console.log(`\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
139
- console.log(`Next: cd into your project and run:`);
140
- console.log(` npx patchcord@latest agent`);
141
- process.exit(0);
142
- }
121
+ if (!hasClaude && !existsSync(codexConfig)) {
122
+ console.log(`${dim}No Claude Code or Codex CLI detected — skipping global setup.${r}`);
123
+ }
143
124
 
144
- // ── agent: per-project interactive setup ──────────────────────
145
- if (cmd === "agent") {
125
+ // ── project setup (inline, not a separate command) ──────────
146
126
  const cwd = process.cwd();
147
- const { readFileSync, writeFileSync } = await import("fs");
148
127
  const { createInterface } = await import("readline");
149
128
 
150
129
  const rl = createInterface({ input: process.stdin, output: process.stdout });
@@ -158,6 +137,15 @@ if (cmd === "agent") {
158
137
  const bold = "\x1b[1m";
159
138
  const r = "\x1b[0m";
160
139
 
140
+ // Project directory confirmation
141
+ console.log(`\n${dim}Project folder:${r} ${bold}${cwd}${r}`);
142
+ console.log(`${dim}Patchcord config will be created here. Run this in your project folder.${r}`);
143
+ const proceed = (await ask(`\n${dim}Continue? (Y/n):${r} `)).trim().toLowerCase();
144
+ if (proceed === "n" || proceed === "no") {
145
+ rl.close();
146
+ process.exit(0);
147
+ }
148
+
161
149
  console.log(`\n${bold}Which tool are you setting up?${r}\n`);
162
150
  console.log(` ${cyan}1.${r} Claude Code`);
163
151
  console.log(` ${cyan}2.${r} Codex CLI`);
@@ -245,6 +233,9 @@ if (cmd === "agent") {
245
233
  let identity = "";
246
234
  let serverUrl = "https://mcp.patchcord.dev";
247
235
 
236
+ console.log(`\n${dim}Get your token at:${r} ${cyan}https://patchcord.dev/console${r}`);
237
+ console.log(`${dim}Create a project → Add agent → Copy token${r}`);
238
+
248
239
  while (!identity) {
249
240
  token = (await ask(`\n${bold}Paste your agent token:${r} `)).trim();
250
241
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchcord",
3
- "version": "0.3.19",
3
+ "version": "0.3.21",
4
4
  "description": "Cross-machine agent messaging for Claude Code and Codex",
5
5
  "author": "ppravdin",
6
6
  "license": "MIT",