$TMPDIR/chatcli-agent-<random>/ e exposto ao agente via a variável de ambiente CHATCLI_AGENT_TMPDIR. Esse diretório resolve duas dores recorrentes:
- O agente precisa criar um script temporário (por exemplo, um
.shpara um patch complexo) mas o boundary do/coderbloqueia escritas fora do projeto, forçando-o a poluir a árvore do repositório. - Quando um tool result é truncado e o ChatCLI salva o conteúdo completo em disco com a marca
[full output saved to /tmp/...], o agente não consegue ler esse arquivo porque o caminho está fora do workspace boundary.
Estrutura
<random> vem de os.MkdirTemp — único por processo. Isso evita colisão entre múltiplos chatcli rodando em paralelo no mesmo host.
Como o agente sabe que existe?
O system prompt do/agent e do /coder recebe automaticamente um bloco com:
- Caminho literal do scratch dir resolvido na hora (o agente não precisa expandir variável).
- Instrução para usar
$CHATCLI_AGENT_TMPDIRem comandos shell quando preferir. - Padrão de uso para os marcadores de truncamento: quando ler
[full output saved to /tmp/chatcli-agent-XXX/tool-results/...], abrir o arquivo comread_fileem vez de refazer a tool call original.
Cenário 1 — Criar e executar script temporário
No/coder, o modelo tem duas vias para staging de script:
Via direta com path absoluto
validatePath do engine reconhece o aux path registrado pela InitSessionWorkspace e libera a escrita.
Via shell expansion no exec
$CHATCLI_AGENT_TMPDIR é o shell filho, que herda a variável do processo do ChatCLI.
Cenário 2 — Recuperar miolo de output truncado
O sistema de orçamento de resultados trunca tool results grandes (> 20K chars por padrão) e salva o conteúdo completo emtool-results/. O preview retornado ao modelo contém um marcador como:
tool-results/ estão na read allowlist do agente, então o modelo simplesmente abre o arquivo:
Lifecycle
| Evento | Ação |
|---|---|
NewChatCLI (startup) | agent.InitSessionWorkspace(logger) cria os dirs, exporta CHATCLI_AGENT_TMPDIR, registra os paths nos validators |
| Cada turno do agente | Aux paths consultados pelo validatePath (engine) e IsReadAllowed (read validator) |
| Tool result excede orçamento | tool-results/ recebe o conteúdo completo; preview com marcador volta para o modelo |
ChatCLI.cleanup() (exit, Ctrl+D, SIGTERM) | ws.Cleanup() faz os.RemoveAll do dir raiz; env var é desexportada |
Configuração
| Variável | Descrição | Default |
|---|---|---|
CHATCLI_AGENT_TMPDIR | Apenas leitura. Caminho absoluto do scratch dir, exportado automaticamente para subprocessos | (definido na inicialização) |
CHATCLI_AGENT_KEEP_TMPDIR | Se true, pula o cleanup e mantém os arquivos após o exit (para depuração) | false |
CHATCLI_BLOCK_TMP_WRITES | Se true, bloqueia a extensão do allowlist para os.TempDir() e /tmp. Só o scratch dir específico da sessão fica acessível. Use em ambientes multi-usuário ou CI com isolamento estrito. | false |
Segurança
O workspace de sessão não afrouxa o boundary do agente para paths sensíveis do sistema:- O scratch dir vive em
os.TempDir()($TMPDIRno macOS,/tmpno Linux), com permissão0700no diretório raiz da sessão. - Os validators (
engine.validatePath,SensitiveReadPaths.IsReadAllowed) seguem aplicando as proteções principais: bloqueio de paths sensíveis (/etc/shadow,~/.ssh,~/.aws/,~/.gnupg, etc.) e o boundary do projeto. - O webfetch com
save_to_file=trueconfina escritas ao scratch dir viafilepath.Base+ verificação pós-resolve, mesmo se o modelo tentar passar um caminho absoluto.
/tmp e os.TempDir() no allowlist por padrão
A partir desta versão, todo os.TempDir() e /tmp (quando existe) são adicionados ao allowlist de leitura/escrita na inicialização da sessão. Motivo prático: praticamente todo modelo moderno, ao escrever um script throwaway, emite caminhos como /tmp/check.sh ou /tmp/debug-X.py por default. Antes, isso caía no boundary check (path "/tmp/check.sh" is outside workspace boundary) e forçava o modelo a adivinhar paths seguros — gerando falhas silenciosas ou retries.
/tmp é compartilhado entre processos não-confiáveis, defina CHATCLI_BLOCK_TMP_WRITES=true e apenas o scratch dir isolado da sessão continua acessível:
Symlinks dentro de
/tmp continuam sendo resolvidos via filepath.EvalSymlinks antes da checagem de allowlist — um symlink /tmp/evil → /etc/shadow ainda é bloqueado pelo sensitivePaths.Próximos Passos
Resultados de Tools
Como o orçamento decide o que truncar e onde persistir.
Subagent Delegation
Delegar tarefas pesadas para um subagente com contexto isolado.
Web Tools
save_to_file do @webfetch usa o scratch dir.Variáveis de Ambiente
Lista completa das variáveis que controlam o workspace.