@popoverinstall/cli 0.7.2 → 0.8.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 +81 -0
- package/README.md +90 -19
- package/dist/changelog.d.ts.map +1 -1
- package/dist/changelog.js +8 -1
- package/dist/changelog.js.map +1 -1
- package/dist/daemon-lock.d.ts +102 -0
- package/dist/daemon-lock.d.ts.map +1 -0
- package/dist/daemon-lock.js +321 -0
- package/dist/daemon-lock.js.map +1 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +11 -0
- package/dist/doctor.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +107 -21
- package/dist/index.js.map +1 -1
- package/dist/login.d.ts.map +1 -1
- package/dist/login.js +38 -5
- package/dist/login.js.map +1 -1
- package/dist/rename.d.ts +18 -0
- package/dist/rename.d.ts.map +1 -0
- package/dist/rename.js +252 -0
- package/dist/rename.js.map +1 -0
- package/dist/snapshot.js +24 -4
- package/dist/snapshot.js.map +1 -1
- package/dist/theme.d.ts +5 -3
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +7 -5
- package/dist/theme.js.map +1 -1
- package/package.json +3 -3
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/README.md +10 -2
- package/plugin/commands/ask.md +65 -0
- package/plugin/commands/fork.md +1 -1
- package/plugin/commands/team.md +37 -64
- package/plugin/commands/tell.md +66 -0
- package/plugin/scripts/announce-roster.mjs +5 -1
- package/plugin/scripts/emit-event.mjs +17 -0
- package/plugin/scripts/ensure-daemon.mjs +41 -1
- package/plugin/scripts/roster.mjs +5 -0
- package/plugin/skills/popover/SKILL.md +23 -8
|
@@ -12,6 +12,16 @@ import { daemonAddress, popoverHome, readStdin, request, sendFireAndForget } fro
|
|
|
12
12
|
|
|
13
13
|
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
14
14
|
|
|
15
|
+
/*
|
|
16
|
+
* A fork has nothing to do here, and doing it is actively harmful.
|
|
17
|
+
*
|
|
18
|
+
* The daemon spawns forks itself, so a daemon demonstrably exists — and registering the
|
|
19
|
+
* fork's session id would put a ghost agent on the team roster for every ask answered. Same
|
|
20
|
+
* guard, same reason, as emit-event.mjs; see its header for what the ghost then does to
|
|
21
|
+
* attribution.
|
|
22
|
+
*/
|
|
23
|
+
if (process.env.CLAUDE_CODE_ENTRYPOINT === "popover-fork") process.exit(0);
|
|
24
|
+
|
|
15
25
|
async function main() {
|
|
16
26
|
const raw = await readStdin().catch(() => "");
|
|
17
27
|
let payload = null;
|
|
@@ -22,7 +32,12 @@ async function main() {
|
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
const alive = await ping();
|
|
25
|
-
|
|
35
|
+
// `updateInProgress()` is the interlock, not an optimisation. `popover update` stops the
|
|
36
|
+
// daemon and hands npm up to five minutes to replace the global install; a daemon started
|
|
37
|
+
// in that window runs out of the tree being replaced and holds its files open, so npm's
|
|
38
|
+
// rename fails EPERM/EBUSY on Windows and the update aborts half-done. Every session on the
|
|
39
|
+
// machine runs this hook, so without the check one of them wins that race almost every time.
|
|
40
|
+
if (!alive && !updateInProgress()) {
|
|
26
41
|
const entry = resolveDaemonEntry();
|
|
27
42
|
if (entry) {
|
|
28
43
|
launch(entry);
|
|
@@ -95,6 +110,31 @@ function resolveDaemonEntry() {
|
|
|
95
110
|
return null;
|
|
96
111
|
}
|
|
97
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Whether `popover update` is replacing the install tree right now.
|
|
115
|
+
*
|
|
116
|
+
* Written by `beginUpdateLock` in packages/cli/src/daemon-lock.ts, which holds the readable
|
|
117
|
+
* version of why this exists. Duplicated here rather than imported for the same reason
|
|
118
|
+
* `resolveDaemonEntry` duplicates its path: this file must resolve no imports beyond the ones
|
|
119
|
+
* it already has, because a hook that throws breaks every session on the machine. Keep the
|
|
120
|
+
* two in step.
|
|
121
|
+
*
|
|
122
|
+
* Every branch fails towards starting the daemon. A marker with no deadline, or one whose
|
|
123
|
+
* deadline has passed, is a crashed update rather than a running one, and refusing to start
|
|
124
|
+
* on that basis would leave a machine permanently without a daemon and nothing on screen to
|
|
125
|
+
* explain it. Only a marker that is present, readable and unexpired holds us back.
|
|
126
|
+
*/
|
|
127
|
+
function updateInProgress() {
|
|
128
|
+
try {
|
|
129
|
+
const file = path.join(popoverHome(), "update.lock");
|
|
130
|
+
if (!existsSync(file)) return false;
|
|
131
|
+
const deadline = Number(JSON.parse(readFileSync(file, "utf8")).deadline);
|
|
132
|
+
return Number.isFinite(deadline) && Date.now() < deadline;
|
|
133
|
+
} catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
98
138
|
function launch(entry) {
|
|
99
139
|
try {
|
|
100
140
|
// Detached with stdio to a log file: the daemon must outlive this hook, this session,
|
|
@@ -18,6 +18,11 @@ const reply = await request(
|
|
|
18
18
|
id: "cli",
|
|
19
19
|
refresh: true,
|
|
20
20
|
...(callerSessionId() ? { fromSessionId: callerSessionId() } : {}),
|
|
21
|
+
// Fallback for the window where the daemon has not yet resolved this session's repo —
|
|
22
|
+
// the same hint the MCP server sends. Without it an unplaceable caller falls through to
|
|
23
|
+
// pure recency across every session on the machine, so `/popover:team` run in one repo
|
|
24
|
+
// could print the roster for another, under a heading claiming it was this one.
|
|
25
|
+
cwd: process.cwd(),
|
|
21
26
|
},
|
|
22
27
|
{ timeoutMs: 8000 },
|
|
23
28
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: popover
|
|
3
|
-
description:
|
|
3
|
+
description: "Judgment for reaching a teammate's Claude Code agent *without being asked to* — when it is worth spending their tokens, and which of /popover:team, /popover:ask, /popover:tell and /popover:fork fits. Nothing to invoke by hand: use it when a question turns on what a colleague decided, ruled out, or is changing right now — why the code is the way it is when the repo does not say, whether work about to start is already in flight, or why something nobody touched is broken."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# popover
|
|
@@ -10,10 +10,21 @@ accumulated context you do not have: the alternatives they rejected, the constra
|
|
|
10
10
|
forced an awkward shape, what they changed twenty minutes ago and have not pushed. popover
|
|
11
11
|
lets you reach those agents.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
**This skill is not a command, and there is nothing here for a user to invoke.** The four
|
|
14
|
+
commands are the things a user types:
|
|
15
|
+
|
|
16
|
+
| | |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `/popover:team` | who is working in this repo right now |
|
|
19
|
+
| `/popover:ask` | one question to one agent, and you wait for the answer |
|
|
20
|
+
| `/popover:tell` | a heads-up into a teammate's live session; nothing comes back |
|
|
21
|
+
| `/popover:fork` | hand this whole conversation to a teammate |
|
|
22
|
+
|
|
23
|
+
This file is the judgment around them: when reaching for one is worth it, which one fits, and
|
|
24
|
+
what each one spends. It exists because the moment to use popover rarely announces itself. The
|
|
14
25
|
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
|
-
|
|
26
|
+
record it — but a colleague's agent worked it out this morning. Nobody will type `/popover:ask`
|
|
27
|
+
for you. Noticing is your job.
|
|
17
28
|
|
|
18
29
|
## The three tools
|
|
19
30
|
|
|
@@ -139,7 +150,11 @@ The tools return errors as text; relay them rather than retrying with different
|
|
|
139
150
|
|
|
140
151
|
## The user-facing commands
|
|
141
152
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
153
|
+
The four commands carry the full flows for when the user drives this explicitly — how to
|
|
154
|
+
present a roster, how to word an ask, how to take delivery of a fork. Do not restate their
|
|
155
|
+
steps here or work around them: **when the user invokes a command, follow that command.** This
|
|
156
|
+
skill is for the other case, where nobody invoked anything and you noticed the moment yourself.
|
|
157
|
+
|
|
158
|
+
When you act on your own, prefer naming the command you are standing in for — "I'll run the
|
|
159
|
+
equivalent of `/popover:ask B1`" — so the user learns the surface they can drive directly next
|
|
160
|
+
time.
|