Skip to main content
L’API mods è l’insieme di metodi che un mod chiama per agire: aggiungere comandi e strumenti, chiamare un modello, eseguire lavoro tra gli eventi e accedere al file system, ai processi e alla rete. Ogni hook la riceve come primo argomento, $, con i metodi raggruppati in namespace come $.ui e $.fs. Events decidono quando un hook viene eseguito, e l’API mods è ciò che l’hook chiama una volta che lo fa. Costruisci il tuo primo mod prima di iniziare qui. Per ogni metodo, vedi mods API methods o leggi i tipi per la tua build.

Aggiungi un comando o uno strumento

Un mod può aggiungere un comando per l’utente da eseguire e uno strumento per Claude da chiamare. Registra entrambi in un hook session.start. Claude Code attende quell’hook prima del primo prompt, quindi ciò che registri è disponibile dal primo turno.

Aggiungi un comando

Un comando è per l’utente. Registralo, quindi gestisci command.run per il suo nome. Questo esempio aggiunge un comando /standup che accetta un numero facoltativo di giorni:
Dopo l’avvio della sessione, /standup appare con la sua descrizione nell’elenco che vedi quando digiti /. L’argumentHint viene visualizzato nel prompt dopo che digiti il comando e uno spazio, come in /standup [days]. Quando esegui /standup 3, il secondo hook restituisce Summary for the last 3 day(s): ..., e la trascrizione mostra quel testo dopo il nome del plugin. L’hook non chiama mai next, perché il comando non ha comportamento diverso dal tuo. Il text che restituisci viene stampato nella trascrizione e Claude lo legge. Per non stampare nulla, come un comando che apre solo un pane, restituisci {}. Per consentire al comando di essere eseguito mentre Claude sta lavorando, aggiungi immediate: true alla registrazione. Scegli un nome che nessun comando integrato utilizza. Digita / in una sessione per vederli. $.command.register genera un’eccezione per un nome occupato, con un messaggio come "/focus" refused: it is the built-in /focus". Un hook che genera un’eccezione viene saltato, quindi il resto del tuo hook session.start non viene eseguito nemmeno. Registra i comandi per ultimi in quell’hook, oppure avvolgi la chiamata in try e catch.

Aggiungi uno strumento

Uno strumento è per Claude. Registralo con un nome, una descrizione che Claude legge e uno JSON Schema per il suo input. Claude lo vede con un nome più lungo composto da mcp__, il nome del tuo plugin, due underscore e il nome che hai registrato. Gestisci le sue chiamate in un hook tool.call filtrato a quel nome completo. Questo esempio, da un plugin denominato my-mod, registra ticket, quindi il nome completo è mcp__my-mod__ticket. Fornisce a Claude uno strumento che cerca un ticket in un issue tracker:
Quando chiedi informazioni su un ticket, Claude può chiamare mcp__my-mod__ticket con il suo id. Il secondo hook recupera il ticket e restituisce il corpo della risposta, che Claude legge come risultato dello strumento. Quando il server risponde con uno stato di errore, Claude legge Lookup failed with status e il numero.

Chiama un modello

Un mod può fare una domanda a un modello di sua iniziativa, al di fuori della conversazione, per un piccolo lavoro come ordinare o riassumere un pezzo di testo. $.model.complete invia un prompt a un modello con le credenziali della tua sessione e si risolve nella risposta. Non ha cronologia della conversazione. Questo hook risponde a un comando /triage, registrato come comando, chiedendo a un piccolo modello di etichettare il testo digitato dopo di esso:
Quando esegui /triage the export button does nothing, il mod invia quel testo al modello e stampa la sua risposta, come Label: bug. La conversazione di Claude non fa parte della richiesta. Quando il modello non risponde, l’etichetta è unknown. Un errore dell’API Claude non rifiuta la chiamata, quindi controlla r.isAnswered e leggi r.reason quando è false. La chiamata rifiuta solo per una richiesta che Claude Code non invierà, come un modello che la tua organizzazione blocca. I tipi per la tua build elencano le altre opzioni, come effort, e i limiti forniscono il valore predefinito di maxTokens. $.model.fork({ prompt }) pone una domanda sulla conversazione corrente, con lo stesso modello e prompt di sistema, quindi l’API Claude serve la maggior parte da prompt caching. Queste chiamate utilizzano il piano o la chiave API dell’utente.

Esegui lavoro in background

Il lavoro che sopravvive a un evento, come controllare qualcosa una volta al minuto, viene eseguito su un timer che avvii da session.start. Un hook stesso viene eseguito per un evento e ha un limite di tempo di 10 secondi del suo tempo di esecuzione. Il tempo trascorso in attesa di next o di una chiamata all’API mods non conta, tranne un $.clock.sleep. $.clock.every e $.clock.after prendono il posto di setInterval e setTimeout, con il ritardo in millisecondi per primo: $.clock.after(5000, fn) chiama fn una volta, cinque secondi da ora. Ognuno restituisce un timer con un metodo cancel(), e await $.clock.now() fornisce l’ora in millisecondi. Questo hook cerca i controlli di una pull request una volta al minuto e mostra il risultato sotto il prompt. summarize è una funzione tua che trasforma l’output JSON del comando in poche parole:
La sessione inizia come al solito. Un minuto dopo, una riga appare sotto il prompt con un ⚠, il nome del mod e poi checks: e il tuo riassunto. Viene sostituito una volta al minuto dopo. Il callback del timer viene eseguito al di fuori di qualsiasi evento, quindi continua a funzionare tra i turni e non ne avvia uno. Se il callback genera un’eccezione, l’errore va al debug log e il timer viene eseguito di nuovo all’intervallo successivo.

Mostra qualcosa senza avviare un turno

Un lavoro in background può mostrare all’utente qualcosa senza avviare un turno. Ognuna di queste chiamate mette il testo in un posto diverso:

Avvia un turno da un lavoro in background

Quando un lavoro in background trova qualcosa che ha bisogno dell’attenzione di Claude, può avviare un turno inviando un prompt con $.prompt.submit({ text }). Claude legge il testo dopo una frase che nomina il tuo mod come mittente. Per inviarlo come parole proprie dell’utente, senza quella frase, aggiungi asUser: true. La chiamata attende fino a quando la sessione è inattiva e quindi avvia un nuovo turno. Si risolve quando quel turno inizia, quindi non await in un handler che viene eseguito mentre Claude sta lavorando.

Interrompi il lavoro in background

Il lavoro in background si interrompe in due modi. I timer si interrompono quando il modulo viene ricaricato. Per il lavoro di lunga durata all’interno di un hook, next.signal è un AbortSignal che si interrompe quando l’evento che il tuo hook sta gestendo viene abbandonato, ad esempio quando l’utente interrompe, quindi passalo a qualsiasi cosa di lunga durata.

Invia e ricevi messaggi tra sessioni

Un mod può inviare un messaggio in testo semplice a un’altra delle tue sessioni o a uno dei subagent di questa sessione e osservare i messaggi che arrivano e partono. $.session.send({ to, text }) ne invia uno, la stessa consegna che lo strumento SendMessage effettua. to è { sessionId } per una sessione, { agentId } per un subagent da $.agent.list(), o l’indirizzo stringa da cui proviene un messaggio ricevuto. La chiamata si risolve una volta che il messaggio è in coda, con { isDelivered: true }. Quando nulla è stato consegnato si risolve con { isDelivered: false, reason }, e reason spiega perché. Questo hook risponde a un comando /ping, registrato come comando, chiedendo alla sessione il cui id digiti dopo di esso uno stato:
Quando il messaggio è in coda, nulla appare nella tua sessione e Claude dell’altra sessione legge Status? One line. Quando nulla è stato consegnato, una piccola casella in alto a destra fornisce il motivo e scompare dopo pochi secondi. Due eventi consentono a un mod di osservare i messaggi. Restituisci next(e) da entrambi per passare ogni messaggio invariato: Una sessione impostata per rifiutare messaggi in entrata rifiuta un messaggio prima che session.receive si attivi, quindi un hook non lo vede mai. Un messaggio che è in sospeso per la tua approvazione raggiunge prima l’hook, quindi un mod può leggere un messaggio che non hai ancora approvato. Il next(e) dell’hook rifiuta quando il messaggio non viene consegnato. Il nome del mittente su un messaggio ricevuto è quello che il mittente ha scritto, quindi non basare una decisione su di esso.

Accedi a file, processi e rete

Un mod accede al file system, ai processi e alla rete attraverso l’API mods, con le stesse autorizzazioni dell’utente che esegue Claude Code. Il modulo hooks stesso non ha API Node.js, nessun timer globale come setTimeout e nessun accesso di rete o file proprio. Le API JavaScript standard e web come URL, TextEncoder, AbortController e crypto.subtle sono disponibili. Ogni namespace di seguito copre un tipo di accesso: File e processi hanno poche regole proprie:
  • Percorsi: un percorso relativo è sotto la directory di lavoro della sessione
  • $.fs.list: restituisce le voci di una directory come { name, kind, size, isLink } e non scende nelle sottodirectory
  • $.process.run: accetta un elenco di argomenti e non utilizza shell. Si risolve in { exitCode, stdout, stderr } indipendentemente dal codice di uscita. Rifiuta se il programma non può avviarsi o è ancora in esecuzione al timeout, che è 30 secondi per impostazione predefinita, quindi avvolgilo in try e catch.
Ognuna di queste chiamate è essa stessa un evento, denominato per il suo namespace e metodo senza il $., come fs.read per $.fs.read. Un mod precedente nella catena può osservare, riscrivere o rifiutare la tua chiamata, che è come un’organizzazione limita ciò che i mod raggiungono.

Passaggi successivi