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:

RegistroAUC
memo0.909
ensaio0.900
blog0.820
geral0.748
docs0.735
email0.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 / allowedWords mesclam com o que estiver no seu dicionário de conta/estilo; register/threshold atuam como padrões de todo o repositório que um flag explícito --register/--threshold ainda sobrescreve.
  • instructions é texto livre, incorporado no instructions do get_style_guide para 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 do set_style_instructions sem styleId, mas versionado no repositório em vez de viver na conta de uma pessoa.
  • style define uma "voz da casa" compartilhada a partir de controles, endereçável em qualquer lugar como styleId: "team" (get_style_guide, e uma vez bifurcada em uma voz treinada real com fork_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_styles a inclui automaticamente quando um .etincelrc no 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 .etincelrc local do repositório definir uma) um estilo compartilhado de equipe
    • get_style_guide: as instruções de rascunho para um estilo
    • train_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 amostras
    • update_style: renomeie uma voz treinada ou ajuste seus controles no local
    • fork_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 como handle/slug, por exemplo, jpleblanc/blunt-memo, o mesmo endereço mostrado em sua página pública em etincel.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 a etincel.ai para buscá-lo, enquanto um fork de predefinição nunca sai desta instalação
    • delete_style: remova permanentemente uma voz treinada
    • set_default_style: lembre qual estilo usar sem precisar repetir
    • check_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 curtas
    • check_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 enquanto
    • audit_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 um register opcional (email / blog / memo / essay / social / docs / general / personal, padrão general) para calibrar a rigorosidade contra o tipo de texto: docs suprime 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. personal está 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 um sourceFacts opcional (detalhes obtidos do usuário, nunca gerados): verifica quantos realmente entraram no rascunho, sinalizando elicited-material-unused abaixo de uma cota de dois usados e pelo menos um em uma frase que não esteja provando uma qualificação
    • second_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_text permanece totalmente disponível, sem necessidade de conta
    • add_banned_word / remove_banned_word: mantenha sua própria lista de vocabulário proibido, verificada por audit_text junto com o corpus integrado
    • add_custom_word / remove_custom_word: mantenha uma lista de "nunca sinalizar": acrônimos ou termos internos da organização, o caso de dicionário corporativo
    • list_dictionary: veja as palavras proibidas/personalizadas de um escopo e, para um estilo, o que realmente se aplica depois de mesclado com a lista global
    • set_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 em get_style_guide da mesma forma que os dicionários são mesclados em audit_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/

mcpscore audit MCP Registry CircleCI CI Étincel lint License: MIT Node Last commit

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. Veja src/data/SOURCES.md para a proveniência e o que ainda não foi portado. O corpus completo está em aistoryhub.co/corpus.
  • email (AUC 0.540) e general (0.748) não estão calibrados. social nã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.