patchcord 0.5.0 → 0.5.2
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/package.json +1 -1
- package/skills/subscribe/SKILL.md +86 -39
package/package.json
CHANGED
|
@@ -12,42 +12,86 @@ description: >
|
|
|
12
12
|
|
|
13
13
|
Spawns `scripts/subscribe.mjs` in the background. The script holds a
|
|
14
14
|
WebSocket to Supabase Realtime and prints one line to stdout per new
|
|
15
|
-
`agent_messages` INSERT for this agent. Claude Code's Monitor tool
|
|
16
|
-
up each line as a notification; Claude wakes up and calls
|
|
15
|
+
`agent_messages` INSERT for this agent. Claude Code's `Monitor` tool
|
|
16
|
+
picks up each line as a notification; Claude wakes up and calls
|
|
17
|
+
`inbox()`.
|
|
17
18
|
|
|
18
19
|
No polling, no tokens burned while idle. The process stays alive until
|
|
19
20
|
the user kills it or closes the Claude Code session.
|
|
20
21
|
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
22
|
+
# How to find the script path (read carefully — this is the one thing that trips agents up)
|
|
23
|
+
|
|
24
|
+
At the top of the skill invocation message, Claude Code shows a header:
|
|
25
|
+
`Base directory for this skill: <ABSOLUTE_PATH>/skills/subscribe`
|
|
26
|
+
|
|
27
|
+
Take that path, strip `/skills/subscribe` from the end — you now have the
|
|
28
|
+
plugin root. The script is at `<PLUGIN_ROOT>/scripts/subscribe.mjs`.
|
|
29
|
+
|
|
30
|
+
**Do not rely on `$CLAUDE_PLUGIN_ROOT`** — it is often unset inside
|
|
31
|
+
the Bash shell even when the skill is running. Always derive the path
|
|
32
|
+
from the "Base directory for this skill" header you were given.
|
|
33
|
+
|
|
34
|
+
Example: if the header says
|
|
35
|
+
`Base directory for this skill: /home/user/.npm/_npx/abc123/node_modules/patchcord/skills/subscribe`
|
|
36
|
+
then the script is at
|
|
37
|
+
`/home/user/.npm/_npx/abc123/node_modules/patchcord/scripts/subscribe.mjs`.
|
|
38
|
+
|
|
39
|
+
# Starting (step by step)
|
|
40
|
+
|
|
41
|
+
1. **Know your identity.** If you don't already have `namespace_id` and
|
|
42
|
+
`agent_id` from this session, call `mcp__patchcord__inbox` once — the
|
|
43
|
+
response starts with `<agent>@<namespace> | N pending` and you can
|
|
44
|
+
read both off that line.
|
|
45
|
+
|
|
46
|
+
2. **Compute the pidfile path:**
|
|
47
|
+
`/tmp/patchcord_subscribe_<namespace_id>_<agent_id>.pid`
|
|
48
|
+
|
|
49
|
+
3. **Check for an existing listener.** One Bash call:
|
|
50
|
+
```bash
|
|
51
|
+
PF=/tmp/patchcord_subscribe_<ns>_<agent>.pid
|
|
52
|
+
if [ -f "$PF" ] && kill -0 "$(cat "$PF")" 2>/dev/null; then
|
|
53
|
+
echo "ALREADY_RUNNING pid=$(cat "$PF")"
|
|
54
|
+
else
|
|
55
|
+
echo "OK_TO_SPAWN"
|
|
56
|
+
fi
|
|
57
|
+
```
|
|
58
|
+
If output is `ALREADY_RUNNING`, tell the user "Patchcord listener
|
|
59
|
+
already active (pid N)" and STOP. Do not spawn another one.
|
|
60
|
+
|
|
61
|
+
4. **Resolve the script path** using the recipe above.
|
|
62
|
+
|
|
63
|
+
5. **Spawn under Monitor** — not Bash with `run_in_background`. Monitor
|
|
64
|
+
is the right tool because every stdout line becomes a notification.
|
|
65
|
+
Example call shape:
|
|
35
66
|
```
|
|
36
|
-
|
|
67
|
+
Monitor(
|
|
68
|
+
description: "patchcord realtime listener (<agent>@<ns>)",
|
|
69
|
+
persistent: true,
|
|
70
|
+
timeout_ms: 3600000,
|
|
71
|
+
command: "exec node \"<absolute-path-to-subscribe.mjs>\" 2>&1 | grep --line-buffered '^PATCHCORD:'"
|
|
72
|
+
)
|
|
37
73
|
```
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
74
|
+
The filter is deliberately narrow: **only** `PATCHCORD:` lines
|
|
75
|
+
(actual message arrivals) become notifications. Everything else the
|
|
76
|
+
script writes — `connected`, `token refreshed`, `cwd=...`,
|
|
77
|
+
`agent=...`, `reconnecting in Nms` — is plumbing the user doesn't
|
|
78
|
+
need to see. Those lines still land in Monitor's output file, so you
|
|
79
|
+
can Read them on demand if something looks off.
|
|
80
|
+
|
|
81
|
+
Crash detection is handled automatically by Monitor itself: when the
|
|
82
|
+
`node` process exits, you get a built-in "stream ended" task
|
|
83
|
+
notification with the exit code. No filter needed for that.
|
|
84
|
+
|
|
85
|
+
6. **Tell the user one short line:**
|
|
41
86
|
"Patchcord listener active — I'll pick up new messages as they arrive."
|
|
42
87
|
|
|
43
88
|
# When a notification fires
|
|
44
89
|
|
|
45
|
-
Monitor surfaces
|
|
90
|
+
Monitor surfaces `PATCHCORD: 1 new from <sender>`. Do this:
|
|
46
91
|
|
|
47
|
-
1. Say one brief line
|
|
48
|
-
"Got a Patchcord ping from <sender> — checking inbox."
|
|
92
|
+
1. Say one brief line: "Got a Patchcord ping from <sender> — checking inbox."
|
|
49
93
|
2. Call `mcp__patchcord__inbox`.
|
|
50
|
-
3. For each pending message
|
|
94
|
+
3. For each pending message, do the work first (follow the
|
|
51
95
|
patchcord:inbox skill), then reply with what you did.
|
|
52
96
|
4. Return to listening — Monitor keeps running.
|
|
53
97
|
|
|
@@ -55,26 +99,29 @@ Monitor surfaces a line like `PATCHCORD: 1 new from backend`. Do this:
|
|
|
55
99
|
|
|
56
100
|
There is no `/patchcord:unsubscribe` command. Tell the user either:
|
|
57
101
|
|
|
58
|
-
- Close this Claude Code session
|
|
59
|
-
running unless they kill it — see below), OR
|
|
102
|
+
- Close this Claude Code session, OR
|
|
60
103
|
- Run `kill $(cat /tmp/patchcord_subscribe_<namespace>_<agent>.pid)` in
|
|
61
104
|
a terminal.
|
|
62
105
|
|
|
63
|
-
# If
|
|
106
|
+
# If the Monitor stream ends
|
|
64
107
|
|
|
65
|
-
|
|
108
|
+
That means the subscribe process exited. Before telling the user
|
|
109
|
+
anything, Read the Monitor output file (the path is in the stream-end
|
|
110
|
+
task notification) to see the last stderr lines. The concrete failure
|
|
111
|
+
strings:
|
|
66
112
|
|
|
67
|
-
- `no .mcp.json in <cwd>` —
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
feature for now. Tell the user.
|
|
113
|
+
- `no .mcp.json in <cwd>` — session is not in a patchcord project dir.
|
|
114
|
+
- `token rejected (HTTP 401|403)` — bearer in `.mcp.json` is bad;
|
|
115
|
+
regenerate from the dashboard.
|
|
116
|
+
- `server not configured for realtime` — server hasn't had
|
|
117
|
+
`SUPABASE_JWT_SECRET` / `SUPABASE_ANON_KEY` set. Self-hosted without
|
|
118
|
+
Supabase does not support this feature yet.
|
|
74
119
|
- `namespace not owned` — the token's namespace lost its owner row;
|
|
75
120
|
regenerate from the dashboard.
|
|
76
|
-
- `already running (pid N)`
|
|
77
|
-
|
|
121
|
+
- `already running (pid N)` (exit code 2) — pidfile guard tripped.
|
|
122
|
+
Another subscribe is active. Report and stop.
|
|
78
123
|
|
|
79
|
-
|
|
80
|
-
|
|
124
|
+
Report the specific cause to the user, do not loop or retry. If the
|
|
125
|
+
process exited cleanly after many successful reconnects with no error
|
|
126
|
+
line, that's either a session close or the user killed it — no action
|
|
127
|
+
needed.
|