Claude Code talks like a Colombian while it works: pick your accent, from rolo to costeño.

A Claude Code mod that makes Claude talk like a Colombian while it works.
✻ Atascado en el trancón… (12s · 1.2k tokens)
✻ Listo, sumercé · 12s
Instead of Sauteing… and Baked for 3s, the spinner says what a Colombian would be doing, in the accent you pick. When a /goal finishes, Claude welcomes you with "Bienvenido a la patria milagro".
/plugin install colombian-claude --marketplace LucasLeguizamo/colombian-claude
Open /config, find colombian-claude → Accent, and choose one:
| Option | Accent | While working | When done |
|---|---|---|---|
rolo (default) | Bogotá | Atascado en el trancón · Esperando el TransMilenio · Tomando onces | Listo, sumercé · Melo, chino · Firmes |
paisa | Antioquia | Voleando machete · Subiendo en el Metrocable · Pidiendo una arepa con quesito | Listo, pues · Qué chimba, parce · Ave María, quedó |
costeno | Caribbean coast | Bailando champeta · Cogiendo fresco bajo el palo e' mango · Prendiendo el picó | Ajá, quedó · Eche, qué nota · Nojoda, quedó bacano |
caleno | Valle del Cauca | Bailando salsa · Pidiendo un cholao · Esperando el MÍO | Ve, qué bacano · Listo, mirá · Oís, quedó |
santandereano | Santander | Comiendo hormigas culonas · Bajando al Chicamocha · Hágale, mano | Listo, mano · Quedó bien verraco, mano |
pastuso | Nariño | Comiendo cuy · Achachay, qué frío · Subiendo al Galeras | Ya está, ve · Quedó bonito, ve |
llanero | Eastern plains | Asando la mamona · Templando el arpa · Cantando un joropo | Listo, compae · Quedó como es |
boyacense | Boyacá | Sembrando papa · Pasando el páramo · Poniéndome la ruana | Listo, sumercé · Ya quedó, mi señor |
mix | All of them | Anything above | Anything above |
Each turn picks one phrase and keeps it until the turn ends.
Everything lives in hooks/accents.ts: one working and one done list per accent. Add a line, open a PR. New accents are welcome too (chocoano, huilense, tolimense, cundiboyacense…): add an entry and its name to userConfig.accent.options in .claude-plugin/plugin.json.
It is a Claude Code function-hooks mod, a single module in hooks/register.tsx:
ui.render on Spinner and TurnDuration swaps the engine's word for one from your accent (the spinner keeps its time, tokens and effort; the closing line is redrawn as ✻ <phrase> · 12s).session.append watches for the row the engine writes when a /goal ends and shows a toast.Known limitation: Claude Code has no "goal met" event for mods yet. A goal writes one status row when it is set and another when it ends, and mods can't read which is which, so the toast fires on every second row. A goal that fails or is cleared early celebrates too.
claude plugin validate .
claude plugin test .
claude --plugin-dir .
MIT
hooks/register.tsx 47 lines1import type { Register } from 'claude-code'
2
3import { accentFor, GOAL_MET } from './accents'
4
5// Hash the engine's sampled word so one turn keeps one phrase across redraws.
6export const pick = (list: string[], seed: string) => {
7 let h = 0
8 for (const c of seed) h = (h * 31 + c.charCodeAt(0)) | 0
9 return list[Math.abs(h) % list.length] ?? list[0]!
10}
11
12export const duration = (ms: number) => {
13 const s = Math.round(ms / 1000)
14 return s < 60 ? `${s}s` : `${Math.floor(s / 60)}m ${s % 60}s`
15}
16
17// The engine raises no goal event. A /goal writes a 'goal_status' row when it is
18// set and another when it ends, and the row carries no text a hook can read, so
19// every second one is the end.
20// ponytail: counts rows; a goal that fails or is cleared early also ends on an even row and celebrates too.
21export const goalWatch = () => {
22 let rows = 0
23 return (name: string | undefined) => name === 'goal_status' && ++rows % 2 === 0
24}
25
26export const register: Register = (on, options) => {
27 const accent = accentFor(options.accent)
28 const isGoalEnd = goalWatch()
29
30 on('ui.render', { component: 'Spinner' }, ($, e, next) =>
31 next({ ...e, props: { ...e.props, word: pick(accent.working, e.props.word + e.requestId) } }),
32 )
33
34 // Drawn whole: rewriting the word alone would leave the engine's English 'for'.
35 on('ui.render', { component: 'TurnDuration' }, ($, e) => {
36 const { Text } = $.ui.resolve(e)
37 const word = pick(accent.done, e.props.word + e.requestId)
38 return <Text dimColor>✻ {word} · {duration(e.props.durationMs)}</Text>
39 })
40
41 on('session.append', async ($, e, next) => {
42 const result = await next(e)
43 if (!e.agentId && isGoalEnd(e.message.name)) $.ui.toast(GOAL_MET)
44 return result
45 })
46}
47hooks/accents.ts 124 lines1// Each accent has two lists: what the spinner says while a turn runs (`working`)
2// and the word that closes the turn in the transcript (`done`, drawn before the
3// duration: "Listo, sumercé 4s").
4
5export type Accent = { label: string; working: string[]; done: string[] }
6
7export const ACCENTS = {
8 rolo: {
9 label: 'Rolo (Bogotá)',
10 working: [
11 'Camellando, sumercé', 'Echándole cráneo', 'Dándole juicio', 'Haciendo la vuelta',
12 'Pidiendo un tintico', 'Comiendo changua', 'Tomando onces', 'Atascado en el trancón',
13 'Esperando el TransMilenio', 'Subiendo a Monserrate', 'Cuadrando la vuelta, chino',
14 'Sacando el paraguas', 'Pidiendo el ajiaco', 'Mojando la almojábana',
15 'Caminando por la Séptima', 'Haciendo fila en el SITP', 'Esquivando el pico y placa',
16 'Escampando el aguacero', 'Calentando el chocolate santafereño', 'Poniéndome la ruana',
17 'Haciendo vaca', 'Pensándola juiciosamente', 'Firmes',
18 ],
19 done: [
20 'Listo, sumercé', 'Qué chévere', 'Bacanísimo', 'Quedó una chimba', 'Melo, chino',
21 'Coronamos', 'Qué nota', 'Juicioso', 'Llegó la buseta', 'De una, sumercé', 'Firmes',
22 ],
23 },
24 paisa: {
25 label: 'Paisa (Antioquia)',
26 working: [
27 'Camellando, parce', 'Echándole berraquera', 'Voleando machete', 'Pensando, pues',
28 'Haciendo la vuelta, mijo', 'Subiendo en el Metrocable', 'Comiéndome una bandeja paisa',
29 'Tomando tinto en el parque', 'Arriando las mulas', 'Desvarando', 'Bajando de Santa Elena',
30 'Armando la silleta', 'Pidiendo una arepa con quesito', 'Montando el sancocho',
31 'Echándole cabeza, pues', 'Dándole como a rata',
32 ],
33 done: [
34 'Listo, pues', 'Qué chimba, parce', 'Eso, mijo', 'Ave María, quedó', 'Bien pueda',
35 'Bacano, parcero', 'Melo, pues', 'Hágale pues', 'Quedó berraco',
36 ],
37 },
38 costeno: {
39 label: 'Costeño (Caribe)',
40 working: [
41 'Rebuscándomela, ajá', 'Echando cerebro', 'Mamando gallo', 'Bailando champeta',
42 "Comiendo arepa e' huevo", 'Esperando la brisa', 'Prendiendo el picó',
43 "Cogiendo fresco bajo el palo e' mango", 'Echando cuento en la terraza',
44 'Tomando Kola Román', 'Haciendo la vaina', 'Arreglando la vaina', 'Pidiendo un bollo limpio',
45 'Comprando raspao', 'Esperando el Carnaval',
46 ],
47 done: [
48 'Ajá, quedó', 'Eche, qué nota', 'Ya está, mi llave', 'Nojoda, quedó bacano',
49 'Erda, coronamos', 'Listo, compadre', 'Quedó fue lo que es', 'Bien hecho, mi llave',
50 ],
51 },
52 caleno: {
53 label: 'Caleño (Valle)',
54 working: [
55 'Camellando, mirá', 'Haciendo el oficio, ve', 'Bailando salsa', 'Tomando lulada',
56 'Comiendo pandebono', 'Pidiendo un cholao', 'Esperando el MÍO', 'Subiendo a San Antonio',
57 'Pegándome un aborrajado', 'Pensándola, oís', 'Dándole al tumbao',
58 'Cogiendo la brisa de las cinco', 'Pidiendo un champús',
59 ],
60 done: [
61 'Ve, qué bacano', 'Listo, mirá', 'Oís, quedó', 'Qué chimba, ve', 'Bien pueda, pues',
62 'Ya está, mi socio',
63 ],
64 },
65 santandereano: {
66 label: 'Santandereano',
67 working: [
68 'Camellando, mano', 'Echándole verraquera, mano', 'Comiendo hormigas culonas',
69 'Pidiendo un mute', 'Tomando chicha', 'Bajando al Chicamocha', 'Hágale, mano',
70 'Pensándola con calma, mano', 'Dándole como es, mano', 'Comiendo carne oreada',
71 'Pidiendo una pepitoria',
72 ],
73 done: [
74 'Listo, mano', 'Quedó bien verraco, mano', 'Qué chimba, mano', 'Coronamos, mano',
75 'Así es, mano',
76 ],
77 },
78 pastuso: {
79 label: 'Pastuso (Nariño)',
80 working: [
81 'Camellando, ve', 'Comiendo cuy', 'Tomando hervido', 'Achachay, qué frío',
82 'Esperando el Carnaval de Negros y Blancos', 'Echándole cabeza, ve', 'Subiendo al Galeras',
83 'Pidiendo un helado de paila', 'Bajando a la Laguna de la Cocha', 'Pasando el frío, ve',
84 ],
85 done: ['Ya está, ve', 'Listo, pues', 'Quedó bonito, ve', 'Coronamos, ve', 'Bien, pues'],
86 },
87 llanero: {
88 label: 'Llanero (Orinoquía)',
89 working: [
90 'Arreando el ganado', 'Asando la mamona', 'Echando cuento al pie del fogón',
91 'Templando el arpa', 'Cantando un joropo', 'Cruzando el caño', 'Ensillando el caballo',
92 'Tomando guarapo', 'Echándole cabeza, compae', 'Esperando que escampe en el llano',
93 ],
94 done: ['Listo, compae', 'Ajá, compae', 'Quedó como es', 'Coronamos, compadre', 'Bien llanero'],
95 },
96 boyacense: {
97 label: 'Boyacense',
98 working: [
99 'Camellando, sumercé', 'Pidiendo un cuchuco', 'Tomando guarapo', 'Ordeñando las vacas',
100 'Arando la tierrita', 'Poniéndome la ruana', 'Sembrando papa', 'Echándole cabeza, sumercé',
101 'Comiendo arepa boyacense', 'Pasando el páramo', 'Subiendo a Villa de Leyva',
102 'Haciendo el mandado, mi señor',
103 ],
104 done: [
105 'Listo, sumercé', 'Ya quedó, mi señor', 'Juicioso, sumercé', 'Qué bonito quedó, sumercé',
106 ],
107 },
108} satisfies Record<string, Accent>
109
110export type AccentName = keyof typeof ACCENTS
111
112const all = Object.values(ACCENTS)
113
114export const MIX: Accent = {
115 label: 'Mix',
116 working: all.flatMap(a => a.working),
117 done: all.flatMap(a => a.done),
118}
119
120export const accentFor = (name: unknown): Accent =>
121 typeof name === 'string' && name in ACCENTS ? ACCENTS[name as AccentName] : name === 'mix' ? MIX : ACCENTS.rolo
122
123export const GOAL_MET = 'Bienvenido a la patria milagro'
124