Skip to content

Princípios de Detecção de Terminal: Mecanismo de Identificação Automática e Detecção de Foco Detalhada

O Que Você Poderá Fazer Após Este Tutorial

  • Entender profundamente o mecanismo de funcionamento e os princípios de implementação da detecção automática de terminal
  • Dominar os detalhes técnicos da detecção de foco no macOS e da obtenção dinâmica de Bundle ID
  • Aprender a substituir manualmente o tipo de terminal para resolver problemas de falha de detecção
  • Compreender as diferenças de detecção entre diferentes plataformas (macOS/Windows/Linux)
  • Entender as implementações de código-fonte relacionadas à detecção de terminal

Seu Cenário Atual

Você já sabe que o opencode-notify suporta 37+ terminais e também sabe que pode especificar manualmente o tipo de terminal. Mas você quer entender mais profundamente:

  • Como a detecção de terminal é implementada na camada inferior?
  • Qual mecanismo é usado para a detecção de foco no macOS?
  • Por que o macOS precisa obter o Bundle ID, enquanto Windows/Linux não precisam?
  • Como o plugin lida quando a detecção automática falha?
  • Como multiplexadores de terminal como o tmux são identificados?

Esta lição o levará a analisar o código-fonte detalhadamente, respondendo a esses detalhes técnicos.

Ideia Central

A implementação da detecção de terminal é dividida em três camadas:

1. Camada de Detecção Automática: biblioteca detect-terminal identifica o tipo de terminal

2. Camada de Adaptação de Plataforma: processamento específico para macOS/Windows/Linux

3. Camada de Aprimoramento de Funcionalidade: detecção de foco, clique para focar, obtenção de Bundle ID

Princípios-chave de Design:

  • Detectar uma vez na inicialização: O plugin detecta o terminal ao iniciar, armazenando o resultado em cache para todas as notificações subsequentes (otimização de desempenho)
  • Prioridade à configuração de sobrescrita: A configuração terminal especificada manualmente tem prioridade sobre a detecção automática
  • Tratamento de fallback em caso de falha: Quando a detecção falha, não impede o envio de notificações, apenas desativa a função de filtragem inteligente
  • Adaptação às diferenças de plataforma: macOS suporta funcionalidade completa, Windows/Linux suportam notificações básicas

Por que detectar apenas na inicialização?

A detecção de terminal envolve escaneamento de processos, chamadas osascript, etc. Se detectada antes de cada notificação, traria uma sobrecarga significativa de desempenho. Por isso, o plugin detecta uma vez na inicialização, armazenando em cache o objeto TerminalInfo, reutilizando-o em notificações subsequentes.

Fluxo Completo de Detecção de Terminal

Análise do Código-Fonte: detectTerminalInfo()

Vamos analisar linha por linha a função de detecção principal:

typescript
// src/notify.ts:145-164
async function detectTerminalInfo(config: NotifyConfig): Promise<TerminalInfo> {
    // Usa substituição de configuração se fornecida
    const terminalName = config.terminal || detectTerminal() || null

    if (!terminalName) {
        return { name: null, bundleId: null, processName: null }
    }

    // Obtém nome do processo para detecção de foco
    const processName = TERMINAL_PROCESS_NAMES[terminalName.toLowerCase()] || terminalName

    // Obtém Bundle ID dinamicamente do macOS (sem hardcoding!)
    const bundleId = await getBundleId(processName)

    return {
        name: terminalName,
        bundleId,
        processName,
    }
}

Decomposição dos Passos:

PassoCódigoDescrição
1config.terminal || detectTerminal()Prioriza substituição de configuração, caso contrário detecta automaticamente
2!terminalName ? return {...}Retorna objeto vazio quando a detecção falha
3TERMINAL_PROCESS_NAMES[...]Consulta tabela de mapeamento para obter nome do processo macOS
4await getBundleId()macOS obtém Bundle ID dinamicamente
5return { name, bundleId, processName }Retorna informações completas do terminal

Estrutura de TerminalInfo Retornado:

typescript
interface TerminalInfo {
    name: string | null       // Nome do terminal, ex: "ghostty"
    bundleId: string | null   // Bundle ID macOS, ex: "com.mitchellh.ghostty"
    processName: string | null // Nome do processo macOS, ex: "Ghostty"
}
Por que o macOS precisa de três campos?
  • name: Nome genérico do terminal (da biblioteca detect-terminal)
  • processName: Nome do processo no gerenciador de processos macOS (usado para detecção de foco)
  • bundleId: Identificador único do aplicativo macOS (usado para clicar e focar)

Por exemplo:

  • name = "ghostty" (retornado por detect-terminal)
  • processName = "Ghostty" (encontrado na tabela de mapeamento)
  • bundleId = "com.mitchellh.ghostty" (consulta dinâmica via osascript)

Funcionamento da Biblioteca detect-terminal

O que é detect-terminal?

detect-terminal é uma biblioteca Node.js especializada em identificar emuladores de terminal, escaneando processos do sistema para identificar o terminal atualmente em execução.

Métodos de Detecção:

  1. Escaneamento de Processos: Verifica a cadeia de processos pai do processo atual
  2. Detecção de Variáveis de Ambiente: Verifica variáveis de ambiente como TERM, TERM_PROGRAM
  3. Correspondência de Nomes de Processo Conhecidos: Compara com nomes de processo de 37+ terminais conhecidos

Métodos de Detecção Suportados:

typescript
// Lógica interna do detect-terminal (simplificada)
function detect() {
    // 1. Verifica variáveis de ambiente
    if (process.env.TERM_PROGRAM) {
        return process.env.TERM_PROGRAM
    }

    // 2. Escaneia cadeia de processos pai
    const parentProcess = getParentProcess()
    if (isKnownTerminal(parentProcess.name)) {
        return parentProcess.name
    }

    // 3. Verifica variáveis de ambiente específicas
    if (process.env.TMUX) return 'tmux'
    if (process.env.VSCODE_PID) return 'vscode'

    return null
}

Quantidade de Terminais Suportados: 37+ (veja a lista completa)

Processamento Especial do macOS

1. Tabela de Mapeamento de Nomes de Processo

O código-fonte define o mapeamento de nomes de terminal para nomes de processo macOS:

typescript
// src/notify.ts:71-84
const TERMINAL_PROCESS_NAMES: Record<string, string> = {
    ghostty: "Ghostty",
    kitty: "kitty",
    iterm: "iTerm2",
    iterm2: "iTerm2",
    wezterm: "WezTerm",
    alacritty: "Alacritty",
    terminal: "Terminal",
    apple_terminal: "Terminal",
    hyper: "Hyper",
    warp: "Warp",
    vscode: "Code",
    "vscode-insiders": "Code - Insiders",
}

Por que é necessária uma tabela de mapeamento?

  • O nome do terminal retornado por detect-terminal pode estar em minúsculas ou ser uma abreviação (como "ghostty")
  • O nome do processo no gerenciador de processos macOS pode ter diferenças de capitalização (como "Ghostty")
  • Alguns terminais têm múltiplas formas de escrita (como "iterm" e "iterm2" ambos correspondem a "iTerm2")

Lógica de Mapeamento:

typescript
const processName = TERMINAL_PROCESS_NAMES[terminalName.toLowerCase()] || terminalName
  • Primeiro converte o nome do terminal para minúsculas e consulta a tabela de mapeamento
  • Se encontrado, usa o nome do processo mapeado
  • Se não encontrado, usa o nome do terminal original

2. Obtenção Dinâmica de Bundle ID

Implementação no Código-Fonte:

typescript
// src/notify.ts:135-137
async function getBundleId(appName: string): Promise<string | null> {
    return runOsascript(`id of application "${appName}"`)
}

Comando osascript:

applescript
id of application "Ghostty"
-- Retorna: com.mitchellh.ghostty

Por que não hardcodar o Bundle ID?

Desvantagens do hardcoding:

  • ❌ O Bundle ID pode mudar quando o terminal é atualizado
  • ❌ É necessário manter manualmente uma lista de Bundle IDs para 37+ terminais
  • ❌ Novos terminais precisam de atualizações de código quando são lançados

Vantagens da obtenção dinâmica:

  • ✅ Adaptação automática a mudanças de versão de terminais
  • ✅ Redução do custo de manutenção
  • ✅ Suporte teórico a qualquer terminal macOS

3. Implementação de Detecção de Foco

Implementação no Código-Fonte:

typescript
// src/notify.ts:139-143
async function getFrontmostApp(): Promise<string | null> {
    return runOsascript(
        'tell application "System Events" to get name of first application process whose frontmost is true',
    )
}

// src/notify.ts:166-175
async function isTerminalFocused(terminalInfo: TerminalInfo): Promise<boolean> {
    if (!terminalInfo.processName) return false
    if (process.platform !== "darwin") return false

    const frontmost = await getFrontmostApp()
    if (!frontmost) return false

    // Comparação sem distinção entre maiúsculas e minúsculas
    return frontmost.toLowerCase() === terminalInfo.processName.toLowerCase()
}

Comando osascript:

applescript
tell application "System Events" to get name of first application process whose frontmost is true
-- Retorna: Ghostty

Fluxo de Detecção:

1. Verifica plataforma: retorna false imediatamente se não for macOS

2. Verifica processName: retorna false se não houver nome de processo

3. Obtém aplicativo em primeiro plano: consulta via osascript

4. Compara nomes de processo: sem distinção entre maiúsculas e minúsculas

5. Retorna resultado: true se iguais (focado), false se diferentes

Uso no Fluxo de Envio de Notificações:

typescript
// src/notify.ts:264-265
// Verifica se o terminal está focado (suprime notificação se o usuário já estiver olhando)
if (await isTerminalFocused(terminalInfo)) return

Quando o terminal está em primeiro plano, o plugin suprime o envio de notificação para evitar lembretes duplicados.

Mecanismo de Substituição de Configuração

Quando é Necessário Substituir Manualmente?

Cenários Aplicáveis:

  1. Falha na detecção automática: detect-terminal não consegue reconhecer seu terminal
  2. Cenário de terminal aninhado: Usando Alacritty dentro do tmux, desejando identificar como tmux
  3. Resultado de detecção impreciso: Identificado incorretamente como outro terminal

Método de Configuração

Arquivo de Configuração: ~/.config/opencode/kdco-notify.json

json
{
  "terminal": "ghostty"
}

Lógica de Prioridade (linha 147 do código-fonte):

typescript
const terminalName = config.terminal || detectTerminal() || null

Ordem de Prioridade:

  1. Substituição de configuração (config.terminal): Prioridade mais alta
  2. Detecção automática (detectTerminal()): Prioridade secundária
  3. Tratamento de fallback (null): Usa null quando a detecção falha

Cenários aplicáveis para substituição de configuração

Se seu terminal puder ser reconhecido corretamente, não é recomendado substituir manualmente. A substituição de configuração é principalmente usada para resolver problemas de falha de detecção ou cenários especiais.

Comparação de Diferenças Entre Plataformas

macOS

FuncionalidadeSituação de SuporteMétodo de Implementação
Notificação nativanode-notifier (NSUserNotificationCenter)
Detecção de terminalBiblioteca detect-terminal
Detecção de focoConsulta de aplicativo em primeiro plano via osascript
Clique para focarParâmetro activate do node-notifier
Obtenção de Bundle IDConsulta dinâmica via osascript
Som personalizadoParâmetro sound do node-notifier

Fluxo de Suporte Completo:

mermaid
graph LR
    A[Detectar Terminal] --> B[Obter Bundle ID]
    B --> C[Armazenar TerminalInfo em Cache]
    C --> D[Evento Acionado]
    D --> E{Terminal Focado?}
    E -->|Sim| F[🚫 Suprimir Notificação]
    E -->|Não| G[Enviar Notificação]
    G --> H{Usuário Clicou?}
    H -->|Sim| I[Ativar Janela do Terminal]
    H -->|Não| J[Notificação Desaparece Automaticamente]

Windows

FuncionalidadeSituação de SuporteMétodo de Implementação
Notificação nativanode-notifier (SnoreToast)
Detecção de terminalBiblioteca detect-terminal
Detecção de focoLimitação do sistema
Clique para focarLimitação do sistema
Obtenção de Bundle IDWindows não tem este conceito
Som personalizadoUsa som padrão do sistema

Fluxo Simplificado:

mermaid
graph LR
    A[Detectar Terminal] --> B[Armazenar TerminalInfo em Cache]
    B --> C[Evento Acionado]
    C --> D{Período de Silêncio?}
    D -->|Sim| E[🚫 Suprimir Notificação]
    D -->|Não| F[Enviar Notificação]
    F --> G[Notificação Desaparece Automaticamente]

Linux

FuncionalidadeSituação de SuporteMétodo de Implementação
Notificação nativanode-notifier (notify-send)
Detecção de terminalBiblioteca detect-terminal
Detecção de focoLimitação do sistema
Clique para focarLimitação do sistema
Obtenção de Bundle IDLinux não tem este conceito
Som personalizadoUsa som padrão do ambiente desktop

Fluxo idêntico ao Windows, apenas o backend de notificação usa notify-send.

Tratamento de Falha de Detecção

Lógica do Código-Fonte

Quando a detecção falha, detectTerminalInfo() retorna um objeto vazio:

typescript
if (!terminalName) {
    return { name: null, bundleId: null, processName: null }
}

Impacto nas Funcionalidades de Notificação

FuncionalidadeComportamento Após Falha de Detecção
Notificação nativaFunciona normalmente (não depende da detecção de terminal)
Detecção de focoDesativada (isTerminalFocused() retorna false diretamente)
Clique para focarDesativado (bundleId é null, parâmetro activate não é definido)
Período de silêncioFunciona normalmente (independente da detecção de terminal)
Verificação de sessão paiFunciona normalmente (independente da detecção de terminal)

Código de Exemplo:

typescript
// src/notify.ts:166-175
async function isTerminalFocused(terminalInfo: TerminalInfo): Promise<boolean> {
    if (!terminalInfo.processName) return false  // ← Retorna false diretamente quando a detecção falha
    if (process.platform !== "darwin") return false
    // ...
}

// src/notify.ts:238-240
if (process.platform === "darwin" && terminalInfo.bundleId) {
    notifyOptions.activate = terminalInfo.bundleId  // ← Não define quando bundleId é null
}

Como Verificar o Estado de Detecção?

Método de Depuração Temporário (requer modificação do código-fonte):

typescript
// Adicione na exportação do plugin em notify.ts
export const NotifyPlugin: Plugin = async (ctx) => {
    const { client } = ctx
    const config = await loadConfig()
    const terminalInfo = await detectTerminalInfo(config)

    // 👇 Adicione log de depuração
    console.log("Informações do Terminal:", JSON.stringify(terminalInfo, null, 2))

    return {
        // ...
    }
}

Exemplo de Saída Normal:

json
{
  "name": "ghostty",
  "bundleId": "com.mitchellh.ghostty",
  "processName": "Ghostty"
}

Exemplo de Falha de Detecção:

json
{
  "name": null,
  "bundleId": null,
  "processName": null
}

Cenário Especial: Terminal tmux

Particularidades do tmux

tmux é um multiplexador de terminal (terminal multiplexer), permitindo criar múltiplas sessões e painéis em uma janela de terminal.

Método de Detecção:

typescript
// Biblioteca detect-terminal detecta tmux através de variáveis de ambiente
if (process.env.TMUX) return 'tmux'

Impacto do Fluxo de Trabalho do tmux:

Como mencionado em terminals/index.md, a detecção de foco não é realizada no fluxo de trabalho do tmux. Isso ocorre porque:

  1. Cenário de múltiplas janelas: O tmux pode estar rodando em várias janelas de terminal
  2. Semântica de foco ambígua: Não é possível determinar em qual painel do tmux o usuário está focado
  3. Consideração de experiência do usuário: Evita suprimir notificações importantes

Evidência do Código-Fonte (função handleQuestionAsked):

typescript
// src/notify.ts:340-341
// Proteção: apenas período de silêncio (sem verificação de foco para perguntas - fluxo de trabalho tmux)
if (isQuietHours(config)) return

Nota: Para eventos do tipo question, o código-fonte comenta explicitamente "no focus check for questions - tmux workflow".

Melhores Práticas para Configuração Manual do Tipo de Terminal

Escolhendo o Nome de Terminal Apropriado

Princípio: Use o nome padrão reconhecido pela biblioteca detect-terminal.

Tabela de Referência Comum:

Seu TerminalValor de ConfiguraçãoResultado de Detecção (detect-terminal)
Ghostty"ghostty"
iTerm2"iterm2" ou "iterm"
Kitty"kitty"
WezTerm"wezterm"
Alacritty"alacritty"
macOS Terminal.app"terminal" ou "apple_terminal"
Hyper"hyper"
Warp"warp"
VS Code Stable"vscode"
VS Code Insiders"vscode-insiders"
Windows Terminal"windows-terminal" ou "Windows Terminal"⚠️ Pode precisar tentar ambos

Verificando se a Configuração Está Ativa

Método 1: Verificar Logs

Se os logs de depuração estiverem habilitados (veja acima), você deve ver:

json
{
  "name": "ghostty",  // ← Deve ser o nome do terminal configurado
  "bundleId": "com.mitchellh.ghostty",
  "processName": "Ghostty"
}

Método 2: Teste Funcional

  1. Após configurar o tipo de terminal, reinicie o OpenCode
  2. Inicie uma tarefa de IA
  3. Mude para outra janela (fazendo o terminal perder o foco)
  4. Aguarde a conclusão da tarefa

Você deve ver: receber uma notificação e, ao clicar na notificação (macOS), a janela do terminal será focada.

Dicas de Solução de Problemas

Problema Comum 1: A Detecção Continua Falhando Após a Configuração

Sintoma: Definiu "terminal": "ghostty", mas a funcionalidade de notificação está anormal.

Etapas de Diagnóstico:

  1. Verifique o formato JSON:
bash
cat ~/.config/opencode/kdco-notify.json | jq .
  1. Verifique a ortografia do nome do terminal:
  • Certifique-se de usar minúsculas (ex: "ghostty" em vez de "Ghostty")
  • Certifique-se de ser um nome suportado pelo detect-terminal
  1. Verifique se reiniciou o OpenCode:

Após modificar o arquivo de configuração, o OpenCode deve ser reiniciado para que as alterações tenham efeito.

Problema Comum 2: Detecção de Foco Imprecisa no macOS

Sintoma: A notificação ainda aparece quando o terminal está em primeiro plano, ou não aparece quando o terminal está em segundo plano.

Possíveis Causas:

  1. Nome do processo não corresponde:

Verifique se há o nome do processo do seu terminal na tabela de mapeamento:

typescript
const TERMINAL_PROCESS_NAMES: Record<string, string> = {
    // ... verifique se seu terminal está na lista
}
  1. Falha na execução do osascript:

Teste manualmente no terminal:

bash
osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true'

Deve retornar o nome do aplicativo atualmente em primeiro plano (ex: Ghostty).

  1. Sensibilidade a maiúsculas/minúsculas:

O código-fonte usa comparação sem distinção entre maiúsculas e minúsculas:

typescript
return frontmost.toLowerCase() === terminalInfo.processName.toLowerCase()

Certifique-se de que o nome do processo na tabela de mapeamento corresponda ao nome real do processo em termos de capitalização.

Problema Comum 3: Configuração Manual Inválida no Windows/Linux

Sintoma: Configurou "terminal": "xxx" no Windows/Linux, mas a detecção ainda falha.

Explicação:

A detecção de terminal do Windows/Linux depende da biblioteca detect-terminal, e a funcionalidade de substituição de configuração é implementada de forma cross-platform no código-fonte. Se a configuração for inválida, as possíveis causas são:

  1. Nome do terminal incorreto: Certifique-se de usar um nome suportado pelo detect-terminal
  2. Terminal não na lista de suporte: Veja a lista completa do detect-terminal

Nota: Windows/Linux não suportam detecção de foco e clique para focar, mesmo com configuração correta, afeta apenas a detecção de terminal, não habilitando essas funcionalidades.

Problema Comum 4: Detecção Incorreta em Cenário de Terminal Aninhado

Cenário: Usando Alacritty dentro do tmux, desejando identificar como tmux.

Sintoma: A detecção automática identifica como "alacritty", mas você deseja identificar como "tmux".

Solução:

Configure manualmente "terminal": "tmux":

json
{
  "terminal": "tmux"
}

Nota: Após essa configuração, o plugin assumirá que você está usando o tmux e não realizará detecção de foco (conforme o fluxo de trabalho do tmux).

Resumo da Lição

A detecção de terminal é a base da funcionalidade de filtragem inteligente do opencode-notify:

  1. Fluxo de Detecção: Detecta automaticamente o terminal através da biblioteca detect-terminal ao iniciar, armazenando o resultado em cache
  2. Processamento Especial do macOS:
    • Tabela de mapeamento de nomes de processo (TERMINAL_PROCESS_NAMES)
    • Obtenção dinâmica de Bundle ID (via osascript)
    • Detecção de foco (consulta de processo de aplicativo em primeiro plano)
  3. Substituição de Configuração: Especificação manual do tipo de terminal tem prioridade sobre a detecção automática
  4. Diferenças de Plataforma:
    • macOS: Funcionalidade completa (notificação + detecção de foco + clique para focar)
    • Windows/Linux: Funcionalidade básica de notificação
  5. Tratamento de Falha: Quando a detecção falha, não impede o envio de notificações, apenas desativa a filtragem inteligente
  6. Cenários Especiais: O fluxo de trabalho do tmux não suporta detecção de foco, evitando suprimir notificações importantes

Localizações-chave do Código-Fonte:

  • detectTerminalInfo(): Função principal de detecção de terminal (linhas 145-164)
  • TERMINAL_PROCESS_NAMES: Tabela de mapeamento de nomes de processo macOS (linhas 71-84)
  • getBundleId(): Obtenção dinâmica de Bundle ID (linhas 135-137)
  • isTerminalFocused(): Implementação de detecção de foco (linhas 166-175)

Prévia da Próxima Lição

Na próxima lição, aprenderemos sobre Uso Avançado.

Você aprenderá:

  • Dicas de configuração e melhores práticas
  • Configuração de ambientes multi-terminal
  • Recomendações de otimização de desempenho
  • Uso em conjunto com outros plugins OpenCode

Apêndice: Referência de Código-Fonte

Clique para expandir e ver a localização do código-fonte

Última atualização: 27/01/2026

FuncionalidadeCaminho do ArquivoNúmero da Linha
Função principal de detecção de terminalsrc/notify.ts145-164
Tabela de mapeamento de nomes de processo macOSsrc/notify.ts71-84
Obtenção de Bundle ID macOSsrc/notify.ts135-137
Detecção de aplicativo em primeiro plano macOSsrc/notify.ts139-143
Detecção de foco macOSsrc/notify.ts166-175
Encapsulamento de execução osascriptsrc/notify.ts120-133
Definição de interface de configuraçãosrc/notify.ts30-54
Detecção de foco no tratamento de conclusão de tarefasrc/notify.ts265
Detecção de foco no tratamento de notificação de errosrc/notify.ts303
Detecção de foco no tratamento de solicitação de permissãosrc/notify.ts326
Configuração de foco ao clicar no macOSsrc/notify.ts238-240
Detecção de terminal ao iniciar o pluginsrc/notify.ts364

Constantes-chave:

  • TERMINAL_PROCESS_NAMES: Tabela de mapeamento de nome de terminal para nome de processo macOS (linhas 71-84)
    • ghostty: "Ghostty"
    • kitty: "kitty"
    • iterm: "iTerm2" / iterm2: "iTerm2"
    • wezterm: "WezTerm"
    • alacritty: "Alacritty"
    • terminal: "Terminal" / apple_terminal: "Terminal"
    • hyper: "Hyper"
    • warp: "Warp"
    • vscode: "Code" / "vscode-insiders": "Code - Insiders"

Funções-chave:

  • detectTerminalInfo(config: NotifyConfig): Promise<TerminalInfo>: Função principal de detecção de terminal (linhas 145-164)

    • Prioriza substituição de configuração (config.terminal)
    • Chama biblioteca detect-terminal para detecção automática
    • Consulta tabela de mapeamento de nomes de processo
    • Obtém Bundle ID dinamicamente (macOS)
    • Retorna objeto completo de informações do terminal
  • isTerminalFocused(terminalInfo: TerminalInfo): Promise<boolean>: Detecta se o terminal está focado (linhas 166-175)

    • Verifica plataforma (apenas macOS)
    • Verifica se processName existe
    • Obtém aplicativo em primeiro plano (osascript)
    • Compara nomes de processo sem distinção de maiúsculas/minúsculas
    • Retorna true indicando terminal em primeiro plano
  • getBundleId(appName: string): Promise<string | null>: Obtém dinamicamente o Bundle ID do aplicativo macOS (linhas 135-137)

    • Usa osascript para consultar identificador do aplicativo
    • Retorna formato como "com.mitchellh.ghostty"
  • getFrontmostApp(): Promise<string | null>: Obtém o nome do aplicativo em primeiro plano do macOS (linhas 139-143)

    • Usa osascript para consultar System Events
    • Retorna nome do processo do aplicativo em primeiro plano
  • runOsascript(script: string): Promise<string | null>: Executa comandos AppleScript (linhas 120-133)

    • Verificação de plataforma (apenas macOS)
    • Usa Bun.spawn para executar osascript
    • Captura e retorna saída
    • Tratamento de exceções retorna null

Regras de Negócio:

  • BR-2-1: Usar biblioteca detect-terminal para identificar 37+ terminais (notify.ts:147)
  • BR-2-2: Tabela de mapeamento de nome de terminal para nome de processo macOS (notify.ts:71-84)
  • BR-2-3: Obtenção dinâmica de Bundle ID, sem hardcoding (notify.ts:135-137)
  • BR-2-4: Detecção de sessão tmux através de variável de ambiente TMUX (implementação da biblioteca de detecção)
  • BR-1-2: Suprimir notificação quando terminal estiver focado (notify.ts:265)
  • BR-1-6: macOS suporta clicar na notificação para focar o terminal (notify.ts:238-240)

Dependências Externas:

  • detect-terminal: Biblioteca de detecção de terminal, suporta 37+ emuladores de terminal
  • node-notifier: Biblioteca de notificações nativas cross-platform
  • macOS osascript: Ferramenta de linha de comando do sistema, usada para executar AppleScript