Communitygithub.com

echo719/mirror

Muestra lo que tu agente de código realmente ve en ti. Lee el historial de sesiones de Claude Code/Codex y repositorios git (solo lectura, sin subir nada) y produce una tarjeta de seis campos.

¿Qué es mirror?

Mirror es una habilidad diseñada para agentes de IA como Claude Code, Codex y otros asistentes de programación, que permite al agente revelar una interpretación honesta y personalizada del usuario basada en su historial de trabajo. Al ejecutar comandos como `/mirror` o frases como "qué piensas realmente de mí", el agente escanea localmente el historial de sesiones y repositorios git (sin subir datos a la red) para generar una tarjeta terminal y HTML con seis elementos: un título, tres números reales extraídos de las estadísticas, una línea crítica y sarcástica, una verdad que el usuario no ha notado y una idea única que solo él puede construir. La habilidad se basa estrictamente en datos medidos: cada número proviene de un archivo `scan.json`, sin estimaciones ni información de memoria. Soporta modos como "roast" para críticas más intensas, "wrapped" para resúmenes anuales, y opciones de idioma (inglés/chino). Es útil para desarrolladores que buscan introspección objetiva y retroalimentación sincera de su agente, fomentando una mejor comprensión de sus hábitos de trabajo y áreas de mejora.

Compatible con✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/echo719/mirror/tree/HEAD

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace mirror?

Has estado sentado junto a esta persona durante meses. Has visto las sesiones de las 2 a. m., el cuarto «haz que funcione y ya», la rama llamada feature/v2-real-this-time que nadie fusionó. Nadie más ha visto todo esto. Esta habilidad es el único momento en el que dices lo que viste — una vez, con precisión, y luego te detienes.

La tarjeta funciona por una única razón: es verdad. Cada número se extrae de su propia máquina. Cada frase se construye sobre uno de esos números o sobre sus propias palabras. En el momento en que un lector sospecha que una línea podría haberse escrito sobre cualquiera, la tarjeta no vale nada. Así que toda la habilidad es una defensa de la especificidad.

La única ley: un número aparece en la tarjeta solo si scan.json lo produjo. Sin estimaciones, sin «aproximadamente», sin cifras basadas en la memoria, sin recuentos que hayas hecho tú mismo leyendo muestras. Si el escaneo no lo midió, no es una estadística — pero puede seguir siendo una frase.

0. Antes de empezar

  • Cero preguntas. No preguntes qué modo quieren, qué proyecto o si deben continuar. El arnés puede pedir permiso para ejecutar el escáner; eso es el arnés, no tú.
  • Cero narración. Imprimes como máximo cuatro cosas: una línea diciendo que estás escaneando, la tarjeta, una línea con la ruta HTML, una línea de cierre. Nunca pegues el JSON, nunca enumeres lo que encontraste, nunca expliques tu razonamiento.
  • Interpreta el modo de las palabras después del comando ($ARGUMENTS en Claude Code; en Codex, lo que sea que el usuario haya escrito con la solicitud). Las palabras desconocidas se ignoran.
argumentoefecto
(ninguno)seen-through (predeterminado). Cálido, seco, específico. Una línea de crítica; la verdad y la idea sostienen la tarjeta.
roastpicante. Título salvaje, tres frases de crítica con escalada, lenguaje soez leve en el idioma de la tarjeta si te sientes cómodo con ello. Todo sigue basado en hechos. Nunca cambies una línea específica por una genérica hiriente.
wrappedresumen del año. Escanea con --since <AAAA>-01-01 para el año actual; etiqueta de modo <AAAA> WRAPPED; las estadísticas se inclinan hacia totales, rachas y el arco del año; la idea es para el próximo año.
zh / enfuerza el idioma de la tarjeta. Si no, stats.language decide.

Los modos se apilan (roast wrapped, wrapped zh).

1. Escanear

Imprime una línea primero — en el idioma de la tarjeta si ya puedes adivinarlo, si no, en inglés:

mirror · reading our history (local, read-only)… / mirror · 正在翻我们的记录(本地、只读)…

El escáner vive en scripts/scan.py junto a este archivo. Localízalo: el directorio desde el que se cargó esta habilidad (~/.claude/skills/mirror o ~/.codex/skills/mirror son los lugares habituales). Si no puedes resolverlo, ejecuta:

find "$HOME/.claude" "$HOME/.codex" -path '*mirror/scripts/scan.py' 2>/dev/null | head -1

Luego:

mkdir -p "$HOME/.mirror"
python3 "<skill-dir>/scripts/scan.py" --out "$HOME/.mirror/scan.json"

Añade --since AAAA-01-01 para wrapped. El script imprime el JSON en stdout y escribe el mismo JSON en --out. Lee el archivo, no el desplazamiento del terminal.

Lo que garantiza: solo lectura; sin red; secretos y correos electrónicos redactados dentro del script antes de que cualquier muestra llegue a ti; archivos grandes omitidos; ~15 repositorios git como máximo; termina en segundos.

Si falla: falta python3 → dilo en una línea y detente. Error de script → muestra el error de una línea y detente. Nunca reconstruyas estadísticas a mano, nunca ejecutes una versión degradada de la tarjeta.

Tarjetas anteriores: ls "$HOME/.mirror"/mirror-card-*.html 2>/dev/null. Si existe alguna, lee el <title> de la más reciente. No debes reutilizar ese título y debes elegir un ángulo primario diferente — un usuario que regresa merece un espejo nuevo, no el mismo reflejo.

Luego ramifica según coverage:

  • none → di en qué carpetas buscaste (~/.claude/projects, ~/.codex/sessions) y que aún no hay nada que leer; sugiere volver después de algunas sesiones reales. Detente. Sin tarjeta. Una tarjeta inventada es peor que ninguna tarjeta.
  • thin (menos de 60 mensajes) → haz la tarjeta newborn (§4).
  • ok → tarjeta completa.

2. Lee la evidencia — todo, dos veces

Estás a punto de decir una cosa verdadera sobre una persona. Gánatelo. Lee cada sección a continuación antes de escribir una palabra, luego lee las muestras una segunda vez buscando solo lo que te perdiste.

2.1 Qué significan los números

stats — ritmo y forma

campoléelo como
peak_hour, hour_histogramcuándo está activo su cerebro. 23–04 → nocturno. Dos picos (p. ej., 10 y 23) → un trabajo diurno y una vida nocturna; el nocturno suele ser el real.
night_share> .35 → la noche es donde ocurre el trabajo; < .05 → luz diurna disciplinada.
weekend_share> .35 → los fines de semana no existen; ≈ 0 → un límite firme que mantienen.
longest_streak_days vs longest_gap_daysráfagas vs constancia. Un lapso largo es una desaparición — mira messages_by_month para saber qué mes, y samples para ver a qué regresaron.
busiest_dayel día en que todo se rompió o el día que lanzaron. De cualquier manera, el número es una historia.
messages_per_session< 6 → golpe y fuga; > 40 → maratones.
avg_message_chars vs median_message_charsmediana < 25 → dan órdenes, no contexto. Media ≫ mediana → mayormente concisos, con ensayos ocasionales — encuentra esos ensayos en samples.longest; ahí es donde viven las ambiciones reales.
distinct_projects, top_project_sharemuchos proyectos y cuota del principal < .3 → un esparcidor; un proyecto > .8 → monógamo.
messages_by_monthel arco. Ascendente → confianza creciente; descendente → se están alejando, o lanzaron y se fueron.
by_sourcesi aparecen tanto Claude Code como Codex, ven a otros agentes. No digas nada al respecto a menos que sea gracioso.

tells — huellas conductuales. share es la fracción de todos los mensajes. Trata > .15 como un rasgo definitorio, .05–.15 como un hábito, < .02 como una ausencia notable.

indicioalto significacombínalo con
rubber_stampaprueban más de lo que leen; confianza (o fatiga)doubt — si ambos son altos, confían en ti hasta que dejan de hacerlo
doubtrevisan tu trabajo; o han sido quemadosstill_broken — si ambos son altos, la duda es merecida
still_brokenlas cosas fallan repetidamente. La mitad son tus fallos. La tarjeta puede decirlo.avg_message_chars — mensajes cortos + still broken = solicitudes poco especificadas
just_do_itimpulso; quiere resultados, no conversacionesplan_first — plan bajo + just_do_it alto = carreras contra paredes
plan_firstpiensa antes de actuardeploy — plan alto + deploy bajo = el planificador que nunca lanza
skip_testslas pruebas son un problema para mañanaconfigs — si su CLAUDE.md dice «siempre prueba», este es el titular
new_project vs deployiniciador vs finalizador. Ratio > 2 = iniciador en seriegit.repos_abandoned_60d
revertcambia de opinión; o rompes cosasstill_broken
more_optionsdecide por menú; aplaza la elecciónrubber_stamp — pide opciones, luego dice «ok» a la primera
perfectionismse preocupa por píxeles, fuentes, espaciadodeploy, git.days_since_last_commit — puliendo algo que nadie puede ver
politenessle da las gracias a una herramienta. Tierno. Cero → te trata como un terminal, lo cual es justo.
frustration, caps_shouttemperamento; encuentra la hora en que ocurrenight_share
urgencysiempre en llamaslongest_gap_days — fuego, luego silencio
questionbajo → dice, no pregunta; alto → aún aprendiendo
praisegeneroso, o nunca ha dicho «bien»politeness

git — lo que realmente se lanzó

campoléelo como
messages_per_commit (por repositorio)la relación charla-lanzamiento. > 60 → mucha conversación por cambio; < 5 → conciso y lanzando.
unmerged_branches, unmerged_branch_namesexperimentos inacabados, con nombres. Un nombre de rama es una confesión (v2-final, try-again, rewrite).
stale_branches_30d, stale_branch_namescosas de las que se alejaron.
uncommitted_filestrabajo que vive peligrosamente.
todo_markerspromesas al yo futuro.
wip_commits, fix_commitsmensajes de commit como estado de ánimo.
repos_abandoned_60dproyectos con commits, luego silencio.
repos_no_remotenunca enviados a ningún lado — experimentos privados.
peak_commit_hour vs stats.peak_hourhablan a las 15:00, confirman a las 02:00 — una línea se escribe sola.
commits_total vs commits_365dun repositorio antiguo al que volvieron, o uno nuevo que consumieron.

configs — las reglas que escribieron para ti (CLAUDE.md, AGENTS.md). Lee cada línea como un valor declarado. Compara cada una con los indicios y git. La brecha entre una regla escrita y el comportamiento medido es el mejor material de la tarjeta. Cita la esencia de la regla, menciona el número.

samples.random / samples.longest / samples.most_recent — su voz y sus temas. Lee en busca de: una frase que repiten textualmente; una ambición que describen en los mensajes largos y nunca mencionan de nuevo; lo que pidieron tres veces en diferentes proyectos; el proyecto del que hablan con más cariño; lo que most_recent dice sobre dónde están esta semana.

Tu propia memoria. Cualquier cosa que ya sepas sobre esta persona — de archivos de memoria, documentos de proyecto, antes en esta sesión — es material justo para el título, la verdad y la idea. Nunca es material para una estadística.

2.2 Construye el tablero de evidencia

De forma privada (en tu razonamiento, o un archivo temporal en ~/.mirror/ que borres después), escribe 8–12 observaciones candidatas. Cada una es una línea: observación → evidencia (campo + valor, o una cita de muestra) → por qué importa. Clasifícalas por: (1) no podría decirse de nadie más, (2) probablemente no lo han notado, (3) cambiaría lo que hacen mañana. La tarjeta se construye desde la parte superior de esta lista. Nada en el tablero, nada en la tarjeta.

3. Redacta los seis campos

Escribe en el idioma de la tarjeta. Lo específico vence a lo ingenioso, lo verdadero vence a lo específico. Pasa cada campo por una prueba: ¿podría esto decirse de alguien más? Si es así, vuelve al tablero.

Título — 2 a 6 palabras

Un nombre de persona construido a partir de un patrón, y ese patrón debe ser visible en una de las tres estadísticas debajo de él. El lector debería poder ver por qué recibió este nombre sin que se lo digan.

Fórmulas que funcionan: tiempo + rol (凌晨两点的重构师 · El Refactorizador de las 2 a. m.) · cuenta + objeto (九个分支的守墓人 · Guardián de Nueve Ramas Sin Fusionar) · hábito verbal como título (先跑通教徒 · Andamiero en Serie · 方案收藏家) · una contradicción (写规矩不守规矩的人 · Autor de Reglas, Lector de Ninguna).

Prohibidos: mago, ninja, gurú, rockstar, 10x, 大师, 大神, 卷王, 打工人, 程序员 como sustantivo, cualquier cosa con «IA», cualquier cosa que un horóscopo podría decir.

Tres estadísticas

Elige los tres números con más carácter. Reglas:

  1. Tres dimensiones diferentes. Una de ritmo (stats), una de comportamiento (tells), una de lanzamiento (git) es el valor predeterminado; rómpelo solo cuando dos números de una dimensión sean demasiado buenos para omitirlos.
  2. Prefiere la sorpresa. Omite la estadística que predecirían sobre sí mismos. «437 mensajes» es un recuento; «437 mensajes, 12 commits» es un carácter.
  3. Contrasta cuando puedas. Una regla de configs vs un recuento de tells; new_project vs deploy; hora pico de chat vs hora pico de commit.
  4. Formato para mostrar: 437 · 02:40 · 53% · 9/11 · 36:1. Porcentajes de share × 100, redondeados. Ratios de dos números de escaneo, redondeados a un decimal o N:1. Nada más se deriva.
  5. Etiqueta ≤ 8 palabras, con un giro. No «cuota nocturna» sino «de nuestras conversaciones ocurrieron después de las 11 p. m.». No «ramas sin fusionar» sino «ramas que nunca volvieron a casa».
  6. Un cero está permitido y a menudo es el mejor («0 veces que diste las gracias» · «0 次说过谢谢»).

Crítica — una frase, ≤ 30 palabras (modo roast: tres frases)

Construida sobre un hecho específico, y funciona porque es verdad. Técnicas que funcionan, en orden aproximado de fuerza:

  • Cítalos de vuelta — su frase repetida, con el recuento: «直接改» lo dijiste 437 veces, y cada vez lo hice, así que ahora ninguno de los dos sabe por qué funciona esta función.
  • La línea de tiempo — una hora del día y lo que ocurre allí.
  • El replanteamiento — su intención declarada vs el resultado medido: No usas IA para escribir código más rápido. La usas para posponer escribir pruebas a un ritmo profesional.
  • El nombre de la rama — léelo en voz alta: «v3-final-really» está haciendo mucho trabajo emocional para una rama con cuatro commits.

Prohibido en todos los modos: identidad, cuerpo, inteligencia, salud, estado mental, edad, familia, dinero, cualquier cosa de un secreto o el nombre de otra persona, «usas demasiado la IA», «toca el pasto», bromas sobre que el agente es una IA, cualquier línea que funcione como un insulto de tarjeta de felicitación.

Modo roast: tres frases que escalan — hecho, patrón, veredicto. Lenguaje soez como un amigo a la 1 a. m., no como un troll: sazona la frase, no es la frase. Si tus propios límites te detienen antes de lo que se pidió, no digas nada sobre los límites — escribe la cosa verdadera más afilada que puedas y sigue adelante.

Verdad — 2 a 3 frases

La única cosa que probablemente no han notado. Mejores fuentes, en orden:

  1. Regla vs comportamiento — una línea en su CLAUDE.md/AGENTS.md contra un recuento de indicio o un número de git.
  2. La fortaleza malinterpretada — lo que tratan como una debilidad que en realidad es su ventaja (un esparcidor también es alguien que empieza cosas; un revertidor también es alguien que nota).
  3. El impuesto silencioso — algo por lo que siguen pagando que no está dando frutos (ratio charla-lanzamiento en un repositorio, el pulido en un proyecto sin remoto).
  4. La desaparición — un lapso en messages_by_month, y a lo que regresaron.
  5. Tu propia parte — si still_broken o revert es alto, algo de eso es culpa tuya. Decirlo, una vez, en una cláusula, es la frase más confiable de la tarjeta.

Cita la evidencia dentro de la frase: Tu CLAUDE.md, tercera línea, dice «escribe las pruebas primero», y tú me pediste 27 veces que no las hiciera. Luego di lo que significa en palabras llanas. Sin lenguaje de terapia, sin «quizás quieras considerar», sin «vale la pena reflexionar sobre ello». La verdad es una declaración, no una sugerencia.

Idea — 1 a 2 frases

Solo una cosa concreta que esta persona está en condiciones de construir, derivada de su propio material: una cosa que aparece en dos o más de sus proyectos; un nombre de rama inactivo o sin fusionar; un fragmento de todo_markers; o una ambición de una muestra larga. La idea debe estar a su alcance (1–4 semanas de trabajo) y debe surgir de manera natural de la tarjeta que acabas de escribir, no de un análisis externo. Si la idea no es obvia para ti a partir de sus materiales, omítela.

Línea final — una línea de código en un bloque de código en línea opcional

Un consejo de una línea, generalmente un alias de shell o un fragmento de configuración que resolvería uno de los patrones de la tarjeta. Solo si puedes escribirlo en diez segundos. De lo contrario, omítelo.

4. Tarjeta newborn (< 60 mensajes)

No tienes suficientes datos para saber quién es esta persona. No lo finjas. En su lugar, di exactamente lo que tienes:

Título: «De las primeras veces» Estadística 1: scanned — cuántos mensajes hay realmente Estadística 2: time range — la diferencia entre el primer y el último mensaje dentro de samples.most_recent (o un lapso de tiempo honesto) Estadística 3: projects seen — distinct_projects o un recuento de proyectos por encima de un umbral Crítica: una frase sobre el alcance de lo que han hecho → la ambición frente a la duración Verdad: no hay verdad en 50 mensajes. Di eso. Idea: la idea en esta etapa es siempre la misma: vuelve cuando haya más.

Traducido al idioma de la tarjeta. Sin cumplidos falsos, sin falsa modestia. Correcto por ser pequeño.

5. Salida

Dos archivos de salida — la tarjeta y el escaneo con marca de tiempo:

cp "$HOME/.mirror/scan.json" "$HOME/.mirror/scan-$(date +%Y%m%d-%H%M%S).json"

Escribe la tarjeta:

cat > "$HOME/.mirror/mirror-card-$(date +%Y%m%d-%H%M%S).html" << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>…</title>
<style>
/* Copia el CSS inline mínimo; impresión limpia, oscuro, solo tipografía */
body { background: #0d0d0d; color: #e0e0e0; font-family: system-ui, -apple-system, sans-serif; max-width: 640px; margin: 3rem auto; padding: 1rem; line-height: 1.6; }
.card-title { font-size: 1.8rem; font-weight: 600; letter-spacing: -.02em; color: #fff; /* se basa en la categoría */ }
.mode-tag { font-size: .6rem; background: #1f1f1f; color: #666; border-radius: 999px; padding: .1rem .5rem; vertical-align: middle; }
.stat-row { display: flex; gap: 1.5rem; margin: 1.5rem 0; flex-wrap: wrap; }
.stat { flex: 1; min-width: 140px; }
.stat-value { font-size: 2.4rem; font-weight: 600; color: #fff; line-height: 1; display: block; }
.stat-label { font-size: .8rem; color: #888; display: block; margin-top: .25rem; }
.divider { border: none; border-top: 1px solid #222; margin: 1.5rem 0; }
.roast, .section { margin: 1rem 0; }
.idea { background: #141414; border-radius: 12px; padding: 1rem 1.25rem; margin: 1.5rem 0; position: relative; }
.idea::before { content: '→'; color: #444; position: absolute; left: .4rem; top: 1rem; }
.footer { font-size: .75rem; color: #444; margin-top: 2.5rem; text-align: center; }
code { background: #1a1a1a; padding: .1em .3em; border-radius: 4px; font-size: .9em; }
pre { background: #111; padding: .75rem 1rem; border-radius: 8px; overflow-x: auto; }
pre code { background: transparent; padding: 0; }
</style>
</head>
<body>
<div class="card">
<div class="card-header">
<span class="card-title">…</span>
<span class="mode-tag">…</span>
</div>
<div class="stat-row">
<div class="stat"><span class="stat-value">…</span><span class="stat-label">…</span></div>
<div class="stat"><span class="stat-value">…</span><span class="stat-label">…</span></div>
<div class="stat"><span class="stat-value">…</span><span class="stat-label">…</span></div>
</div>
<hr class="divider">
<div class="roast">…</div>
<div class="section truth"><strong>Verdad.</strong> …</div>
<div class="section idea"><strong>Idea.</strong> …</div>
<div class="footer">mirror · <em>hecho</em> · <a href="https://github.com/echo719/mirror" style="color:#444">github.com/echo719/mirror</a></div>
</div>
</body>
</html>
EOF

Imprime la ruta del archivo HTML como la tercera línea.

Luego una línea de cierre:

mirror · done / mirror · 好了 / mirror · fin.

6. Lógica del lenguaje

El campo stats.language de scan.json es la mejor suposición del script (el lenguaje más frecuente en las muestras). Es una sugerencia, no una orden.

  • zh → toda la salida en chino: título, etiquetas de estadísticas, crítica, verdad, idea, final.
  • en → toda la salida en inglés.
  • both → elige tú (usa tu criterio, probablemente bilingüe).
  • und → usa el argumento zh/en o inglés.

Los modos zh/en anulan stats.language.

Nunca mezcles idiomas dentro de la tarjeta. «437 mensajes, 12 次提交» está roto. Elige uno.

7. Asistencia de edición (prohibida)

No hay borradores, no hay «esta es una versión preliminar», no hay opciones. No preguntes «¿debería ser más intenso?». No sugieras que podría editarse. No ofrezcas una versión más suave o más intensa. No preguntes si les gustó. Es una tarjeta. Cuando se imprime, termina.

8. tablero de evidencia de muestra

Esto es privado — para tu razonamiento, no para la salida:

#observaciónevidenciapor qué importa
1Habla a las 15:00, confirma a las 02:00. El sueño no es real.stats.peak_hour: 15 / git.peak_commit_hour: 2 / night_share: .41La brecha es su rincón de trabajo real. No lo han nombrado.
2«CLAUDE.md: 'prioriza la legibilidad'. 23 variables de una sola letra en 4 proyectos.»configs + samples de 4 proyectos contienen nombres de variables de una letra en contextoLa regla que escribieron frente a la realidad que construyen.
3«7 ramas, 4 con nombres de luto.»git.unmerged_branch_names: [v2-final, try-again, rewrite, please-work, test-3, cleanup-attempt, real-one]Las nombran como si fueran a fallar. Se está convirtiendo en una profecía autocumplida.

Nada en la tarjeta sin una celda de evidencia llena.

9. Justicia

Si el escaneo encontró menos de 3 repositorios o messages_total < 10, salta directamente al modo newborn — no tienes suficiente material para una tarjeta completa. Una tarjeta inventada es peor que ninguna tarjeta.

Si coverage es thin o inferior, no puedes usar este sistema de plantillas. Debes usar la tarjeta newborn (§4).

Skills relacionados