Etincel
Encontre os sinais de IA na sua prosa. De forma determinística, local, no CI.
Documentação
Étincel: Conector de Escrita Não-Ficção
___ ___ ___ ___ ___ ___
/\ \ /\ \ ___ /\__\ /\ \ /\ \ /\__\
/::\ \ \:\ \ /\ \ /::| | /::\ \ /::\ \ /:/ /
/:/\:\ \ \:\ \ \:\ \ /:|:| | /:/\:\ \ /:/\:\ \ /:/ /
/::\~\:\ \ /::\ \ /::\__\ /:/|:| |__ /:/ \:\ \ /::\~\:\ \ /:/ /
/:/\:\ \:\__\ /:/\:\__\ __/:/\/__/ /:/ |:| /\__\ /:/__/ \:\__\ /:/\:\ \:\__\ /:/__/
\:\~\:\ \/__/ /:/ \/__/ /\/:/ / \/__|:|/:/ / \:\ \ \/__/ \:\~\:\ \/__/ \:\ \
\:\ \:\__\ /:/ / \::/__/ |:/:/ / \:\ \ \:\ \:\__\ \:\ \
\:\ \/__/ \/__/ \:\__\ |::/ / \:\ \ \:\ \/__/ \:\ \
\:\__\ \/__/ /:/ / \:\__\ \:\__\ \:\__\
\/__/ \/__/ \/__/ \/__/ \/__/
Encontre os "tells" de IA na sua prosa. De forma determinística, local e em CI.
npx etincel lint README.md
Sem instalação, sem conta, sem chamada de modelo, sem rede.
$ 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 é duas coisas. Uma auditoria determinística que encontra os padrões que fazem a prosa parecer escrita por máquina, como CLI, GitHub Action e ferramenta MCP. E uma camada de voz que treina Claude, Cursor ou qualquer cliente MCP para redigir em um estilo medido a partir da sua própria escrita, para que o problema seja menor antes mesmo de você ler o rascunho.
Prosa redigida por IA tem uma forma reconhecível: parágrafos uniformes, autoridade hesitante, travessões onde uma vírgula bastaria, fechamentos que resolvem de forma arrumada demais. Étincel codifica as regras contra essa forma e, tão importante quanto, mostra o que encontrou e por quê, em vez de sobrescrever silenciosamente sua voz. Não há chamada de modelo em nenhum lugar do caminho de auditoria, e você decide o que muda. Você continua sendo o autor.
Funciona?
Medimos em vez de afirmar. AUC agrupada por registro, medida por assay contra corpora rotulados com uma semente de bootstrap fixa, para que qualquer PR que derrube esses números falhe no CI:
| Registro | AUC |
|---|---|
| memo | 0.909 |
| ensaio | 0.900 |
| blog | 0.820 |
| geral | 0.748 |
| docs | 0.735 |
| 0.540 |
Email está perto de um cara ou coroa. Está deliberadamente não calibrado, e mesmo assim o rastreamos para que uma regressão acidental não passe despercebida. general também não é calibrado. Os registros calibrados são docs, blog, memo e essay; use esses se o número for importante para você. Veja efficacy-baselines.json e src/data/SOURCES.md para método e proveniência.
Como isso se compara
vs. Vale + vale-ai-tells Vale é um excelente linter com ciência de marcação e vale-ai-tells é um pacote sério de 78 regras. Eles comparam tokens com padrões. Étincel mede forma: variância de ritmo de frase, uniformidade de comprimento de parágrafo e repetição em relação aos seus próprios rascunhos anteriores, o tipo de camada estatística que o próprio README do vale-ai-tells diz exigir análise além do que a correspondência de tokens consegue fazer. Étincel também alimenta uma voz treinada para o modelo antes de você redigir, o que nenhum linter faz. Rodar ambos é razoável; eles se sobrepõem menos do que você esperaria.
vs. arquivos de skill (stop-slop, avoid-ai-writing, no-slop) Esses são instruções para um modelo, e ajudam. Mas um prompt não consegue verificar se funcionou, não consegue produzir um código de saída e não consegue bloquear um merge. Use um e rode isso no CI.
vs. humanizadores (Undetectable.ai, QuillBot, StealthWriter) Esses reescrevem seu texto para evitar detectores. O Turnitin agora tem um recurso dedicado de detecção de paráfrase por IA, expandido em 2025 para mirar especificamente a saída de humanizadores. Étincel faz o trabalho oposto: nunca modifica seu texto e seria uma ferramenta ruim para enganar alguém.
vs. detectores (GPTZero, Pangram, Originality.ai, Copyleaks) Esses respondem "uma máquina esteve envolvida?" com uma probabilidade, sobre um documento inteiro, como um veredito sobre autoria, na nuvem. Étincel responde "quais padrões específicos fazem isto parecer escrito por máquina?" com localizações e severidades, localmente, e nunca emite veredito sobre quem escreveu algo.
Instalação
Também listado no registro oficial de MCP como ai.etincel/etincel-nonfiction, para que clientes com consciência de MCP que descobrem servidores automaticamente a partir dali (a galeria @mcp do VS Code, por exemplo) o encontrem sem nenhuma das configurações abaixo.
Claude Code
/plugin marketplace add AIStoryHub/etincel
/plugin install etincel-nonfiction
Ou a partir de um clone local: /plugin marketplace add /path/to/etincel.
Claude Desktop / outros hosts MCP
{
"mcpServers": {
"etincel-nonfiction": {
"command": "npx",
"args": ["etincel", "serve"]
}
}
}
A partir de um clone local: npm install && npm run build, depois aponte args para ["/path/to/etincel/dist/server.js"] com "command": "node".
Remoto (hospedado, multi-tenant)
Uma versão hospedada também está disponível em etincel.ai, expondo as mesmas ferramentas via Streamable HTTP (https://etincel.ai/api/mcp) com autenticação por conta em vez de stdio. Aponte qualquer cliente MCP diretamente para ela:
{
"mcpServers": {
"etincel-nonfiction": {
"url": "https://etincel.ai/api/mcp"
}
}
}
O servidor hospedado não faz parte deste repositório; este repositório é o motor local/stdio, a CLI e a skill sobre os quais a versão hospedada é construída.
Como usar
Depois de instalado, basta pedir o que você normalmente pediria, como "redija um email para o time sobre o atraso", "escreva um post de blog sobre X" ou "limpe este memorando", dentro do Claude Code ou do Claude Desktop. A skill é ativada automaticamente para prosa de não-ficção com tamanho significativo. Para treinar sua própria voz:
Treine um estilo chamado "eu" a partir destes três emails que escrevi: [cole amostras]
Depois, ou nomeie-o por solicitação ("escreva isto na minha voz") ou defina-o como padrão:
Defina meu estilo padrão como "eu"
Predefinições de estilo
Doze predefinições prontas acompanham o produto: seis tons emocionais (Direto e Caloroso, Briefing Executivo, Ensaísta Reflexivo, Memorando de Fundador, Analista Simples, Irônico e Franca) mais seis predefinições de caso de uso (Revisão de PR, Comentário de Código, Mensagem no Slack, Post no LinkedIn, Texto de Site, Post de Blog). Cada uma carrega controles de formalidade/calor/diretividade, além de uma descrição de ritmo de frase e voz que é alimentada ao modelo como contexto de redação, não um modelo que preenche lacunas. O servidor lê esses de src/data/presets.json. Bifurque qualquer predefinição em uma voz treinada com fork_style para torná-la sua.
Lint de linha de comando
audit_text é uma função pura internamente, então também acompanha como CLI, para lintar prosa fora de um cliente de chat (READMEs, docs, descrições de PR em CI):
npx etincel lint 'docs/**/*.md'
npx etincel lint README.md --register docs --threshold yellow
Sai com código diferente de zero se o nível de qualquer arquivo correspondente estiver em ou acima de --threshold (padrão orange). Arquivos .md/.mdx usam automaticamente o registro docs (suprime os falsos positivos da estrutura Markdown, já que um cabeçalho real não é um tell de chatbot); passe --register para sobrescrever. Adicione --json para um relatório legível por máquina. Rode npx etincel lint --help para a lista completa de opções.
Uma GitHub Action encapsula a mesma CLI (veja action.yml, e .github/workflows/lint.yml neste repositório para um exemplo funcional):
- uses: AIStoryHub/etincel@main
with:
patterns: "docs/**/*.md README.md"
threshold: orange
Configuração local ao repositório: dicionário, instruções e um estilo compartilhado de equipe
As regras de uma equipe não precisam viver apenas no ~/.etincel/ local de cada pessoa. Coloque um .etincelrc (ou .etincelrc.json / etincel.config.json) na raiz do repositório e ele será detectado automaticamente pela CLI e pelo servidor local (stdio), revisável na revisão de código e versionado, em vez de invisível e perdido quando alguém sai:
{
"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/allowedWordsmesclam com o que estiver no seu dicionário de conta/estilo;register/thresholdatuam como padrões de todo o repositório que um flag explícito--register/--thresholdainda sobrescreve.instructionsé texto livre, incorporado noinstructionsdoget_style_guidepara todos os estilos, não apenas o da equipe, antes das suas próprias instruções globais de nível de conta: o equivalente de toda a equipe doset_style_instructionssemstyleId, mas versionado no repositório em vez de viver na conta de uma pessoa.styledefine uma "voz da casa" compartilhada a partir de controles, endereçável em qualquer lugar comostyleId: "team"(get_style_guide, e uma vez bifurcada em uma voz treinada real comfork_style, em qualquer outro lugar também), para que uma equipe tenha uma voz inicial já ajustada desde o primeiro dia, em vez de cada pessoa treinar ou ajustar manualmente a sua do zero.list_stylesa inclui automaticamente quando um.etincelrcno repositório atual define uma.
O servidor hospedado não usa nada disso (ele não tem repositório local para olhar).
Compartilhando configuração entre uma equipe sem versioná-la
.etincelrc é a camada versionada e revisável em código acima; a camada abaixo dela é ETINCEL_HOME, uma variável de ambiente que aponta o servidor local (stdio) e a CLI para um diretório a ser usado no lugar do ~/.etincel/ padrão. Aponte o ETINCEL_HOME de cada colega para o mesmo diretório compartilhado, sincronizado ou montado (um caminho externo ao repositório que a máquina de todos consegue ler, por exemplo, algo sincronizado pela sua configuração usual de compartilhamento de arquivos) e vozes treinadas, o estilo padrão e instruções/dicionários de nível de conta são compartilhados também, não apenas o subconjunto versionado via .etincelrc:
{
"mcpServers": {
"etincel-nonfiction": {
"command": "node",
"args": ["/path/to/etincel/dist/server.js"],
"env": { "ETINCEL_HOME": "/path/to/shared/etincel-home" }
}
}
}
Nada mais para exportar ou importar: apontar ETINCEL_HOME para o mesmo diretório é a sincronização, da mesma forma que já é para o ~/.etincel/ de uma única pessoa.
O que tem aqui
- Um servidor MCP (
src/server.ts) expondo vinte ferramentas:list_styles: predefinições de tom prontas, quaisquer vozes que você treinou e (se um.etincelrclocal do repositório definir uma) um estilo compartilhado de equipeget_style_guide: as instruções de rascunho para um estilotrain_style: aprenda uma voz a partir de suas próprias amostras de escrita (ritmo de frases, taxa de contrações, hábitos de travessão, variação de parágrafos, frases recorrentes: medido, não adivinhado)create_style_from_dials: construa um estilo a partir de controles explícitos de formalidade/calor/diretividade e mecânicos, em vez de amostrasupdate_style: renomeie uma voz treinada ou ajuste seus controles no localfork_style: copie os controles e o guia de uma predefinição para uma nova voz treinada que você pode retreinar ou ajustar manualmente, ou crie um fork do estilo de outro instalador depois que ele o publicar publicamente na galeria hospedada (endereçado comohandle/slug, por exemplo,jpleblanc/blunt-memo, o mesmo endereço mostrado em sua página pública emetincel.ai/v/handle/slug); um fork de estilo público também carrega seus controles mecânicos e qualquer dicionário/instruções que o instalador de origem definiu especificamente para aquele estilo (nunca os privados da conta), e faz uma chamada de rede aetincel.aipara buscá-lo, enquanto um fork de predefinição nunca sai desta instalaçãodelete_style: remova permanentemente uma voz treinadaset_default_style: lembre qual estilo usar sem precisar repetircheck_voice_match: compare o ritmo medido de um rascunho com a linha de base de uma voz treinada. Uma verificação de ritmo/mecânica, não uma verificação de autoria ou detecção de IA, e com baixa confiança em entradas curtascheck_self_repetition: compare um rascunho com as amostras de treinamento recentes da própria voz para hábitos, não para indícios de IA: a mesma abertura, ou uma frase, recorrente em várias peças anteriores ("você abriu assim em 4 das suas últimas 6 peças"). Somente instalação local por enquantoaudit_text: uma verificação determinística e baseada em regras para indícios de IA, retornando um nível, achados específicos com gravidade e um sinal de pontos fortes (especificidade, razão concreto-vs-abstrato, variação de ritmo de frases) para que as correções não aplaniem a prosa. Aceita umregisteropcional (email/blog/memo/essay/social/docs/general/personal, padrãogeneral) para calibrar a rigorosidade contra o tipo de texto:docssuprime falsos positivos de estrutura Markdown (cabeçalhos, termos em negrito) e recalibra a detecção de ritmo/vocabulário contra prosa de referência longa em vez de textos curtos e mais diretos.personalestá estruturado (aceito, ainda não suprime nada extra) mas ainda não calibrado: sem supressões de termos, peso de ritmo ou corpus rotulado próprio até que um seja medido. Também aceita umsourceFactsopcional (detalhes obtidos do usuário, nunca gerados): verifica quantos realmente entraram no rascunho, sinalizandoelicited-material-unusedabaixo de uma cota de dois usados e pelo menos um em uma frase que não esteja provando uma qualificaçãosecond_read: uma única chamada de modelo que lê um rascunho e relata o que um editor humano cuidadoso notaria, sem pontuação e sem níveis, nunca uma reescrita. Somente hospedado: esta instalação sempre falha com uma explicação clara, pois uma chamada de modelo precisa de uma conta, um modelo fixado e uma superfície de cobrança que esta instalação não tem.audit_textpermanece totalmente disponível, sem necessidade de contaadd_banned_word/remove_banned_word: mantenha sua própria lista de vocabulário proibido, verificada poraudit_textjunto com o corpus integradoadd_custom_word/remove_custom_word: mantenha uma lista de "nunca sinalizar": acrônimos ou termos internos da organização, o caso de dicionário corporativolist_dictionary: veja as palavras proibidas/personalizadas de um escopo e, para um estilo, o que realmente se aplica depois de mesclado com a lista globalset_style_instructions/clear_style_instructions/get_style_instructions: salve, remova ou leia regras de redação em texto livre para um escopo (elementos obrigatórios, tópicos proibidos, restrições de formato), mescladas emget_style_guideda mesma forma que os dicionários são mesclados emaudit_text
- Uma habilidade do Claude Code / Claude Desktop (
skills/etincel-nonfiction/) que usa essas ferramentas quando você está redigindo ou revisando prosa de não ficção de qualquer tamanho significativo.
Vozes treinadas, dicionários e seu estilo padrão ficam localmente em ~/.etincel/: nada é enviado a lugar algum. audit_text é código determinístico puro (análise de strings + um corpus curado de indícios de escrita de IA), não uma chamada de modelo. A única exceção é criar um fork de um estilo público via fork_style, que busca (nunca envia) o guia desse estilo da galeria pública do etincel.ai; criar um fork de uma predefinição, ou qualquer outra coisa nesta lista, ainda não toca a rede de forma alguma.
Dicionários personalizados
Além do corpus integrado de indícios de IA, você pode manter suas próprias listas de palavras proibidas e "sempre permitidas": basta dizer ao Claude (ou a qualquer cliente MCP) coisas como "adicione [palavra] à minha lista de palavras proibidas" ou "adicione [palavra] à minha lista de palavras personalizadas, é uma das nossas". Cada lista vive em um escopo: global (aplica-se em todos os lugares, o padrão quando nenhum estilo é nomeado) ou um id de estilo específico, cuja lista é mesclada sobre global quando você audita contra esse estilo. list_dictionary mostra o que está salvo para um escopo, além da lista efetiva mesclada para um estilo. Editar a lista global já é a maneira de manter uma palavra em sincronia em todos os estilos: ela é mesclada automaticamente, ao vivo, toda vez que audit_text ou list_dictionary é executado.
Desenvolvimento
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/
O selo mcpscore audita o servidor remoto hospedado (etincel.ai/api/mcp), não o mecanismo local/stdio neste repositório; os dois expõem as mesmas ferramentas, mas rodam como implantações separadas.
Status e limitações
Início, e honestamente assim.
- O corpus de auditoria em
src/data/é um subconjunto curado, não exaustivo. Vejasrc/data/SOURCES.mdpara a proveniência e o que ainda não foi portado. O corpus completo está em aistoryhub.co/corpus. email(AUC 0.540) egeneral(0.748) não estão calibrados.socialnão tem corpus rotulado e não é monitorado.check_voice_matché uma verificação de ritmo e mecânica, não detecção de autoria, e tem baixa confiança em entradas curtas.check_self_repetitioné somente para instalação local por enquanto.- Indícios de IA são um alvo em movimento: a OpenAI corrigiu o hábito de travessão do ChatGPT em novembro de 2025. É por isso que a eficácia é medida em vez de afirmada: quando um indício deixa de ser um indício, o AUC se move e a verificação de regressão o detecta.