13/Documentation
Segurança: leia antes de executar
O que o Collie expõe, as defesas e o pareamento de dispositivos: a credencial para cada requisição
O Collie fornece acesso remoto via shell à sua máquina por design. Uma única chamada de API do Collie envia pressionamentos de teclas arbitrários diretamente para um painel de terminal ativo. Qualquer dispositivo pareado por você pode ler todos os painéis (código-fonte, segredos, variáveis de ambiente, saída do agente) e executar comandos com o seu usuário. Desde a versão 1.18.0, toda requisição de API precisa do token de um dispositivo pareado, incluindo leituras; portanto, a porta de entrada é o próprio pareamento: qualquer pessoa que consiga acessar a URL e tenha um código de pareamento válido obtém o mesmo acesso. Antes da versão 1.18.0, qualquer pessoa que conseguisse acessar a URL podia ler todos os painéis.
Não há sandbox nem lista de permissões de comandos, pois filtrar comandos iria contra o propósito da ferramenta. Trate cada dispositivo pareado como um login de root, e um código de pareamento como uma senha. Revogue imediatamente um dispositivo perdido com collie devices revoke <label>. O pareamento reduz o risco, mas não o elimina; portanto, mantenha a URL em uma rede privada, como uma tailnet, nunca na internet pública.
Parear um dispositivo: a credencial de escrita
Desde a versão 1.18.0, esta é a credencial para cada requisição, leituras incluídas, não apenas para gravações.
# on the host — prints an 8-character code and a QR code, good for 10 minutes
bin/collie pairO pareamento está sempre ativo, e as leituras precisam do token de pareamento tanto quanto as gravações. Até que um dispositivo seja pareado, o Collie responde a qualquer celular e navegador com 403 device not paired. Execute collie pair primeiro, no host, antes de abrir o Collie no celular.
Abra o Collie no celular, acerte Configurações → Dispositivos pareados e digite o código com um rótulo para o dispositivo, ou escaneie o código QR exibido pelo comando para abrir diretamente nessa tela com o código já preenchido. O celular armazena o token retornado. O Collie guarda apenas o hash, e o token é exibido uma única vez. Não é necessário reiniciar o processo; o daemon em execução aplica pareamentos e revogações na requisição seguinte.
Os dois controles de dispositivo respondem a perguntas diferentes, e você pode usar qualquer um deles, ambos ou nenhum:
| pergunta | confia em | revogue | |
|---|---|---|---|
COLLIE_DEVICE_HEADER | este dispositivo está na lista do operador? | seu proxy, para injetar um nome que ele sanitizou | editando COLLIE_DEVICE_ALLOWLIST e depois reiniciando |
| pareamento | este dispositivo possui uma credencial que eu emiti? | nada na rede | collie devices revoke <label>: ao vivo |
O pareamento não requer infraestrutura extra. Ele se adapta a uma configuração direta de tailscale serve onde não existe proxy para injetar cabeçalhos.
O pareamento controla o acesso a cada rota /api, incluindo leituras. Apenas duas rotas ficam abertas: /api/health, consultada por um monitor ou balanceador de carga, e /api/pair, necessária para um dispositivo antes de reter um token. /api/health responde a versão do build, o modo de equipe e três contagens dos últimos sete dias (com que frequência a caixa de entrada foi lida como livre, com que frequência não pôde ser lida e com que frequência uma pessoa enviou dados manualmente ignorando uma tela que o Collie não conseguiu ler). As contagens não mencionam nenhum painel, nenhum texto e nenhuma pessoa.
O cabeçalho de dispositivo controla as gravações e duas leituras: o Visualização Files, que pode exibir todos os arquivos sob a pasta de um workspace, e o Browse da página New, que lista nomes de pastas sob a home (ADR 0086).
bin/collie devices list # what holds a credential, and when each was last seen
bin/collie devices revoke old-phone # effective immediately, no restartUma instalação limpa não tem nenhum dispositivo emparelhado, então o Collie não responde a nenhum telefone até você executar collie pair. Revogar o último dispositivo não abre o Collie novamente: todo dispositivo recebe device not paired. Para recuperar, execute collie pair no host e emparelhe o telefone novamente. collie doctor avisa enquanto nenhum dispositivo estiver emparelhado.
Nota. O link de crew e a standby door mantêm suas próprias credenciais. Um lead encaminha uma leitura para um membro via mutual TLS fixado e o segredo de crew, portanto um membro não precisa de um dispositivo emparelhado próprio (crew).
Cinco tentativas incorretas invalidam o código, o que exige executar collie pair novamente. Além disso, a bridge recusa mais de dez tentativas de emparelhamento por endereço de origem por minuto com 429 e Retry-After: 60. Atrás de uma front door na mesma máquina, o endereço de origem é a última entrada de X-Forwarded-For, aquela adicionada pela front door. De qualquer outro par, esse cabeçalho é ignorado. Os contadores ficam na memória e são redefinidos quando a bridge reinicia.
Leituras da própria CLI
A cada inicialização, a bridge grava um novo segredo aleatório em local-secret na sua pasta de estado. collie doctor e collie crew update o enviam para ler sua própria bridge na mesma máquina. O arquivo tem permissão exclusiva para o proprietário, portanto apenas a sua conta pode lê-lo, e uma parada limpa o remove. A bridge o aceita apenas para leituras, nunca para gravação ou para a visualização Files, e nunca a partir de outra máquina. Ela aceita o segredo apenas via loopback, e nunca em uma requisição que contenha o cabeçalho de um proxy, como X-Forwarded-For. Um membro de crew que vincula COLLIE_HOST ao seu endereço na tailnet não tem nada no loopback, portanto ali a bridge também o aceita a partir dos endereços desta própria máquina. Um relay TCP simples na mesma máquina, como socat ou ssh -L, ainda pode repassar o segredo. O arquivo é o que mantém o segredo protegido, portanto mantenha a pasta de estado com acesso exclusivo do proprietário.
Definir uma expiração para um dispositivo
Um dispositivo emparelhado mantém seu token até você revogá-lo. Para limitar isso, passe um tempo de vida ao emparelhar:
bin/collie pair --expires 30d # also 12h, 2w; at most 3650d
bin/collie devices set-expiry pixel 90d # a new lifetime, counted from now
bin/collie devices clear-expiry pixel # no expiry againO tempo de vida começa a contar a partir do momento em que o telefone resgata o código. Sem --expires, um token nunca expira, exatamente como antes, e nenhum token existente é alterado. Após a expiração, a bridge recusa o token com device expired em vez de device not paired. O telefone então limpa o que o emparelhamento deixou e exibe Emparelhar novamente em Settings, portanto execute collie pair para obter um novo código. collie devices list e a tela Settings mostram a expiração de cada dispositivo. Um dispositivo expirado permanece na lista até você revogá-lo ou definir uma nova expiração com set-expiry. Para emparelhá-lo novamente, você pode usar o mesmo nome: o novo emparelhamento substitui a entrada expirada e revoga o token antigo, e o log de auditoria registra a revogação. Um nome que um dispositivo ainda usa, com um token que não expirou, é recusado. A standby door de um deputy de crew também recusa um token expirado.
Em um host executando múltiplas instâncias, use COLLIE_INSTANCE=<name> como prefixo nos comandos e abra a URL daquela instância específica no celular (Várias instâncias do Collie em um único host).
O que desemparelhar limpa no telefone
Quando um emparelhamento termina, o telefone apaga o que o Collie armazenou nele. Isso acontece quando você desemparelha o telefone em Settings e quando a bridge recusa seu token com device not paired ou device expired.
O telefone exclui o token, todos os rascunhos não enviados, o texto salvo do painel e do herd, a inscrição de push, as confirmações de "Sem avisos" e os caches do Collie, exceto o app shell. Suas configurações permanecem: tema, idioma, itens fixados e outras preferências não guardam texto de sessão. As Configurações solicitam confirmação antes de revogar qualquer dispositivo.
A limpeza feita pelo próprio telefone é a única. A bridge não envia o cabeçalho Clear-Site-Data, pois esse cabeçalho também apagaria suas configurações e o app offline, e em um nome de host compartilhado afetaria também as outras aplicações locais.
Se a bridge não conseguir ler sua lista de dispositivos emparelhados, por exemplo em caso de arquivo gravado pela metade, ela responde com 503 pairing unavailable. O telefone então mantém seu token e tudo o que armazenou, e tenta novamente.
O que o telefone mantém
O telefone mantém uma cópia pequena e limitada do que viu por último, para que uma inicialização a frio possa exibi-la enquanto a bridge estiver inacessível. Cada item abaixo tem um limite de tamanho e um tempo de vida.
| O que | Onde | Por quanto tempo | Ao desemparelhar |
|---|---|---|---|
| Token de emparelhamento | localStorage | até desemparelhar, revogar ou expirar | apagado |
| Settings: tema, idioma, pins | localStorage | até você alterá-los | mantido |
| Rascunhos não enviados | localStorage | 48 horas | apagado |
| Endpoint de push | localStorage | até mudar | apagado |
| Shell do app | Cache Storage | até o próximo build | mantido |
| Fontes e títulos de push | Cache Storage | até ser substituído | apagado |
| Arquivos do motor e do modelo de voz Whistle (somente se você optou por copiá-los) | Cache Storage | até você removê-los | apagado |
| Texto do herd e do painel, conforme visto pela última vez | IndexedDB collie-store | 24 horas | apagado |
| Turnos mais recentes do Chat de cada painel | IndexedDB collie-store | 1 dia, ou a configuração "Keep chat on this phone" | apagado |
As duas últimas linhas são o armazenamento no dispositivo. Ele guarda apenas o texto que a bridge já mascarado, no máximo 256 KiB por painel e 10 MiB no total, e descarta primeiro as entradas mais antigas. O texto do painel e os turnos do Chat recebem metade dos 256 KiB de um painel cada, de modo que um nunca expulsa o outro. Os turnos do Chat são mantidos inteiros, como o Chat os desenhou, nunca como a tela bruta do terminal. "Keep chat on this phone" definido como Off não mantém nenhum e exclui os que foram guardados. Quando um painel pede uma senha, o telefone descarta as entradas daquele painel. Nada no armazenamento pode enviar uma tecla ou resposta. As exclusões ao desparear são as descritas em O que desemparelhar limpa no telefone.
O alternador de apps do telefone também pode mostrar um painel. Quando você sai do Collie, o telefone guarda uma imagem da tela para sua lista de apps recentes, e essa imagem pode exibir o texto do painel. Um web app não pode impedir isso: o Android tirou a foto antes que a página soubesse que foi para segundo plano (testado em um Pixel, 2026-10-08), e o iOS também não dá garantias. Se isso for importante para você, bloqueie o telefone ou feche o Collie antes de entregá-lo a alguém.
Modelo de risco
Principais limites de segurança e riscos:
- Ele roda com as permissões do seu usuário. O Collie herda todos os seus direitos de acesso, incluindo
~/.ssh,git push --force,rm -rfesudo. - A autenticação identifica dispositivos, não humanos. O Tailscale verifica o endpoint de hardware em vez do usuário que o segura. Não há senhas nem sessões de usuário; um telefone desbloqueado ou roubado oferece uma shell aberta. O pareamento vincula o acesso a uma credencial no dispositivo (acima), portanto revogue um telefone perdido imediatamente. O bloqueio por ociosidade integrado apenas apaga uma tela sem uso e não fornece nenhuma barreira real de segurança (ADR 0007).
- Todos os usuários locais do sistema podem acessar a porta. Sockets padrão de multiplexadores de terminal (
tmux,zellij,herdr) usam permissões do sistema de arquivos para restringir o acesso a outros usuários locais. O Collie escuta em uma porta TCP local, o que o expõe a qualquer UID local. As leituras precisam do token de pareamento, portanto outro usuário local sem o token lê apenas/api/health. O token é o limite: um usuário local que pode ler o perfil do seu navegador também pode ler o token (ARCHITECTURE.md §6). - Uma permissão retida aguarda o toque de uma pessoa. Com
collie hooks install claude --hold-permissions, o hook de permissão do Claude consulta a bridge através de um arquivo de socket. Apenas o seu usuário pode abri-lo (modo 0600 em um diretório 0700). O hook verifica o proprietário do socket, o diretório e o state dir acima dele antes de se conectar. A bridge responde apenas para um processo que ela coloca em um painel. Ela nunca responde sozinha. Um toque deve conter o hash do que o card exibiu. Um card de tela nunca responde a uma requisição cujo diálogo não esteja na tela (Permissões retidas para o celular). - A visualização Files lê arquivos do seu disco. Mostra qualquer arquivo sob a pasta de um workspace, exceto uma pasta
.git, as pastas de configuração e estado do próprio Collie e arquivos com nomes semelhantes a um segredo de estado do Collie. Portanto, exige um dispositivo autorizado, assim como uma escrita (ADR 0083). - O Browse da página New lista nomes de pastas sob a sua home. Apenas nomes, com os limites da visualização Files: sem pastas com ponto a menos que digitadas, sem
.git, sem pasta de estado ou configuração do Collie, sem link para fora da home, no máximo 200 linhas. Também exige um dispositivo autorizado (Pastas favoritas e recentes). - Todo dispositivo pareado pode ler arquivos sob a pasta do workspace. Isso inclui arquivos
.env. Pareie apenas os dispositivos nos quais você confia com a própria shell. - Arquivos de credenciais sob a pasta de um workspace podem ser lidos. Um workspace aberto em
~/.claude,~/.codex,~/.config/ghou~/.sshmostra o que está lá. O mesmo vale para o.envde um segundo Collie cuja pasta de configuração fica sob o workspace. Um hard link dentro da pasta para um arquivo fora dela também não é detectado. - Um dispositivo emparelhado pode adicionar inicializadores. Com o padrão
[phone] adds = true, um telefone pode adicionar uma linha criada a partir de uma receita: um agente mais opções cujas flags a bridge escolhe da sua própria tabela. Uma linha digitada manualmente precisa defree_text = true, que fica desativado por padrão. Uma receita ainda pode pular confirmações de permissão. Essa linha exibe um selo "Sem avisos", e cada dispositivo a confirma uma vez. Revogar um dispositivo remove as linhas que ele adicionou. Definaadds = falsepara desativar todas as linhas adicionadas por telefone (Seus próprios inicializadores, ADR 0094). - Um dispositivo emparelhado pode executar um comando avulso. Com o padrão
[phone] run = true, um telefone pode digitar uma linha escrita por ele em um novo shell de uma máquina. Isso não concede permissões adicionais, pois um telefone emparelhado já pode abrir um shell e digitar nele. A linha segue a regra de caracteres de linha livre, e a bridge a recusa se não houver dispositivo emparelhado. Cada comando iniciado é mantido, até o limite de 12, emcommands-recent.jsonna pasta de estado (modo 0600). Uma linha que pareça conter um segredo (uma atribuição comoTOKEN=…, uma URL com senha ou uma palavra comotokenoupassword) é executada, mas não é mantida. A verificação é uma aproximação, então um segredo ainda pode escapar para a lista; o log de auditoria registra apenas a primeira palavra da linha e seu comprimento. Desemparelhar ou revogar um dispositivo mantém a lista intacta, pois executar uma linha novamente exige um dispositivo emparelhado. Definarun = falsepara remover o atalho (Comandos avulsos, ADR 0095). - Cada máquina guarda as linhas de shell que você envia pelo Collie. O Sent mantém uma linha enviada a um painel de shell, e cada comando avulso, em
sent.jsonlna pasta de estado (modo 0600). Um dispositivo emparelhado pode lê-lo, assim como pode ler os painéis. Alguns segredos ainda são preservados (Sent: as linhas de shell que você enviou). - Uma única instância expõe todas as sessões do Herdr. Por padrão, um único processo do Collie atende a todas as sessões do Herdr detectadas sob o diretório raiz de configuração do Herdr, incluindo sessões sandbox (Multissessão).
- Gravações são registradas em
<state-dir>/audit.log, que é~/.local/state/collie/audit.loga menos queCOLLIE_STATE_DIRo mova. O servidor registra todas as teclas digitadas recebidas, respostas, uploads de arquivos e eventos do ciclo de vida de painéis/abas. Observe que um log de auditoria fornece visibilidade após o ocorrido, em vez de controle de acesso. Os caracteres enviados no modo Type nunca são gravados no log:COLLIE_AUDIT_CONTENT=noneoculta cada um deles, e a pré-visualização padrão registra apenas uma contagem de marcas•. Teclas nomeadas como Enter e Ctrl+C continuam legíveis (ARCHITECTURE.md §6). As respostas, envios, paradas, toques de botão, inicializações, reaberturas e renomeações de um agente durável também são gravados (O que é registrado no log). - Cabeçalhos de resposta. Cada resposta traz
X-Content-Type-Options: nosniff,Referrer-Policy: no-referrerePermissions-Policy: camera=(), geolocation=(), microphone=(self), payment=(), usb=(). O microfone continua permitido para a configuração de fala com as mãos livres. A Content-Security-Policy no shell do app incluiobject-src 'none',form-action 'self'eframe-ancestors 'none'. OStrict-Transport-Securityé enviado apenas quando uma requisição chega por HTTPS, seja em um listener TLS ou comX-Forwarded-Proto: httpsa partir do seu proxy. Ele cobre o nome de host que respondeu e não seus subdomínios, porque o Collie costuma compartilhar um domínio pai com outros serviços. A bridge em si fala HTTP simples atrás detailscale serve, e o navegador ignora o cabeçalho nesse caso. Imagens servidas a partir de/api/blobs/são conteúdo de sessão, portanto trazemCache-Control: private, no-storee nenhum cache as retém, nem mesmo o do próprio telefone. - Controles defensivos padrão. O Collie se vincula estritamente a interfaces de loopback, roteia tráfego exclusivamente pelo
tailscale serveou por um proxy reverso equivalente, e aplica regras rígidas de CSP, verificações de mesma origem e validação de cabeçalho Host. A saída do painel é renderizada como nós de texto React em vez deinnerHTML. Nunca usetailscale funnelnem exponha uma porta bruta. Para autorizar hardware específico, use pareamento diretamente ou, se o seu proxy injetar IDs de dispositivo, as duas variáveisCOLLIE_DEVICE_*abaixo.
| variável | o que faz |
|---|---|
COLLIE_ALLOW_NON_LOOPBACK_BIND=1 | Desativa o vínculo exclusivo com loopback; se não estiver definida, a bridge se recusa a vincular a 0.0.0.0. |
COLLIE_ALLOW_ANY_HOST=1 | Desativa a validação do cabeçalho Host, que normalmente fica ativada por padrão e falha de forma fechada. |
COLLIE_TRUSTED_USER | Rejeita uma requisição cujo cabeçalho Tailscale-User-Login esteja ausente ou não corresponda. |
COLLIE_TRUSTED_USER_OPTIONAL=1 | Permite a ausência do cabeçalho Tailscale-User-Login (nós marcados com tag nunca enviam um). |
COLLIE_ACCESS_TEAM + COLLIE_ACCESS_AUD | Apenas Cloudflare Tunnel. Rejeita todas as requisições remotas a menos que seu Cf-Access-Jwt-Assertion seja verificado para este app do Access. Apenas um processo local em loopback, /api/health e os links de crew o ignoram, e o pareamento ainda se aplica. Outras portas de entrada, como tailscale serve, também são recusadas (Cloudflare Tunnel). |
COLLIE_DEVICE_HEADER | Nome do cabeçalho que seu proxy injeta com um id de dispositivo. |
COLLIE_DEVICE_ALLOWLIST | Lista separada por vírgulas de ids de dispositivos com permissão de escrita; qualquer outro dispositivo permanece somente leitura (docs/deployment.md). |
COLLIE_REDACT=off | Desativa a máscara de segredos no texto do painel, diffs e texto de arquivos (abaixo). Ativado por padrão. |
COLLIE_SENT=off | Não mantém registro das linhas de shell enviadas por você (abaixo). Ativado por padrão. |
🚫 O Nunca usetailscale funnelcom o Collie. Funnel roteia tráfego para a internet pública, enquanto otailscale serverestringe o acesso à sua tailnet privada. Não há caso de uso com suporte para executar o Collie via Funnel.
Restrinja o acesso ainda mais com ACLs da Tailscale e COLLIE_TRUSTED_USER. Fornecido no estado em que se encontra, sem garantias.
Durable agents
Um agente durável que você anexa é código que você executa ou faz deploy, e o Collie trata seu texto como não confiável. Um socket privado impede o acesso de outros usuários, mas não de um processo do seu próprio usuário, e um token é a única proteção via https. As regras de confiança por transporte, o que o Collie faz com o texto de um agente durável e o que o log de auditoria armazena estão em Segurança de um durable agent.
O motor de voz (Whistle)
O Whistle executa código de terceiros: um motor WebAssembly da Cactus Compute. Ele roda no telefone, ou no host como o usuário da bridge. O Collie restringe o que esse código pode alcançar. Ele não pode remover o alcance por completo.
- Incluído no repositório e fixado. O motor consiste em dois arquivos,
needle.jseneedle.wasm, mantidos byte por byte como o upstream os publicou, com a licença do upstream e uma nota de procedência (web/public/stt/needle-3-93e88ede/). Um teste fixa o sha256 de ambos os arquivos e a lista das dezesseis funções que o wasm pode solicitar ao seu host. Uma nova importação é motivo para parar. Apenas uma pessoa atualiza a fixação e lê o diff antes. O modelo tem seu próprio hash fixado, e o Collie só mantém uma cópia baixada quando ela coincide. - No telefone, um worker com sua própria política. O wasm roda em um worker dedicado. A bridge serve todos os scripts em
stt/com esta política, e nenhuma outra página a recebe:Content-Security-Policy: default-src 'none'; script-src 'self' 'wasm-unsafe-eval'; base-uri 'none'O worker não tem rede, não tem DOM e não tem como carregar código de outros lugares. Ele não pode ler o token de pareamento, que fica em
localStorage, e workers não têmlocalStorage. Antes de fazer qualquer outra coisa, ele compila um módulo wasm minúsculo. Um navegador que não concede ao worker sua própria política recusa isso, e Este telefone aparece como indisponível ali. - A política da página não muda. A política do documento nunca recebe
'wasm-unsafe-eval'e mantémconnect-src 'self'. - O que o worker ainda consegue alcançar. Ele pode ler e gravar no IndexedDB e no Cache Storage desta origem, os quais nenhuma diretiva de política bloqueia. O
collie-storearmazena texto recente de painéis e Chat (O que o telefone mantém). Esse texto já estava mascarado, mas é legível. Esse alcance é aceito e está registrado no ADR. Se começar a importar, o próximo passo é um frame em sandbox ao redor do worker. - No host, um processo filho do próprio binário do Collie. Um processo filho de vida curta por ditado executa
_whistle-transcribecom uma lista de argumentos fixa escrita pelo Collie. Ele valida o motor, o wasm e o modelo contra seus hashes fixados antes de compilar qualquer coisa. Ele tem um limite de tempo de 60 segundos, encerrado com SIGKILL, um teto de saída de 256 KiB e no máximo dois simultâneos. Ele não recebe nenhuma das variáveisCOLLIE_*da bridge. A bridge define apenas duas, a pasta de estado e a pasta de instalação, para caminhos que ela própria resolveu. Nada da requisição alcança a lista de argumentos, exceto a gravação. - Uma segunda chamada de saída, acionada pelo toque de uma pessoa. A checagem de atualizações é a primeira. O download do modelo é a segunda: um arquivo, de um endereço fixado do Hugging Face, gravado somente após a validação do hash. Um telefone nunca chama o Hugging Face. Ele copia o modelo a partir do host, com o token de pareamento. As rotas exigem um dispositivo com permissão de escrita, rodam somente no lead, permitem um download por vez e são auditadas.
- A configuração a partir de Ajustes é uma exceção à regra de que "configurar é um ato do CLI". Provedores que armazenam uma credencial ou indicam um comando permanecem no terminal. O Whistle não faz nada disso. Um token de escrita roubado já pode digitar em terminais e iniciar uma atualização, portanto o toque de configuração não concede nada de novo a ele.
- Alternar para o Codex a partir de Ajustes é a outra exceção. Um dispositivo de escrita pode alternar o host entre Whistle, Codex e Off, e nada mais. O Codex exige o consentimento completo, as mesmas palavras que
collie stt setupexibe, e um toque em Aceito; a bridge então executa a própria sondagem do CLI. Um token de escrita roubado poderia apontar a voz do host para a conta autenticada do ChatGPT do operador. Ele não pode adicionar uma chave ou um comando, nem substituir um. O token já pode digitarcodexem um terminal. O ADR 0097 pondera isso. Uma alteração a partir de Ajustes também grava o nome do dispositivo pareado, como fornecido no pareamento, e a hora emstt.json, para que Voz do host possa indicar quem o alterou por último. Nenhum token e nenhum endereço é gravado. Uma execução decollie stt setupremove essa linha. - Dispositivos pareados podem ler o que as configurações de voz do host indicam, apenas pelo nome. Trata-se do nome do comando, do nome de um arquivo de modelo e do nome de host de um serviço de voz, nunca de um caminho, um argumento, uma chave ou um caminho de URL.
Por que foi feito assim: ADR 0096. Os passos de configuração estão em Entrada de voz e Web Push.
Walky talky
O walky talky transporta mensagens entre sessões de agentes, portanto esta seção explica o que uma mensagem comprova e o que ela não comprova. Os comandos estão em Walky talky.
# in .env, then run `collie restart`
COLLIE_WALKY=offEssa linha faz esta máquina recusar qualquer mensagem destinada aos seus painéis. A CLI na máquina ainda pode enviar.
- Uma chave de crew assina uma mensagem entre máquinas. Um membro assina uma mensagem com sua chave de crew. O lead verifica a assinatura em relação à chave fixada para esse membro e adiciona sua própria assinatura para a máquina de destino. Uma instalação individual não tem chave de crew. Ela não assina nada e não envia nada para fora da máquina.
- O destinatário verifica o remetente, pela palavra do lead. Um membro fixa apenas o seu lead. Assim, o lead envia o certificado do remetente junto com a mensagem e assina uma declaração curta confirmando que esse certificado pertence àquele membro da crew. A máquina de destino verifica essa declaração e depois verifica a assinatura do remetente em relação ao certificado. Se qualquer verificação falhar, ela recusa a mensagem. Ela continua confiando no lead para saber quem faz parte da crew.
- Apenas o lead pode registrar um resultado de volta. O lead envia a um membro os resultados das mensagens daquele próprio membro. O membro só os aceita do seu lead fixado, e apenas para uma mensagem que enviou e ainda registra em log. Os resultados e o registro do que o lead recebeu permanecem na memória e expiram após 10 minutos.
- O card do telefone precisa do log. O telefone só renderiza um card de mensagem se o próprio log da bridge contiver esse id de mensagem. Um cabeçalho que um agente apenas exibe na tela permanece como texto puro, com a marcação "no log record on this machine".
- Um token de painel não é segredo. O token em um endereço, como
#k3f9, impede que uma mensagem chegue a uma nova sessão que assumiu o id de um painel fechado.collie walky whoo exibe para todos os agentes, e<stateDir>/walky/instances.jsonpode ser lido pelo seu usuário. Ele não comprova nada sobre quem envia. - Toda máquina por onde uma mensagem passa a mantém gravada. A máquina do remetente, o lead e a máquina de destino registram a mensagem em
<stateDir>/walky/. O log guarda 7 dias e no máximo 2.000 linhas. Nunca coloque um segredo em uma mensagem. - A mensagem de um agente são as palavras de um par. O painel recebe uma linha com o cabeçalho do remetente e sem corpo. O agente lê o corpo como a saída de
collie walky inbox <id>, que um harness trata como dados e não como uma instrução sua. A skill instalada instrui o agente a avaliá-la e nunca executar um comando destrutivo porque um par solicitou.
Nota. Um agente roda como seu usuário, portanto pode ler a crew key e abrir o socket local. Ele poderia assinar uma mensagem ou reivindicar um painel que não é seu. A assinatura protege uma mensagem em seu trajeto entre máquinas e informa ao receptor qual máquina a enviou. Ela não protege você de um programa na mesma máquina que mente sobre si mesmo.
O walky talky não adiciona nenhuma chamada de saída. Uma mensagem para outra máquina utiliza o crew link que já existe, e nenhum modelo, serviço de nuvem ou terceiro a vê.
O que sai da máquina é mascarado
O Collie mascara padrões conhecidos de segredos no texto do painel e no conteúdo de arquivos antes que cheguem ao telefone.
# in your .env, only to turn the mask off; it is on by default
COLLIE_REDACT=offA máscara roda na bridge, em cinco caminhos: o espelhamento do terminal, as visualizações Chat e History, cada notificação push, os diffs na visualização Changes e o texto do arquivo na visualização Files. O que ela esconde vira marcas • da mesma largura, preservando colunas e contagens de linha. Um prefixo de fornecedor continua legível, de modo que sk-o•••• ainda indica o que foi ocultado.
Ele corresponde apenas a formatos de alta confiança:
| formato | exemplo do que é mascarado |
|---|---|
| chaves de API com prefixo | sk-…, sk-ant-…, sk-or-v1-…, ghp_…, github_pat_…, xoxb-…, AKIA…, AIza…, glpat-…, npm_… |
| JWTs | três partes em base64url, com a primeira começando com eyJ |
| chaves privadas PEM | cada linha entre BEGIN … PRIVATE KEY e sua linha END |
| tokens de portador (bearer) | o token após Bearer , com 20 caracteres ou mais |
| valores nomeados | o valor após password=, secret:, token=, api_key: e semelhantes, com 8 caracteres ou mais |
Atenção. Esta é uma mitigação, não uma garantia. Uma senha avulsa em texto puro, um valor puro em hexadecimal ou base64 e uma chave com prefixo fora da lista são ignorados de propósito. Um padrão para eles mascararia texto comum e código em todas as telas.
Algum texto comum também é mascarado, por exemplo uma linha de texto ou YAML contendo token: something. O que você digita e envia nunca é mascarado, e a trilha de auditoria segue suas próprias regras (COLLIE_AUDIT_CONTENT).
A opção existe apenas na bridge, como COLLIE_REDACT. Configurações → Sistema a exibe em modo somente leitura, como "Mascaramento de segredos". O telefone não tem essa opção de propósito: uma opção no telefone permitiria que qualquer telefone pareado, ou roubado, desativasse a máscara. Para ler um valor mascarado, leia-o na máquina. Na primeira vez que um painel exibir texto mascarado, um aviso curto no telefone informará isso, uma vez por dispositivo. Se você colar texto mascarado em uma resposta, um aviso abaixo da caixa indicará que o painel recebe os pontos, e não o segredo.
Em uma crew, cada membro mascara seu próprio texto, e o líder o mascara novamente antes que seu telefone o receba. O líder mascara o espelho de um membro, o Chat, o Histórico, diffs, texto de arquivos e títulos de painéis com a mesma máscara que usa para si, de modo que um membro que ainda execute a 1.17.x não possa enviar uma chave em texto claro para o seu telefone. O texto mascarado permanece inalterado ao ser mascarado novamente. O texto só chega ao telefone sem máscara quando COLLIE_REDACT=off estiver definido tanto no líder quanto no membro. Um caso de borda: um membro na 1.17.x não mascara nada por conta própria; portanto, quando um segredo estiver nas linhas contra as quais uma resposta é verificada, o telefone pode recusar essa resposta com "A tela mudou antes que isso pudesse ser enviado". A resposta então aguarda até que o membro execute a 1.18.0.
Se o líder não puder ler a resposta de um membro para mascará-la, ele não a repassará. O telefone exibirá essa leitura como falha, assim como faz para um membro inalcançável.
Uma notificação push também nomeia um painel apenas pelo nome que você deu a ele: o rótulo do painel, o nome /rename do Claude ou o nome de uma aba de painel único. Ela nunca usa o título definido por um programa no painel, pois qualquer programa pode definir esse título, e um título pode conter um caminho, um comando ou um segredo. Um painel sem esse nome é chamado pelo seu harness, por exemplo claude.
Sent: as linhas de shell que você enviou
Cada máquina mantém um registro das linhas de shell que você envia pelo Collie, para que você possa encontrar e enviar uma novamente.
# in your .env, to keep no record on this machine
COLLIE_SENT=off| pergunta | resposta |
|---|---|
| O que é mantido | Uma linha que você envia para um painel de shell e cada comando avulso da página New. Para cada linha: o texto, sua pasta, o horário e qual dos dois tipos ela era. |
| O que nunca é mantido | Prompts para um agente, texto para um programa, chaves do painel Keys e o modo Type. |
| Onde | sent.jsonl na pasta de estado, ~/.local/state/collie/ a menos que COLLIE_STATE_DIR a mova. O arquivo tem permissão 0600, em uma pasta com 0700. |
| Por quanto tempo | No máximo 5000 linhas em cada máquina, e nenhuma com mais de 365 dias. |
| Quem pode ler | Um dispositivo emparelhado, já que ele pode ler os painéis para onde as linhas foram. |
| Em uma crew | Cada máquina mantém seu próprio arquivo. O lead consulta seus membros quando seu telefone solicita, e não guarda cópia. |
O Collie envia cada linha em que você toca e depois decide se deve mantê-la. Ele não guarda nada sobre uma linha que:
- começa com um espaço ou um tab,
- define uma variável, como
TOKEN=abc deployouexport AWS_SECRET_ACCESS_KEY=…, - contém uma URL com senha, como
https://user:pass@host, - contém uma palavra como
password,secret,token,bearerouauthorization, - contém um formato que a máscara de segredos reconhece, como uma chave do
ghp_…ou dosk-…, - tem mais de 4096 caracteres.
Uma linha assim não deixa linha no registro, nem contagem, nem linha de log com seu texto.
Para deixar uma linha de fora, comece-a com um espaço. O shell a executa normalmente, e o Collie não guarda nada.
Atenção. A verificação é uma estimativa. Ela mantém uma senha que você passa como argumento comum, como mysql -pPASS, e qualquer segredo com formato que ela não reconheça. Comece esse tipo de linha com um espaço.Para esquecer uma linha, use Forget na linha correspondente na planilha Sent. Para esquecer uma máquina inteira, use Clear Sent. Ambos funcionam enquanto COLLIE_SENT=off estiver definido. O log de auditoria registra cada esquecimento com uma contagem, nunca a linha. Cada linha passa pela máscara de segredos antes de sair da máquina.
Por que isso foi construído assim: ADR 0107.
Arquivos secretos no Windows
No Windows (experimental), o Collie mantém seus arquivos secretos privados para a sua conta, SYSTEM e Administrators. "Sua conta" é a conta do Windows que executa o Collie.
O NTFS não possui o modo 0600, portanto o Collie usa a lista de controle de acesso (ACL) de sua pasta de estado e de sua pasta de configuração. Cada arquivo que o Collie grava ali recebe a mesma lista. As pastas padrão no seu perfil de usuário já são fechadas para outros usuários padrão. A verificação é mais importante quando você move uma pasta com COLLIE_STATE_DIR ou outra configuração.
Na inicialização, a bridge verifica ambas as pastas e seus arquivos secretos. Se outras contas puderem ler uma delas, a bridge a repara, mas apenas nas próprias pastas do Collie. Ela salva a lista antiga primeiro, em acl-backups na pasta de estado, e imprime o comando icacls /restore que a restaura. Execute esse comando em um terminal executado como administrador. Uma pasta que também contém outros arquivos é verificada, não modificada: o Collie imprime o comando icacls para você executar. Outros comandos, como collie version, apenas verificam e alertam.
collie doctor mostra o resultado como secrets-private. Uma pasta que outras contas podem ler é um erro, acompanhado da correção. Uma pasta que o Collie não consegue verificar é um aviso: cannot confirm.
| Caso | O que acontece |
|---|---|
Você copia, restaura ou sincroniza a pasta (zip, robocopy sem /SEC, OneDrive, Histórico de Arquivos, uma unidade USB) | A cópia pode perder a lista. O Collie verifica novamente na próxima inicialização. |
| O antivírus ou o Acesso controlado a pastas bloqueia a alteração | O Collie informa que não conseguiu tornar a pasta privada e fornece a correção. |
| A pasta está em FAT, exFAT ou em um compartilhamento de rede | Não existe uma lista que o Collie possa usar. O Collie informa cannot confirm. Mova a pasta de estado para uma unidade NTFS neste PC. |
COLLIE_NO_ACL_REPAIR=1 | O Collie não altera nenhuma lista. Ele ainda verifica e avisa, e o doctor ainda relata. |
Nota. Isto não é proteção contra um administrador. Administradores ainda podem ler os arquivos. Também não cobre outros programas executados como sua conta, hard links dentro da pasta, backups de agentes em ~/.claude ou uma pasta de estado dentro do OneDrive ou de Documentos.O que sai da sua máquina
Nada, por padrão e por política. O Collie não envia eventos de instalação, estatísticas de uso, relatórios de falha nem telemetria. Não existe nenhuma flag para habilitá-los.
A única chamada externa não solicitada é a verificação de atualização: um GET HTTPS anônimo para a API pública de tags do GitHub (bridge/update.ts) que compara sua versão com a tag mais recente. Ela não envia dados sobre você ou sua máquina, apenas o user-agent estático collie-update-check.
O download do modelo do Whistle é a outra chamada de saída. Ele acontece apenas quando alguém toca em Baixar para o host ou executa collie stt whistle, e não envia dados sobre você (O motor de voz (Whistle)).
O walky talky não adiciona nenhuma chamada de saída. Uma mensagem para outra máquina utiliza o crew link e não vai para nenhum outro lugar (Walky talky).
Informar um problema não faz chamadas externas. Após envios com falha, o celular pode abrir o formulário de nova issue do GitHub, preenchido, como um link no seu próprio navegador. Você lê todo o texto primeiro e o envia sob sua própria conta. O Collie não armazena tokens do GitHub e o celular nunca faz chamadas ao GitHub (ADR 0123).
Se você definir COLLIE_ACCESS_TEAM, o Collie também buscará as chaves públicas dessa equipe do Cloudflare Access, na inicialização e uma vez por hora. Essa chamada fica a seu critério ativar, e ela também não envia nada sobre você.
Se você anexar um agente durável por URL, o Collie chamará essa URL a cada verificação com o token bearer do agente durável no cabeçalho Authorization. Essa chamada também depende de você para ser ativada, e nada é enviado até que você anexe um (Segurança de um durable agent).
Se a coleta for implementada algum dia, o limite máximo será o opt-in explícito: desativada por padrão, solicitada com uma pergunta visível, nunca ativada por uma flag ou valor padrão. Quebrar essa promessa seria uma breaking change (ADR 0034).