@popoverinstall/cli 0.9.0 → 0.10.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 +91 -0
- package/README.md +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/threads.d.ts +163 -0
- package/dist/threads.d.ts.map +1 -0
- package/dist/threads.js +576 -0
- package/dist/threads.js.map +1 -0
- package/dist/vaults.d.ts +1 -102
- package/dist/vaults.d.ts.map +1 -1
- package/dist/vaults.js +15 -294
- package/dist/vaults.js.map +1 -1
- package/package.json +47 -47
- package/plugin/.claude-plugin/plugin.json +19 -19
- package/plugin/commands/ask.md +18 -9
- package/plugin/commands/message.md +152 -0
- package/plugin/commands/team.md +9 -7
- package/plugin/commands/tell.md +12 -3
- package/plugin/commands/vault.md +34 -13
- package/plugin/hooks/hooks.json +25 -1
- package/plugin/mcp/index.mjs +1081 -585
- package/plugin/scripts/_ipc.mjs +49 -1
- package/plugin/scripts/announce-roster.mjs +5 -4
- package/plugin/scripts/deliver-messages.mjs +7 -5
- package/plugin/scripts/emit-event.mjs +11 -2
- package/plugin/scripts/inject-message.mjs +297 -0
- package/plugin/scripts/nudge-vault.mjs +517 -0
- package/plugin/skills/popover/SKILL.md +294 -175
package/package.json
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@popoverinstall/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "See your teammates' active Claude Code agents and ask them questions.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"claude",
|
|
7
|
-
"claude-code",
|
|
8
|
-
"agents",
|
|
9
|
-
"team",
|
|
10
|
-
"collaboration",
|
|
11
|
-
"cli"
|
|
12
|
-
],
|
|
13
|
-
"type": "module",
|
|
14
|
-
"license": "MIT",
|
|
15
|
-
"homepage": "https://github.com/many-ideations/popover",
|
|
16
|
-
"bugs": "https://github.com/many-ideations/popover/issues",
|
|
17
|
-
"repository": {
|
|
18
|
-
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/many-ideations/popover.git",
|
|
20
|
-
"directory": "packages/cli"
|
|
21
|
-
},
|
|
22
|
-
"engines": {
|
|
23
|
-
"node": ">=20"
|
|
24
|
-
},
|
|
25
|
-
"publishConfig": {
|
|
26
|
-
"access": "public"
|
|
27
|
-
},
|
|
28
|
-
"main": "./dist/index.js",
|
|
29
|
-
"bin": {
|
|
30
|
-
"popover": "./dist/index.js"
|
|
31
|
-
},
|
|
32
|
-
"files": [
|
|
33
|
-
"dist",
|
|
34
|
-
"plugin",
|
|
35
|
-
".claude-plugin",
|
|
36
|
-
"README.md",
|
|
37
|
-
"CHANGELOG.md"
|
|
38
|
-
],
|
|
39
|
-
"scripts": {
|
|
40
|
-
"build": "tsc -b",
|
|
41
|
-
"prepack": "node ../../scripts/stage-plugin.mjs && tsc -b"
|
|
42
|
-
},
|
|
43
|
-
"dependencies": {
|
|
44
|
-
"@popoverinstall/daemon": "0.
|
|
45
|
-
"@popoverinstall/shared": "0.
|
|
46
|
-
}
|
|
47
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@popoverinstall/cli",
|
|
3
|
+
"version": "0.10.0",
|
|
4
|
+
"description": "See your teammates' active Claude Code agents and ask them questions.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"agents",
|
|
9
|
+
"team",
|
|
10
|
+
"collaboration",
|
|
11
|
+
"cli"
|
|
12
|
+
],
|
|
13
|
+
"type": "module",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"homepage": "https://github.com/many-ideations/popover",
|
|
16
|
+
"bugs": "https://github.com/many-ideations/popover/issues",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/many-ideations/popover.git",
|
|
20
|
+
"directory": "packages/cli"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"bin": {
|
|
30
|
+
"popover": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"plugin",
|
|
35
|
+
".claude-plugin",
|
|
36
|
+
"README.md",
|
|
37
|
+
"CHANGELOG.md"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc -b",
|
|
41
|
+
"prepack": "node ../../scripts/stage-plugin.mjs && tsc -b"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@popoverinstall/daemon": "0.10.0",
|
|
45
|
+
"@popoverinstall/shared": "0.10.0"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
|
-
"name": "popover",
|
|
4
|
-
"displayName": "Popover",
|
|
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.
|
|
7
|
-
"author": {
|
|
8
|
-
"name": "Quolabs"
|
|
9
|
-
},
|
|
10
|
-
"homepage": "https://github.com/many-ideations/popover",
|
|
11
|
-
"repository": "https://github.com/many-ideations/popover",
|
|
12
|
-
"license": "MIT",
|
|
13
|
-
"keywords": [
|
|
14
|
-
"team",
|
|
15
|
-
"collaboration",
|
|
16
|
-
"agents",
|
|
17
|
-
"mcp"
|
|
18
|
-
]
|
|
19
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
|
+
"name": "popover",
|
|
4
|
+
"displayName": "Popover",
|
|
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.10.0",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Quolabs"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/many-ideations/popover",
|
|
11
|
+
"repository": "https://github.com/many-ideations/popover",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"team",
|
|
15
|
+
"collaboration",
|
|
16
|
+
"agents",
|
|
17
|
+
"mcp"
|
|
18
|
+
]
|
|
19
|
+
}
|
package/plugin/commands/ask.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Deprecated, use /popover:message — ask a teammate's agent a question and wait for the answer
|
|
3
3
|
# Quoted because an unquoted value starting with `[` is parsed as a YAML flow sequence,
|
|
4
4
|
# which fails and silently drops EVERY field here, allowed-tools included.
|
|
5
5
|
argument-hint: "[agent-handle] <question>"
|
|
@@ -10,6 +10,14 @@ allowed-tools: mcp__plugin_popover_popover__team_list, mcp__plugin_popover_popov
|
|
|
10
10
|
|
|
11
11
|
The user ran `/popover:ask`. Arguments, which may be empty: **$ARGUMENTS**
|
|
12
12
|
|
|
13
|
+
> **Deprecated as of 0.10.0. `/popover:message` does this and more.** Everything below
|
|
14
|
+
> still runs: the user typed this, so carry it out rather than answering with a
|
|
15
|
+
> correction, and mention the newer command once at the end in a single line. It
|
|
16
|
+
> supersedes this one because choosing between asking and telling was never the user's
|
|
17
|
+
> decision to make — it turns on what the target agent is doing at that second, which the
|
|
18
|
+
> daemon knows and the person typing does not (`docs/messages.md` §1). A message also
|
|
19
|
+
> threads, so the answer can be replied to and replied to again, where an ask ends.
|
|
20
|
+
|
|
13
21
|
Only agents working in **this repo** are reachable. A teammate running Claude Code in a
|
|
14
22
|
different repository is neither listed nor askable, so "nobody to ask" means nobody else is
|
|
15
23
|
working *here* — not that the team is idle. Say it that way if it comes up.
|
|
@@ -28,12 +36,13 @@ Stop there. Do not ask anything on the user's behalf.
|
|
|
28
36
|
Call `mcp__plugin_popover_popover__team_ask` with:
|
|
29
37
|
|
|
30
38
|
- `target`: the handle or name they used, exactly as typed
|
|
31
|
-
- `question`: the rest of their message, as a **self-contained** question. The answering
|
|
32
|
-
has none of this conversation
|
|
33
|
-
just read. Expand every pronoun and vague reference ("that bug" → "the token refresh
|
|
34
|
-
the auth service"), name files by path, and say what the user is trying to do rather
|
|
35
|
-
only what they want to know.
|
|
36
|
-
|
|
39
|
+
- `question`: the rest of their message, as a **self-contained** question. The answering
|
|
40
|
+
agent has none of this conversation: it cannot see the file you are looking at or the error
|
|
41
|
+
you just read. Expand every pronoun and vague reference ("that bug" → "the token refresh
|
|
42
|
+
bug in the auth service"), name files by path, and say what the user is trying to do rather
|
|
43
|
+
than only what they want to know. Then stop, at whatever length that took. You are not
|
|
44
|
+
spending your only round trip, so there is nothing to buy by padding it out — a follow-up
|
|
45
|
+
is available and cheaper than it looks.
|
|
37
46
|
|
|
38
47
|
When the answer comes back, show it clearly attributed:
|
|
39
48
|
|
|
@@ -57,8 +66,8 @@ Call `mcp__plugin_popover_popover__team_list` first. Then:
|
|
|
57
66
|
rather than guessing at another agent.
|
|
58
67
|
- **One agent per question.** Never fan out across the roster to see who answers best.
|
|
59
68
|
- An answer comes from a **read-only copy** of their session. Their live session is not
|
|
60
|
-
interrupted
|
|
61
|
-
machine, and nothing else.
|
|
69
|
+
interrupted or modified while it answers, and is told afterwards what was asked. It costs
|
|
70
|
+
the teammate tokens on their own machine, and nothing else.
|
|
62
71
|
- If the tool errors or times out, relay it plainly. Do not silently re-ask, and do not retry
|
|
63
72
|
a different agent unless the user asks.
|
|
64
73
|
- If the user is trying to hand a colleague *work* rather than get an answer, say plainly that
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Message a teammate's agent and carry on the thread — the system picks how it reaches them
|
|
3
|
+
# Quoted because an unquoted value starting with `[` is parsed as a YAML flow sequence,
|
|
4
|
+
# which fails and silently drops EVERY field here, allowed-tools included.
|
|
5
|
+
argument-hint: "[agent-handle] <message>"
|
|
6
|
+
allowed-tools: mcp__plugin_popover_popover__team_list, mcp__plugin_popover_popover__team_message, AskUserQuestion
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Message a teammate's agent
|
|
10
|
+
|
|
11
|
+
The user ran `/popover:message`. Arguments, which may be empty: **$ARGUMENTS**
|
|
12
|
+
|
|
13
|
+
This is the one verb for reaching another agent, and it replaces `/popover:ask` and
|
|
14
|
+
`/popover:tell`. Those still work and are still carried out; they are deprecated because the
|
|
15
|
+
difference between them was never the user's to decide. Whether a message is answered by the
|
|
16
|
+
live session or by a read-only copy of it depends on what that agent is doing at this second
|
|
17
|
+
— a fact the daemon holds and the person typing does not. See `docs/messages.md` §1.
|
|
18
|
+
|
|
19
|
+
So **never say which transport will be used before you send.** The tool reports which one
|
|
20
|
+
carried it afterwards, and that is the only honest moment to mention it.
|
|
21
|
+
|
|
22
|
+
Only agents working in **this repo** are reachable. A teammate running Claude Code in a
|
|
23
|
+
different repository is neither listed nor reachable, so "nobody to message" means nobody
|
|
24
|
+
else is working *here* — not that the team is idle. Say it that way if it comes up.
|
|
25
|
+
|
|
26
|
+
## No arguments
|
|
27
|
+
|
|
28
|
+
Call `mcp__plugin_popover_popover__team_list`, print what it returns **verbatim** in a fenced
|
|
29
|
+
block, and show the form:
|
|
30
|
+
|
|
31
|
+
`/popover:message B1 is the repo_keys migration applied on prod?`
|
|
32
|
+
|
|
33
|
+
Stop there. Do not message anyone on the user's behalf.
|
|
34
|
+
|
|
35
|
+
## A handle and a message
|
|
36
|
+
|
|
37
|
+
If this conversation has no open thread with that agent, **confirm before opening one — and
|
|
38
|
+
say what opening it will cost.**
|
|
39
|
+
|
|
40
|
+
Look first at what that agent is doing. `mcp__plugin_popover_popover__team_list` already
|
|
41
|
+
returns it, so this needs no round trip and costs nothing; call it if you have not this turn.
|
|
42
|
+
Their state decides how the first message travels, which is the one thing that turns this
|
|
43
|
+
confirmation from a formality into a decision the user can actually make:
|
|
44
|
+
|
|
45
|
+
- **working** — "B1 is working right now, so this will interrupt them mid-task."
|
|
46
|
+
- **idle** — "B1 is idle; a read-only copy of their session will answer at their expense."
|
|
47
|
+
- **waiting** — the same line as *idle*. Their agent is blocked asking its own human
|
|
48
|
+
something, so no turn is running and nothing gets interrupted. The name reads as though it
|
|
49
|
+
were the busy case and it is not (`docs/messages.md` §4).
|
|
50
|
+
- **offline** — do not confirm anything. They are unreachable; say so and stop.
|
|
51
|
+
|
|
52
|
+
Then call `AskUserQuestion` with exactly two options, so Esc cancels:
|
|
53
|
+
|
|
54
|
+
- **Open the thread** — "<the state line above> They can reply, and you can reply to that,
|
|
55
|
+
without me asking you again."
|
|
56
|
+
- **Don't** — "Leave it"
|
|
57
|
+
|
|
58
|
+
Two things about that wording, and neither is decoration (`docs/messages.md` §2, §2.1):
|
|
59
|
+
|
|
60
|
+
- **The consent is to the channel, not to one delivery.** The user is agreeing to a
|
|
61
|
+
conversation with that colleague, which is precisely why they are not asked again for the
|
|
62
|
+
second message — opening the channel is the deliberate act, and no human re-consents to a
|
|
63
|
+
conversation per sentence. Word it that way rather than as a one-off send, or the promise
|
|
64
|
+
not to ask again will read as something you took rather than something they gave.
|
|
65
|
+
- **The state line is true of the first message and is not a promise about the thread.**
|
|
66
|
+
Routing is decided per message, so a thread opened against an idle agent may reach a
|
|
67
|
+
working one ten minutes later and spend the other kind of cost. Say what the first message
|
|
68
|
+
will do and stop there. Do not claim the whole conversation is priced, because it is not.
|
|
69
|
+
|
|
70
|
+
On a yes, call `mcp__plugin_popover_popover__team_message` with:
|
|
71
|
+
|
|
72
|
+
- `target`: the handle or name they used, exactly as typed
|
|
73
|
+
- `body`: the rest of their message, made **self-contained**. The first message on a thread
|
|
74
|
+
arrives with none of this conversation attached: the recipient cannot see the file you are
|
|
75
|
+
looking at or the error you just read. Expand every pronoun and vague reference ("that
|
|
76
|
+
bug" → "the token refresh bug in the auth service"), name files by path, and say what the
|
|
77
|
+
user is trying to do rather than only what they want to know.
|
|
78
|
+
|
|
79
|
+
Write it at whatever length it takes and stop there. There is no length to hit in either
|
|
80
|
+
direction and none is prescribed — a message of six words is a good message when six words
|
|
81
|
+
are the message, and a follow-up is available, so nothing is bought by padding.
|
|
82
|
+
|
|
83
|
+
Then report what came back:
|
|
84
|
+
|
|
85
|
+
- **An answer** — show it attributed, `> **B1** (Bob Chen, api-server): …answer…`, and say
|
|
86
|
+
how it bears on the work in hand, if it does.
|
|
87
|
+
- **No answer on this call** — the message reached a live session mid-task. Say so in one
|
|
88
|
+
line and carry on. A reply, if they send one, arrives later rather than never: it comes
|
|
89
|
+
back through `team_receipts` as a `kind: "thread"` record, announced by a line your own
|
|
90
|
+
daemon prints (`docs/messages.md` §4.1). So do not wait on it and do not send the message
|
|
91
|
+
again — but do read it when you are told it is there, because that one may have somebody
|
|
92
|
+
waiting on the other end.
|
|
93
|
+
|
|
94
|
+
Either way, keep the thread id the tool returned. It is how the conversation continues.
|
|
95
|
+
|
|
96
|
+
## A message with no handle
|
|
97
|
+
|
|
98
|
+
Call `mcp__plugin_popover_popover__team_list` first. Then:
|
|
99
|
+
|
|
100
|
+
- If exactly one agent plausibly fits, name it in the confirmation above and say why you
|
|
101
|
+
picked it — the user still gets a yes or no, with the cost line, before anything is sent.
|
|
102
|
+
- If several fit, call `AskUserQuestion` with up to 4 of them as options (label = the handle,
|
|
103
|
+
description = owner, repo, and whether messaging it interrupts them or spends their tokens).
|
|
104
|
+
Choosing a recipient *is* the consent — which is why the cost has to be in the options they
|
|
105
|
+
are choosing between, not mentioned afterwards — so no second confirmation follows it.
|
|
106
|
+
- If none fit, say so and show the roster instead. Never fan out across the roster.
|
|
107
|
+
|
|
108
|
+
## Continuing a thread
|
|
109
|
+
|
|
110
|
+
A thread runs both ways: they can reply, you can reply to that, and either side can keep
|
|
111
|
+
going. Pass `thread_id` — the one the earlier call returned — and leave `target` as it was.
|
|
112
|
+
A thread already knows who is on the other end.
|
|
113
|
+
|
|
114
|
+
Do not confirm again. Consent was granted when the thread was opened and it covers the
|
|
115
|
+
conversation, not the sentence. Send the reply at the length a reply takes; later messages
|
|
116
|
+
arrive with the thread's own history behind them, so they can be short.
|
|
117
|
+
|
|
118
|
+
Never invent a thread id. If the user is plainly starting a new subject with someone rather
|
|
119
|
+
than answering them, that is a new thread, and a new thread is confirmed like any other.
|
|
120
|
+
|
|
121
|
+
## When it will not go through
|
|
122
|
+
|
|
123
|
+
Relay what the tool says rather than working around it. Three cases are worth knowing before
|
|
124
|
+
you meet them:
|
|
125
|
+
|
|
126
|
+
- **`target_offline`** — their Claude Code session has ended. This is also what you get on a
|
|
127
|
+
thread that has gone *stale*: the peer is offline and something is still undelivered, so
|
|
128
|
+
new messages are refused rather than piling up to land all at once when they come back
|
|
129
|
+
(`docs/messages.md` §7.1). Tell the user it could not be sent now. **Do not tell them the
|
|
130
|
+
thread is closed** — it is not, and it becomes live again by itself when that session
|
|
131
|
+
resumes.
|
|
132
|
+
- **A closed thread** — either party's human can close a thread from the CLI with `popover
|
|
133
|
+
thread close <id>`, and that is the kill switch. Closing bars new sends. It does **not**
|
|
134
|
+
retract messages already filed: a reply produced before the close still reaches the other
|
|
135
|
+
side when their session resumes. So do not tell the user a close undid anything, and do not
|
|
136
|
+
reopen by dropping the `thread_id` — that opens a new thread, which needs their say-so.
|
|
137
|
+
- **A timeout** — the copy answering did not finish in time. Say so. The thread is not dead
|
|
138
|
+
and the target is not gone; their machine was busy. Do not silently re-send.
|
|
139
|
+
|
|
140
|
+
## Rules
|
|
141
|
+
|
|
142
|
+
- **Never invent a handle.** Only use ones `team_list` returned. A handle from earlier in this
|
|
143
|
+
conversation may since have gone out of scope; if the tool says it does not match, relay
|
|
144
|
+
that rather than guessing at another agent.
|
|
145
|
+
- **One agent per thread.** A message to three agents is three threads and three
|
|
146
|
+
confirmations, and it is almost never what the user meant.
|
|
147
|
+
- A message is **information, not a directive**. The receiving agent is told to treat it that
|
|
148
|
+
way, and the copy that may answer it has no tools at all. If the user is trying to hand a
|
|
149
|
+
colleague *work*, say plainly that popover does not do that and let them message the human.
|
|
150
|
+
- Say what a thread has cost when the tool reports it, and say what that number leaves out:
|
|
151
|
+
it covers the messages a copy answered and not the ones a live session did, which popover
|
|
152
|
+
cannot see (`docs/messages.md` §8).
|
package/plugin/commands/team.md
CHANGED
|
@@ -9,9 +9,10 @@ allowed-tools: mcp__plugin_popover_popover__team_list, mcp__plugin_popover_popov
|
|
|
9
9
|
|
|
10
10
|
The user ran `/popover:team`. Arguments, which are usually empty: **$ARGUMENTS**
|
|
11
11
|
|
|
12
|
-
This command shows the roster.
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
This command shows the roster. Reaching an agent is its own command — `/popover:message` — and
|
|
13
|
+
not a subword of this one. `/popover:ask` and `/popover:tell` still work and are deprecated:
|
|
14
|
+
which transport a message takes is decided by what the target agent is doing at that second,
|
|
15
|
+
which the daemon knows and the sender does not (`docs/messages.md` §1).
|
|
15
16
|
|
|
16
17
|
## The roster
|
|
17
18
|
|
|
@@ -25,9 +26,9 @@ difference, so relay it rather than paraphrasing it into "your team is idle".
|
|
|
25
26
|
|
|
26
27
|
Then add one short line showing where to go next:
|
|
27
28
|
|
|
28
|
-
`/popover:
|
|
29
|
+
`/popover:message B1 why did you rule out redis?`
|
|
29
30
|
|
|
30
|
-
Stop there. Do not
|
|
31
|
+
Stop there. Do not message anyone on the user's behalf.
|
|
31
32
|
|
|
32
33
|
## If they typed `ask` or `tell` anyway
|
|
33
34
|
|
|
@@ -56,5 +57,6 @@ If the tool errors or times out, relay it plainly rather than retrying or trying
|
|
|
56
57
|
- Asking costs the *teammate* money and runs on *their* machine. Telling costs their attention
|
|
57
58
|
and notifies them. One agent per request either way.
|
|
58
59
|
- An answer comes from a read-only copy of their session. Their live session is not interrupted
|
|
59
|
-
|
|
60
|
-
next prompt —
|
|
60
|
+
or modified while it answers; it is told afterwards what was asked. A tell **is** delivered
|
|
61
|
+
into their live session, before its next prompt — and it is the only thing in popover a
|
|
62
|
+
teammate can aim *at* a running agent, which is why it is the one that asks first.
|
package/plugin/commands/tell.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Deprecated, use /popover:message — send a short heads-up into a teammate's live session
|
|
3
3
|
# Quoted because an unquoted value starting with `[` is parsed as a YAML flow sequence,
|
|
4
4
|
# which fails and silently drops EVERY field here, allowed-tools included.
|
|
5
5
|
argument-hint: "[agent-handle] <message>"
|
|
@@ -10,6 +10,14 @@ allowed-tools: mcp__plugin_popover_popover__team_list, mcp__plugin_popover_popov
|
|
|
10
10
|
|
|
11
11
|
The user ran `/popover:tell`. Arguments, which may be empty: **$ARGUMENTS**
|
|
12
12
|
|
|
13
|
+
> **Deprecated as of 0.10.0. Use `/popover:message`.** Everything below still runs — carry
|
|
14
|
+
> out what the user asked for, then name the newer command once at the end. A tell was the
|
|
15
|
+
> half of the surface that reached a *live* session, and which half you wanted was never a
|
|
16
|
+
> question worth putting to a person: `/popover:message` routes there by itself when the
|
|
17
|
+
> target is mid-turn (`docs/messages.md` §1, §4). Two things also change with it. Consent
|
|
18
|
+
> is confirmed once when a thread is opened rather than for every sentence (§2), and a
|
|
19
|
+
> message can be answered, where a tell is one-way by construction.
|
|
20
|
+
|
|
13
21
|
A tell is the one thing in popover that reaches a **running** agent: it is delivered into a
|
|
14
22
|
teammate's live session before its next prompt, and their user is notified. It costs a
|
|
15
23
|
colleague's attention rather than their tokens, which is why it is its own command and why the
|
|
@@ -60,7 +68,8 @@ If none fit, show the roster instead. Never broadcast to several agents.
|
|
|
60
68
|
give another agent a task, say so and offer `/popover:ask` instead — or suggest they message
|
|
61
69
|
the human.
|
|
62
70
|
- **Never invent a handle**, and do not fan out to several agents unless asked in as many words.
|
|
63
|
-
-
|
|
64
|
-
|
|
71
|
+
- **Nothing throttles this but you.** The bar for sending is the whole of the protection, so
|
|
72
|
+
carry it rather than expecting to be stopped at some number. If the tool refuses a message,
|
|
73
|
+
relay the refusal rather than retrying it.
|
|
65
74
|
- If it is genuinely ambiguous whether the user meant to ask or tell, prefer **`/popover:ask`**
|
|
66
75
|
— it interrupts nobody.
|
package/plugin/commands/vault.md
CHANGED
|
@@ -125,18 +125,37 @@ user would rather type them there.)
|
|
|
125
125
|
|
|
126
126
|
## Vaulting without being asked
|
|
127
127
|
|
|
128
|
-
**You decide.** This is the one place in popover where you
|
|
129
|
-
|
|
130
|
-
need permission first. Say what you are doing and why, in a
|
|
131
|
-
surprised — but do not ask for a yes before you start.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
128
|
+
**You decide, and the default is yes.** This is the one place in popover where you act on your
|
|
129
|
+
own judgement rather than asking: you create a vault because you concluded the conversation
|
|
130
|
+
was worth keeping, and you do not need permission first. Say what you are doing and why, in a
|
|
131
|
+
line — the user should never be surprised — but do not ask for a yes before you start.
|
|
132
|
+
|
|
133
|
+
### The moment is task completion
|
|
134
|
+
|
|
135
|
+
Not some time later, and not when it occurs to you. When you finish a task, vault before you
|
|
136
|
+
report completion. You have just built the thing, your grasp of the work is as good as it is
|
|
137
|
+
ever going to get, the user is about to move on to something else, and everything in this
|
|
138
|
+
conversation that the diff does not record is about to be deleted along with it.
|
|
139
|
+
|
|
140
|
+
`docs/vaults.md` §3 fixes that as the trigger and records why it beat the obvious
|
|
141
|
+
alternative. Vaulting on compaction was carried as an idea for a release, on the reasoning that
|
|
142
|
+
a session is largest, and about to lose most of itself, at the moment it compacts. What retired
|
|
143
|
+
it was selection rather than principle: compaction fires on the longest sessions, and a session
|
|
144
|
+
is usually long because it wandered, not because it concluded anything worth asking later.
|
|
145
|
+
Compaction says "this is about to be lost", which is urgency. Completion says "nobody is ever
|
|
146
|
+
going to understand this better than right now", which is quality — and quality is what
|
|
147
|
+
makes an archive worth asking rather than merely large.
|
|
148
|
+
|
|
149
|
+
So the burden runs the other way from every other proactive act in popover. Elsewhere you ask
|
|
150
|
+
first, or you offer and wait. Here you vault unless the exception below applies, because nobody
|
|
151
|
+
is going to interrupt an afternoon of debugging to say "this should be archived", and if it
|
|
152
|
+
waits for a prompt it does not happen.
|
|
153
|
+
|
|
154
|
+
That reversal is a deliberate departure from `/popover:fork`, where you may raise the idea and
|
|
155
|
+
only the user may act on it, and it is taken with that rule in full view. A fork discloses one
|
|
135
156
|
conversation to one named individual. A vault publishes to a team that already shares the
|
|
136
157
|
repository and the work, so the disclosure is small — and the cost of missing the moment is
|
|
137
|
-
high
|
|
138
|
-
notice. Nobody is going to interrupt an afternoon of debugging to say "this should be
|
|
139
|
-
archived". If it waits for a prompt, it does not happen.
|
|
158
|
+
high.
|
|
140
159
|
|
|
141
160
|
Vault when the conversation worked something out that the diff will not record:
|
|
142
161
|
|
|
@@ -151,9 +170,11 @@ Do **not** vault a conversation that only did what its diff says, a session with
|
|
|
151
170
|
concluded in it, or one carrying secrets or a customer's data — a vault is readable by the
|
|
152
171
|
service and outlives everyone in the room.
|
|
153
172
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
173
|
+
With the default reversed, that exception is carrying all the weight, so hold it honestly
|
|
174
|
+
rather than as a formality. Two failure modes make this rule wrong and you should be watching
|
|
175
|
+
for both in yourself: vaulting everything, which produces an index nobody trusts, and vaulting
|
|
176
|
+
nothing, which is the ask-first habit wearing a different hat. Reversing the default is what
|
|
177
|
+
makes the archive exist at all; the exception is what keeps it worth asking.
|
|
157
178
|
|
|
158
179
|
## Rules
|
|
159
180
|
|
package/plugin/hooks/hooks.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Publishes this machine's Claude Code session activity to the popover daemon.",
|
|
2
|
+
"description": "Publishes this machine's Claude Code session activity to the popover daemon, and tells the agent when teammates arrive or a task has just landed.",
|
|
3
3
|
"hooks": {
|
|
4
4
|
"SessionStart": [
|
|
5
5
|
{
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/ensure-daemon.mjs"],
|
|
11
11
|
"async": true,
|
|
12
12
|
"timeout": 30
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"type": "command",
|
|
16
|
+
"command": "node",
|
|
17
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/nudge-vault.mjs"],
|
|
18
|
+
"timeout": 5
|
|
13
19
|
}
|
|
14
20
|
]
|
|
15
21
|
}
|
|
@@ -67,6 +73,18 @@
|
|
|
67
73
|
]
|
|
68
74
|
}
|
|
69
75
|
],
|
|
76
|
+
"PostToolBatch": [
|
|
77
|
+
{
|
|
78
|
+
"hooks": [
|
|
79
|
+
{
|
|
80
|
+
"type": "command",
|
|
81
|
+
"command": "node",
|
|
82
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/inject-message.mjs"],
|
|
83
|
+
"timeout": 5
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
],
|
|
70
88
|
"Notification": [
|
|
71
89
|
{
|
|
72
90
|
"matcher": "agent_needs_input",
|
|
@@ -90,6 +108,12 @@
|
|
|
90
108
|
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/emit-event.mjs"],
|
|
91
109
|
"async": true,
|
|
92
110
|
"timeout": 15
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"type": "command",
|
|
114
|
+
"command": "node",
|
|
115
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/nudge-vault.mjs"],
|
|
116
|
+
"timeout": 5
|
|
93
117
|
}
|
|
94
118
|
]
|
|
95
119
|
}
|