- Ao testar o OpenCode, agente de programação com IA de código aberto que recebeu 161 mil estrelas no GitHub, com o Qwen3.6-27B local, tanto a qualidade das ferramentas quanto o design de segurança estavam em um nível que justificava parar de usar
- Recarregar o
AGENTS.md, podar contexto por distância fixa, inserir a data atual e trocar de modo invalidam repetidamente o cache de prompt, de modo que até em um M4 Max pode levar até 10 minutos para começar a gerar uma resposta - Compactação de sessão, prompt de sistema, checagem de permissões, controle de subagentes e a TUI não se encaixam direito, causando perda de contexto e mensagens, e o sistema pode escrever código esquecendo especificações importantes
- O filtro de permissões baseado em Bash AST e padrões de string não consegue bloquear execução indireta, caminhos absolutos, variáveis, Python, redirecionamentos etc., e as restrições de acesso a arquivos externos e permissões permanentes também são facilmente contornadas
- Considerando a conexão padrão com modelos remotos, acesso irrestrito à internet e a antiga vulnerabilidade de RCE no servidor HTTP, Docker por si só não basta; é preciso bloquear executáveis, usar caminhos somente leitura e isolamento no nível do sistema operacional
Escopo da avaliação e premissas
- OpenCode é um projeto apresentado por seus criadores como um agente de programação com IA, e no momento da análise tinha 161 mil estrelas no GitHub
- O teste foi feito com o LLM local Qwen3.6-27B e a versão Git
baef5cd4do OpenCode - Em vez de ser uma divulgação formal de segurança, o texto examina como a camada de pipeline falha numa estrutura que envia a saída do LLM para o Bash
- O uso de LLM em si e a possibilidade de a máquina do usuário ser comprometida ou apagada com facilidade são tratados como questões separadas
Uma estrutura que quebra repetidamente o cache de prompt
- APIs da família OpenAI
/v1/chat/completionsenviam toda a conversa até então em JSON e respondem com um fluxo SSE delta com metadados JSON- Quanto mais longa a sessão, o custo de upload aumenta quadraticamente
- Chamadas de ferramenta usam dupla codificação, remontando vários deltas JSON novamente em JSON
- O servidor é stateless, mas faz cache dos resultados de avaliação por desempenho
- Procura o prefixo em cache mais longo que corresponda à requisição
- Faz prefill do fim desse prefixo até a última mensagem
- Gera novos tokens até o token de término
- Num M4 Max com cerca de 0,5 TB/s de largura de banda de memória, a geração de tokens do Qwen3.6-27B era utilizável, mas o prefill de contexto longo exigia muita computação
- Se não encontrar um cache de prefixo adequado, a GPU pode ficar em uso máximo e só começar a gerar resposta depois de cerca de 10 minutos
- O OpenCode faz glob no sistema de arquivos a cada turno SSE e relê o
AGENTS.mdinserido no primeiro prompt de sistema- Mesmo que se altere o
AGENTS.mdpara a sessão seguinte, toda a sessão atual é reavaliada
- Mesmo que se altere o
- Ao trocar do agente para o usuário, ele poda o contexto de chamadas de ferramenta, invalidando grandes trechos do cache
- Como descarta resultados de ferramenta mais antigos que
PRUNE_PROTECT = 40_000, mesmo no melhor caso ocorre um cache miss de 40 mil tokens - Como interrupções também são tratadas como troca para o usuário, corrigir um rumo errado descarta o cache e obriga a esperar de novo
- Como descarta resultados de ferramenta mais antigos que
- Como coloca a data atual no primeiro prompt de sistema e reavalia a cada turno SSE, ao passar da meia-noite ocorre um cache miss completo
Poda e compactação de sessão
- A poda é aplicada da mesma forma a todos os resultados de ferramenta, exceto
skill, e não protege separadamente materiais importantes lidos no início- Lê a especificação primeiro numa nova sessão
- Ao ler mais código relacionado, ultrapassa o limite de 40 mil tokens
- O modelo entra em raciocínios desnecessários ou segue uma direção errada, e o usuário interrompe
- A interrupção remove a especificação do contexto
- O modelo implementa sem conseguir mais consultar a especificação original
- A compactação de sessão (compaction) adiciona um novo prompt no início da sessão existente, faz prefill de tudo novamente e resume em alguns bullets
- Colocar o prompt de resumo no fim da sessão evitaria esse prefill completo
- Funcionou melhor fazer o próprio modelo escrever uma nota de handoff em arquivo, que também podia ser editada ou reutilizada em várias sessões
- A compactação é uma abstração com vazamento que faz a janela de contexto finita parecer infinita, e o problema piora quando usada junto com poda
- É melhor reconhecer a janela de contexto e o cache de prompt como restrições fundamentais e oferecer meios de gerenciá-los; a árvore de sessões do Pi faz uso intencional do cache de prompt
Prompt de sistema e modo Plan
- O prompt de sistema padrão é muito longo, e uma parte considerável dele é usada para mandar o modelo responder de forma concisa
- Também inclui preferências fortes de programação, como instruir subagentes a usar
ABSOLUTELY NO COMMENTS - A passagem de Plan para Build não é fluida, e se o planejamento ficar detalhado demais pode chegar perto do fim da janela de contexto
- O autor prefere escrever o resultado da discussão em arquivo, editar e depois passar para uma nova sessão
- O aviso do modo Plan diz que não é possível escrever em nenhum diretório, mas na prática é possível escrever em
.opencode/plans- Houve falhas nos dois sentidos: escrever nesse diretório sem instrução e recusar a escrita mesmo quando solicitada explicitamente
- Não é possível modificar globalmente o prompt de sistema padrão, então é preciso copiá-lo por projeto
- Se apenas o prompt do modo Build for redefinido, mudar para o modo Plan causa um cache miss completo de prompt
- Prompts por modelo variam bastante em conteúdo e qualidade
- O Beast Mode para GPT-4, o1 e o3 instrui que, para entender pacotes e dependências de terceiros, é indispensável fazer verificação no Google
Fadiga de julgamento causada pela checagem de permissões
- Quando detecta acesso a arquivos fora do projeto por análise improvisada de strings, abre uma janela de permissão com
Yes,No,Alwayse pausa a execução até haver resposta- Não existe a opção
Neverpara continuar recusando esse tipo de ação no futuro
- Não existe a opção
- Quando um subagente tenta ler a saída de um script em
/tmpe se escolheNo, o agente encerra e o contexto da tarefa também se perde- Para preservar o andamento, às vezes surge a situação de ter de escolher
Yesaté para acessos externos indesejados
- Para preservar o andamento, às vezes surge a situação de ter de escolher
- Se pedidos de permissão se repetem e a única opção para manter a produtividade é
Yes, o usuário pode acabar aprovando também pedidos perigosos - A proteção padrão contra escrita fora do diretório não deveria depender da atenção humana contínua
Interação entre mensagens e subagentes
- Mensagens enviadas durante streaming SSE entram numa fila, mas não fica claro quando de fato são transmitidas
- O código parece enviá-las ao fim do turno de chamada de ferramenta, mas também houve casos em que a ferramenta passou para cadeia de raciocínio sem enviar a mensagem pendente
- Se o usuário interrompe, a mensagem sai do estado pendente e fica só no log, sem poder ser enviada; por isso é preciso uma segunda mensagem para iniciar um novo stream
- Em alguns casos, desfazer uma mensagem também não consegue removê-la do log
- Não é possível conversar diretamente com subagentes nem interromper seu progresso
- Se eles seguem um caminho errado, resta encerrar e perder contexto ou assistir ao consumo de tokens
- Parece que esse recurso existia no passado, mas hoje desapareceu
- Mesmo mencionando um subagente com
@mentionno chat principal, isso não funciona de forma útil e tampouco permite interrompê-lo
- Se uma chamada de ferramenta de um subagente falha, como quando o Qwen coloca chamadas de ferramenta na cadeia de raciocínio, ocorre um erro fatal e o contexto acumulado até ali se perde
- Reutilizar subagentes entra em conflito com o objetivo de dividir o trabalho em contextos pequenos
- Um subagente existente pode ser reutilizado para tarefas sem relação
- Ficar alternando entre o agente principal com contexto grande e subagentes provoca cache misses
- A interação para humanos pode ser rica, mas as opções oferecidas ao modelo deveriam ser menores
- Há também uma issue no GitHub relacionada ao comportamento dos subagentes
Design das ferramentas do agente
editfaz, por padrão, busca e substituição exatas de um trecho de texto que tenha correspondência única- Como o modelo consegue lembrar com precisão o conteúdo do arquivo, mas pode perder o número de linhas após várias edições, esse método é adequado
- A opção de substituição global causou várias correções subsequentes, e removê-la deixaria o design igual ao
editdo Pi
- A ferramenta
questionde múltipla escolha no modo Plan é mais incômoda do que simplesmente fazer perguntas em linguagem natural no prompt de sistema grepeglobpodem ser substituídos porbash, e de fato o modelo executagrepourgdentro do Bash- A intenção pode ser impedir que um agente somente leitura como
Exploreuse Bash - Isso se conecta ao problema de que é difícil determinar efeitos colaterais sem executar o comando Bash
- A intenção pode ser impedir que um agente somente leitura como
todocostuma ser útil, mas o modelo esquece de verificar os TODOs
TUI e qualidade da documentação
- A TUI do OpenCode usa cerca de 1 GB de RAM para renderizar texto
- No campo de entrada de mensagem, a quebra de linha com Shift+Enter não funcionava, e uma issue existente foi encerrada após a resposta “na minha máquina funciona”
- Quando mensagens longas quebram linha automaticamente, o campo de entrada e o cursor se movem, mas os caracteres da nova linha podem não aparecer
- Selecionar texto durante o streaming faz a rolagem automática cancelar a seleção
Ctrl-Cfecha a sessão imediatamente em vez de interromper o comando em execução- Pela convenção de shells interativos,
Ctrl-Cdeveria interromper o comando, eCtrl-Ddeveria encerrar a sessão quando não houver comando em execução
- Pela convenção de shells interativos,
- Não há suporte a atalhos comuns de navegação por palavras, como Option+seta esquerda/direita no Mac
- Quando mensagens ou cadeia de raciocínio ficam longas, operações como rerenderização de Markdown levam vários segundos, com um problema de desempenho que parece ter complexidade quadrática
- Por causa dos problemas de entrada, era preciso escrever a mensagem num editor externo e colar
- A documentação é inconsistente e parece mais feita para ser lida por modelos do que por pessoas
Conexão remota por padrão e exposição de dados
- O OpenCode se conecta por padrão a modelos remotos
- A documentação não traz um exemplo simples de configuração de modelo local, e um erro de configuração leva à conexão com modelo remoto
- Mesmo especificando corretamente um modelo local, após iniciar o programa ainda é preciso escolhê-lo de forma interativa, e até lá o modelo remoto e o shell local já estão conectados
- A URL do modelo padrão não fica fixa na distribuição: ela é baixada do models.dev, ligado ao OpenCode
- O código relacionado está em
opencode/src/provider/provider.ts, linha 1684
- O código relacionado está em
- Depois de instalar do zero, bastam executar
opencode, digitar um caractere e apertar Enter para que um modelo remoto possa se conectar ao shell local sem nenhuma configuração do usuário - Se a primeira mensagem estiver vazia ou ambígua, o modelo agente frequentemente faz glob no diretório atual e lê arquivos, e os dados lidos entram na requisição POST seguinte
Acesso à internet e prompt de sistema
- O OpenCode fornece a ferramenta
WebFetche o prompt de sistema instrui explicitamente o seu uso - O prompt padrão permite usar URLs presentes na mensagem do usuário ou em arquivos locais e, de forma ambígua, também permite gerar ou adivinhar URLs se o modelo tiver confiança de que sejam URLs úteis para programação
- Como o Bash não tem sandbox de rede, um problema ainda maior que o
WebFetché a estrutura assumir que o modelo não executará comandos comocurl | bash
Como contornar o filtro de permissões do Bash
- Em
opencode.json,"bash": {"git *": "deny"}bloqueiagit statusouecho hello && git push --force - A implementação usa a gramática Bash·PowerShell do tree-sitter para analisar o comando em AST, percorre nós de comando e compara com regex criadas a partir da configuração
- Porém, checagens baseadas em texto permitem várias formas de execução indireta
echo 'git clean -fdx .' | bashenv git status- usar alias para ligar
gita outro nome de comando /usr/bin/git status,$(which git) statusGIT=git && $GIT status- decodificar em Base64 um
git reset --harde enviá-lo ao Bash git push --forcedentro de um heredoc- executar
git checkout .via Pythonsubprocess.run
- Mesmo que o modelo normalmente não seja malicioso, ele é treinado para contornar falhas de forma persistente, então pode naturalmente agir como entrada adversarial
- Filtros de comando por string não são um mecanismo de segurança, e sim uma falsa sensação de proteção
Permissões permanentes e exceções de CWD
- Se o usuário escolhe
Alwaysparapython3 -c 'print("hello")', todo o prefixopython3fica permanentemente liberado- Depois disso, um comando Python que leia uma chave privada SSH também pode ser tratado como já aprovado
- As permissões são salvas em disco e permanecem em sessões futuras
cd,chdir,popd,pushd,push-location,set-locationestão numa lista de exceções de CWD assumidas como sem efeitos colaterais- Esses comandos contornam explicitamente a checagem de permissões, mesmo se a configuração estiver definida para negar todos os comandos Bash
Brechas na verificação de acesso a arquivos
- A configuração padrão tenta bloquear acesso a arquivos fora do menor caminho entre o diretório em que o OpenCode foi iniciado e o repositório Git
- Na ferramenta Bash, ele percorre a AST do tree-sitter para interpretar e verificar valores que pareçam caminhos
cat /tmp/logfilepede permissãopython3 -c 'import shutil; shutil.rmtree("/")'não é detectado
cargopode ler, escrever e executar livremente em~/.cargo, mas se o modelo tentar ler diretamente o código-fonte de um pacote em~/.cargo/registry/src, aí a permissão é exigida- Os comandos considerados capazes de acessar arquivos ficam limitados a uma lista fixa chamada
FILES- Ela inclui
rm,cp,mv,mkdir,touch,chmod,chown,cate alguns comandos do PowerShell - Comandos fora da lista são tratados como se não acessassem arquivos, então os caminhos passados a eles não são verificados
- Ela inclui
Combinação de redirecionamento com comandos permitidos
- Se o usuário escolhe
Alwaysparaecho "hello world!", depois ficam liberadas também escritas em arquivos ou dispositivos usandoecho- Isso inclui comandos com redirecionamento para caminhos como
/sys/class/gpioligados a GPIO
- Isso inclui comandos com redirecionamento para caminhos como
- Na AST de
echo foo > bar.txt,redirectionnão é filho decommand, mas nó irmão- A verificação de caminho olha apenas os filhos de
command, então o destino do redirecionamento não é verificado - O próprio
echotambém não está na listaFILES, então a validação de caminho nem começa
- A verificação de caminho olha apenas os filhos de
Autoatualização e casos de execução remota de código
- O OpenCode tem vários caminhos de autoatualização, e ao executar
opencode upgradenuma instalação via curl ele baixa a resposta dehttps://opencode.ai/installe a executa na entrada padrão do Bash - Isso não difere tanto do risco assumido ao usar o instalador via curl, mas continua sendo um caso de executar script remoto diretamente em produção
- Na época do CVE-2026-22812, o OpenCode expunha no servidor HTTP padrão os seguintes recursos
- cabeçalhos CORS totalmente permissivos
- uma API POST para executar comandos arbitrários de shell
- uma API GET para ler arquivos arbitrários
- Um site visitado pelo usuário podia enviar requisições para a porta padrão conhecida e obter acesso ao sistema no nível de permissões do usuário
- A equipe respondeu desativando o servidor por padrão e dizendo que era necessária uma exceção de CORS para permitir que
opencode.aiexecutasse código remoto na máquina; depois não houve acompanhamento, e a issue foi encerrada pelo stale bot - Outra issue relatou que o comando de autenticação buscava e executava conteúdo de uma URL arbitrária fornecida pelo usuário; ela também foi encerrada pelo stale bot
Por que Docker não resolve sozinho
- O autor não quer uma abordagem que torne a instalação de dependências de desenvolvimento tão complexa numa máquina nova a ponto de depender de Docker
- O próprio Docker também pode criar problemas de segurança
- cria um serviço poderoso executado como root
- abre deliberadamente passagens no firewall
ufw
- Se todos os dados a proteger estão dentro do contêiner e o shell local interno tem acesso à internet, o escopo de proteção fica indefinido
- Se o objetivo é impedir exclusão recursiva do sistema de arquivos raiz, há mecanismos mais diretos no sistema operacional, como Landlock, Seatbelt, Restricted Tokens
- Segurança de agentes de programação não deveria ser algo terceirizado para um contêiner, e sim a maior prioridade do harness
- Bloquear Git deveria significar bloquear o executável
git, não a string do comando - O diretório
.gitdeveria ser somente leitura - Em vez de higienizar comandos Bash como texto, deveria haver isolamento nativo do sistema operacional
- Bloquear Git deveria significar bloquear o executável
Experiência de uso com LLM local
- Modelos locais como o Qwen3.6-27B também podem prejudicar a estabilidade e a consistência conceitual de uma base de código como modelos de fronteira, mas há três diferenças
- há menos “vale da estranheza” entre parecer inteligente e agir de forma burra; os limites são mais claros, então é mais fácil ajustar a interação
- a quantidade de pesos é pequena demais para reproduzir diretamente os dados de treino, o que muda a avaliação sobre contaminação da saída
- não é necessário apoiar ou depender de um provedor de nuvem
- O autor obteve bons resultados em tarefas de busca centradas na entrada, fornecendo código, sintomas e causas estimadas, lendo o código relacionado e exigindo caminhos de chamada e citações de código
- delimitar o escopo como problema de busca ajuda a reduzir a tendência do modelo de inventar fatos
- Geração de código derruba repetidamente o planejamento de arquitetura
- o modelo pega atalhos, como mover estado mutável para o meio de uma estrutura projetada para ser compartilhada por vários componentes
- o problema vai além de não ter sido escrito diretamente pelo autor; ele prejudica a própria capacidade de entender o código
- Tirar respostas diretamente do conhecimento dos pesos do modelo causa alucinações mesmo em modelos com trilhões de parâmetros
- Para que LLMs virem ferramentas comuns, o software ao redor precisa aplicar de fato engenharia de sistemas para eliminar lacunas de segurança, e esse trabalho precisa ser feito por pessoas
1 comentários
Comentários no Hacker News
Um título melhor para este texto seria algo como “pequenos incômodos que, se corrigidos, melhorariam o OpenCode”
Reler
AGENTS.mdtoda vez ou ter falha no cache de prompt por causa de mudança de data é algo tolerávelO problema de compressão e poda não funcionar direito também já apareceu no Codex e no Claude, e o prompt de sistema padrão também existe por consistência, então, se não gostar, dá para mudar
Estabilidade, desempenho e uso de memória também pioraram, e embora eu gostasse do OpenCode antes, é difícil considerá-lo um software bem escrito
Agora substituí tudo por Pi, e já existem várias opções novas que aprenderam com o OpenCode e aplicaram um design mais contido onde necessário
Agora não fazemos mais poda de chamadas de ferramentas, mas, para continuar a mesma tarefa por muito tempo com uma janela de contexto limitada, é preciso resumir o progresso atual, então a compressão continua sendo um mal necessário por enquanto
O V2, atualmente em beta, inclui uma nova forma de manter atualizadas instruções de sistema que mudam, como
AGENTS.mde as tecnologias disponíveis, evitando ao máximo falhas de cachehttps://x.com/kitlangton/status/2075749116760457346/video/1
Há uma seção separada, “Alarming Things”, que também inclui uma subseção chamada “It’s Fucking Full of RCEs”, e há várias vulnerabilidades de execução remota de código além das causadas pelos problemas mostrados na seção anterior
O texto organiza bem os riscos dos CLIs com agentes, mas o título focado só no OpenCode é estranho por dois motivos
Primeiro, não propõe uma alternativa clara. Como muitos problemas são fundamentais, talvez seja necessário redesenhar e reescrever quase tudo do zero, então simplesmente sugerir correções para o OpenCode também não basta, mas não há nenhuma proposta construtiva, então no fim parece quase um texto dizendo “pare de usar LLMs”
Segundo, os principais problemas de “Alarming Things” não são exclusivos do OpenCode; também se aplicam ao Claude CLI e provavelmente a agentes de outros provedores de modelos de ponta
Ainda assim, tem grande valor como registro que incentiva a criação de ferramentas melhores desde o início, então pretendo salvar e compartilhar bastante, mas, por melhor que o texto seja, o título e o foco parecem ainda mais equivocados
Em especial, a reclamação de que
echo git | bashainda executa parece absurdaA frase “Se você não conhece o OpenCode, imagine uma bota pisando num rosto humano para sempre. A bota é feita de TypeScript e o rosto é tudo o que aprendemos sobre segurança e software de sistemas desde a invenção dos computadores eletrônicos na década de 1940” é candidata ao prêmio Bulwer-Lytton na categoria de metáfora forçada
O estilo do texto é excessivamente raivoso e duro
Concordo em geral com vários pontos, mas a partir do momento em que chama o OpenCode de “lixo turbo de carro de palhaço com postura de segurança nível ‘papai, eu me abaixo para você’” e manda todo mundo parar de usar, perde minha vontade de ler
Esse software também foi feito por pessoas comuns, e não sei desde quando atacar open source desse jeito virou algo normal; isso me faz pensar em como eu me sentiria se um software meu recebesse esse tipo de avaliação
Até no antigo
comp.lang.lisphavia quem se divertisse rebaixando pessoas por escreverem código abaixo dos padrões da torre de marfim; alguns foram embora, e outros aceitaram isso como se fosse uma medalha, achando por engano que eram broncas necessárias para melhorarDiscussão antiga relacionada no HN: https://news.ycombinator.com/item?id=587045
Parece que não entendem o quanto essa retórica é prejudicial tanto para os desenvolvedores atingidos quanto para quem normaliza esse comportamento
python3acima” foi engraçadaPor causa da stack tecnológica dos clientes, uso Claude Code, e em projetos pessoais usei uma versão específica do OpenCode; como o OpenCode era muito melhor, este texto me deixou triste
Todas as anomalias que eu tinha visto até agora e ignorado batem com o texto, que inclusive explica a causa. Tirando os exageros e as partes com que não concordo emocionalmente, no geral faz sentido, então acho que vou precisar procurar outra ferramenta de execução
Gostaria de recomendações sobre se a arquitetura do Pi é realmente melhor, ou se existe alguma alternativa ainda melhor
Independentemente dos defeitos, depois de usar várias ferramentas, foi no OpenCode que tive a maior produtividade
A maior parte do que o texto cita são pequenos incômodos ou diferenças de opinião, e, em especial, ele entendeu de forma completamente errada o objetivo da filtragem de comandos. Isso não é um mecanismo de segurança, mas um mecanismo para orientar o comportamento do modelo
Não parece que o autor realmente construiu algo com o OpenCode e, se usou, não tratou em nenhum momento daquilo que mais importa: a qualidade do resultado
Em especial, dá para usar facilmente o modo de planejamento e terminar o trabalho rápido
Depois de mudar do OpenCode para o Pi, o desempenho das chamadas de ferramenta melhorou bastante e também parece haver menos bugs
O OpenCode também parece ter sumido de https://openrouter.ai/apps/category/coding
Pelo que lembro, um deles permite ativar a confirmação nas configurações e o outro precisa de plugin
Esse comportamento aumenta ainda mais o risco de ataques à cadeia de suprimentos
É absurdo que um app desktop TUI que só mostra texto seja mais pesado do que apps nativos e até do que a maioria dos apps desktop baseados em navegador, desperdiçando RAM, CPU, energia e bateria
Estou desenvolvendo em C++ Qt6 minha própria ferramenta de execução de IA que também funciona como app de chat, e mesmo com subagentes, diff de código, emulador de terminal, editor simples, pré-visualização de Markdown, fundo translúcido, temas do usuário, permissões, MCP, integração com Git, sistema de docking e abas de projeto, ela continua mais leve que outras ferramentas
Ainda não publiquei porque estou eliminando alguns bugs e simplificando e refinando a UI: https://zeteo.krysoph.com/preview.html
Só agora descobri que o OpenCode apagava comentários por causa do “Use ABSOLUTELY NO COMMENTS” no prompt de sistema padrão, e isso me irrita muito
Mas, mais do que um incômodo menor, o risco de segurança também se aplica a outras ferramentas de execução. Essas ferramentas têm acesso a enormes volumes de dados, são atualizadas quase diariamente e, por sua natureza de vibe coding, é bem provável que ninguém esteja auditando direito as inúmeras dependências npm que elas puxam
Basta um caso como o do
left-padacontecer uma vez para virar um desastre em toda a cadeia de suprimentosColocar a data no prompt de sistema para invalidar o cache à meia-noite é uma decisão razoável, e a maioria das outras ferramentas de execução também usa esse mesmo método
Colocar a data e a hora completas seria irresponsável, mas o OpenCode não faz isso
Isso poderia ser resolvido facilmente avaliando a data só uma vez por sessão, ou apenas uma vez a cada execução do binário
opencode, para evitar que sessões longas demais fiquem presas em uma data antiga