Bannière en gras (noir sur jaune) affichant le nom de la session de travail en cours

Mods pour Claude Code : de petits plugins de hooks qui modifient l'interface ou le comportement de l'outil et se rechargent à chaud.
| Dossier | Rôle |
|---|---|
message-banniere/ | Affiche le nom de la session de travail en cours, en gras, noir sur fond jaune (panneau, plus une ligne de statut imitée en Unicode). |
claude --plugin-dir <chemin>/message-banniere
Vérifier et tester un mod :
claude plugin validate message-banniere
claude plugin test message-banniere
Dans une session cloud affichée par l'application desktop, la bande et le panneau dessinés par un mod ne s'affichent pas (observé le 2026-10-05) ; seule la ligne de statut apparaît. Pour le rendu complet, utiliser une session locale ou un terminal.
hooks/register.tsx 87 lines1import { atom, read, update } from 'claude-code'
2import type { Register } from 'claude-code'
3
4import type { Titre } from '../types'
5
6// Texte noir sur fond jaune vif : contraste maximal (rendu du panneau).
7const TEXTE = '#000000'
8const FOND = '#FFD400'
9
10// Affiché tant que la session n'a pas encore de nom.
11const SANS_NOM = 'SESSION SANS NOM'
12
13const PANNEAU = 'banniere'
14const TITRE_PANNEAU = 'Session de travail'
15
16// Largeur demandée au panneau ancré : assez pour le nom, sans écraser la conversation.
17const COLONNES = 32
18
19// La ligne de statut n'accepte que du texte brut. Majuscules simples et barres :
20// les lettres Unicode « gras » et les emojis se rendent à des largeurs inégales.
21const ligne = (nom: string): string => `▌ ${nom.toUpperCase()} ▐`
22
23const titre = atom({ plugin: 'message-banniere', key: 'titre' } as const, null as Titre)
24
25export const register: Register = on => {
26 // Le nom de la session accompagne ces deux événements « classic » ;
27 // on le mémorise dès qu'il est présent (il peut apparaître après le démarrage).
28 on('classic.SessionStart', async ($, e, next) => {
29 if (e.session_title) await update($, titre, () => e.session_title ?? null)
30 $.ui.status(ligne((await read($, titre)) ?? SANS_NOM))
31 return next(e)
32 })
33
34 on('classic.UserPromptSubmit', async ($, e, next) => {
35 if (e.session_title) await update($, titre, () => e.session_title ?? null)
36 $.ui.status(ligne((await read($, titre)) ?? SANS_NOM))
37 return next(e)
38 })
39
40 // Panneau ouvert au démarrage (la surface peut le garder en attente si elle est trop étroite)...
41 on('session.start', async ($, e, next) => {
42 await $.command.register({
43 name: 'banniere',
44 description: 'Affiche le nom de la session de travail en cours',
45 })
46 $.ui.status(ligne((await read($, titre)) ?? SANS_NOM))
47 void $.ui.open({ id: PANNEAU, title: TITRE_PANNEAU, columns: COLONNES })
48
49 return next(e)
50 })
51
52 // ...et rouvert à chaque message : une action de la personne place le panneau à toute largeur.
53 on('prompt.submit', async ($, e, next) => {
54 $.ui.status(ligne((await read($, titre)) ?? SANS_NOM))
55 void $.ui.open({ id: PANNEAU, title: TITRE_PANNEAU, columns: COLONNES })
56
57 return next(e)
58 })
59
60 on('command.run', { command: 'banniere' }, async $ => {
61 $.ui.status(ligne((await read($, titre)) ?? SANS_NOM))
62 await $.ui.open({ id: PANNEAU, title: TITRE_PANNEAU, columns: COLONNES })
63
64 return { text: 'Bannière ouverte.' }
65 })
66
67 on('ui.render', { component: 'Pane', requestId: PANNEAU }, async ($, e) => {
68 const { Box, Text } = $.ui.resolve(e)
69 const nom = (await read($, titre)) ?? SANS_NOM
70
71 return (
72 <Box
73 backgroundColor={FOND}
74 paddingX={3}
75 paddingY={1}
76 flexGrow={1}
77 alignItems="center"
78 justifyContent="center"
79 >
80 <Text bold color={TEXTE} backgroundColor={FOND}>
81 {nom.toUpperCase()}
82 </Text>
83 </Box>
84 )
85 })
86}
87types/index.d.ts 8 lines1export type Titre = string | null
2
3declare module 'claude-code' {
4 interface PluginState {
5 'message-banniere': { titre: Titre }
6 }
7}
8