@popoverinstall/cli 0.6.1 → 0.7.0
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/CHANGELOG.md +13 -0
- package/dist/next-steps.d.ts.map +1 -1
- package/dist/next-steps.js +14 -10
- package/dist/next-steps.js.map +1 -1
- package/dist/scene.d.ts.map +1 -1
- package/dist/scene.js +12 -4
- package/dist/scene.js.map +1 -1
- package/package.json +3 -3
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/hooks/hooks.json +6 -0
- package/plugin/scripts/announce-roster.mjs +127 -0
- package/plugin/scripts/deliver-messages.mjs +5 -4
- package/plugin/skills/popover/SKILL.md +145 -0
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,19 @@ already here:
|
|
|
15
15
|
Every version that ships needs an entry — an update with nothing to print says nothing at
|
|
16
16
|
all, which reads as though the update did not happen.
|
|
17
17
|
|
|
18
|
+
## 0.7.0
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
- Claude Code now notices your teammates without being asked. An agent used to learn that
|
|
23
|
+
popover existed only once you typed `/popover:team`, which meant the moment most worth using
|
|
24
|
+
it for — you are about to edit a file somebody else's agent is already in — went past
|
|
25
|
+
unremarked. A session in a repo where a teammate is working now begins with the roster in
|
|
26
|
+
hand, says so before it collides with them, and can ask their agent why something is the way
|
|
27
|
+
it is when the repo itself does not record it. It will say when it is about to ask, and ask
|
|
28
|
+
you first before sending anyone a heads-up: an ask spends a teammate's tokens on their own
|
|
29
|
+
machine, while a heads-up spends their attention.
|
|
30
|
+
|
|
18
31
|
## 0.6.1
|
|
19
32
|
|
|
20
33
|
### Fixes
|
package/dist/next-steps.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next-steps.d.ts","sourceRoot":"","sources":["../src/next-steps.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;GAIG;AACH,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,OAAO,6CAA6C,CAAC;AAClE,eAAO,MAAM,iBAAiB,2EAC4C,CAAC;
|
|
1
|
+
{"version":3,"file":"next-steps.d.ts","sourceRoot":"","sources":["../src/next-steps.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;GAIG;AACH,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,OAAO,6CAA6C,CAAC;AAClE,eAAO,MAAM,iBAAiB,2EAC4C,CAAC;AAwB3E,wBAAgB,SAAS,IAAI,IAAI,CA4ChC"}
|
package/dist/next-steps.js
CHANGED
|
@@ -18,19 +18,23 @@ export const TAGLINE_SECONDARY = "Let your team's AI agents communicate and coll
|
|
|
18
18
|
/**
|
|
19
19
|
* Things the agent can genuinely do, phrased the way someone would actually type them.
|
|
20
20
|
*
|
|
21
|
-
* Checked against what the plugin actually exposes —
|
|
22
|
-
* rather than invented to sound capable. Suggesting anything else here
|
|
23
|
-
* teaching people a command that fails
|
|
24
|
-
* repo, and it can put one question to a teammate's agent, which a read-only copy answers.
|
|
25
|
-
* That is the whole surface.
|
|
21
|
+
* Checked against what the plugin actually exposes — three tools, `team_list`, `team_ask`
|
|
22
|
+
* and `team_tell` — rather than invented to sound capable. Suggesting anything else here
|
|
23
|
+
* would be the CLI teaching people a command that fails.
|
|
26
24
|
*
|
|
27
|
-
* One per tool,
|
|
28
|
-
*
|
|
25
|
+
* One per tool, in that order, because it is also the order you use them in: the roster is
|
|
26
|
+
* where a name comes from, and the other two are the two things you can do with one. Naming
|
|
27
|
+
* teammates rather than handles like `B1` is deliberate — `target` takes either, and a
|
|
28
|
+
* handle printed here is one the reader does not have yet.
|
|
29
|
+
*
|
|
30
|
+
* Three different opening verbs, and no "Ask Popover" prefix: the heading above these
|
|
31
|
+
* already says whose job this is, and every character spent on the prefix is a character
|
|
32
|
+
* closer to wrapping in an 80-column terminal.
|
|
29
33
|
*/
|
|
30
34
|
const ASK_EXAMPLES = [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
"Who else is working in this repo right now, and on what?",
|
|
36
|
+
"Ask Greg what they already tried on the flaky auth test.",
|
|
37
|
+
"Tell Jenny that I'm rewriting globals.css right now.",
|
|
34
38
|
];
|
|
35
39
|
export function nextSteps() {
|
|
36
40
|
// Wrapped to the window, like the welcome box, and before styling — `wrap` counts
|
package/dist/next-steps.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next-steps.js","sourceRoot":"","sources":["../src/next-steps.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAE/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC;AAC/B,MAAM,CAAC,MAAM,OAAO,GAAG,0CAA0C,CAAC;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAC5B,wEAAwE,CAAC;AAE3E
|
|
1
|
+
{"version":3,"file":"next-steps.js","sourceRoot":"","sources":["../src/next-steps.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAE/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC;AAC/B,MAAM,CAAC,MAAM,OAAO,GAAG,0CAA0C,CAAC;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAC5B,wEAAwE,CAAC;AAE3E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,YAAY,GAAG;IACnB,0DAA0D;IAC1D,0DAA0D;IAC1D,sDAAsD;CACvD,CAAC;AAEF,MAAM,UAAU,SAAS;IACvB,kFAAkF;IAClF,4DAA4D;IAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAE9D,KAAK,EAAE,CAAC;IACR,GAAG,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,GAAG,KAAK,0BAA0B,CAAC;QAChD,KAAK,EAAE;YACL,EAAE;YACF,GAAG,IAAI,CAAC,GAAG,KAAK,+CAA+C,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YACtF,GAAG,IAAI,CAAC,4DAA4D,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;YAC1F,EAAE;SACH;QACD,QAAQ,EAAE,EAAE;KACb,CAAC,CAAC;IAEH,KAAK,EAAE,CAAC;IACR,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAC3C,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,mCAAmC,CAAC,EAAE,CAAC,CAAC;IAC7F,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;IAEpF,KAAK,EAAE,CAAC;IACR,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAC3C,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;QACnC;;;;;;WAMG;QACH,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,OAAO,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;QAC/B,2FAA2F;QAC3F,iEAAiE;QACjE,KAAK,MAAM,IAAI,IAAI,IAAI;YAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,EAAE,CAAC;IACR,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC,CAAC;IAC/D,KAAK,EAAE,CAAC;IACR,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,6CAA6C;AAC7C,SAAS,MAAM,CAAC,IAAY;IAC1B,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AAC5E,CAAC"}
|
package/dist/scene.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,gEAAgE;AAChE,eAAO,MAAM,aAAa,QAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,gEAAgE;AAChE,eAAO,MAAM,aAAa,QAAY,CAAC;AA8PvC,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wFAAwF;IACxF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,YAAiB,GAAG,MAAM,EAAE,GAAG,IAAI,CAqBnE"}
|
package/dist/scene.js
CHANGED
|
@@ -34,16 +34,24 @@ export const SCENE_COLUMNS = WIDTH + 3;
|
|
|
34
34
|
* character, which cannot be half a cell tall.
|
|
35
35
|
*
|
|
36
36
|
* Mirrored from the reference so it opens back towards the aardvark.
|
|
37
|
+
*
|
|
38
|
+
* The horns are then drawn by hand rather than left where the coverage pass put them.
|
|
39
|
+
*
|
|
40
|
+
* Anti-aliasing a circle gives every row exactly the width its arc has, which stops the top and
|
|
41
|
+
* bottom rows short and leaves the moon reading as a disc with a notch. Carried out to the left
|
|
42
|
+
* and lengthened, they wrap around the opening instead, and the shape reads as a C. Their leading
|
|
43
|
+
* stipple is column 0 on all four of the rows that have one — the two horns and the two beside
|
|
44
|
+
* them — because a soft edge that steps in and out looks like a mistake rather than a curve.
|
|
37
45
|
*/
|
|
38
46
|
// prettier-ignore
|
|
39
47
|
const MOON = [
|
|
40
|
-
"
|
|
41
|
-
"
|
|
48
|
+
"dMMMMMMMMMMMd.",
|
|
49
|
+
"d.....ddMMMMM.",
|
|
42
50
|
".........MMMMM",
|
|
43
51
|
".........dMMMM",
|
|
44
52
|
".........MMMMM",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
53
|
+
"d.....ddMMMMM.",
|
|
54
|
+
"dMMMMMMMMMMMd.",
|
|
47
55
|
];
|
|
48
56
|
/**
|
|
49
57
|
* Disc and eight rays, on the moon's footprint so the sky does not reflow at dawn.
|
package/dist/scene.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene.js","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/F,MAAM,KAAK,GAAG,EAAE,CAAC;AACjB,+DAA+D;AAC/D,MAAM,MAAM,GAAG,EAAE,CAAC;AAElB,gEAAgE;AAChE,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,GAAG,CAAC,CAAC;AAEvC,6EAA6E;AAE7E
|
|
1
|
+
{"version":3,"file":"scene.js","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@popoverinstall/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "See your teammates' active Claude Code agents and ask them questions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"prepack": "node ../../scripts/stage-plugin.mjs && tsc -b"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@popoverinstall/daemon": "0.
|
|
45
|
-
"@popoverinstall/shared": "0.
|
|
44
|
+
"@popoverinstall/daemon": "0.7.0",
|
|
45
|
+
"@popoverinstall/shared": "0.7.0"
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "popover",
|
|
4
4
|
"displayName": "Popover",
|
|
5
5
|
"description": "See your teammates' active Claude Code agents and ask them questions. A read-only fork answers from the agent's full context without interrupting your teammate.",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.7.0",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Quolabs"
|
|
9
9
|
},
|
package/plugin/hooks/hooks.json
CHANGED
|
@@ -29,6 +29,12 @@
|
|
|
29
29
|
"command": "node",
|
|
30
30
|
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/deliver-messages.mjs"],
|
|
31
31
|
"timeout": 5
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"type": "command",
|
|
35
|
+
"command": "node",
|
|
36
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/announce-roster.mjs"],
|
|
37
|
+
"timeout": 5
|
|
32
38
|
}
|
|
33
39
|
]
|
|
34
40
|
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Announces which teammate agents are here, once per change in the cast.
|
|
3
|
+
//
|
|
4
|
+
// The skill file tells an agent that popover exists. This tells it who is present *right
|
|
5
|
+
// now* — the part doctrine cannot reliably produce. An agent acts on a fact sitting in its
|
|
6
|
+
// context long before it remembers to go looking for one, and the case that pays for this
|
|
7
|
+
// hook is the cheap one: it is about to edit a file a teammate's agent is already in, and
|
|
8
|
+
// the roster line is what makes the overlap visible before the edit rather than at merge.
|
|
9
|
+
//
|
|
10
|
+
// Registered synchronously on UserPromptSubmit, because that is the one event whose stdout
|
|
11
|
+
// is injected into the model's context. That makes this the second hook here allowed to
|
|
12
|
+
// print — see the header of deliver-messages.mjs — and it inherits every constraint that
|
|
13
|
+
// one documents: it runs before every prompt, so it must be fast and must fail open.
|
|
14
|
+
//
|
|
15
|
+
// It announces on change rather than on every prompt. A line repeated ahead of all fifty
|
|
16
|
+
// prompts in a session stops being information and becomes wallpaper: the model habituates,
|
|
17
|
+
// the user pays for it every turn, and the one turn where it mattered looks like the other
|
|
18
|
+
// forty-nine. So the cast last announced is remembered on disk and nothing is printed until
|
|
19
|
+
// it differs.
|
|
20
|
+
|
|
21
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
22
|
+
import path from "node:path";
|
|
23
|
+
import { callerSessionId, popoverHome, request } from "./_ipc.mjs";
|
|
24
|
+
|
|
25
|
+
// A fork answering a teammate's question must not be handed this. Its output goes back to
|
|
26
|
+
// whoever asked, and the cast of the machine it happens to run on is not theirs.
|
|
27
|
+
if (process.env.CLAUDE_CODE_ENTRYPOINT === "popover-fork") process.exit(0);
|
|
28
|
+
|
|
29
|
+
const sessionId = callerSessionId();
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
// No stdin read at all. deliver-messages.mjs spends 150ms on the payload because a missed
|
|
33
|
+
// tell is a real loss; here the environment variable is enough, and 150ms would be a
|
|
34
|
+
// sixth of the whole budget.
|
|
35
|
+
if (!sessionId) process.exit(0);
|
|
36
|
+
|
|
37
|
+
// `refresh: false` is what makes the tight timeout survivable — this reads whatever the
|
|
38
|
+
// daemon already has, so it costs one socket round trip and no network. A hook sitting
|
|
39
|
+
// between a keystroke and the model must never be the thing that calls the cloud.
|
|
40
|
+
const reply = await request(
|
|
41
|
+
{ t: "roster", id: "hook", refresh: false, fromSessionId: sessionId },
|
|
42
|
+
{ timeoutMs: 250 },
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// Daemon down, or signed out. Silence is right: the skill tells an agent how to read a
|
|
46
|
+
// daemon-down error when it actually reaches for a tool, and guessing here would put a
|
|
47
|
+
// wrong explanation in front of the model instead.
|
|
48
|
+
if (reply?.t !== "roster.ok") process.exit(0);
|
|
49
|
+
|
|
50
|
+
const peers = reply.entries.filter(
|
|
51
|
+
(e) => !e.isSelf && e.reachable && e.status !== "offline",
|
|
52
|
+
);
|
|
53
|
+
if (peers.length === 0) process.exit(0); // Working alone, which is most of the time.
|
|
54
|
+
|
|
55
|
+
// The cast, not what the cast is doing. Keying on activity would re-announce every time a
|
|
56
|
+
// teammate moved from one file to the next, which is printing on every prompt again.
|
|
57
|
+
const signature = peers
|
|
58
|
+
.map((e) => e.handle)
|
|
59
|
+
.sort()
|
|
60
|
+
.join(",");
|
|
61
|
+
if (signature === lastAnnounced(sessionId)) process.exit(0);
|
|
62
|
+
|
|
63
|
+
process.stdout.write(`${render(peers)}\n`);
|
|
64
|
+
remember(sessionId, signature);
|
|
65
|
+
} catch {
|
|
66
|
+
// Fail open, always. Whatever went wrong, the user's prompt must still go through.
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
process.exit(0);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* One line the model can act on, and one sentence saying what it is for.
|
|
73
|
+
*
|
|
74
|
+
* Activity leads, owner follows. What a teammate's agent is touching is the part that
|
|
75
|
+
* collides with what this one is about to do, and the whole value of announcing is that the
|
|
76
|
+
* overlap is noticed before the edit.
|
|
77
|
+
*
|
|
78
|
+
* The closing sentence is not padding. Without it the model reads a bare roster as news
|
|
79
|
+
* worth repeating and opens with "2 teammates are online!" ahead of an unrelated question —
|
|
80
|
+
* which is how a useful signal gets itself turned off.
|
|
81
|
+
*/
|
|
82
|
+
function render(peers) {
|
|
83
|
+
const who = peers
|
|
84
|
+
.map((e) => {
|
|
85
|
+
const doing = e.activity?.verb
|
|
86
|
+
? `${e.activity.verb}${e.activity.target ? ` ${e.activity.target}` : ""}, `
|
|
87
|
+
: "";
|
|
88
|
+
return `${e.handle} (${doing}${e.ownerName})`;
|
|
89
|
+
})
|
|
90
|
+
.join(", ");
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
`[popover] Teammate agents now active in this repo: ${who}. ` +
|
|
94
|
+
`Before editing a file one of them is already in, say so rather than colliding with it. ` +
|
|
95
|
+
`If something here turns on a decision or a reason this repo does not record, you can ` +
|
|
96
|
+
`ask one with popover's team_ask tool. Do not mention this notice to the user unless it ` +
|
|
97
|
+
`turns out to be relevant.`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Per-session, so a new session hears the cast once even when it has not changed since the
|
|
102
|
+
// last one ended.
|
|
103
|
+
//
|
|
104
|
+
// Loose end: nothing prunes these. They are a few dozen bytes each and a session id is a
|
|
105
|
+
// uuid, so a heavy user accretes a directory of them over months. Either sweep entries older
|
|
106
|
+
// than a day from here, or fold the state into what the daemon already keeps per session and
|
|
107
|
+
// drop the files — the daemon knows when a session ends and this script does not.
|
|
108
|
+
function stateFile(id) {
|
|
109
|
+
return path.join(popoverHome(), "announced", `${id}.txt`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function lastAnnounced(id) {
|
|
113
|
+
try {
|
|
114
|
+
return readFileSync(stateFile(id), "utf8").trim();
|
|
115
|
+
} catch {
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function remember(id, signature) {
|
|
121
|
+
try {
|
|
122
|
+
mkdirSync(path.join(popoverHome(), "announced"), { recursive: true });
|
|
123
|
+
writeFileSync(stateFile(id), signature, "utf8");
|
|
124
|
+
} catch {
|
|
125
|
+
// An unwritable state file means announcing again next prompt. Annoying, not broken.
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Delivers tells into a live session.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
// registered `async: true` and forbidden from
|
|
6
|
-
// is injected into the model's context — see
|
|
7
|
-
// the channel a tell needs, so this hook is
|
|
4
|
+
// One of the two hooks in the plugin that write to stdout on purpose — announce-roster.mjs
|
|
5
|
+
// is the other. Every one of the rest is registered `async: true` and forbidden from
|
|
6
|
+
// printing, because for UserPromptSubmit stdout is injected into the model's context — see
|
|
7
|
+
// the header of emit-event.mjs. That is precisely the channel a tell needs, so this hook is
|
|
8
|
+
// synchronous and its output is the message.
|
|
8
9
|
//
|
|
9
10
|
// Which makes it the riskiest script here, and it is written accordingly:
|
|
10
11
|
//
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: popover
|
|
3
|
+
description: Reach a teammate's Claude Code agent working in this same repo. Use when a question is about what a colleague decided, already ruled out, or is changing right now — why the code is the way it is when the repo does not say, whether work you are about to start is already in flight, or why something you did not touch is broken. Also covers handing this whole conversation to a teammate as a fork.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# popover
|
|
7
|
+
|
|
8
|
+
Your teammates are running their own Claude Code sessions in this repo. Each one has
|
|
9
|
+
accumulated context you do not have: the alternatives they rejected, the constraint that
|
|
10
|
+
forced an awkward shape, what they changed twenty minutes ago and have not pushed. popover
|
|
11
|
+
lets you reach those agents.
|
|
12
|
+
|
|
13
|
+
The reason this skill exists is that the moment to use popover rarely announces itself. The
|
|
14
|
+
user asks why something is the way it is, and the honest answer is that the repo does not
|
|
15
|
+
record it — but a colleague's agent worked it out this morning. Nobody will type
|
|
16
|
+
`/popover:team` for you. Noticing is your job.
|
|
17
|
+
|
|
18
|
+
## The three tools
|
|
19
|
+
|
|
20
|
+
They arrive as deferred MCP tools, so you have their names but not their schemas. Load them
|
|
21
|
+
before use:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
ToolSearch("select:mcp__plugin_popover_popover__team_list,mcp__plugin_popover_popover__team_ask,mcp__plugin_popover_popover__team_tell")
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Their own descriptions are detailed and authoritative on arguments and limits — read them
|
|
28
|
+
once loaded rather than guessing. In short:
|
|
29
|
+
|
|
30
|
+
- **`team_list`** — who is active in this repo, what they are doing, and each one's short
|
|
31
|
+
handle (`B1`). Takes nothing. Read-only and cheap.
|
|
32
|
+
- **`team_ask`** — one question to one agent, and you wait for the answer. A read-only copy
|
|
33
|
+
of their session answers from its full context. Their live session is not interrupted and
|
|
34
|
+
cannot be changed by it. Takes up to ~90s by default.
|
|
35
|
+
- **`team_tell`** — a one- or two-sentence heads-up delivered into a teammate's live session
|
|
36
|
+
before its next prompt. Nothing comes back, and their user is notified that you sent it.
|
|
37
|
+
|
|
38
|
+
## When to reach for it on your own
|
|
39
|
+
|
|
40
|
+
Check the roster and consider an ask when:
|
|
41
|
+
|
|
42
|
+
- **The user asks *why*** — why a library was chosen, why a function is shaped oddly, why an
|
|
43
|
+
obvious approach was not taken — **and the repo does not answer it.** Read the code, the
|
|
44
|
+
comments, `git log`, `git blame`, and `CLAUDE.md` first. If the reasoning is not written
|
|
45
|
+
down anywhere, that is precisely the case popover was built for: it exists only in
|
|
46
|
+
somebody's session.
|
|
47
|
+
- **You are about to start something that may already be underway** — a rename spanning many
|
|
48
|
+
files, a dependency bump, a refactor of a shared module. One `team_list` costs almost
|
|
49
|
+
nothing and can save the user an afternoon of conflicted work.
|
|
50
|
+
- **You are blocked by something you did not break** — a migration that appears unapplied, a
|
|
51
|
+
failing build on untouched code, an endpoint that disagrees with its own types. Ask the
|
|
52
|
+
person whose agent is in that area before you debug their in-flight change as if it were a
|
|
53
|
+
bug.
|
|
54
|
+
- **You are about to edit a file a teammate's agent is working in right now.** The roster
|
|
55
|
+
often says what each agent is doing. Prefer a `tell` here — it is a collision, not a
|
|
56
|
+
question.
|
|
57
|
+
- **The user names a colleague.** "Did Bob get the webhook working?", "what is Sarah doing to
|
|
58
|
+
globals.css" — that is a direct signal, and you do not need to be asked twice.
|
|
59
|
+
|
|
60
|
+
Say what you are doing and why before you ask, in a line. The user should never be surprised
|
|
61
|
+
that you spent a teammate's tokens.
|
|
62
|
+
|
|
63
|
+
## When not to
|
|
64
|
+
|
|
65
|
+
- **When the repo can answer.** Reading is free and instant; an ask runs on someone else's
|
|
66
|
+
machine at their expense. Exhaust local evidence first, always.
|
|
67
|
+
- **For curiosity or completeness.** Do not ask because a second opinion would be tidy. Ask
|
|
68
|
+
because you are stuck and they are not.
|
|
69
|
+
- **More than one agent per question.** Never fan out across the roster to see who answers
|
|
70
|
+
best. Pick the one that fits; if none obviously does, show the user the roster instead.
|
|
71
|
+
- **To hand off work.** A `tell` is information, not a directive — the receiving agent is
|
|
72
|
+
explicitly told to treat it that way — and an ask talks to a read-only copy that cannot act.
|
|
73
|
+
Neither one delegates. If the user wants a colleague to *do* something, say plainly that
|
|
74
|
+
popover does not do that, and let them message the human.
|
|
75
|
+
- **For anything outside this repo.** Only agents in the same repository are visible or
|
|
76
|
+
reachable. An empty roster means nobody else is working *here* — not that the team is idle.
|
|
77
|
+
Phrase it that way, or you will imply something false about your user's colleagues.
|
|
78
|
+
|
|
79
|
+
## The cost asymmetry, which governs consent
|
|
80
|
+
|
|
81
|
+
Three tools, three different things being spent:
|
|
82
|
+
|
|
83
|
+
| | Costs | Ask the user first? |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| `team_list` | Nothing meaningful | No — just do it |
|
|
86
|
+
| `team_ask` | The teammate's tokens and compute, on their machine. Interrupts nobody. | No, but say you are doing it |
|
|
87
|
+
| `team_tell` | A colleague's **attention**. It lands in their live session and notifies them. | **Yes, every time** |
|
|
88
|
+
|
|
89
|
+
`team_tell` is the only thing in popover that reaches a running agent. Treat it as something
|
|
90
|
+
the user should have deliberately meant to do, and confirm before sending. It is also rate
|
|
91
|
+
limited to 10 messages an hour to any one agent, which is a hint about its intended frequency.
|
|
92
|
+
|
|
93
|
+
If it is genuinely ambiguous whether to ask or tell, ask. It interrupts nobody.
|
|
94
|
+
|
|
95
|
+
## Writing an ask worth the money
|
|
96
|
+
|
|
97
|
+
The answering agent has none of your conversation. It cannot see the file you are looking at
|
|
98
|
+
or the error you just read. So make the question stand alone:
|
|
99
|
+
|
|
100
|
+
- Expand every pronoun and vague reference. "that bug" → "the token refresh bug in the auth
|
|
101
|
+
service".
|
|
102
|
+
- Name files by path, and say what you are trying to do, not only what you want to know.
|
|
103
|
+
- Ask one well-formed question, not three exploratory ones. You get one round trip for the
|
|
104
|
+
price.
|
|
105
|
+
|
|
106
|
+
A poor ask — *"why is it done this way?"* — comes back useless and you have spent a
|
|
107
|
+
colleague's tokens to learn nothing. A good one — *"`apps/web/src/lib/auth-redirect.ts`
|
|
108
|
+
derives the origin from the request Host header, with a comment saying
|
|
109
|
+
`NEXT_PUBLIC_APP_URL` still points at the old Vercel domain. Is that variable going to be
|
|
110
|
+
corrected, or is reading Host the intended long-term approach?"* — comes back with the
|
|
111
|
+
reasoning, because that is knowledge about shared state that lives in a person's head rather
|
|
112
|
+
than in the repo.
|
|
113
|
+
|
|
114
|
+
Never invent a handle. Use only what `team_list` returned, and note that a handle from
|
|
115
|
+
earlier in this conversation may have gone out of scope since. If the tool says it does not
|
|
116
|
+
match, relay that instead of trying a different agent.
|
|
117
|
+
|
|
118
|
+
## Forks are a different thing
|
|
119
|
+
|
|
120
|
+
A fork hands over **this entire conversation**, frozen, and the recipient continues it in
|
|
121
|
+
their own session. Nothing comes back. That includes the contents of every file read into the
|
|
122
|
+
context, so it is a far larger disclosure than an ask, and it is only ever something the user
|
|
123
|
+
asks for in as many words — never something you suggest doing on their behalf and then do.
|
|
124
|
+
|
|
125
|
+
When the user wants an *answer* rather than to hand over the whole conversation, an ask is the
|
|
126
|
+
cheaper and more private thing. Offer it.
|
|
127
|
+
|
|
128
|
+
## When it does not work
|
|
129
|
+
|
|
130
|
+
The tools return errors as text; relay them rather than retrying with different arguments.
|
|
131
|
+
|
|
132
|
+
- **"the popover daemon is not running"** — teammate agents are unreachable from this machine.
|
|
133
|
+
`popover daemon start`, or `popover doctor` to diagnose. Do not treat it as an empty roster.
|
|
134
|
+
- **Empty roster** — print what the tool returned verbatim; it knows whether the answer is
|
|
135
|
+
"nobody is working here" or something else. Do not paraphrase it into "your team is idle".
|
|
136
|
+
- **Handle does not match** — relay it. Do not guess at another agent.
|
|
137
|
+
- **Ask times out** — say so. Their machine may be busy or the session may have ended. Do not
|
|
138
|
+
silently re-ask.
|
|
139
|
+
|
|
140
|
+
## The user-facing commands
|
|
141
|
+
|
|
142
|
+
`/popover:team` and `/popover:fork` carry the full flows for when the user drives this
|
|
143
|
+
explicitly, including how to present a roster and how to take delivery of a fork. Do not
|
|
144
|
+
restate their steps here or work around them — when the user invokes a command, follow it.
|
|
145
|
+
This skill is for the case where nobody invoked anything and you noticed the moment yourself.
|