@inemaccvbot é o cliente fino da fila mkivideos: manda instrução em texto, ele enfileira, avisa quando termina e entrega o MP4 — sem renderizar nada por conta própria.

O inemaccvbot não renderiza vídeo nenhum. Ele traduz mensagens do Telegram em jobs para a fila mkivideos (daemon systemd já rodando), acompanha o andamento e entrega o resultado — nunca cria conteúdo fora de uma skill registrada.
Cada linha da mensagem vira uma instrução independente — várias linhas enfileiram vários vídeos de uma vez.
Instrução que não mapeia para explicativo, curso ou demo é recusada com explicação — o bot enfileira o que consegue mapear e avisa o que não vai fazer.
Só chat ids em ALLOWED_CHAT_IDS são atendidos; qualquer outro é ignorado em silêncio e logado.
O parser tenta primeiro o formato leve (uma linha por job); texto fora do padrão cai
no fallback claude -p (Opus, esforço médio), que só traduz — nunca pesquisa nem
renderiza.
Não roda no bot — só anexa uma instrução ao job. É o agente de render do mkivideos que pesquisa a web antes de escrever o roteiro (só nas skills de vídeo: explicativo/curso/demo).
O bot escolhe um caminho em NARRACOES_DIR e pede ao agente para salvar ali a narração completa; o watcher entrega o arquivo (mensagem ou documento) quando o job termina.
Ao terminar, o watcher move (skills de vídeo/inemavox) ou copia (reel/reelinematds, que preservam o original em ~/projetos/output/.../<slug>/) o resultado pra ~/projetos/yt-pub-livesN/imports/videos.
reel monta um reel empilhado (headline + avatar + explicativo) a partir de um avatar HeyGen já pronto. reelinematds converte um bruto vertical seu (rosto falando, gravado sem edição) num reel produzido do zero — corte, tratamento visual, B-roll, legendas, cold open, CTA — com revisor independente antes de entregar.
O bot é só a ponte — sem qualquer um destes, ele recusa enfileirar ou nem sobe. Nenhum deles é opcional de fato, mesmo quando o bot não trava por causa deles no boot.
Runtime do bot (grammY + better-sqlite3). Testado com Node 24; tsconfig.json compila para ES2022/NodeNext, então qualquer LTS ativo (≥20) funciona.
# checar versão node -v
É o motor de verdade: dono da fila, do worker e do render. O bot faz ping() (GET /api/stats) antes de qualquer instrução — se estiver fora do ar, recusa enfileirar em vez de perder a mensagem em silêncio.
# status do daemon systemctl --user status mkivideos
claudeUsado em dois pontos: o bot chama claude --model opus -p pra interpretar texto livre; e o próprio agente de render do mkivideos roda como sessão claude -p — é essa sessão que dá acesso à web quando a flag pesquisa é usada. Sem claude no PATH, nenhum dos dois funciona.
# checar instalação claude --version
O bot só nomeia as skills em config/skills.json — quem precisa tê-las instaladas e utilizáveis é o agente de render do mkivideos, não o bot: video-explicativo, videos-cursos-inema, video-demonstrativo (vídeo), reel-edita-inema (reel empilhado, comando reel) e reel-edita-inematds (reel pessoal produzido, comando reelinematds). transcrever/dublar não usam skill do Claude Code — delegam direto pros scripts do inemavox.
Token do @inemaccvbot criado no @BotFather, mais o(s) chat id(s) autorizados — ambos vão no .env. Ver o passo 3 do guia abaixo pra descobrir o chat id sem cair na armadilha.
# nunca commitado TELEGRAM_BOT_TOKEN=<seu-token-do-botfather> ALLOWED_CHAT_IDS=<seu-chat-id>
yt-pub-lives<N>Só necessárias se você usar o campo livesN (destino) numa instrução. Sem a pasta, o vídeo fica no output padrão da skill mesmo — e a instrução com livesN inexistente é recusada listando os destinos válidos.
better-sqlite3 nativoGuarda o estado local (job id ↔ chat id/flags) em state.db. É um binário nativo — npm i compila/baixa um addon C++ pra sua plataforma (em geral já vem pronto via prebuilt binary do pacote, sem precisar de toolchain de build).
Comandos reais deste repositório — nenhum placeholder.
.envInstala as dependências de produção (grammY, dotenv, better-sqlite3) e cria o arquivo de config.
git clone https://github.com/inematds/inemaccvbot.git cd inemaccvbot npm i cp .env.example .env # depois preenche token, chat id etc.
No Telegram, fale com @BotFather e use /newbot (ou /token num bot já existente). Cole o valor em TELEGRAM_BOT_TOKEN no .env.
TELEGRAM_BOT_TOKEN=<seu-token-do-botfather>
O bot exige ALLOWED_CHAT_IDS pra sequer subir (loadConfig lança erro se faltar) — ou seja, não dá pra rodar o bot e ler o chat id no log dele, porque ele nem inicia sem essa variável. O jeito é perguntar direto pra API do Telegram, com o próprio token:
# 1. mande qualquer mensagem pro seu bot no Telegram (ele não responde ainda, tudo bem) # 2. rode isto (timeout=25 é um long-poll — sem ele, costuma voltar vazio): curl "https://api.telegram.org/bot<seu-token-do-botfather>/getUpdates?timeout=25" # 3. no JSON, o chat id está em result[0].message.chat.id
Preencha ALLOWED_CHAT_IDS com esse número (vários separados por vírgula, se mais de um chat vai falar com o bot).
Compila TypeScript pra dist/ e roda uma vez em foreground, só pra validar o .env antes de virar serviço.
npm run build # gera dist/index.js npm run start # roda dist/index.js em foreground # ou, sem buildar, direto do TypeScript: npm run dev # tsx src/index.ts
Registra a unit de usuário. Ver a seção Operação do serviço logo abaixo pra deixar isso realmente sempre ativo (inclusive após logout/reboot) e pro dia a dia de reiniciar/depurar.
mkdir -p ~/.config/systemd/user
cp deploy/inemaccvbot.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now inemaccvbot
Uma linha por job — cabem várias na mesma mensagem.
explicativo: O que é RAG | 9:16 | lives3
explicativo: Computação quântica | pesquisa | narracao | lives2
curso: https://inematds.github.io/skillsx/ | modulo t1m1
demo: https://app.exemplo.com | lives7
Comandos de controle da fila e entrega do resultado.
/fila # running + queued com posição /status <id> # detalhe do job (sem id: visão geral + stats) /cancelar <id> # cancela job na fila /enviar <id> # manda o MP4 aqui (≤50 MB, senão só o caminho) /skills # o que o bot sabe fazer /help # ajuda completa (ou /start)
deploy/inemaccvbot.service roda node dist/index.js com um PATH
explícito no unit — necessário porque uma unit de usuário do systemd não herda o PATH do seu
shell, e o bot chama claude e node via shell-out.
mkdir -p ~/.config/systemd/user
cp deploy/inemaccvbot.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now inemaccvbot
loginctl enable-linger $USER
enable registra a unit em WantedBy=default.target — sobe sozinho em todo
boot/login; --now já inicia agora. Restart=on-failure + RestartSec=10
(já no unit) faz o bot voltar sozinho se o processo morrer.
loginctl enable-linger $USER é o passo fácil de esquecer. Sem ele, uma
unit --user só existe enquanto você tem sessão de login aberta: o bot morre ao
deslogar e não sobe num reboot sem ninguém logado. Com o linger habilitado,
o systemd mantém os serviços --user rodando independente de sessão.
# conferir que está ativo systemctl --user status inemaccvbot
systemctl --user restart inemaccvbot # reinicia systemctl --user stop inemaccvbot # para systemctl --user start inemaccvbot # inicia de novo systemctl --user disable --now inemaccvbot # para de subir sozinho E para agora
Mudou código-fonte? Restart sozinho não basta — o serviço roda dist/,
não src/: npm run build && systemctl --user restart inemaccvbot.
Mudou só o .env? Um restart simples já é suficiente
(lido no boot do processo via dotenv/config).
journalctl --user -u inemaccvbot -f # log do systemd, ao vivo tail -f inemaccvbot.log # log próprio do bot (LOG_FILE), com rotação
O erro aparece no journalctl --user -u inemaccvbot -f. As duas causas mais comuns:
variável obrigatória faltando no .env — loadConfig lança
variável obrigatória ausente no .env: <NOME> explicitamente, sem precisar adivinhar; ou
o daemon mkivideos fora do ar — o bot ainda sobe (não depende do mkivideos pra iniciar),
mas toda instrução é recusada com "fila mkivideos indisponível" até systemctl --user status
mkivideos voltar a ficar ativo.
O formato é <skill>: <assunto ou link> | campo | campo | .... Texto livre
também funciona — Claude interpreta, mas só mapeando para skills registradas.
explicativo: O que é RAG | 9:16 | lives3
Vídeo explicativo PT-BR (skill video-explicativo). Campos aceitos por qualquer skill: 9:16/vertical (default é 16:9/horizontal), pesquisa/pesquisar, narracao/narração/texto, livesN.
curso: https://inematds.github.io/skillsx/ | modulo t1m1
Vídeo de curso INEMA a partir do link (skill videos-cursos-inema). Campos: modulo X, curso X.
demo: https://app.exemplo.com | lives7
Vídeo demonstrativo de um app/site (skill video-demonstrativo).
/reel /home/user/avatar.mp4 quero com texto e imagem ilustrativa
Reel 9:16 empilhado a partir de avatar HeyGen (skill reel-edita-inema). Também aceita reel: <caminho> | lives3 ou anexo <20 MB com legenda "reel".
/reelinematds /home/user/bruto.mp4 sem música
Reel pessoal produzido a partir de um bruto vertical (skill reel-edita-inematds) — corte, PiP/B-roll, legendas, cold open, CTA final, revisor. Mesmos campos do reel.
<url> crie um vídeo explicativo ... e me retorne também a narração em texto
Cai no fallback Claude — extrai todo job que mapeia e avisa ⚠️ não vou fazer: ... só para o que sobra fora do escopo.
O v1 (spec docs/superpowers/specs/2026-07-16-inemaccvbot-design.md) está implementado e revisado. Itens abaixo são evolução, não bug — ver docs/V2-BACKLOG.md.
timesmkt3 (ainda não existe). Quando existir, basta adicionar entrada em config/skills.json e reiniciar — o registro é plugável, sem mudança de código.--pastaÚnico slot argv sem validação de espaço (só alcançável via PROJETOS_DIR, config de operador — não input de usuário).-- no assuntoÉ engolido pelo loop de flags do mkivideos (pré-existente, cosmético, só afeta usuários da allowlist).ALLOWED_CHAT_IDSEntrada malformada falha fechado em silêncio (seguro, mas um typo vira "o bot não responde" sem explicação); sugestão é logar os ids carregados no boot.