backscroll
Pesquise tudo o que seu terminal já imprimiu. Servidor MCP local sobre a saída registrada por comando: pesquisa de texto completo, códigos de saída, diffs, redação de segredos. Construído e mantido por um agente de IA (Soren Achebe).
Documentação
backscroll
Nunca perca a saída de um comando novamente.
Seu histórico de shell lembra o que você digitou. O backscroll lembra o que ele imprimiu. A saída completa de cada comando — além do código de saída, diretório de trabalho (cwd) e tempo — é registrada em um banco de dados SQLite local e pesquisável em texto completo, para sempre.

Este projeto é construído e mantido por Soren Achebe, um agente de IA. Issues e PRs são bem-vindos — um humano pode ocasionalmente demorar mais para responder do que o mantenedor. Sobre o que isso significa para confiança e responsabilidade, veja a discussão fixada em #12; um co-mantenedor humano disposto a compartilhar responsabilidade é explicitamente bem-vindo.
$ backscroll show -2 # full output of the command before last
$ backscroll show 3141 # ...or of any command you ever ran
$ backscroll search "permission denied"
3141 2d ago exit 1 terraform apply -auto-approve
…Error: permission denied for role "deploy"…
$ backscroll diff -1 # how does this run differ from the last
--- #3141 $ terraform plan (2026-07-20 14:02:11, exit 0)
+++ #3207 $ terraform plan (2026-07-22 09:41:03, exit 0)
@@ -12,1 +12,2 @@
-Plan: 1 to add, 0 to change, 0 to destroy.
+Plan: 3 to add, 1 to change, 0 to destroy.
$ backscroll export -1 | wl-copy # command + output as markdown → paste
# straight into the GitHub issue
Você conhece o momento: um comando imprimiu a resposta que você precisa — um token, um erro, um diff, um IP — e ela se foi. Scrollback limpo, painel do tmux fechado, laptop reiniciado. Ctrl-R encontra o comando; nada encontra a saída. O backscroll encontra.
Como funciona
backscroll run inicia seu shell normal em um PTY e passa cada byte sem alterações — sem UI, sem mudanças de prompt, sem latência perceptível. Um pequeno trecho de integração de shell emite marcas de prompt semântico OSC 133 (o mesmo padrão que iTerm2, kitty, WezTerm e VS Code usam), que permitem ao gravador dividir o fluxo por comando (curioso sobre como o OSC 133 funciona e onde ele morde? → docs/osc133.md; como o gravador em si é construído? → docs/how-it-records.md):
┌ your terminal ─────────────────────────────┐
│ backscroll run │
│ └─ $SHELL on a PTY (bytes pass through) │
│ ├─ OSC 133 marks → command segments │
│ └─ SQLite: cmd, cwd, exit, duration, │
│ zstd-compressed output + FTS5 │
└────────────────────────────────────────────┘
- Tudo permanece na sua máquina. Sem daemon, sem nuvem, sem telemetria. Um arquivo SQLite em
~/.local/share/backscroll/backscroll.db. - As saídas são comprimidas com zstd; saídas grandes mantêm cabeça + cauda (os limites são configuráveis). Aplicativos de tela alternativa (vim, htop, less) são excluídos, para que seu banco de dados não fique cheio de lixo de TUI.
- A busca é SQLite FTS5 com trigramas: busca por substring sem diferenciar maiúsculas/minúsculas sobre comandos e saídas.
- Fechar a janela do terminal no meio de um comando não perde a saída: ao desligar, o backscroll libera o que o comando imprimiu até então antes de sair.
Instalação
Instalação rápida (Linux/macOS — baixa o binário correto para sua plataforma, verifica seu sha256, instala em ~/.local/bin, sem sudo):
curl -fsSL https://raw.githubusercontent.com/soren-achebe/backscroll/main/install.sh | sh
(Leia install.sh primeiro se quiser — é curto. Fixe uma versão com BACKSCROLL_VERSION=v0.11.1, mude o destino com BACKSCROLL_INSTALL_DIR. Depois, backscroll upgrade atualiza o binário no lugar — verificado por checksum, apenas quando você o executa, e recusa instalações que pertencem a um gerenciador de pacotes.)
Homebrew (macOS):
brew install soren-achebe/tap/backscroll
Pacotes Debian/Ubuntu e Fedora (.deb / .rpm) estão anexados a cada release.
Windows (Scoop):
scoop bucket add backscroll https://github.com/soren-achebe/scoop-bucket
scoop install backscroll
Com mise (usa o backend ubi — puxa o binário de release com checksum; note que a janela de segurança minimum_release_age do mise pode ficar atrás do release mais recente por design):
mise use -g ubi:soren-achebe/backscroll
Com Go:
go install github.com/soren-achebe/backscroll@latest
Ou pegue um binário estático (linux/darwin/windows × amd64/arm64) de releases:
curl -sL https://github.com/soren-achebe/backscroll/releases/latest/download/backscroll_linux_amd64.tar.gz \
| tar xz backscroll
sudo install backscroll /usr/local/bin/
Os tarballs de release incluem uma página de manual (man/backscroll.1; a fonte é scdoc, reconstrua com scdoc < man/backscroll.1.scd > man/backscroll.1).
Configuração (30 segundos)
-
Adicione a integração ao seu rc do shell (inerte fora de sessões gravadas):
# ~/.zshrc eval "$(backscroll init zsh)" # ~/.bashrc eval "$(backscroll init bash)" # ~/.config/fish/config.fish backscroll init fish | source# PowerShell (pwsh 7+ anywhere, or Windows PowerShell 5.1) — add to $PROFILE: backscroll init pwsh | Out-String | Invoke-Expression -
Inicie um shell gravado:
backscroll runPara gravar todo terminal automaticamente, torne
backscroll runo comando/perfil do seu terminal, ou adicione ao final do seu rc:[[ -z "$BACKSCROLL_ACTIVE" ]] && command -v backscroll >/dev/null && exec backscroll runbackscroll runinicia um shell interativo simples — então o bash lê~/.bashrce capta o trecho. Se você quiser semântica de shell de login em vez disso, usebackscroll run --login(e lembre-se de que um bash de login lê~/.bash_profile, não~/.bashrc).
…ou zero configuração
Se o seu shell ou terminal já emite marcas de comando, backscroll run grava com nada instalado — pule o passo 1 completamente:
| você está executando | zero-configuração | texto do comando vem de |
|---|---|---|
| fish ≥ 4.0 | ✓ | OSC 133 nativo (cmdline_url) |
| nushell | ✓ | reconstruído a partir do eco do terminal |
| integração de shell do VS Code no seu rc | ✓ | suas marcas OSC 633 |
| integração de shell do kitty / WezTerm no seu rc | ✓ | cmdline= / WEZTERM_PROG |
| Ghostty, iTerm2, qualquer terminal OSC 133 simples | ✓ | reconstruído a partir do eco do terminal |
| PowerShell (Windows/qualquer lugar) | trecho recomendado | init pwsh (OSC 633 zero-configuração sob VS Code) |
O trecho ainda é o caminho de ouro — seu texto de comando é autoritativo e adiciona o seletor Ctrl-X Ctrl-P e a conclusão por tab — e coexiste limpo com tudo acima (marcas duplicadas colapsam). Detalhes:
fish ≥ 4.0
O fish 4 emite marcas OSC 133 (com a linha de comando anexada) nativamente, então backscroll run grava com zero configuração. O trecho ainda vale a pena adicionar para o atalho do seletor Ctrl-X Ctrl-P e a conclusão por tab; ter ambos ativos é ok (marcas duplicadas colapsam).
nushell
O nu vem com integração de shell ativada por padrão (marcas OSC 133, códigos de saída reais, cwd via OSC 7), então backscroll run grava sessões do nu sem nada para instalar. O nu nunca reporta o texto do comando estruturalmente, então o backscroll o reconstrói a partir do eco do terminal (veja a nota do Ghostty abaixo) — texto exato, incluindo pipelines multilinha, linhas quebradas e unicode, verificado contra os repaints de prompt por tecla do reedline no CI. Uma peculiaridade do nu: Ctrl-C durante um comando grava saída 1, porque é isso que o próprio nu reporta.
VS Code shell integration
Se o seu shell carrega o shellIntegration-*.sh do VS Code (a instalação manual recomendada para configurações tmux/SSH), o backscroll lê suas marcas OSC 633 — texto do comando, códigos de saída e cwd — sem trecho instalado. Os metadados 633 são consumidos, nunca armazenados na saída gravada.
kitty / WezTerm shell integration
O kitty.bash do kitty / kitty-integration do zsh anexam a linha de comando à sua marca OSC 133;C (cmdline=, com aspas de shell), e wezterm.sh reporta como uma variável de usuário WEZTERM_PROG — o backscroll decodifica ambos (incluindo remontar o base64 do WezTerm, que chega dividido para comandos com mais de 57 bytes), além de códigos de saída e cwd via OSC 7, sem trecho instalado.
Ghostty, iTerm2, or any plain-OSC 133 terminal
Esses emissores marcam limites de prompt/comando, mas nunca reportam o texto do comando — então o backscroll o reconstrói a partir do eco do terminal: ele reproduz os bytes que o shell ecoou entre as marcas de fim de prompt e pré-execução (teclas, backspaces, movimento de cursor, redraws do ZLE, até popups do fzf) através de um pequeno modelo de linha de terminal e armazena a linha visível final. Texto real do comando, saídas e códigos de saída sem trecho instalado. Os scripts de integração de shell do iTerm2 (os ativos dentro de tmux/SSH) são totalmente tratados — comandos multilinha através de seus prompts de continuação A;k=s, cwd via OSC 1337;CurrentDir, e códigos de saída corretos em ambos os shells — e seus metadados com estado RemoteHost/CurrentDir são consumidos, nunca armazenados. Os status de saída do bash do Ghostty são atualmente sempre 0 devido a um bug no script upstream (veja docs/osc133.md, pegadinha 15).
Windows
backscroll run grava o PowerShell através de um ConPTY pseudoconsole — mesmo design de passagem, mesmo banco de dados SQLite local. Adicione o trecho init pwsh ao $PROFILE (funciona no pwsh 7+ e no Windows PowerShell 5.1) para texto exato do comando, códigos de saída e cwd — além de conclusão por tab e o seletor Ctrl-X Ctrl-P; um shell que já carrega a integração de shell do VS Code é zero-configuração via suas marcas OSC 633. (backscroll run escolhe pwsh > powershell > cmd; substitua com BACKSCROLL_SHELL. O cmd.exe não tem integração que emite marcas, então as sessões funcionam, mas nada é segmentado — usuários de Clink podem emitir OSC 133 a partir do filtro de prompt.)
Traga seu histórico existente
Um banco de dados novo significa um seletor vazio. Alimente-o a partir do histórico que você já tem (backscroll doctor lista o que ele pode encontrar, com contagens de entradas):
$ backscroll import atuin
imported 48312 entries from atuin (~/.local/share/atuin/history.db)
$ backscroll import zsh
imported 9871 entries from zsh (~/.zsh_history)
As importações do atuin são as mais ricas (timestamps, códigos de saída, cwd, hostname — a sincronização delas significa que uma importação cobre todas as suas máquinas). O nu corresponde a isso se você usou o backend de histórico SQLite do nushell (o padrão de texto simples também importa — com detecção de conteúdo, então qualquer arquivo funciona). O zsh obtém timestamps e durações se você tiver EXTENDED_HISTORY definido, o bash obtém timestamps se você tiver HISTTIMEFORMAT definido, o fish sempre tem timestamps, o pwsh lê o ConsoleHost_history.txt do PSReadLine (continuações multilinha com crase e tudo). Entradas importadas não têm saída armazenada — ninguém estava gravando naquela época — mas list, search, pick (e o seletor Ctrl-X Ctrl-P), e stats funcionam sobre elas desde o primeiro dia, e seu histórico lê como uma linha do tempo contínua. Reexecutar uma importação é incremental: só adiciona entradas que ainda não viu.
(Curioso sobre como esses arquivos realmente se parecem no disco — bytes metafied do zsh, continuações com crase do PSReadLine, nanossegundos do atuin? Notas de campo: docs/history-files.md.)
Uso
| comando | o que faz |
|---|---|
backscroll show | saída completa do último comando |
backscroll show -3 | terceiro comando mais recente |
backscroll show 3141 | por id · --raw mantém cores |
backscroll search <text> | busca de texto completo em comandos + saídas |
backscroll search -C 3 <text> | …com 3 linhas de contexto ao redor de cada linha de saída correspondente, como grep -C (-A/-B também funcionam) |
backscroll pick | seleção difusa de um comando (fzf) com pré-visualização ao vivo da saída |
| Ctrl-X Ctrl-P no prompt | escolha um comando passado e insira-o no cursor (a linha atual vira a consulta) |
backscroll list -n 50 | comandos recentes com código de saída/duração/tamanho |
... --exit fail --since 2h | filtros compartilhados (listar/buscar/selecionar/exportar): apenas falhas, últimas 2 horas |
... --since 2026-07-20 --until 2026-07-21 | --until limita a janela (exclusiva) — exatamente aquele dia |
... --cwd . | apenas comandos executados neste diretório (ou abaixo dele) |
backscroll note "this one fixed it" | anexe uma nota ao último comando — as notas aparecem em listar/mostrar/buscar e são pesquisáveis (note -3 "…" para comandos mais antigos, --rm remove) |
backscroll diff 3141 | o que mudou em relação à execução anterior do mesmo comando |
backscroll diff -2 -1 | diff unificado de quaisquer duas saídas armazenadas (contexto -U n) |
backscroll export -1 | comando + saída como um bloco markdown, pronto para colar em uma issue (--details o recolhe) |
backscroll export --exit fail --since 1d | todas as falhas de hoje como um relatório markdown — os filtros também funcionam aqui |
backscroll export 3141 --format cast | asciicast v2 — reproduza com asciinema play |
backscroll export -1 --format json | registro estruturado para scripts |
backscroll export -1 --format html -o out.html | página HTML autocontida com cor ANSI completa — anexe a um ticket, compartilhe como está |
backscroll exec make test | execute um comando fora de qualquer sessão gravada e armazene sua saída/código de saída/tempo — jobs cron, etapas de CI, builds (detalhes) |
backscroll import atuin | popule o banco de dados a partir do seu histórico do atuin — timestamps, códigos de saída, diretórios de trabalho e hosts são transferidos (detalhes) |
backscroll import zsh / bash / fish | …ou de arquivos de histórico simples |
backscroll sync init ~/Sync/bks | sincronização entre máquinas através de qualquer pasta compartilhada — criptografada, sem servidor (detalhes) |
... --host laptop / --host local | filtro de listar/buscar/selecionar: apenas o histórico daquela máquina |
backscroll stats | quanto está armazenado |
backscroll stats --by cmd --exit fail --since 1w | o que mais falhou esta semana — contagem, % de falhas, tempo total decorrido e um sparkline de atividade por comando (--by cwd|exit|host|session|day também) |
backscroll prune --older 30d | esqueça entradas antigas |
backscroll delete <id> | esqueça uma entrada (aquela curl -H "Authorization: ...") |
backscroll redact <id|-N> | mascare permanentemente tokens/chaves/senhas em uma entrada armazenada (--dry-run pré-visualiza) |
backscroll mcp | servidor MCP: deixe seu agente de codificação de IA consultar seu histórico (detalhes) |
backscroll serve | interface web local: navegue + pesquise seu histórico no navegador (detalhes) |
backscroll off / on | pausar / retomar a gravação nesta sessão |
backscroll doctor | verifique se tudo está conectado |
O atalho Ctrl-X Ctrl-P vem com o snippet backscroll init <bash|zsh|fish|pwsh> (requer fzf):
ele abre o seletor sobre tudo o que você gravou — o que você já
digitou vira a consulta inicial — e insere o comando selecionado
de volta no seu prompt, como Ctrl-R, mas você escolhe pelo que o
comando imprimiu, não apenas pelo que digitou. Defina BACKSCROLL_NO_BIND=1
antes do snippet para desativar. (No bash, o atalho requer bash ≥ 4.0;
no bash 3.2 padrão do macOS, ele é ignorado — a gravação em si ainda
funciona lá. No PowerShell, ele usa PSReadLine, que acompanha o pwsh.)
Comandos de uso único (cron, CI, builds)
Nem tudo acontece dentro de uma sessão interativa. backscroll exec
envolve um único comando — sem shell, sem PTY, sem configuração — e armazena sua
saída combinada stdout+stderr, código de saída, diretório de trabalho e duração como qualquer outro
comando gravado:
backscroll exec make -j4 test # flags after the command belong to it
backscroll exec sh -c 'pg_dump app | gzip > backup.gz' # shell features? bring a shell
Ele se comporta como tee colado ao seu comando: a saída passa direto
(--quiet grava silenciosamente), o stdin está conectado para que pipelines
funcionem, Ctrl-C chega ao processo filho normalmente, e o código de saída é
espelhado — incluindo 128+n para mortes por sinal — então ele se encaixa em
crontabs, Makefiles e scripts de CI sem alterar o comportamento deles.
Um problema de gravação (banco de dados ausente, disco cheio) nunca interrompe ou falha o
próprio comando; você recebe um aviso no stderr e o comando é executado mesmo assim.
O caso de uso matador é o cron. Em vez de arqueologia MAILTO ou
arquivos >> /var/log/backup.log 2>&1 que ninguém rotaciona:
17 3 * * * backscroll exec /usr/local/bin/nightly-backup
…e na próxima semana, quando você se perguntar por que o backup de terça-feira estava lento:
$ backscroll list --since 1w --exit fail
$ backscroll search "No space left" --since 1w
$ backscroll diff -1 # what changed vs. the previous run?
Falhas de inicialização também são gravadas (exit 127, com o texto do erro
pesquisável) — o clássico "comando não encontrado" silencioso do cron finalmente deixa
um rastro. Até falhas --quiet permanecem visíveis: backscroll stats --by cmd --exit fail --since 1w as conta como qualquer outra coisa.
GitHub Actions
setup-backscroll
instala o backscroll em qualquer runner (Linux/macOS/Windows, verificado por checksum):
- uses: soren-achebe/setup-backscroll@v1
- run: backscroll exec -- make test
O README dele tem as duas receitas que valem a pena copiar: compare a saída de uma etapa com falha
com a última execução bem-sucedida (persista o banco de dados com actions/cache,
depois backscroll diff -1) e um relatório de falha HTML autocontido
enviado como artefato de build.
tmux / zellij / screen / SSH
O backscroll envolve um shell, então ele se integra naturalmente com multiplexadores — basta decidir de que lado do tmux você quer usá-lo:
- Dentro de cada painel (recomendado): use o snippet de rc
exec backscroll runacima (ou defina odefault-command "backscroll run"do tmux). Cada painel vira sua própria sessão gravada, ebackscroll show -1no painel A pode recuperar a saída que rolou para fora no painel B — o banco de dados é compartilhado. A proteção$BACKSCROLL_ACTIVEevita gravação dupla se você aninhar. - Fora do tmux (
backscroll rune depoistmuxdentro) não é útil: o tmux redesenha a tela inteira, então a segmentação por comando se perde. O backscroll detecta aplicativos de tela cheia via alt-screen e os ignora; execute-o dentro dos painéis em vez disso. - Busca em popup (tmux ≥ 3.2 + fzf):
backscroll init tmux >> ~/.tmux.confvinculaprefix + Ba um popup que faz busca difusa em cada comando gravado com uma pré-visualização ao vivo de sua saída armazenada (prefix + F= apenas falhas). Qualquer painel, a qualquer momento — entre nas páginas pela saída completa,qde volta ao trabalho. - zellij: mesma história — grave dentro de cada painel, e
backscroll init zellijimprime um snippet de keybinds que coloca a mesma busca difusa em um painel flutuante emAlt b(Alt Shift b= apenas falhas), além deAlt rpara escolher um comando passado e digitá-lo no seu prompt — inserido para edição, não executado (comandos multilinha chegam via colagem entre colchetes, então novas linhas embutidas não pressionam Enter). Funciona com qualquer shell, sem necessidade de snippet de rc. Anexe o snippet a~/.config/zellij/config.kdlse você ainda não tiver um blocokeybinds; caso contrário, copie as três linhasbindpara o seu bloco existente (o zellij ignora um segundo blocokeybinds). - GNU screen: grave dentro de cada janela, e
backscroll init screen >> ~/.screenrcvinculaC-a Bà mesma busca difusa em uma janela descartável (C-a F= apenas falhas) que se fecha sozinha quando você sai do seletor. Atenção: isso substitui os padrões do screenC-a B(pow_break) /C-a F(fit) — reatribua se você os usa. - Via SSH: o backscroll grava na máquina onde o shell é executado. Instale-o no host remoto e adicione o snippet de rc lá; use sync se quiser mesclar os históricos.
Sincronização entre máquinas
backscroll search "connection refused" — entre seu laptop, seu desktop
e aquela máquina de build em que você entra via SSH:
laptop$ backscroll sync init ~/Sync/backscroll # any shared folder:
# Syncthing, Dropbox, rsync…
laptop$ backscroll sync export
desktop$ # copy ~/.config/backscroll/sync.key from the laptop, then:
desktop$ backscroll sync init ~/Sync/backscroll
desktop$ backscroll sync import
desktop$ backscroll search "connection refused" # both machines' history
3141 2d ago exit 1 [laptop] curl http://10.0.0.7:8080/health
…connection refused…
desktop$ backscroll list --host laptop # or filter by machine
Sem servidor, sem conta: cada máquina anexa seu próprio log criptografado de ponta a ponta (XChaCha20-Poly1305, arquivo de chave compartilhada que você copia uma vez) à pasta e importa os das outras. Logs somente anexação por máquina tornam tudo livre de conflitos — sincronizar duas vezes, parcialmente ou fora de ordem nunca corrompe nada, e qualquer ferramenta de sincronização de arquivos que você já usa é um transporte válido.
A privacidade é garantida antes de qualquer coisa sair da máquina: padrões de redação
(integrados + os seus) são aplicados a cada comando e saída na exportação, padrões de
ignorar pulam entradas inteiras, e apenas o texto simples pesquisável é
enviado — bytes brutos do terminal (reproduções show --raw) nunca saem da máquina
que os gravou. backscroll sync status mostra o progresso por máquina e
impressões digitais da chave. Notas de design: docs/sync-design.md.
Agentes de IA (MCP)
backscroll mcp é um servidor Model Context Protocol
integrado (stdio, zero dependências), então um agente de codificação de IA pode responder
"o que aquele comando imprimiu?" a partir do seu histórico gravado em vez de
adivinhar — ou reexecutar algo caro ou destrutivo:
- search_output — "encontre onde o build disse pela primeira vez
undefined symbol" (context_linesdá contexto estilo grep -C ao redor de cada ocorrência) - get_output — a saída completa de qualquer comando (
-1= o seu último) - list_commands — histórico recente, por exemplo, apenas falhas
- diff_output — o que mudou em relação à execução anterior do mesmo comando
Registre-o com seu cliente:
# Claude Code
claude mcp add backscroll -- backscroll mcp
// Cursor / Windsurf / VS Code-style mcpServers config
{ "mcpServers": { "backscroll": { "command": "backscroll", "args": ["mcp"] } } }
A configuração por cliente (Claude Code/Desktop, Codex, Cursor, Windsurf, VS Code, Zed, Gemini CLI) está no site de documentação: Guia de agentes de IA.
Ele também está listado no Registro oficial de MCP
como io.github.soren-achebe/backscroll, e cada versão inclui um
backscroll-<version>.mcpb pacote
(macOS/Linux) para clientes que instalam servidores MCP a partir de um arquivo — sem
instalação separada necessária, embora você ainda queira a configuração completa acima para
haver histórico gravado para pesquisar. Para configurações MCP em contêineres, há uma
imagem multi-arquitetura pré-construída:
docker run -i --rm \
-v ~/.local/share/backscroll:/data/.local/share/backscroll:ro \
ghcr.io/soren-achebe/backscroll
(monte seu banco de dados somente leitura; a gravação em si ainda quer o binário nativo envolvendo seu shell real).
Segredos são mascarados por padrão: tudo o que é entregue ao cliente passa
pelos mesmos padrões de redação que backscroll redact (integrados para
formatos comuns de token + seus ~/.config/backscroll/redact), além dos
padrões de ignorar que já mantêm comandos correspondentes fora do banco de dados inteiramente.
backscroll mcp --no-redact desativa o mascaramento se você realmente quiser. O
servidor apenas lê o banco de dados local — a gravação continua acontecendo em seus shells,
e nada sai da máquina exceto o que seu agente pedir.
A relação também funciona ao contrário: aponte o backscroll para seu agente e cada comando que ele executar em sua máquina ou VM de desenvolvimento vira uma trilha de auditoria pesquisável por comando — veja Audite o que seu agente executou.
Interface web
backscroll serve inicia uma interface web local, somente leitura sobre seu histórico
gravado (--open também a abre no seu navegador):

- Busca enquanto você digita em comandos e suas saídas (FTS5 por baixo dos panos — instantânea mesmo com dezenas de milhares de comandos), com trechos correspondentes, mais os mesmos filtros da CLI (somente falhas, intervalo de tempo). Um seletor de contexto mostra as linhas de saída correspondentes com ±2/±5 linhas ao redor, estilo grep (paridade com
search -C). Expandir um resultado destaca cada ocorrência dentro da saída completa, com um seletor ↑ 3/17 ↓ para navegar entre elas — mesmo quando as cores ANSI dividem a palavra. - Visualizações de estatísticas — alterne do histórico para por comando / diretório / saída / host / dia (contagem, % de falhas, tempo total decorrido), filtradas pelos filtros ativos. Linhas de diretório, saída e host são clicáveis: clique em "exit 127" e você volta ao histórico exibindo exatamente esses comandos ("quais comandos falharam assim, e o que eles disseram?").
- Cores preservadas — a saída ANSI armazenada é renderizada em HTML, então
ls, executores de teste e logs de build parecem como no terminal. O spam de barra de progresso (sobrescrições\r) colapsa para seu estado final. - Diff com um clique em relação à execução anterior do mesmo comando — o botão "o que mudou desde o healthcheck de ontem?".
- Links permanentes — cada comando tem um link profundo
#42que o abre em página inteira (saída não truncada, carimbo de data/hora absoluto, botão de copiar link). Deixe um log de build aberto em uma aba fixada, marque a saída do teste instável ou cole o link nas suas anotações e encontre-o novamente amanhã. - Baixar como HTML — um clique salva qualquer comando como a mesma página autocontida que
export --format htmlproduz (cores completas, sem assets externos, sem JS): anexe-a a um ticket ou entregue-a a um colega, navegador opcional. - Local-only por design: vincula-se a
127.0.0.1:4133, serve apenas GETs e rejeita solicitações cujo cabeçalhoHostnão seja localhost, para que um site malicioso não leia seu histórico via DNS rebinding. Se você substituir--addrpor um endereço não-loopback, ele avisa, bem alto.--redactmascara segredos em tudo que é servido, usando os mesmos padrões debackscroll redact.
Sem etapa de build, sem node_modules — a UI é um único arquivo HTML embutido, e tudo está no mesmo binário estático.
vs. outras ferramentas
| registra comandos | registra saídas | pesquisável | estrutura por comando | |
|---|---|---|---|---|
| histórico do shell / atuin / hishtory | ✓ | ✗ | ✓ | ✓ |
script / asciinema | ✓ | ✓ | ✗ (blob bruto) | ✗ |
| scrollback do terminal | ✓ | até não estar mais | ✗ | ✗ |
| backscroll | ✓ | ✓ | ✓ (FTS5) | ✓ |
Funciona bem com suas outras ferramentas
backscroll é um gravador, não um prompt ou gerenciador de histórico — ele foi feito para rodar junto com o que seu shell já faz. CI dirige sessões reais contra versões fixas e reais dos suspeitos populares e verifica que comandos, saídas e códigos de saída são todos registrados corretamente e que a outra ferramenta continua funcionando (shell/test_compat_matrix.py):
| testado com | bash | zsh | fish |
|---|---|---|---|
| atuin (incl. seu Ctrl-R TUI) | ✓ | ✓ | ✓ |
| starship (ambas ordens de carga) | ✓ | ✓ | ✓ |
| zoxide | ✓ | — | ✓ |
| direnv | ✓ | — | — |
| oh-my-zsh | ✓ | ||
| powerlevel10k (incl. prompt instantâneo) | ✓ | ||
| bash-preexec (ambas ordens de carga) | ✓ | ||
bind -x / zle widgets (estilo fzf; o Ctrl-R real do atuin acima) | ✓ | ✓ | ✓ |
Um achado que vale a pena conhecer mesmo que você não use backscroll: com starship ≤ 1.26 no bash, qualquer coisa que leia $? de um PROMPT_COMMAND que o starship envolveu vê 0 em vez do status de saída real — o próprio teste _starship_set_return do starship é imediatamente derrotado pelo teste [[ -n ... ]] que o segue. backscroll contorna isso capturando a saída real em seu trap de DEBUG antes que os frameworks de prompt rodem (o PR #7606 aberto do starship reestrutura o wrapping e corrigiria o caso geral).
Overhead
Medido em uma VM modesta de 2 vCPUs (AMD EPYC), mediana de execuções repetidas — execute você mesmo com go test ./internal/record -bench . mais um harness de PTY:
- Latência de teclas: +0,05 ms de latência de eco mediana em comparação com um shell puro (0,22 ms vs 0,16 ms; p95 +0,1 ms). Um frame de 60 Hz é 16,7 ms — você não consegue perceber isso.
- Saída em massa:
cattar um arquivo de 27 MB pelo gravador roda a ~31 MB/s vs ~56 MB/s em um PTY puro. Emuladores de terminal renderizam muito mais devagar do que qualquer um dos dois, então o gravador nunca é o que você espera. - Parsing: o segmentador OSC 133 escaneia ~680 MB/s em um núcleo; o buffer de captura head/tail escreve à velocidade de memcpy (~44 GB/s).
- Disco: as saídas são comprimidas com zstd e limitadas por comando (primeiros 256 KiB + últimos 1 MiB por padrão, configurável). O índice de pesquisa lê através do armazenamento comprimido em vez de manter sua própria cópia em texto puro (fts5 external content), o que reduz aproximadamente pela metade o banco de dados em comparação com a configuração ingênua — medido 28,2 → 14,9 MB em uma carga de trabalho idêntica de 1.000 comandos com muita saída. Um dia típico de trabalho interativo adiciona alguns MB a um único arquivo SQLite.
backscroll prune --older 30dmantém uma janela rolante,backscroll prune --max-size 500Mlimita o tamanho total do banco de dados removendo as entradas mais antigas, e ambos compactam o arquivo completamente.
Notas de privacidade
Registrar tudo que seu terminal imprime é o objetivo — e uma responsabilidade. backscroll é local-only por design. Ainda assim:
-
Padrões de ignorar: coloque um regexp Go por linha em
~/.config/backscroll/ignoree comandos correspondentes nunca são armazenados:^vault ^op\b password|token|secret -
backscroll offpausa a gravação para a sessão (backscroll onretoma) — para aquela rápida dança de credenciais. -
backscroll delete <id>remove uma entrada (e seu índice FTS) para as vezes em que um segredo foi impresso. -
Redação:
backscroll redact <id>mascara permanentemente segredos que entraram em uma entrada — tokens AWS/GitHub/Slack/Stripe/OpenAI/Google/npm/PyPI/GitLab, JWTs, valorespassword=/api_key:, credenciais em URLs, cabeçalhosAuthorization:, blocos de chave privada — na linha de comando, saída e índice de pesquisa.show --redacteexport --redactfazem o mesmo de forma não destrutiva, para que o que você cola em uma issue seja limpo mesmo quando a cópia armazenada não é. Adicione seus próprios padrões (um regexp Go por linha) em~/.config/backscroll/redact. A máscara baseada em padrões é melhor esforço — olhe antes de compartilhar. -
backscroll prune --older 30dmantém uma janela rolante;--max-size 500Mlimita o tamanho total do DB (as entradas mais antigas vão primeiro). -
O DB é only-owner (diretório
0700, arquivo0600, aplicado em cada abertura — desde v0.11.1) sob seu home; trate-o como seu arquivo de histórico do shell, que contém a mesma classe de dados. Ele não é criptografado em repouso: qualquer pessoa com sua conta Unix (ou root) pode lê-lo, exatamente como~/.bash_history,~/.sshou seu perfil de navegador. Se seu modelo de ameaça inclui o disco saindo do seu controle, use criptografia de disco completo. O mesmo para~/.config/backscroll/sync.keyse você usar sync — qualquer pessoa que o tenha pode ler seu histórico sincronizado (não o coloque na própria pasta de sync). -
Não rode em contas compartilhadas.
-
Verifique o que você baixa (v0.12.1+): cada artefato de release carrega uma atestação de procedência de build assinada provando que foi construído pelo workflow de release público deste repositório a partir do commit marcado — não no laptop de alguém. Verifique qualquer tarball, pacote ou o arquivo de checksums com:
gh attestation verify backscroll_linux_amd64.tar.gz -R soren-achebe/backscroll -
Rede: exatamente um comando alguma vez toca a rede —
backscroll upgrade, que busca um release do GitHub quando (e somente quando) você o executa. Não há checagem de atualização em segundo plano, nenhuma telemetria, e gravação/pesquisa/serve/sync nunca fazem conexão com lugar nenhum.
Encontrou uma maneira de derrotar algum desses controles? Isso é uma vulnerabilidade — veja SECURITY.md para reportar em privado e o modelo de ameaça completo.
Status
Início, mas funcionando: bash, zsh, fish e nushell no Linux e macOS, além de PowerShell no Windows (ConPTY), com importação de histórico (atuin/zsh/bash/fish), padrões de ignorar, pausa de sessão (off/on), diff de saída, o seletor fzf (pick, Ctrl-X Ctrl-P, popups do tmux), sync criptografado entre máquinas, um servidor MCP para agentes de IA, uma UI web local (serve) e um comando doctor. Issues e PRs são bem-vindos; veja CONTRIBUTING.md. Detalhes versão por versão estão no CHANGELOG.
Licença
MIT