Etincel
Encuentra las señales de IA en tu prosa. De forma determinista, local, en CI.
Documentación
Étincel: Conector de escritura de no ficción
___ ___ ___ ___ ___ ___
/\ \ /\ \ ___ /\__\ /\ \ /\ \ /\__\
/::\ \ \:\ \ /\ \ /::| | /::\ \ /::\ \ /:/ /
/:/\:\ \ \:\ \ \:\ \ /:|:| | /:/\:\ \ /:/\:\ \ /:/ /
/::\~\:\ \ /::\ \ /::\__\ /:/|:| |__ /:/ \:\ \ /::\~\:\ \ /:/ /
/:/\:\ \:\__\ /:/\:\__\ __/:/\/__/ /:/ |:| /\__\ /:/__/ \:\__\ /:/\:\ \:\__\ /:/__/
\:\~\:\ \/__/ /:/ \/__/ /\/:/ / \/__|:|/:/ / \:\ \ \/__/ \:\~\:\ \/__/ \:\ \
\:\ \:\__\ /:/ / \::/__/ |:/:/ / \:\ \ \:\ \:\__\ \:\ \
\:\ \/__/ \/__/ \:\__\ |::/ / \:\ \ \:\ \/__/ \:\ \
\:\__\ \/__/ /:/ / \:\__\ \:\__\ \:\__\
\/__/ \/__/ \/__/ \/__/ \/__/
Encuentra las señales de IA en tu prosa. De forma determinista, local y en CI.
npx etincel lint README.md
Sin instalación, sin cuenta, sin llamada a modelo, sin red.
$ npx etincel lint drafts/announcement.md --register blog
✗ drafts/announcement.md RED 100/100 (8 findings, 169 words, register: blog)
Heavy AI styling. Multiple strong tells stacking up, worth a structural
rewrite, not a word-swap pass.
Whole-piece rhythm
medium uniform-paragraph-length
6 paragraphs, most running about the same length with little
variation between them. Vary paragraph length more.
medium low-burstiness
13 sentences averaging 13 words, with little variation in length
from one sentence to the next. Mix short sentences with long;
allow fragments.
medium mechanical-register-drift
Fragment rate and structural variety (sentence openers,
punctuation mix) sit off where blog prose typically lands. Allow
more sentence fragments and vary openers/punctuation more.
Vocabulary and phrasing
high comprehensive L3:C30 → thorough, complete
high cutting-edge L3:C109 → newest, latest
high leverage L3:C99 → use
high seamless L3:C150 → smooth, easy
high streamline L3:C70 → simplify, speed up
strengths specificity 11.4/1k · concrete:abstract 0.40 · burstiness 0.32
1 file audited, 1 at or above orange.
Étincel son dos cosas. Una auditoría determinista que encuentra los patrones que hacen que la prosa se lea como escrita por una máquina, como CLI, una GitHub Action y una herramienta MCP. Y una capa de voz que entrena a Claude, Cursor o cualquier cliente MCP para redactar en un estilo medido a partir de tu propia escritura, de modo que el problema sea menor antes de que siquiera leas el borrador.
La prosa redactada por IA tiene una forma reconocible: párrafos uniformes, autoridad atenuada, guiones largos donde bastaría una coma, cierres que se resuelven demasiado limpiamente. Étincel codifica las reglas contra esa forma y, igual de importante, te muestra qué encontró y por qué, en lugar de sobrescribir silenciosamente tu voz. No hay ninguna llamada a modelo en la ruta de auditoría, y tú decides qué cambios hacer. Tú sigues siendo el autor.
¿Funciona?
Lo medimos en lugar de afirmarlo. AUC agrupado por registro, medido mediante ensayo contra corpus etiquetados con una semilla de bootstrap fija, de modo que cualquier PR que baje estos números falla en CI:
| Registro | AUC |
|---|---|
| memorando | 0.909 |
| ensayo | 0.900 |
| blog | 0.820 |
| general | 0.748 |
| documentación | 0.735 |
| correo electrónico | 0.540 |
El correo electrónico está cerca de un lanzamiento de moneda. Está deliberadamente sin calibrar, y lo rastreamos de todos modos para que una regresión accidental no pase desapercibida. general también está sin calibrar. Los registros calibrados son docs, blog, memo y essay; usa esos si el número te importa. Consulta efficacy-baselines.json y src/data/SOURCES.md para conocer el método y la procedencia.
Cómo se compara
vs. Vale + vale-ai-tells Vale es un excelente linter consciente del marcado y vale-ai-tells es un paquete serio de 78 reglas. Hacen coincidir tokens con patrones. Étincel mide la forma: varianza del ritmo de las frases, uniformidad de la longitud de los párrafos y repetición con respecto a tus propios borradores anteriores, el tipo de capa estadística que el propio README de vale-ai-tells dice que necesita un análisis más allá de lo que puede hacer la coincidencia de tokens. Étincel también alimenta una voz entrenada al modelo antes de que redactes, algo que ningún linter hace. Ejecutar ambos es razonable; se superponen menos de lo que esperarías.
vs. archivos de skill (stop-slop, avoid-ai-writing, no-slop) Esas son instrucciones para un modelo, y ayudan. Pero un prompt no puede verificar que funcionó, no puede producir un código de salida y no puede bloquear una fusión. Usa uno y ejecuta esto en CI.
vs. humanizadores (Undetectable.ai, QuillBot, StealthWriter) Esos reescriben tu texto para evadir detectores. Turnitin ahora tiene una función dedicada de detección de paráfrasis de IA, ampliada en 2025 para apuntar específicamente a la salida de humanizadores. Étincel hace el trabajo opuesto: nunca modifica tu texto, y sería una mala herramienta para engañar a cualquiera.
vs. detectores (GPTZero, Pangram, Originality.ai, Copyleaks) Esos responden '¿estuvo involucrada una máquina?' con una probabilidad, sobre un documento completo, como un veredicto sobre la autoría, en la nube. Étincel responde '¿qué patrones específicos hacen que esto se lea como escrito por una máquina?' con ubicaciones y severidades, localmente, y nunca emite un veredicto sobre quién escribió algo.
Instalación
También está listado en el registro oficial de MCP como ai.etincel/etincel-nonfiction, por lo que los clientes compatibles con MCP que auto-descubren servidores desde allí (la galería @mcp de VS Code, por ejemplo) lo encuentran sin ninguna de las configuraciones siguientes.
Claude Code
/plugin marketplace add AIStoryHub/etincel
/plugin install etincel-nonfiction
O desde un clon local: /plugin marketplace add /path/to/etincel.
Claude Desktop / otros hosts MCP
{
"mcpServers": {
"etincel-nonfiction": {
"command": "npx",
"args": ["etincel", "serve"]
}
}
}
En su lugar, desde un clon local: npm install && npm run build, luego apunta args a ["/path/to/etincel/dist/server.js"] con "command": "node".
Remoto (alojado, multiinquilino)
También hay una versión alojada disponible en etincel.ai, que expone
las mismas herramientas a través de Streamable HTTP (https://etincel.ai/api/mcp) con
autenticación por cuenta en lugar de stdio. Apunta cualquier cliente MCP directamente a ella:
{
"mcpServers": {
"etincel-nonfiction": {
"url": "https://etincel.ai/api/mcp"
}
}
}
El servidor alojado no forma parte de este repositorio; este repositorio es el motor local/stdio, la CLI y la skill sobre los que se construye la versión alojada.
Uso
Una vez instalado, solo pide lo que normalmente pedirías, como 'redacta un correo electrónico al equipo sobre el retraso', 'escribe una entrada de blog sobre X' o 'limpia este memorando', dentro de Claude Code o Claude Desktop. La skill se activa automáticamente para prosa de no ficción de longitud significativa. Para entrenar tu propia voz:
Entrena un estilo llamado 'me' a partir de estos tres correos que escribí: [pega ejemplos]
Luego, nómbralo por solicitud ('escribe esto con mi voz') o establécelo como predeterminado:
Establece mi estilo predeterminado en 'me'
Ajustes preestablecidos de estilo
Doce ajustes preestablecidos vienen de serie: seis tonos emocionales (Directo y cálido, Resumen ejecutivo, Ensayista reflexivo, Memorando de fundador, Analista directo, Irónico y franco) más seis ajustes de caso de uso (Revisión de PR, Comentario de código, Mensaje de Slack, Publicación de LinkedIn, Texto de sitio web, Entrada de blog). Cada uno lleva controles de formalidad/calidez/directividad, además de una descripción de ritmo de frase y voz que se alimenta al modelo como contexto de redacción, no como una plantilla que rellena espacios en blanco. El servidor los lee desde src/data/presets.json. Haz un fork de cualquier ajuste preestablecido en una voz entrenada con fork_style para hacerlo tuyo.
Lint de línea de comandos
audit_text es una función pura por debajo, por lo que también se distribuye como CLI, para hacer lint de prosa fuera de un cliente de chat (READMEs, documentación, descripciones de PR en CI):
npx etincel lint 'docs/**/*.md'
npx etincel lint README.md --register docs --threshold yellow
Sale con código distinto de cero si el nivel de cualquier archivo coincidente está en o por encima de --threshold (por defecto orange). Los archivos .md/.mdx usan por defecto el registro docs automáticamente (suprime los falsos positivos de estructura de Markdown, ya que un encabezado real no es una señal de chatbot); pasa --register para anularlo. Añade --json para un informe legible por máquina. Ejecuta npx etincel lint --help para la lista completa de opciones.
Una GitHub Action envuelve el mismo CLI (consulta action.yml, y .github/workflows/lint.yml en este repositorio para un ejemplo funcional):
- uses: AIStoryHub/etincel@main
with:
patterns: "docs/**/*.md README.md"
threshold: orange
Configuración local del repositorio: diccionario, instrucciones y un estilo de equipo compartido
Las reglas de un equipo no tienen que vivir solo en el ~/.etincel/ local de cada persona. Coloca un .etincelrc (o .etincelrc.json / etincel.config.json) en la raíz del repositorio y será recogido automáticamente por el CLI y por el servidor local (stdio), revisable en la revisión de código y versionado en lugar de invisible y desaparecido cuando alguien se va:
{
"bannedWords": ["Acme Cloud Platform"],
"allowedWords": ["leverage"],
"register": "docs",
"threshold": "orange",
"instructions": "Always include a one-line CTA at the end.",
"style": {
"name": "House Voice",
"dials": {
"formality": 6,
"warmth": 4,
"directness": 7,
"sentenceLength": 40,
"sentenceRhythmVariance": 50,
"paragraphVariance": 30,
"contractionUse": 20,
"emDashUse": 0,
"fragmentTolerance": 10,
"questionUse": 5,
"entropy": 60
}
}
}
bannedWords/allowedWordsse fusionan junto con lo que haya en tu diccionario de cuenta/estilo;register/thresholdactúan como valores predeterminados de todo el repositorio que un indicador explícito--register/--thresholdaún anula.instructionses texto libre, integrado en elinstructionsdeget_style_guidepara cada estilo, no solo el del equipo, antes de tus propias instrucciones globales a nivel de cuenta: el equivalente a nivel de equipo deset_style_instructionssinstyleId, pero comprometido en el repositorio en lugar de vivir en la cuenta de una persona.styledefine una 'voz de casa' compartida a partir de controles, direccionable en todas partes comostyleId: "team"(get_style_guide, y una vez bifurcada en una voz entrenada real confork_style, en todas partes también) para que un equipo tenga una voz inicial ya ajustada desde el primer día en lugar de que todos entrenen o ajusten manualmente la suya desde cero.list_stylesla incluye automáticamente cuando un.etincelrcen el repositorio actual define una.
El servidor alojado no usa nada de esto (no tiene un repositorio local en el que mirar).
Compartir configuración en un equipo sin comprometerla
.etincelrc es la capa versionada y revisable en código de arriba; la capa debajo es ETINCEL_HOME, una variable de entorno que apunta el servidor local (stdio) y el CLI a un directorio para usar en lugar del ~/.etincel/ predeterminado. Apunta el ETINCEL_HOME de cada compañero al mismo directorio compartido, sincronizado o montado (una ruta externa al repositorio que la máquina de todos pueda leer, p. ej., algo sincronizado por tu configuración habitual de intercambio de archivos) y las voces entrenadas, el estilo predeterminado y las instrucciones/diccionarios a nivel de cuenta también se comparten, no solo el subconjunto comprometido con .etincelrc:
{
"mcpServers": {
"etincel-nonfiction": {
"command": "node",
"args": ["/path/to/etincel/dist/server.js"],
"env": { "ETINCEL_HOME": "/path/to/shared/etincel-home" }
}
}
}
No hay nada más que exportar o importar: apuntar ETINCEL_HOME al mismo directorio es la sincronización, de la misma manera que ya lo es para el ~/.etincel/ de una sola persona.
Qué hay aquí
- Un servidor MCP (
src/server.ts) que expone veinte herramientas:list_styles: ajustes de tono predefinidos, cualquier voz que hayas entrenado y (si un.etincelrclocal al repositorio define uno) un estilo de equipo compartidoget_style_guide: las instrucciones de redacción para un estilotrain_style: aprende una voz a partir de tus propias muestras de escritura (ritmo de oraciones, tasa de contracciones, hábitos de guiones largos, variación de párrafos, frases recurrentes: medido, no adivinado)create_style_from_dials: construye un estilo a partir de controles explícitos de formalidad/calidez/directez y ajustes mecánicos en lugar de muestrasupdate_style: renombra una voz entrenada o ajusta sus parámetros en el lugarfork_style: copia los ajustes y la guía de un preajuste en una nueva voz entrenada que puedas reentrenar o ajustar manualmente, o bifurca el estilo de otro instalador una vez que lo haya publicado públicamente en la galería alojada (referenciado comohandle/slug, p. ej.jpleblanc/blunt-memo, la misma dirección que se muestra en su página pública enetincel.ai/v/handle/slug); una bifurcación de estilo público también transfiere sus ajustes mecánicos y cualquier diccionario/instrucción que el instalador de origen haya configurado específicamente para ese estilo (nunca los privados a nivel de cuenta), y realiza una llamada de red aetincel.aipara obtenerlo, mientras que una bifurcación de preajuste nunca sale de esta instalacióndelete_style: elimina permanentemente una voz entrenadaset_default_style: recuerda qué estilo usar sin repetirtecheck_voice_match: compara el ritmo medido de un borrador con la línea base de una voz entrenada. Es una comprobación de ritmo/mecánica, no de autoría ni de detección de IA, y tiene baja confianza en entradas cortascheck_self_repetition: compara un borrador con las muestras de entrenamiento recientes de una voz para detectar hábitos, no señales de IA: el mismo inicio, o una frase, que se repite en varias piezas pasadas ("has abierto así en 4 de tus últimas 6 piezas"). Solo instalación local por ahoraaudit_text: un escaneo determinista basado en reglas para detectar señales de IA, que devuelve un nivel, hallazgos específicos con severidad y una señal de fortalezas (especificidad, proporción concreto-vs-abstracto, variación del ritmo de oraciones) para que las correcciones no aplanen la prosa. Acepta unregisteropcional (email/blog/memo/essay/social/docs/general/personal, por defectogeneral) para calibrar la rigurosidad según el tipo de texto:docssuprime los falsos positivos de estructura Markdown (encabezados, términos en negrita) y recalibra la detección de ritmo/vocabulario contra prosa de referencia de formato largo en lugar de textos cortos más contundentes.personalestá esbozado (aceptado, aún no suprime nada extra) pero aún no calibrado: sin supresiones de términos, peso de ritmo ni corpus etiquetado propio hasta que se mida uno. También acepta unsourceFactsopcional (detalles solicitados al usuario, nunca generados): comprueba cuántos llegaron realmente al borrador, marcandoelicited-material-unusedpor debajo de una cuota de dos usados y al menos uno en una oración que no esté demostrando una calificaciónsecond_read: una única llamada de modelo que lee un borrador e informa lo que un editor humano cuidadoso notaría, sin puntuación ni niveles, nunca una reescritura. Solo alojado: esta instalación siempre falla con una explicación clara, ya que una llamada de modelo necesita una cuenta, un modelo fijado y una superficie de facturación que esta instalación no tiene.audit_textsigue totalmente disponible, sin necesidad de cuentaadd_banned_word/remove_banned_word: mantén tu propia lista de vocabulario prohibido, verificada poraudit_textjunto con el corpus integradoadd_custom_word/remove_custom_word: mantén una lista de "nunca marcar esto": acrónimos propios de una organización o términos internos, el caso del diccionario corporativolist_dictionary: ve las palabras prohibidas/personalizadas de un ámbito y, para un estilo, lo que realmente aplica una vez fusionado con la lista globalset_style_instructions/clear_style_instructions/get_style_instructions: guarda, elimina o lee reglas de redacción en texto libre para un ámbito (elementos requeridos, temas prohibidos, restricciones de formato), fusionadas enget_style_guidede la misma manera que los diccionarios se fusionan enaudit_text
- Una habilidad de Claude Code / Claude Desktop (
skills/etincel-nonfiction/) que usa esas herramientas cuando redactas o revisas prosa de no ficción de cualquier longitud significativa.
Las voces entrenadas, los diccionarios y tu estilo predeterminado viven localmente en ~/.etincel/: nada se envía a ningún lado. audit_text es código determinista simple (análisis de cadenas + un corpus curado de señales de escritura por IA), no una llamada de modelo. La única excepción es bifurcar un estilo público mediante fork_style, que obtiene (nunca envía) la guía de ese estilo desde la galería pública de etincel.ai; bifurcar un preajuste, o cualquier otra cosa en esta lista, no toca la red en absoluto.
Diccionarios personalizados
Además del corpus integrado de señales de IA, puedes mantener tus propias listas de palabras prohibidas y "siempre permitidas": solo dile a Claude (o a cualquier cliente MCP) cosas como "añade [palabra] a mi lista de palabras prohibidas" o "añade [palabra] a mi lista de palabras personalizadas, es una de las nuestras". Cada lista vive en un ámbito: global (aplica en todas partes, el predeterminado cuando no se nombra un estilo) o un id de estilo específico, cuya lista se fusiona sobre global cuando auditas contra ese estilo. list_dictionary muestra lo guardado para un ámbito, además de la lista fusionada efectiva para un estilo. Editar la lista global ya es la forma de mantener una palabra sincronizada en todos los estilos: se fusiona automáticamente, en vivo, cada vez que se ejecuta audit_text o list_dictionary.
Desarrollo
npm install
npm test # run the engine/tools test suite (node:test via tsx)
npm run dev # run the MCP server over stdio via tsx, for local testing
npm run build # compile to dist/
La insignia de mcpscore audita el servidor remoto alojado (etincel.ai/api/mcp), no el motor local/stdio en este repositorio; los dos exponen las mismas herramientas pero se ejecutan como implementaciones separadas.
Estado y limitaciones
Temprano, y honestamente.
- El corpus de auditoría en
src/data/es un subconjunto curado, no exhaustivo. Versrc/data/SOURCES.mdpara la procedencia y qué no se ha portado aún. El corpus completo está en aistoryhub.co/corpus. email(AUC 0.540) ygeneral(0.748) no están calibrados.socialno tiene corpus etiquetado en absoluto y no se rastrea.check_voice_matches una comprobación de ritmo y mecánica, no detección de autoría, y tiene baja confianza en entradas cortas.check_self_repetitiones solo de instalación local por ahora.- Las señales de IA son un objetivo cambiante: OpenAI parchó el hábito de guiones largos de ChatGPT en noviembre de 2025. Por eso la eficacia se mide en lugar de afirmarse: cuando una señal deja de ser una señal, el AUC se mueve y la comprobación de regresión lo detecta.