O blog tem bastante conteúdo sobre software, Python e hardware embarcado. Mas há um lado que nunca apareceu por aqui: o ambiente de trabalho em si. Este é o primeiro relato sobre o setup com o compositor Wayland niri e o DankMaterialShell — e começa pelo primeiro plugin criado do zero para esse ambiente.
A motivação foi simples: queria ver no painel a versão do kernel em uso e o tempo de uptime do sistema. Sem abrir terminal, sem script externo. Só um widget discreto na barra mostrando 6.19.6-arch1-1 ⏱ 7h 54m.
O que parecia ser coisa de meia hora revelou algumas camadas de surpresa que valem ser documentadas.
O ambiente
O setup é um HP 250 G9 rodando EndeavourOS com o compositor Wayland niri. A barra e o shell visual são fornecidos pelo DankMaterialShell (DMS) v1.4.3, um projeto baseado em Quickshell que expõe uma API de plugins em QML — a mesma linguagem usada no Qt. O DMS cuida de tudo: barra de tarefas, notificações, applets de rede, áudio, bluetooth.
O sistema de plugins funciona com uma pasta em ~/.config/DankMaterialShell/plugins/ contendo um manifesto plugin.json e o componente QML principal. O DMS carrega e injeta o widget na barra automaticamente.
A ideia
Para exibir o kernel, uname -r resolve na hora. Para o uptime, a primeira opção óbvia seria uptime -p, mas esse comando traz um prefixo “up” e varia conforme a locale do sistema. A alternativa mais sólida é ler direto de /proc/uptime, que contém os segundos de uptime desde o boot como um número puro, e processar via awk.
A lógica ficou assim:
| |
A saída é adaptativa: 3d 2h 15m quando há dias, 5h 42m quando não, 38m nos primeiros momentos após o boot. Sem prefixos desnecessários, sem zeros que não acrescentam nada.
Estrutura do plugin
O manifesto é direto:
| |
O componente QML usa Process do Quickshell para executar os comandos e capturar a saída, e um Timer para atualizar o uptime a cada 60 segundos:
| |
Parece simples. E é — quando se sabe o que usar. Chegar nesse código final levou algumas tentativas.
O que deu errado primeiro
A primeira versão usou SplitParser como coletor de stdout, que aparece em alguns exemplos online de Quickshell. O DMS rejeitou na hora:
SplitParser is not a type
Trocando para StdioCollector com o sinal onStreamEnded, o erro mudou:
Cannot assign to non-existent property "onStreamEnded"
Tentando onDone, mesmo resultado. A documentação oficial do Quickshell não cobre esses detalhes com clareza, e a versão empacotada no DMS nem sempre corresponde aos exemplos mais recentes que aparecem em buscas.
A solução foi simples mas não óbvia: procurar como o próprio DMS usa esses tipos internamente.
| |
O retorno foi imediato:
| |
O sinal correto é onStreamFinished. Não está na documentação de forma destacada, mas está no código que já funciona em produção. Essa é a fonte mais confiável quando a documentação fica vaga.
O problema de cache
Após corrigir o arquivo, o DMS continuava reportando o erro antigo. Verificar o arquivo mostrava o conteúdo correto — mas o erro no log ainda apontava para a versão antiga, inclusive com o número de linha original.
O DMS mantém cache agressivo. Nem dms ipc call plugins reload nem dms restart foram suficientes para limpar. A solução foi parar o serviço de verdade:
| |
PLUGIN_ENABLE_SUCCESS: sysinfo
O resultado
O widget apareceu na barra exatamente como planejado, com kernel e uptime lado a lado, atualizando automaticamente a cada minuto. Sem daemon externo, sem polybar, sem script em cron. Tudo dentro do ecossistema niri + DMS + Quickshell.

O que ficou de aprendizado
O principal atalho para desenvolver plugins no DMS é usar o próprio código-fonte do shell como referência. Quando um tipo ou sinal não se comporta como o esperado, grep -r em /usr/share/quickshell/dms/ resolve mais rápido do que qualquer busca externa — o código que já funciona em produção mostra exatamente como os tipos são usados nessa versão específica.
O segundo ponto é sobre o cache: alterações em arquivos QML não são suficientes para recarregar o estado do Quickshell em memória. Para desenvolvimento iterativo, um systemctl --user restart dms limpo (com cache deletado) evita muita confusão.
E sobre o uptime em si: /proc/uptime é mais confiável do que uptime -p para scripts, porque não depende de locale nem de formatação variável entre distribuições. O número bruto em segundos e um pouco de awk resolvem com mais controle.
