Stop hook surfaces raw <teammate-message> XML as the notification title when an Agent Teams message is the last user-type transcript entry
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 68/100
Línea de trabajo
Start with plugins/warp/scripts/on-stop.sh, especially the jq filter at lines 39-51 and truncation at lines 60-62. Reproduce the Stop hook with an Agent Teams or cross-session message, then trace how the last user-type entry becomes QUERY. Done means recognized internal envelopes are handled as described, summaries can supply a title when needed, and unrecognized input still passes through unchanged.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
plugins/warp/scripts/on-stop.sh derives the notification title ("the user's last prompt") by scraping the session transcript for the last type: "user" entry containing a text block. Claude Code's Agent Teams feature records incoming teammate messages as type: "user" entries whose content is the raw internal delivery envelope — so when a teammate message is the most recent user-type entry at Stop time, Warp's in-app notification displays serialization internals instead of anything human-readable:
Another Claude session sent a message:
<teammate-message teammate_id="oss-record-researcher" color="…Task completed.
(The mid-attribute cutoff is the script's 197-char slice; Warp's own title clamp compounds it.)
Environment
- Warp Stable
0.2026.07.01.09.21.01, macOS (Darwin 27) - Claude Code
2.1.205 - Plugin
warp@claude-code-warp2.1.0(installed via Warp's in-app prompt)
Reproduction
- In Warp, run a Claude Code session with the plugin installed.
- Have another Claude Code session send it a message (Agent Teams
SendMessage, or any cross-session message — e.g. a background teammate reporting completion). - Let the receiving session finish its turn so the
Stophook fires while the teammate message is the most recent user-type transcript entry. - The completion toast shows the raw
<teammate-message …>envelope as its title.
Root cause
plugins/warp/scripts/on-stop.sh:39-51 — the jq filter selects the last type == "user" entry that has string content or at least one text block, on the assumption (per the comment at lines 33-38) that this distinguishes human prompts from tool-result messages. That assumption no longer holds: Claude Code injects teammate/cross-session messages into the transcript as user-type entries with plain-text content, beginning with a framing line followed by a <teammate-message teammate_id="…" color="…" summary="…">…</teammate-message> envelope. The filter has no provenance awareness (no handling of teammate, system-reminder, or meta-flagged entries anywhere in the repo), so the envelope is captured verbatim as QUERY, blindly truncated at 197 chars + ... (lines 60-62), and shipped to Warp, which renders query as the toast title.
Suggested fix (defense in depth — improve recognized patterns, pass everything else through)
The hook can't control what Claude Code writes into the transcript, so the goal is: accept garbage in, and only improve the output when the content is confidently recognized. Never reject or blank out unrecognized input — an odd-looking title is better than a missing notification.
- Skip confidently-recognized internal injections when selecting the "last user prompt", falling back to the previous qualifying entry. Anchor detection on the XML envelope tags (
<teammate-messageat the start of the text; content consisting solely of a<system-reminder>…</system-reminder>block) — these are stable ASCII identifiers that won't change under localization. The human-language framing line ("Another Claude session sent a message") may be translated in localized Claude Code builds, so treat it only as a secondary, best-effort signal, never the sole trigger. Matching must be Unicode-safe (message bodies can contain arbitrary Unicode; only the tag anchors are assumed ASCII). If Claude Code's transcript format exposes a meta/provenance flag (e.g.isMeta) on injected entries, prefer that over string matching entirely. - When the last entry is a recognized teammate-message envelope and no earlier human prompt exists, extract its
summary="…"attribute as the title instead — it's the sender's own human-readable one-liner, exactly what a notification wants. - Anything not confidently recognized passes through unchanged. No generic XML stripping, no rejection of "weird" input — only rewrite patterns that are positively identified as Claude Code internals.
This is Claude-transcript-specific knowledge, so the fix belongs in this plugin's scripts only — no shared/abstracted change that would affect the codex/gemini/antigravity integrations (though those repos may want an equivalent audit if their CLIs grow multi-session messaging).
Related
- The same last-user-entry scraping pattern appears in other scripts in this repo;
on-stop.shis the one that reproduces this symptom, but the class of bug is latent wherever user-type entries are assumed human-authored. - Defense-in-depth on the Warp side would also help: Warp core uses the plugin-supplied
queryas a notification title verbatim; preferring the payload'ssummaryfield or applying word-aware truncation there would soften any future plugin-side regression. Happy to file that separately againstwarpdotdev/warpif useful.
- Lenguaje dominante
- Shell
- Estrellas
- 234
- Forks
- 60
- Merge medio
- 2 d 8 h
- PR fusionados (30 d)
- 2
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de warpdotdev/claude-code-warp
-
on-stop.sh slurps the entire transcript with jq -s every turn — ~1 GB RSS on long sessions, triggered a host OOMPosiblemente ocupada @GeiserX la tomó hace 16 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
warpdotdev/claude-code-warp#63 · 2 comentarios ·
Todos los issues de warpdotdev/claude-code-warp
Issues similares
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 92/100
Los mantenedores suelen responder en 1 día
-
[Resource]: Valpas Keep AwakeAbiertoresource-submission validation-passed
Dificultad 1/5 Menos de una hora Aptitud para principiantes 67/100
hesreallyhim/awesome-claude-code#3264 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
area: install bug good first issue hacktoberfest
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Los mantenedores suelen responder en 3 días
-
Good first issue
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
armbian/build#11107 · 2 comentarios ·
Los mantenedores suelen responder en 1 día