TL;DR: A Linear lançou um agente de IA integrado. Legal, mas não resolve o problema dos desenvolvedores que trabalham com coding agents no terminal. O que precisamos não é outro agente, mas sim uma CLI robusta que o agente que já temos possa usar. E se for para construir, que seja em Rust — por isso nasceu lql, uma CLI para Linear projetada para agentes.
Ontem, a Linear anunciou seu agente de IA. Um chatbot integrado ao app que entende seu roadmap, seus issues e seu código. Você conversa com ele no Slack, o menciona em um comentário, e ele sintetiza contexto, sugere ações e até cria issues para você.
Parece ótimo. Sério, parece ótimo.
E, ainda assim, ao ler o anúncio, a primeira coisa que pensei foi: “não é isso que eu precisava”.
A odisseia Linear
Para entender por que digo isso, você precisa de contexto. Minha relação com a Linear é uma história de amor e ódio digna de uma novela mexicana.
Ato 1: o MCP. A Linear tinha um servidor MCP para que os agentes de IA interagissem com ele. Funcionava como um fósforo ao vento: tecnicamente acendia, mas a chama apagava em questão de segundos. Intermitente, lento, e com um talento especial para falhar no exato momento em que você precisava. Eu desinstalei.
Ato 2: a API GraphQL. A alternativa era interagir com a Linear diretamente via GraphQL. E funciona, claro. Até o momento em que você tenta adicionar caracteres especiais à descrição de um issue, e a necessidade de escaping faz você questionar suas escolhas de vida. Uma vez levei mais tempo lidando com a forma correta de escapar um parêntese do que para escrever o código do issue que o parêntese deveria descrever.
Ato 3: a CLI da Linear. E então chegou a linear CLI, um projeto da comunidade. brew install schpet/tap/linear e pronto. Uma ferramenta modesta, sem pretensões, que fazia exatamente o que eu precisava: criar, listar e atualizar issues diretamente do terminal, sem brigar com GraphQL, sem MCPs fantasmas, sem popups.
Escrevi um post inteiro aposentando ferramentas graças a esta CLI. Criei 49 issues em menos de um minuto com um script Bash. Com o MCP teria levado uma hora e meia.
Entra o Agente
E agora a Linear lança seu agente. A promessa: um assistente integrado que entende seu workspace, conecta com seu código e automatiza fluxos de trabalho.
Preste atenção: sabe o que o agente não faz? Funcionar no terminal. Não é uma ferramenta para seu agente de IA. É um agente da Linear que vive dentro do app da Linear.
Se você trabalha com Claude Code, Codex ou qualquer outro coding agent no terminal, o agente da Linear não te ajuda em nada. Seu agente não pode invocar o agente da Linear para criar um issue. Ele não é composível. Não é uma peça de Lego que se encaixa no seu fluxo. É um produto fechado dentro de outro produto fechado.
Ou seja: a Linear construiu um agente para product managers que trabalham dentro do app da Linear. Não para desenvolvedores que trabalham no terminal com agentes de IA.
Você já tinha seu agente
Aqui está a epifania que tive ao ler o anúncio: eu já tinha um agente para Linear. Ele se chama Claude Code.
Eu não preciso que a Linear coloque um chatbot dentro do seu app. Eu preciso que a interface programática da Linear não seja uma gambiarra. Que eu possa dizer ao meu agente “crie um issue com esses dados” e que funcione. Sempre. Sem drama.
E isso é exatamente o que uma CLI bem-feita oferece. Meu agente — Claude Code — já sabe usar o terminal. Já sabe executar comandos. Já sabe interpretar output. Tudo o que ele precisa é de uma ferramenta confiável do outro lado.
Você diz ao Claude Code “crie um issue na Linear com prioridade alta”, e ele executa um comando no terminal. Dá certo. Próxima tarefa. Sem chatbot. Sem interface gráfica. Sem Slack. Um comando, um resultado.
O futuro é a CLI (por incrível que pareça)
Aqui vem a opinião contundente: num mundo onde todos estão construindo agentes de IA com interfaces conversacionais dentro de seus apps, o futuro para desenvolvedores é, paradoxalmente, a command-line interface.
Por quê? Porque a CLI é a interface universal entre agentes. Seu coding agent não pode clicar em botões. Não pode navegar por uma webapp. Não pode usar um chatbot dentro de outro app. Mas pode executar um comando e ler o output.
A CLI é a API mais democrática que existe. Não precisa de SDK, não precisa de autenticação OAuth com quinze redirects, não precisa de um MCP que cai toda terça-feira. Um binário, algumas flags, stdin/stdout. O Unix está há 50 anos nesse modelo porque funciona.
O problema é que a maioria das CLIs de ferramentas SaaS são uma ideia tardia. Um pensamento secundário. “Ah, eles também precisam de uma CLI? Então peça para algum estagiário colocar um wrapper na API REST.” E é assim que você acaba com ferramentas que geram JSON ilegível, não têm autocompletar, falham silenciosamente ou requerem um token que expira a cada 37 minutos.
500 erros que ninguém viu
Mas antes de falar em reescrever algo, eu queria dados. Não intuições — dados. Então, fiz algo que só alguém com um LLM com milhões de tokens de contexto faria: pedi ao Claude Code que analisasse suas próprias sessões passadas e extraísse todas as vezes que ele falhou ao interagir com a Linear.
165 sessões. 11 projetos. Meses de histórico. E o resultado foi… revelador.
500+ erros. 370+ tentativas de correção. Uma estimativa conservadora de 700.000 tokens por mês desperdiçados tentando interagir com a Linear.
Os erros se agrupam em categorias que causam vergonha quando listados juntos:
O clássico: --sort esquecido. A CLI da Linear exige --sort priority em todo comando list. Não tem padrão. Se você esquecer, erro. Claude esqueceu 40 vezes. Quarenta. O mesmo erro. Várias vezes. Sem aprender.
O tradutor: estados da UI vs CLI. Na interface da Linear, você vê “Todo”, “In Progress” e “Done”. Na CLI, são unstarted, started e completed. Claude usou os nomes da UI 12 vezes. --state "Todo" → erro. --state "In Progress" → erro. Sempre o mesmo problema.
O otimista: flags inexistentes. --status em vez de --state (11 vezes). --priority urgent em vez de --priority 1 (17 vezes). --no-pager em comandos que não suportam (15 vezes). --comment em update (11 vezes — deveria ser um subcomando separado). --filter, --query, --label em list — nenhum existe. Claude os inventava por analogia com git ou gh, e o erro nunca era evidente.
O assassino silencioso: ausência de --no-interactive. 64 vezes Claude executou linear issue create sem --no-interactive, e o comando ficou travado esperando input do teclado. Sem mensagem clara de erro. Apenas… silêncio. E, depois de dois minutos, timeout.
O pesadelo: JSON/GraphQL mal escapado. Quando a CLI falhava e era necessário recorrer diretamente à API GraphQL, descrições com markdown produziam JSON quebrado. Aspas, backticks, quebras de linha — cada um desses caracteres podia quebrar a query. 25 erros de escapamento, cada um com 3-5 tentativas de correção enquanto Claude tentava resolver. 80+ comandos desperdiçados só nessa categoria.
O zumbi: o team desativado. O team TOK foi desativado quando consolidamos de 12 times para 5. Claude continuou usando --team TOK durante 97 comandos adicionais, até falhar com “Could not modify retired team”. Documentar na memória ajudou, mas não resolveu completamente.
E o grand finale? 171 chamadas ao MCP da Linear — que já estava desinstalado. Em 4 projetos distintos, Claude seguia tentando utilizá-lo. Eu precisei escrever literalmente: “o MCP da Linear é uma porcaria, use a API”.
Como o lql resolve cada problema
Não basta reclamar. Cada erro tem uma solução prática:
| Erro | Frequência | Solução no lql |
|---|---|---|
--sort esquecido | 40+ | Padrão priority. lql list funciona sem argumentos. |
--state "Todo" | 12+ | Alias automático. Todo → unstarted, Done → completed. |
--priority urgent | 17+ | Alias automático. urgent → 1, high → 2. |
--no-interactive ausente | 64 | Não há modo interativo. Nunca trava. |
| JSON mal escapado | 25+ (80+ retries) | Variáveis GraphQL nativas. JSON construído com tipos, não com strings. |
--no-pager onde não serve | 15+ | Nunca usa pager. Flag ignorado se passado. |
--status vs --state | 11+ | Alias de flag. --status é normalizado para --state. |
--comment em update | 11 | Subcomando separado: lql comment PROD-587 "texto". |
| Team desativado (TOK) | 97+ | Configuração fixa com teams ativos. Erro claro: “TOK está desativado, use PROD”. |
| Labels inventados | 10+ | Validação contra API. lql labels para ver os reais. |
| MCP da Linear | 171 | Não existe. Lql é a única interface. |
A chave: o LLM não precisa lembrar de nada. Não há flags obrigatórios para esquecer. Não há nomes internos para memorizar. lql list funciona. lql create "Corrigir bug" --priority urgent funciona. lql update PROD-587 --state Done funciona. A ferramenta se adapta ao usuário, não o contrário.
Se for para reescrever, que seja em Rust
E aqui é onde a história toma um rumo que ninguém esperava (ou que todo mundo esperava, se me conhece bem).
Se a CLI é a interface crítica entre seu agente e seu issue tracker, então essa ferramenta merece ser escrita com carinho. Com uma linguagem que não permita compilar código ruim. Com tratamento de erros de verdade. Com um binário estático que não precise de um runtime do Node ou Python.
Vamos com tudo: se vamos reescrever algo, que seja em Rust.
E aqui não posso evitar a piada. O projeto se chama lql — Linear Query Language. Assim como o SQL é o idioma para consultar bancos de dados, o lql é o idioma para consultar seu backlog. E como todo projeto que se preze em 2026, ele é escrito em Rust.
Isso significa que Ferris — a mascote do Rust, o caranguejo mais famoso no mundo do software — aprova. Mas sempre que ouço “Ferris”, penso em Curtindo a Vida Adoidado, o garoto dos anos 80 que matava aula com criatividade admirável. E uma boa CLI faz exatamente isso: permite que você “mate aula” da interface gráfica. Pule o app. Vá direto ao ponto.
Ferris Bueller’s Day Off, mas para seu issue tracker. O caranguejo tira folga da GUI.
O que o lql precisa fazer
Não é uma reescrita completa do CLI da Linear. É uma CLI opinada, projetada para que um coding agent a use com confiabilidade:
| O que eu preciso | Por quê |
|---|---|
lql create "Corrigir auth" com descrição em stdin | Nada de escapamento. Sem batalhas com strings |
| Output compacto, uma linha por issue | Meu agente precisa ler a resposta sem gastar 7.000 tokens |
| Erros tipificados e códigos de saída claros | exit 1 não serve. É auth? É limite de requisição? É entrada inválida? |
| Tolerância de interface | --status Done funciona, mesmo se o flag real for --state completed |
| Binário estático sem dependências | cargo install e pronto. Um único binário em ~/.local/bin/ |
Nada disso é revolucionário. É o básico que uma CLI deveria oferecer. Mas quando você olha para as CLIs existentes de ferramentas SaaS, percebe que “o básico” é surpreendentemente raro.
A lição
A Linear construiu um agente de IA impressionante. Sério, a “Code Intelligence” que analisa sua base de código e diagnostica funcionalidades parece incrível. Mas é um agente para humanos que trabalham dentro da Linear.
Se você trabalha com um coding agent no terminal, não precisa de outro agente. Precisa de uma ferramenta sólida que seu agente possa usar. E essa ferramenta, por incrível que pareça em 2026, é uma CLI.
A ironia é deliciosa: enquanto todos correm para construir agentes que falam em linguagem natural, a interface mais útil para os próprios agentes continua sendo a que Thompson e Ritchie inventaram nos anos 70. Flags, argumentos, códigos de saída. Zero ambiguidade.
E se essa CLI vai ser a peça crucial entre seu agente e o mundo exterior, merece ser escrita em uma linguagem que não permita construir gambiarra.
Ah, um dado: a CLI oficial da Linear pesa 157 MB (Node.js embutido). lql pesa 4.7 MB. Um binário estático, 33 vezes menor, sem runtime. É isso que acontece quando você não carrega um interpretador JavaScript para executar curl.
Ferris o caranguejo aprova esta mensagem. 🦀
Série: Adversarial Programming