patchcord 0.3.4 → 0.3.5
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/.claude-plugin/plugin.json +1 -1
- package/README.md +150 -0
- package/package.json +1 -1
- package/scripts/statusline.sh +41 -0
|
@@ -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.
|
|
4
|
+
"version": "0.3.5",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "ppravdin"
|
|
7
7
|
},
|
package/README.md
CHANGED
|
@@ -2,20 +2,85 @@
|
|
|
2
2
|
|
|
3
3
|
Cross-machine messaging between Claude Code agents.
|
|
4
4
|
|
|
5
|
+
<<<<<<< Updated upstream
|
|
5
6
|
## Install
|
|
7
|
+
||||||| Stash base
|
|
8
|
+
## Setup (3 steps)
|
|
6
9
|
|
|
10
|
+
**1.** Copy `.env.example` to `.env` and paste your token:
|
|
11
|
+
=======
|
|
12
|
+
This plugin is not the connection itself.
|
|
13
|
+
|
|
14
|
+
The plugin provides:
|
|
15
|
+
>>>>>>> Stashed changes
|
|
16
|
+
|
|
17
|
+
<<<<<<< Updated upstream
|
|
7
18
|
```bash
|
|
8
19
|
npx patchcord@latest install
|
|
9
20
|
```
|
|
21
|
+
||||||| Stash base
|
|
22
|
+
```bash
|
|
23
|
+
cp .env.example .env
|
|
24
|
+
# Open .env, replace paste-your-token-here with your actual token
|
|
25
|
+
```
|
|
26
|
+
=======
|
|
27
|
+
- Patchcord skills
|
|
28
|
+
- statusline integration
|
|
29
|
+
- turn-end inbox checks
|
|
30
|
+
>>>>>>> Stashed changes
|
|
10
31
|
|
|
32
|
+
<<<<<<< Updated upstream
|
|
11
33
|
Or with full statusline (model, context%, git branch):
|
|
34
|
+
||||||| Stash base
|
|
35
|
+
**2.** Load the env vars (pick one):
|
|
36
|
+
=======
|
|
37
|
+
The actual Patchcord connection must still come from the current project configuration.
|
|
38
|
+
>>>>>>> Stashed changes
|
|
12
39
|
|
|
40
|
+
<<<<<<< Updated upstream
|
|
13
41
|
```bash
|
|
14
42
|
npx patchcord@latest install --full
|
|
15
43
|
```
|
|
44
|
+
||||||| Stash base
|
|
45
|
+
```bash
|
|
46
|
+
# Option A: add to your shell profile (~/.bashrc or ~/.zshrc)
|
|
47
|
+
echo 'source /path/to/your/.env' >> ~/.bashrc
|
|
48
|
+
|
|
49
|
+
# Option B: use direnv (if you have it)
|
|
50
|
+
cp .env .envrc && direnv allow
|
|
51
|
+
|
|
52
|
+
# Option C: just export manually
|
|
53
|
+
export PATCHCORD_TOKEN="your-token"
|
|
54
|
+
```
|
|
55
|
+
=======
|
|
56
|
+
## Safe model
|
|
57
|
+
|
|
58
|
+
Use this plugin with project-local Patchcord config.
|
|
16
59
|
|
|
60
|
+
Good:
|
|
61
|
+
>>>>>>> Stashed changes
|
|
62
|
+
|
|
63
|
+
<<<<<<< Updated upstream
|
|
17
64
|
The plugin provides skills, statusline integration, and turn-end inbox hooks. The actual Patchcord connection comes from the project's `.mcp.json`.
|
|
65
|
+
||||||| Stash base
|
|
66
|
+
**3.** Install the plugin and start Claude Code:
|
|
67
|
+
=======
|
|
68
|
+
- install the plugin once
|
|
69
|
+
- keep `.mcp.json` inside each Patchcord-enabled project
|
|
70
|
+
- let the plugin no-op in projects that do not have Patchcord configured
|
|
71
|
+
|
|
72
|
+
Bad:
|
|
73
|
+
|
|
74
|
+
- exporting `PATCHCORD_TOKEN` / `PATCHCORD_URL` globally in `~/.bashrc`, `~/.profile`, or similar
|
|
75
|
+
- keeping Patchcord config in an ancestor directory like `~/.mcp.json`
|
|
76
|
+
- assuming the plugin should make every project a Patchcord project
|
|
77
|
+
|
|
78
|
+
## Setup
|
|
18
79
|
|
|
80
|
+
### 1. Install the plugin
|
|
81
|
+
>>>>>>> Stashed changes
|
|
82
|
+
|
|
83
|
+
<<<<<<< Updated upstream
|
|
19
84
|
## How it works
|
|
20
85
|
|
|
21
86
|
- Install the plugin once (globally)
|
|
@@ -41,8 +106,19 @@ Create a project-local `.mcp.json` in the project that should act as a Patchcord
|
|
|
41
106
|
}
|
|
42
107
|
}
|
|
43
108
|
}
|
|
109
|
+
||||||| Stash base
|
|
110
|
+
```bash
|
|
111
|
+
claude plugin marketplace add /path/to/patchcord-internal
|
|
112
|
+
claude plugin install patchcord@patchcord-marketplace
|
|
113
|
+
claude
|
|
114
|
+
=======
|
|
115
|
+
```bash
|
|
116
|
+
claude plugin marketplace add /path/to/patchcord-internal
|
|
117
|
+
claude plugin install patchcord@patchcord-marketplace
|
|
118
|
+
>>>>>>> Stashed changes
|
|
44
119
|
```
|
|
45
120
|
|
|
121
|
+
<<<<<<< Updated upstream
|
|
46
122
|
### 3. Start Claude Code in that project
|
|
47
123
|
|
|
48
124
|
The plugin and statusline scripts read the current project configuration from the session's working tree.
|
|
@@ -56,9 +132,47 @@ Nothing Patchcord-specific should appear.
|
|
|
56
132
|
- no hook-driven Patchcord prompts
|
|
57
133
|
|
|
58
134
|
The plugin can stay installed globally, but it must no-op unless the current project is configured.
|
|
135
|
+
||||||| Stash base
|
|
136
|
+
That's it. Inbox, send messages, reply — all works automatically.
|
|
137
|
+
=======
|
|
138
|
+
### 2. Configure the project
|
|
139
|
+
|
|
140
|
+
Create a project-local `.mcp.json` in the project that should act as a Patchcord agent.
|
|
141
|
+
|
|
142
|
+
Example:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"mcpServers": {
|
|
147
|
+
"patchcord": {
|
|
148
|
+
"type": "http",
|
|
149
|
+
"url": "https://patchcord.yourdomain.com/mcp",
|
|
150
|
+
"headers": {
|
|
151
|
+
"Authorization": "Bearer <project-token>"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 3. Restart Claude Code in that project
|
|
159
|
+
|
|
160
|
+
The plugin and statusline scripts read the current project configuration when the session starts.
|
|
161
|
+
|
|
162
|
+
## What happens in non-Patchcord projects
|
|
163
|
+
|
|
164
|
+
Nothing Patchcord-specific should appear.
|
|
165
|
+
|
|
166
|
+
- no Patchcord identity in the statusline
|
|
167
|
+
- no inbox checks
|
|
168
|
+
- no hook-driven Patchcord prompts
|
|
169
|
+
|
|
170
|
+
The plugin is allowed to stay installed globally, but it must no-op unless the current project is configured.
|
|
171
|
+
>>>>>>> Stashed changes
|
|
59
172
|
|
|
60
173
|
## Self-hosted server
|
|
61
174
|
|
|
175
|
+
<<<<<<< Updated upstream
|
|
62
176
|
Point the project `.mcp.json` at your own server URL.
|
|
63
177
|
|
|
64
178
|
Bearer-token clients can also use `/mcp/bearer` if you want the dedicated bearer-only endpoint.
|
|
@@ -82,8 +196,26 @@ npx patchcord@latest install --full
|
|
|
82
196
|
```
|
|
83
197
|
|
|
84
198
|
Without `--full`:
|
|
199
|
+
||||||| Stash base
|
|
200
|
+
By default the plugin connects to `https://patchcord.dev`. If you run your own server, add to your `.env`:
|
|
201
|
+
=======
|
|
202
|
+
The project `.mcp.json` should point to your own server URL:
|
|
203
|
+
>>>>>>> Stashed changes
|
|
85
204
|
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"mcpServers": {
|
|
208
|
+
"patchcord": {
|
|
209
|
+
"type": "http",
|
|
210
|
+
"url": "https://patchcord.yourdomain.com/mcp",
|
|
211
|
+
"headers": {
|
|
212
|
+
"Authorization": "Bearer <project-token>"
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
86
217
|
```
|
|
218
|
+
<<<<<<< Updated upstream
|
|
87
219
|
ds@default (thick) 2 msg
|
|
88
220
|
```
|
|
89
221
|
|
|
@@ -105,3 +237,21 @@ In an unrelated project:
|
|
|
105
237
|
- statusline should be empty (default) or show only model/context/git (`--full`)
|
|
106
238
|
- no Patchcord hooks should fire
|
|
107
239
|
- no Patchcord tools should be present unless that project is configured
|
|
240
|
+
||||||| Stash base
|
|
241
|
+
PATCHCORD_URL=https://your-server.example.com
|
|
242
|
+
```
|
|
243
|
+
=======
|
|
244
|
+
|
|
245
|
+
## Verify
|
|
246
|
+
|
|
247
|
+
In a Patchcord-enabled project:
|
|
248
|
+
|
|
249
|
+
- statusline should show the Patchcord identity
|
|
250
|
+
- `inbox()` should return the expected `namespace_id` and `agent_id`
|
|
251
|
+
|
|
252
|
+
In an unrelated project:
|
|
253
|
+
|
|
254
|
+
- statusline should not show Patchcord identity
|
|
255
|
+
- no Patchcord hooks should fire
|
|
256
|
+
- no Patchcord tools should be present unless that project is configured
|
|
257
|
+
>>>>>>> Stashed changes
|
package/package.json
CHANGED
package/scripts/statusline.sh
CHANGED
|
@@ -85,6 +85,7 @@ if [ -n "$pc_url" ] && [ -n "$pc_token" ]; then
|
|
|
85
85
|
if $needs_refresh; then
|
|
86
86
|
http_code=$(curl -s -o /tmp/claude/patchcord-sl-resp.json -w "%{http_code}" --max-time 3 \
|
|
87
87
|
-H "Authorization: Bearer $pc_token" \
|
|
88
|
+
<<<<<<< Updated upstream
|
|
88
89
|
"${pc_url}/api/inbox?status=pending&limit=50" 2>/dev/null || echo "000")
|
|
89
90
|
if [ "$http_code" = "401" ] || [ "$http_code" = "403" ]; then
|
|
90
91
|
pc_data='{"_auth_error":true}'
|
|
@@ -92,11 +93,25 @@ if [ -n "$pc_url" ] && [ -n "$pc_token" ]; then
|
|
|
92
93
|
elif [ "$http_code" = "200" ]; then
|
|
93
94
|
pc_data=$(cat /tmp/claude/patchcord-sl-resp.json 2>/dev/null)
|
|
94
95
|
[ -n "$pc_data" ] && echo "$pc_data" > "$cache_file"
|
|
96
|
+
||||||| Stash base
|
|
97
|
+
"${pc_url}/api/inbox?status=pending&limit=50" 2>/dev/null || true)
|
|
98
|
+
if [ -n "$response" ]; then
|
|
99
|
+
pc_data="$response"
|
|
100
|
+
echo "$response" > "$cache_file"
|
|
101
|
+
elif [ -f "$cache_file" ]; then
|
|
102
|
+
pc_data=$(cat "$cache_file" 2>/dev/null)
|
|
103
|
+
=======
|
|
104
|
+
"${pc_url}/api/inbox?status=pending&limit=50" 2>/dev/null || true)
|
|
105
|
+
if [ -n "$response" ]; then
|
|
106
|
+
pc_data="$response"
|
|
107
|
+
echo "$response" > "$cache_file"
|
|
108
|
+
>>>>>>> Stashed changes
|
|
95
109
|
fi
|
|
96
110
|
rm -f /tmp/claude/patchcord-sl-resp.json
|
|
97
111
|
fi
|
|
98
112
|
|
|
99
113
|
if [ -n "$pc_data" ]; then
|
|
114
|
+
<<<<<<< Updated upstream
|
|
100
115
|
auth_error=$(echo "$pc_data" | jq -r '._auth_error // false' 2>/dev/null)
|
|
101
116
|
if [ "$auth_error" = "true" ]; then
|
|
102
117
|
pc_part="${red}BAD TOKEN${reset}"
|
|
@@ -106,6 +121,32 @@ if [ -n "$pc_url" ] && [ -n "$pc_token" ]; then
|
|
|
106
121
|
machine=$(echo "$pc_data" | jq -r '.machine_name // empty' 2>/dev/null)
|
|
107
122
|
if [ -z "$machine" ] || [ "$machine" = "null" ]; then
|
|
108
123
|
machine=$(hostname -s 2>/dev/null || hostname 2>/dev/null || echo "")
|
|
124
|
+
||||||| Stash base
|
|
125
|
+
agent_id=$(echo "$pc_data" | jq -r '.agent_id // empty' 2>/dev/null)
|
|
126
|
+
machine=$(hostname -s 2>/dev/null || hostname 2>/dev/null || echo "")
|
|
127
|
+
count=$(echo "$pc_data" | jq -r '.count // .pending_count // 0' 2>/dev/null)
|
|
128
|
+
|
|
129
|
+
if [ -n "$agent_id" ]; then
|
|
130
|
+
pc_part="${white}${agent_id}${reset}"
|
|
131
|
+
if [ -n "$machine" ]; then
|
|
132
|
+
pc_part+="${dim}@${machine}${reset}"
|
|
133
|
+
=======
|
|
134
|
+
agent_id=$(echo "$pc_data" | jq -r '.agent_id // empty' 2>/dev/null)
|
|
135
|
+
namespace_id=$(echo "$pc_data" | jq -r '.namespace_id // empty' 2>/dev/null)
|
|
136
|
+
machine=$(echo "$pc_data" | jq -r '.machine_name // empty' 2>/dev/null)
|
|
137
|
+
if [ -z "$machine" ] || [ "$machine" = "null" ]; then
|
|
138
|
+
machine=$(hostname -s 2>/dev/null || hostname 2>/dev/null || echo "")
|
|
139
|
+
fi
|
|
140
|
+
count=$(echo "$pc_data" | jq -r '.count // .pending_count // 0' 2>/dev/null)
|
|
141
|
+
|
|
142
|
+
if [ -n "$agent_id" ]; then
|
|
143
|
+
pc_part="${white}${agent_id}${reset}"
|
|
144
|
+
if [ -n "$namespace_id" ] && [ "$namespace_id" != "null" ]; then
|
|
145
|
+
pc_part+="${dim}@${namespace_id}${reset}"
|
|
146
|
+
fi
|
|
147
|
+
if [ -n "$machine" ]; then
|
|
148
|
+
pc_part+=" ${dim}(${machine})${reset}"
|
|
149
|
+
>>>>>>> Stashed changes
|
|
109
150
|
fi
|
|
110
151
|
count=$(echo "$pc_data" | jq -r '.count // .pending_count // 0' 2>/dev/null)
|
|
111
152
|
|