Muninn
Faça seu agente iniciar a ditadura (apenas OSX)
Documentação
muninn
Ditado nativo de macOS na barra de menus, feito para texto de desenvolvedores.
Muninn grava a fala, transcreve, processa a transcrição por um pipeline de texto configurável e injeta o texto final no aplicativo ativo. O pipeline padrão é projetado para ditado próximo a código: comandos, flags, nomes de pacotes, caminhos de arquivos, variáveis de ambiente, siglas e outros tokens que o ditado de uso geral frequentemente altera.
Conteúdo
- O que o Muninn faz
- Início rápido
- Instalar e executar
- Configurar o Muninn
- Provedores de transcrição
- Modelo de pipeline
- Transcrição em streaming
- Perfis contextuais e vozes
- Controle externo
- Privacidade, reprodução e depuração
- Desenvolvimento
- Limitações atuais
- Mapa do código-fonte
O que o Muninn faz
Fluxo padrão no modo de gravação:
hotkey or tray click
-> record temporary WAV
-> resolve transcription provider route
-> transcribe with the first usable provider
-> run the refine step
-> run optional external filters
-> inject final text into the active app
O Muninn inclui:
- um aplicativo de barra de menus do macOS com indicador de bandeja ao vivo
- atalhos globais para push-to-talk, alternância do modo concluído e cancelamento
- captura de microfone para um WAV temporário, padrão de 16 kHz mono
- uma rota de transcrição local-first entre Apple Speech, whisper.cpp, Deepgram, OpenAI, Google e SpaceXAI (xAI) com transcrição gravada
- um modo de streaming opcional para provedores que suportam transcrição ao vivo neste código
- uma etapa
refineintegrada que aplica um prompt conservador de ditado para desenvolvedores (OpenAI ou SpaceXAI / xAI) - suporte a filtros Unix externos para etapas personalizadas do pipeline
- injeção de texto por eventos de teclado no aplicativo atual
- controle externo opcional por URLs
muninn://e um servidor MCP em localhost - artefatos de reprodução opcionais para depuração de enunciados
Controles padrão:
| Ação | Padrão |
|---|---|
| Push-to-talk | ctrl com gatilho double_tap e janela de toque duplo de 300 ms |
| Alternância do modo concluído | ctrl + shift + d |
| Cancelar captura ativa | ctrl + shift + x |
| Clique esquerdo na bandeja | Alternar: iniciar quando ocioso, parar quando gravando |
Alterações de atalhos são lidas da configuração, mas o recarregamento ao vivo da configuração não substitui os atalhos ativos. Reinicie o Muninn após alterar os atalhos.
Início rápido
Use este caminho quando quiser executar o Muninn a partir deste repositório.
Pré-requisitos
- macOS
- Rust 1.88.0 ou mais recente
- Ferramentas de linha de comando do Xcode para builds locais
- Permissões do macOS para Microfone, Acessibilidade e Monitoramento de Entrada
- Chaves opcionais de provedores em nuvem ao usar Deepgram, OpenAI, Google, SpaceXAI (xAI) ou uma etapa
refinecom suporte em nuvem
1. Compilar o binário
cargo build --release --bin muninn
2. Criar um arquivo de configuração
O Muninn lê a configuração nesta ordem:
MUNINN_CONFIG$XDG_CONFIG_HOME/muninn/config.toml~/.config/muninn/config.toml
Se o arquivo de configuração resolvido estiver ausente, o Muninn cria uma configuração padrão inicializável. Para começar pela configuração de exemplo:
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/muninn"
mkdir -p "$CONFIG_DIR"
cp configs/config.sample.toml "$CONFIG_DIR/config.toml"
3. Definir credenciais quando necessário
O Muninn carrega ./.env do diretório de trabalho atual por padrão. Variáveis de ambiente existentes do shell substituem .env e valores de configuração.
Crie .env apenas com as chaves que você usa:
OPENAI_API_KEY=<OPENAI_API_KEY>
DEEPGRAM_API_KEY=<DEEPGRAM_API_KEY>
GOOGLE_API_KEY=<GOOGLE_API_KEY>
GOOGLE_STT_TOKEN=<GOOGLE_STT_TOKEN>
XAI_API_KEY=<XAI_API_KEY>
Defina MUNINN_LOAD_DOTENV=0, false ou no para desativar o carregamento de .env.
4. Executar o aplicativo de bandeja
cargo run --release --bin muninn
Resultado esperado: o Muninn aparece na barra de menus do macOS com um indicador de bandeja M.
5. Conceder permissões e verificar
Conceda estas permissões ao próprio Muninn:
| Permissão | Por que o Muninn precisa | Caminho nas Configurações do Sistema |
|---|---|---|
| Microfone | Gravar sua fala | Privacidade e Segurança > Microfone |
| Acessibilidade | Injetar texto final no aplicativo ativo | Privacidade e Segurança > Acessibilidade |
| Monitoramento de Entrada | Ouvir atalhos globais enquanto outro aplicativo está ativo | Privacidade e Segurança > Monitoramento de Entrada |
Para verificar o aplicativo:
- Foque um campo de texto em outro aplicativo.
- Clique no ícone de bandeja do Muninn para iniciar a gravação.
- Fale uma frase curta.
- Clique no ícone de bandeja novamente para parar a gravação.
Resultado esperado: o Muninn transcreve o enunciado, executa o pipeline e digita o texto final no aplicativo focado.
Se o macOS parar de mostrar o prompt de permissão, redefina o serviço TCC afetado e reinicie o Muninn:
tccutil reset ListenEvent
tccutil reset Accessibility
tccutil reset Microphone
Instalar e executar
Instalar a partir do crates.io
cargo install muninn-speech-to-text
muninn
O nome do pacote é muninn-speech-to-text; o nome do binário é muninn.
Executar a partir da configuração de exemplo
MUNINN_CONFIG="$PWD/configs/config.sample.toml" cargo run --release --bin muninn
Isso é útil para desenvolvimento local, pois evita alterar sua configuração de usuário.
Instalar um binário de versão
O fluxo de trabalho de versão compila arquivos tar para:
aarch64-apple-darwinx86_64-apple-darwin
Após extrair um arquivo de versão, mantenha o binário em um caminho estável antes de conceder permissões do macOS:
mkdir -p "$HOME/.local/bin"
mv muninn "$HOME/.local/bin/muninn"
chmod +x "$HOME/.local/bin/muninn"
"$HOME/.local/bin/muninn"
As permissões do macOS são vinculadas à identidade exata do aplicativo ou binário. Mover ou substituir um binário bruto pode exigir conceder permissões novamente.
Compilar um pacote .app local
Use o pacote de aplicativo quando quiser uma identidade de aplicativo estável, tratamento de URL muninn:// e comportamento normal de Itens de Login.
cargo build --release --bin muninn
bash scripts/package-macos-app.sh
open dist/Muninn.app
O script de empacotamento cria dist/Muninn.app, assina ad hoc por padrão e cria dist/Muninn.app.zip quando ditto está disponível. Defina CODESIGN_IDENTITY para usar um certificado Developer ID, ou defina CODESIGN_APP=0 para pular a assinatura.
Configuração recomendada do pacote de aplicativo:
- Mova
dist/Muninn.apppara/Applications/Muninn.app. - Inicie uma vez e conceda permissões a
Muninn. - Adicione em Configurações do Sistema > Geral > Itens de Login.
- Mantenha
[app].autostart = falseao usar Itens de Login.
O Finder e os Itens de Login não herdam o ambiente do seu shell. Armazene credenciais na configuração ou certifique-se de que o diretório de trabalho do Muninn contenha o arquivo .env que você espera que ele leia.
Ativar inicialização automática de binário bruto
Defina [app].autostart = true para permitir que o Muninn grave um LaunchAgent para o caminho do executável atual.
Comportamento:
- O Muninn grava
~/Library/LaunchAgents/com.bnomei.muninn.plistquando inicia ou recarrega a configuração. - As alterações entram em vigor no próximo login do macOS.
- O LaunchAgent inclui
MUNINN_CONFIG. - O LaunchAgent não herda exportações interativas do shell.
- Ao usar
Muninn.app, prefira Itens de Login do macOS em vez deste caminho de LaunchAgent de binário bruto.
Configurar o Muninn
O exemplo canônico está em configs/config.sample.toml. O esquema raiz está em src/config.rs.
Seções importantes da configuração
| Seção | Finalidade |
|---|---|
[app] | Perfil padrão, contrato estrito de etapas, inicialização automática de binário bruto |
[hotkeys.*] | Atalhos de push-to-talk, alternância do modo concluído e cancelamento |
[indicator] | Visibilidade e cores do indicador de bandeja |
[recording] | Formato de captura WAV e pós-processamento opcional de tempo com FFmpeg; padrão mono, 16 kHz e postprocess_speed = 1.0 |
[transcription] | Modo gravado versus streaming e rota ordenada de provedores |
[pipeline] | Prazo do pipeline, formato de payload e etapas pós-transcrição |
[transcript] | Prompt base e texto de anexo de prompt para a etapa de refinamento integrada |
[refine] | Provedor de refinamento (openai ou xai), endpoint, modelo, temperatura e proteções |
[voices.*] | Comportamento de refinamento nomeado e glifo opcional de um caractere na bandeja |
[profiles.*] | Substituições específicas de contexto para gravação, rota, pipeline, transcrição ou refinamento |
[[profile_rules]] | Correspondências ordenadas para o aplicativo em primeiro plano e título da janela |
[external_control] | Esquema de URL e configurações de controle de gravação via MCP |
[logging] | Artefatos de reprodução, retenção e detalhes de depuração |
[providers.*] | Credenciais de provedores, endpoints, modelos e configurações de streaming |
Pós-processamento de tempo do WAV gravado
Defina uma velocidade acima de 1.0 para pós-processar cada captura concluída com FFmpeg antes que um provedor gravado a leia. O filtro preserva o tom:
[recording]
postprocess_speed = 2.0
O padrão, 1.0, deixa o WAV finalizado inalterado. Valores de 1.0 a 16.0 são aceitos; valores acima de 2× são expressos como múltiplos estágios atempo do FFmpeg para evitar o comportamento de pular amostras do filtro em um único fator alto. O Muninn precisa de ffmpeg em PATH quando o valor configurado está acima de 1.0 (por exemplo, brew install ffmpeg); se indisponível, a bandeja pisca em estado de erro vermelho e a captura é descartada. Provedores de streaming ainda recebem quadros de captura ao vivo em velocidade normal; o WAV pós-processado é usado para transcrição gravada, fallback e reprodução após o término da captura.
Rota de provedores
A rota padrão de provedores é local-first:
[transcription]
providers = ["apple_speech", "whisper_cpp", "deepgram", "openai", "google", "xai"]
Perfis podem substituir apenas a rota:
[profiles.mail.transcription]
providers = ["deepgram", "openai", "google", "xai"]
Se você ainda tiver etapas stt_* explícitas em pipeline.steps, o Muninn as aceita e infere a rota dessa ordem. Novas configurações devem preferir [transcription].providers.
Etapas do pipeline
Cada etapa do pipeline tem:
idcmdargsopcionalio_modeopcionaltimeout_mson_error
Valores suportados de io_mode:
| Valor | Comportamento |
|---|---|
auto | Integrados usam JSON de envelope; comandos externos usam filtragem de texto por padrão |
envelope_json | A etapa lê e grava o envelope JSON completo |
text_filter | A etapa lê o texto da transcrição e grava texto de substituição |
Valores suportados de on_error:
| Valor | Comportamento |
|---|---|
continue | Manter o envelope anterior e executar etapas posteriores |
fallback_raw | Substituir transcript.raw_text e continuar |
abort | Parar o pipeline e exibir a falha |
Exemplo:
[transcription]
providers = ["apple_speech", "whisper_cpp", "deepgram", "openai", "google", "xai"]
[[pipeline.steps]]
id = "refine"
cmd = "refine"
timeout_ms = 2500
on_error = "continue"
[[pipeline.steps]]
id = "uppercase"
cmd = "/usr/bin/tr"
args = ["[:lower:]", "[:upper:]"]
timeout_ms = 250
on_error = "continue"
Dicas de prompt de refinamento
transcript.system_prompt e transcript.system_prompt_append orientam a etapa refine integrada. Eles não alteram o provedor de fala para texto, e o Muninn não analisa JSON anexado em APIs de adaptação nativas do provedor.
[transcript]
system_prompt = "Prefer minimal corrections. Focus on technical terms, developer tools, package names, commands, flags, file names, paths, env vars, acronyms, and obvious dictation errors. If uncertain, keep the original wording."
system_prompt_append = """
Vocabulary JSON:
{"terms":["Muninn","whisper.cpp","Deepgram","Cargo.toml"],"commands":["cargo test --all-targets","rg --files"],"paths":["src/config.rs",".env"]}
"""
Provedores de transcrição
| Provider | Modo gravado | Modo streaming | Credenciais | Observações |
|---|---|---|---|---|
| Apple Speech | Sim | Não | Nenhuma | Provedor local para macOS 26+. Usa os recursos de Speech gerenciados pela Apple para o idioma selecionado. |
| whisper.cpp | Sim | Não | Nenhuma | Provedor local. Padrão para tiny.en, armazenado em ~/.local/share/muninn/models, com device = "auto". |
| Deepgram | Sim | Sim | DEEPGRAM_API_KEY ou providers.deepgram.api_key | Uploads gravados usam /v1/listen; streaming usa a API WebSocket ao vivo. |
| OpenAI | Sim | Sim | OPENAI_API_KEY ou providers.openai.api_key | Uploads gravados são pré-validados contra o limite de áudio de 25 MB da OpenAI; streaming usa transcrição em tempo real. |
| Sim | Não chamável atualmente | GOOGLE_API_KEY, GOOGLE_STT_TOKEN ou valores de configuração | A transcrição REST gravada funciona pelo endpoint configurado. O adaptador de streaming do Google constrói solicitações Speech-to-Text v2, mas a dependência fixada google-cloud-speech-v2 1.12.0 não expõe uma RPC de streaming chamável, então o Muninn relata google_official_client_streaming_rpc_unavailable. | |
| SpaceXAI (xAI) | Sim | Sim | XAI_API_KEY ou providers.xai.api_key | ID de configuração xai, etapa stt_xai. Uploads gravados usam POST https://api.x.ai/v1/stt (multipart; sem campo STT model). Streaming usa wss://api.x.ai/v1/stt com autenticação Bearer, PCM mono de 16 kHz e handshake transcript.created. Opcionais language, format, keyterm, diarize, filler_words e vad_threshold em [providers.xai]. Substituições por variáveis de ambiente: XAI_STT_ENDPOINT, XAI_STT_STREAMING_ENDPOINT, XAI_STT_LANGUAGE. |
A etapa refine não é um provedor de STT. Ela usa a configuração [refine] e HTTP compatível com chat-completions por padrão (provider = "openai"). Defina provider = "xai" para refinar com SpaceXAI / xAI (https://api.x.ai/v1/chat/completions, modelo grok-4.5 por padrão). Definir apenas o provedor alterna endpoint e modelo para os padrões do fornecedor, para que uma chave xAI nunca seja enviada a uma URL da OpenAI.
Variáveis de ambiente
| Assunto | Variáveis |
|---|---|
| Caminho de configuração | MUNINN_CONFIG |
Carregamento de .env | MUNINN_LOAD_DOTENV |
| Deepgram | DEEPGRAM_API_KEY, DEEPGRAM_STT_ENDPOINT, DEEPGRAM_STT_MODEL, DEEPGRAM_STT_LANGUAGE, MUNINN_DEEPGRAM_STUB_TEXT |
| Transcrição e refinamento OpenAI | OPENAI_API_KEY, MUNINN_OPENAI_STUB_TEXT, MUNINN_REFINE_STUB_TEXT |
| Transcrição gravada Google | GOOGLE_API_KEY, GOOGLE_STT_TOKEN, GOOGLE_STT_ENDPOINT, GOOGLE_STT_MODEL, MUNINN_GOOGLE_STUB_TEXT |
| Transcrição e refinamento SpaceXAI (xAI) | XAI_API_KEY, XAI_STT_ENDPOINT, XAI_STT_STREAMING_ENDPOINT, XAI_STT_LANGUAGE, MUNINN_XAI_STT_STUB_TEXT, MUNINN_REFINE_STUB_TEXT |
Variáveis simuladas (stub) são destinadas a verificações locais rápidas e testes. Elas ignoram chamadas reais ao provedor para a etapa correspondente.
Ciclo de vida do modelo whisper.cpp
Comportamento padrão:
providers.whisper_cpp.modelnão definido resolve paratiny.entiny.enresolve paraggml-tiny.en.bin- diretório de modelo padrão é
~/.local/share/muninn/models - Muninn baixa automaticamente modelos canônicos conhecidos no primeiro uso
- caminhos de modelos personalizados explícitos devem já existir
device = "auto"usa Metal em builds Apple Silicon compatíveis e CPU caso contrário
Pré-aqueça o cache do modelo padrão:
mkdir -p "$HOME/.local/share/muninn/models"
curl -L \
-o "$HOME/.local/share/muninn/models/ggml-tiny.en.bin" \
"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en.bin"
Se uma rota somente local apontar para um modelo personalizado ausente, o Muninn registra um diagnóstico missing_whisper_cpp_model e não injeta nada, a menos que outro provedor produza transcript.raw_text posteriormente.
Modelo de pipeline
O Muninn passa um envelope por todas as etapas internas e externas. Etapas internas de STT preenchem transcript.raw_text; etapas de transformação, como refine, escrevem output.final_text. A injeção prefere output.final_text e pode recorrer a transcript.raw_text.
Comandos de etapas internas:
| Comando | Finalidade |
|---|---|
stt_apple_speech | Transcrição Apple Speech de gravação concluída |
stt_whisper_cpp | Transcrição local whisper.cpp de gravação concluída |
stt_deepgram | Transcrição Deepgram de gravação concluída |
stt_openai | Transcrição OpenAI de gravação concluída |
stt_google | Transcrição Google REST de gravação concluída |
stt_xai | Transcrição SpaceXAI / xAI de gravação concluída |
refine | Limpeza de ditado do desenvolvedor via chat-completions (openai ou xai) |
Execute uma etapa interna diretamente para verificações rápidas:
cargo run -q -- __internal_step <stt_apple_speech|stt_whisper_cpp|stt_deepgram|stt_openai|stt_google|stt_xai|refine>
Use os fixtures JSON em tests/fixtures para exemplos de envelopes de entrada.
Transcrição em streaming
O modo gravado é o padrão. Habilite o streaming explicitamente:
[transcription]
mode = "streaming"
providers = ["deepgram", "openai", "xai"]
[transcription.streaming]
frame_ms = 100
finish_timeout_ms = 10000
fallback_to_recorded_on_error = true
Comportamento do streaming:
- O streaming Deepgram envia áudio LINEAR16 mono via WebSocket.
- O streaming OpenAI usa transcrição em tempo real e força captura mono de 24 kHz para essa elocução.
- O streaming SpaceXAI / xAI usa
wss://api.x.ai/v1/sttcom BearerXAI_API_KEY, aguardatranscript.created, envia quadros PCM mono de 16 kHz e finaliza comaudio.done. Quando xAI é o provedor de streaming ativo, o Muninn força captura mono de 16 kHz para essa elocução. - O streaming Google não é chamável atualmente porque a dependência fixada
google-cloud-speech-v21.12.0 expõe tipos de solicitação e resposta, mas nenhum método de streaming chamável. - O Muninn ainda grava o WAV concluído durante o streaming.
- Quando o streaming falha e
fallback_to_recorded_on_error = true, o Muninn pode executar a rota de WAV concluído. - Uma transcrição de streaming bem-sucedida alimenta
transcript.raw_text;refine, pontuação, reprodução e injeção usam o mesmo pipeline downstream do modo gravado. - Resultados intermediários de streaming são transitórios. O Muninn não mostra uma interface de transcrição parcial nem persiste histórico de transcrição parcial.
Perfis contextuais e vozes
O Muninn pode alterar o comportamento de refinamento com base no aplicativo em primeiro plano. Ele captura o ID do bundle, o nome do aplicativo e um título de janela de melhor esforço, e então aplica a primeira entrada profile_rules correspondente. Se nenhuma regra corresponder, o comportamento recai em [app].profile; o glifo da bandeja ociosa recai em M.
Ordem de resolução:
- Comece pela configuração base.
- Aplique a voz correspondente, se o perfil correspondente nomear uma.
- Aplique as substituições do perfil por último.
Voz significa comportamento de modelagem de texto mais um glifo opcional de bandeja, não uma voz de áudio.
[app]
profile = "default"
[voices.codex]
indicator_glyph = "C"
system_prompt = "Prefer terse developer dictation. Keep commands, flags, file names, and code tokens intact."
system_prompt_append = """
Vocabulary JSON:
{"terms":["Codex","Muninn","Cargo.toml"],"commands":["cargo test --all-targets","cargo clippy --all-targets -- -D warnings"]}
"""
[voices.terminal]
indicator_glyph = "T"
system_prompt = "Preserve shell commands exactly. Prefer minimal punctuation changes."
[profiles.codex]
voice = "codex"
[profiles.terminal]
voice = "terminal"
[[profile_rules]]
id = "codex-app"
profile = "codex"
app_name = "Codex"
[[profile_rules]]
id = "terminal-app"
profile = "terminal"
bundle_id = "com.apple.Terminal"
Comportamento da bandeja:
- a pré-visualização ociosa mostra o glifo da voz correspondente, ou
M - gravação e processamento congelam o glifo resolvido para essa elocução
?é reservado para feedback de credenciais ausentes
Controle externo
O Muninn pode ser controlado por agentes e scripts por meio de dois transportes:
- esquema de URL
muninn://, disponível para o.appmacOS empacotado - servidor MCP HTTP streamable em localhost, desabilitado por padrão
Ambos os transportes usam o mesmo vocabulário de controle de gravação dos eventos de bandeja e atalho.
[external_control]
url_scheme_enabled = true
mcp_enabled = false
start_recording_enabled = false
mcp_bind_address = "127.0.0.1:2769"
Semântica de ações:
| Ação | Comportamento |
|---|---|
start | Inicia a gravação somente quando ocioso e start_recording_enabled = true |
stop | Interrompe uma gravação ativa e executa o pipeline; sem efeito quando ocioso |
toggle | Inicia quando ocioso e permitido; caso contrário, interrompe uma gravação ativa |
cancel | Descarta uma gravação ativa sem transcrição ou injeção |
O início externo é desabilitado por padrão porque inicia a captura do microfone. Habilitar start_recording_enabled = true é a decisão de confiança local para agentes e scripts configurados.
Esquema de URL
O .app empacotado registra muninn:// por meio de CFBundleURLTypes.
| URL | Ação |
|---|---|
muninn://record, muninn://start | iniciar |
muninn://stop, muninn://done | parar |
muninn://toggle | alternar |
muninn://cancel, muninn://abort | cancelar |
open "muninn://record"
Um binário iniciado com cargo run não recebe esses links do LaunchServices.
Servidor MCP
Quando mcp_enabled = true, o Muninn serve MCP em:
http://127.0.0.1:2769/mcp
Ferramentas:
get_statusstart_recordingstop_recordingcancel_recording
Exemplo de registro com um cliente compatível com MCP:
auggie mcp add muninn --transport http --url http://127.0.0.1:2769/mcp
get_status é somente leitura e retorna JSON como:
{
"state": "idle",
"recording_active": false,
"busy": false,
"permissions": {
"microphone": "granted",
"accessibility": "granted",
"input_monitoring": "granted"
}
}
state é um de idle, recording_active, permission_blocked, already_running ou failed.
Restrições de segurança:
- O servidor MCP não tem autenticação.
mcp_bind_addressdeve ser um endereço de socket loopback explícito, como127.0.0.1:2769ou[::1]:2769.- O Muninn recusa binds curinga, LAN, hostname e outros não loopback.
- O servidor MCP inicia somente na inicialização do aplicativo. Alterar
mcp_enableddepois exige reiniciar o Muninn.
Privacidade, reprodução e depuração
Logs de rastreamento vão para stderr e são controlados com RUST_LOG.
RUST_LOG=recording=debug cargo run --release --bin muninn
O log de reprodução é desabilitado por padrão. Quando habilitado:
replay_detail = "minimal"armazena apenas metadados esparsos de elocuçãoreplay_detail = "full_debug"armazena configuração redigida, contexto de destino, envelopes finais, resultado do pipeline, contexto de refinamento e rota de injeçãoreplay_retain_audio = truemantém áudio somente quandoreplay_detail = "full_debug"- áudio retido usa hard link quando possível e recorre a cópia
- snapshots de depuração completa redigem segredos do provedor e campos de prompt
- artefatos de reprodução são para inspeção, não para reexecução
[logging]
replay_enabled = true
replay_detail = "minimal"
replay_retain_audio = false
replay_dir = "~/.local/state/muninn/replay"
replay_retention_days = 7
replay_max_bytes = 52428800
Verificações comuns de recuperação:
| Sintoma | Verificação |
|---|---|
| Atalho não inicia a gravação | Conceda Monitoramento de Entrada ao Muninn e reinicie após alterar a configuração do atalho |
| Clique na bandeja grava, mas o atalho não | Monitoramento de Entrada ausente ou o ouvinte de atalho precisa ser reiniciado |
| Texto não é injetado | Conceda Acessibilidade ao Muninn |
| Nenhum texto é injetado após uma rota Whisper somente local | Verifique missing_whisper_cpp_model e confirme o caminho do modelo configurado |
| Início externo via MCP é rejeitado | Defina external_control.start_recording_enabled = true e reinicie se o servidor MCP não foi habilitado na inicialização |
| Streaming Google recai ou relata indisponível | Use transcrição Google gravada, streaming Deepgram, streaming OpenAI ou streaming xAI |
| SpaceXAI / xAI sem credenciais | Defina XAI_API_KEY ou providers.xai.api_key; para refinamento, defina também [refine] provider = "xai" |
Desenvolvimento
Execute as verificações principais:
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets
O repositório também inclui hooks prek:
prek validate-config
prek run --all-files
prek install
Execute a suíte de benchmarks:
cargo bench --bench runtime_bottlenecks
Filtre para um grupo de benchmark:
cargo bench --bench runtime_bottlenecks pipeline_runner
cargo bench --bench runtime_bottlenecks replay_persist
O alvo do benchmark foca em caminhos de latência por elocução que não exigem chamadas de rede:
- transformação e reamostragem de saída de áudio
- idas e voltas JSON de envelope
- construção do corpo de solicitação do Google
- resolução de perfil e voz
- pontuação de substituição
- sobrecarga do executor de pipeline em processo
- persistência de reprodução com e sem artefatos de áudio retidos
Limitações atuais
- O runtime suportado do Muninn é macOS.
- Apple Speech exige macOS 26+ e recursos de Speech gerenciados pela Apple.
- whisper.cpp e Apple Speech são provedores somente de gravação concluída.
- A construção de solicitação de streaming Google existe, mas o streaming Google ao vivo não é chamável até que o cliente oficial fixado exponha uma RPC de streaming.
- O modo streaming usa apenas o texto final do provedor. Não há interface de transcrição parcial.
- Artefatos de reprodução são para inspeção, não reprodução determinística.
- Transcrição baseada em provedor precisa de orçamentos de tempo limite realistas.
- O servidor MCP de controle externo não tem autenticação, é desabilitado por padrão, faz bind somente em loopback e inicia apenas na inicialização do aplicativo.
- O fluxo de release do repositório empacota binários brutos; use o script de empacotamento local quando precisar de um bundle
.app.
Mapa de fontes
Use estes arquivos ao verificar afirmações do README contra o código-fonte:
