Skip to main content

Lensfy

Português · English

Gerenciador local de clusters Kubernetes — uma alternativa open-source ao Lens/OpenLens que roda inteiramente na sua máquina, sem serviços externos obrigatórios.

Multi-cluster, logs e métricas em tempo real, terminal/exec integrado, shell kubectl, port-forward, deploy de manifestos/Helm, editor YAML (Monaco) com histórico de versões, e um assistente de IA (Claude API) que diagnostica problemas e automatiza operações no cluster — com aprovação.

A interface é um PWA instalável, servida pelo próprio backend (FastAPI + Jinja2 + JS/CSS vanilla — sem build step, sem npm). O acesso é restrito à máquina local e protegido por um token de dispositivo (sem login/senha).


Sumário


Recursos

Multi-cluster

  • Importar kubeconfig por caminho, upload de arquivo ou colando o conteúdo — detecção de contextos com checklist (importe vários de uma vez).
  • Importar do Google Cloud (GKE): aba gcloud lista projetos e clusters e roda get-credentials por você (requer gcloud + gke-gcloud-auth-plugin).
  • Seletor de clusters com busca, status/versão por item, troca em um clique, reordenação por arrastar e remoção. Importar nunca trava a UI (clusters sobem em segundo plano).
  • Sessão por cluster: ao voltar a um cluster, o Lensfy restaura onde você parou — a view, o filtro de namespace e as abas abertas no dock (logs/console/YAML/IA).

Explorer de recursos

  • Árvore com Pods, Deployments, StatefulSets, DaemonSets, Jobs, CronJobs, Services, Ingress, ConfigMaps, Secrets, PVC, StorageClasses, Namespaces, Nodes, Events, RBAC (roles/bindings), LimitRanges e ResourceQuotas.
  • Tabelas ao vivo (/ws/watch): pods criados/removidos, status e restarts atualizam sozinhos — reconciliação incremental sem flicker (seleção e scroll preservados).
  • Filtro global de namespace multi-seleção (estilo Lens) e busca global / command palette (foco com /).
  • Painel de detalhes (drawer) por recurso: resumo, metadados, status, containers (estado/restarts/imagens), condições, métricas ao vivo (CPU/mem) e eventos.

Observabilidade

  • Dashboard: saúde do cluster (nós, versões), fases dos pods, restarts, deployments disponíveis vs desejados, uso de CPU/memória e eventos de alerta.
  • Métricas: nós/pods via metrics.k8s.io, cards de resumo, colunas ordenáveis e barras coloridas por limiar.
  • Problemas: varredura do cluster que lista issues por categoria e severidade (CrashLoop, ImagePull, OOMKilled, pendentes, PVC não vinculado, nós com pressão/cordon, etc.).
  • Recursos & Cotas: soma de requests/limits por namespace, ResourceQuota usado/limite e containers sem requests/limits (risco de OOM/SLA).
  • Mapa de tráfego: topologia Ingress → Service → Workload → Pods em SVG, com zoom/pan.

Tempo real (terminal, logs, console)

  • Logs ao vivo: filtro, auto-scroll, copiar, baixar e seletor de container.
  • Terminal/console (xterm.js): exec em pod (PTY), shell de nó (estilo Lens, via pod privilegiado + nsenter) e shell kubectl com o contexto do cluster.
  • Dock inferior estilo Lens: logs, console, YAML e IA em abas, várias ao mesmo tempo, painel redimensionável que empurra a view (não sobrepõe).

Editor YAML & deploy

  • Editor YAML (Monaco) para ver/editar/aplicar qualquer recurso, com autocomplete de Kubernetes e diff.
  • Histórico de versões (até 5) por recurso, gravado a cada Aplicar: carregar uma versão, diff contra o editor ou diff entre duas versões.
  • Apply robusto: realinha o resourceVersion ao estado atual e repete em conflito (sem falhas intermitentes de save).
  • Deploy de manifestos: editor Monaco com templates, Construtor (formulário → YAML), validação dry-run, e arrastar-e-soltar de arquivos/pastas YAML (multi-documento).

Operações

  • Workloads: escalar, restart (rollout), excluir.
  • Rollout: histórico de revisões, undo (rollback) e pause/resume.
  • Nós: cordon/uncordon e drain (respeitando PodDisruptionBudgets via Eviction API).
  • CronJobs: trigger (executar agora) e suspend/resume.
  • Recursos: editar requests/limits por container; editar Secrets/ConfigMaps in-place.
  • Port-forward: túneis para pods, gerenciados na UI.
  • Helm: releases, install/upgrade/rollback e uninstall.

Assistente de IA (opcional)

  • Agente SRE sobre a Claude API: ferramentas read-only (visão geral, listar/ver recursos, logs, top) rodam automaticamente; ações que alteram o cluster (escalar/restart/excluir/cordon/drain/rollback/cronjob) exigem Aprovar/Negar na UI.
  • Pode ser desligado por completo (LENSFY_AI_ALLOW_MUTATIONS=false) e os diagnósticos podem ser salvos como relatórios.

Plataforma

  • Segurança local sem login: acesso só de loopback, allowlist de Host (anti DNS-rebinding) e token de dispositivo; tela de onboarding gera o token na primeira execução.
  • PWA instalável com app shell offline.

Requisitos

  • Python 3.12+ (testado em 3.14).
  • Um kubeconfig com acesso aos seus clusters (~/.kube/config ou importado pela UI).
  • Opcionais (cada recurso degrada com aviso quando ausente):
    • kubectl — para o shell kubectl do header.
    • helm — para a aba Helm.
    • gcloud (+ gke-gcloud-auth-plugin) — para importar clusters GKE.
    • metrics-server no cluster — para gráficos de CPU/memória.
    • Uma chave da Claude API (LENSFY_ANTHROPIC_API_KEY) — para o assistente de IA.

Instalação

Via PyPI (pip) — mais rápido

pip install --user lensfy   # cria o comando `lensfy` e o atalho "Lensfy" no menu
lensfy                      # sobe em segundo plano e abre o navegador (http://127.0.0.1:8645)
lensfy status               # está rodando? (PID, endereço, versão, log)
lensfy stop                 # para
lensfy serve                # alternativa: roda em primeiro plano (Ctrl+C para)
lensfy --port 9000          # outra porta (ou LENSFY_PORT=9000)

Requer Python 3.12+. Como no Jupyter, o pip install --user instala também o atalho do menu (~/.local/share/applications/lensfy.desktop, com ícone) — clicar nele faz o mesmo que lensfy; pip uninstall lensfy remove tudo. Com pipx/venv o comando funciona, mas o atalho fica dentro do ambiente isolado (não aparece no menu). Os dados ficam em ~/.lensfy/, a configuração (ex.: LENSFY_ANTHROPIC_API_KEY) em ~/.config/lensfy/env (KEY=VALUE, 0600) e o log do servidor em ~/.local/state/lensfy/server.log. Para iniciar automaticamente no login, use o instalador desktop abaixo.

1. Instalador desktop (Linux)

Instala num venv isolado, cria o comando lensfy e um atalho no menu de aplicativos (sem root):

git clone https://gitlab.com/fabiocax/lensfy.git
cd lensfy
./install.sh                 # instala/atualiza (re-rodar atualiza no lugar)
./install.sh --service       # + serviço systemd --user (inicia no login)

Depois:

lensfy            # inicia (se preciso) e abre no navegador
lensfy status     # estado + health + versão
lensfy stop       # para
lensfy logs       # acompanha o log
lensfy version    # versão instalada

Com o serviço systemd instalado (--service), lensfy start|stop|restart|status|logs delegam para systemctl --user … lensfy / journalctl --user -u lensfy. Re-rodar ./install.sh (com ou sem --service) atualiza a unit e reinicia o serviço se ele estiver ativo.

Configuração do app instalado: ~/.config/lensfy/env (linhas KEY=VALUE, permissão 0600), criado pelo instalador a partir de backend/.env.example — é lido pelo launcher e pelo serviço systemd. Ex.: LENSFY_ANTHROPIC_API_KEY=sk-ant-…. Depois de editar: lensfy restart. O .env do repositório nunca é copiado para a instalação nem para o .rpm.

Ou abra “Lensfy” no menu de aplicativos. Layout instalado:

Caminho Conteúdo
~/.local/share/lensfy/app código + UI
~/.local/share/lensfy/venv dependências (runtime)
~/.local/share/lensfy/VERSION versão instalada (git describe + data)
~/.config/lensfy/env configuração LENSFY_* (0600) — preservada
~/.config/systemd/user/lensfy.service serviço (só com --service)
~/.local/bin/lensfy launcher
~/.local/share/applications/lensfy.desktop atalho de menu
~/.local/state/lensfy/ pid + log (modo sem systemd; rotação a 10 MB, 0600)
~/.lensfy/ dados (SQLite, token) — preservado

Desinstalar: ./uninstall.sh (use --purge para apagar também ~/.lensfy e ~/.config/lensfy).

2. Pacote .rpm (Fedora/RHEL)

Gera um .rpm distribuível, com as dependências embutidas (instalação offline):

sudo dnf install -y rpm-build rpmdevtools python3-pip
./packaging/rpm/build-rpm.sh          # → packaging/rpm/dist/lensfy-<versão>.rpm

sudo dnf install packaging/rpm/dist/lensfy-*.rpm
lensfy                                  # ou pelo menu de aplicativos
sudo dnf remove lensfy

Os wheels embutidos são específicos da plataforma e da versão do Python do host de build (ex.: x86_64 / Python 3.14). Gere o pacote num ambiente compatível com o destino. Ajuste a licença em packaging/rpm/lensfy.spec (atualmente um placeholder). A configuração continua por usuário em ~/.config/lensfy/env.

3. A partir do código (desenvolvimento)

git clone https://gitlab.com/fabiocax/lensfy.git
cd lensfy/backend

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt   # runtime + ferramentas de teste
cp .env.example .env                  # opcional: configuração local (LENSFY_*)

requirements.txt tem só as dependências de runtime (usado pelo instalador e pelo .rpm); requirements-dev.txt inclui também pytest & cia.

Python 3.14: se algum pacote tentar compilar do código-fonte, force wheels prontas: pip install --only-binary=:all: -r requirements-dev.txt


Como rodar

Scripts de controle (a partir do código)

Na raiz do projeto:

./start.sh            # inicia em background → http://127.0.0.1:8645
./lensfy.sh status    # estado + health
./lensfy.sh logs      # acompanha o log
./lensfy.sh restart   # reinicia
./stop.sh             # para (encerra o grupo de processos)

Forma manual (desenvolvimento)

cd backend
source .venv/bin/activate
uvicorn lensfy.main:app --reload --port 8645

Editar arquivos em backend/lensfy/templates/ ou backend/lensfy/static/ só exige atualizar o navegador (sem rebuild).


Segurança

Lensfy é um app local de um usuário e foi pensado para não ser acessível de outras máquinas — sem login nem senha. Três camadas, aplicadas a toda requisição HTTP e WebSocket:

  1. Somente loopback — conexões fora de 127.0.0.0/8/::1 são recusadas (mesmo que o servidor seja exposto por engano).
  2. Allowlist de Host — bloqueia ataques de DNS-rebinding (um site remoto resolvendo seu domínio para 127.0.0.1).
  3. Token de dispositivo — gerado uma vez no equipamento (~/.lensfy/device_token, permissão 0600) e exigido em /api e /ws. A SPA o obtém em runtime; uma página de outra origem não consegue lê-lo nem forjá-lo (também derrota CSRF). Na primeira execução, uma tela de onboarding gera o token.
Variável Default Efeito
LENSFY_SECURITY_ENABLED true false desliga todas as camadas (ambiente confiável/testes).
LENSFY_ALLOW_REMOTE false true permite acesso fora do loopback (LAN) — o token continua valendo. Use com cuidado.
LENSFY_ALLOWED_HOSTS [] Valores extras aceitos no header Host (ex.: o hostname da máquina).

Outras notas:

  • O assistente de IA só executa ações que alteram o cluster após aprovação explícita; desligue com LENSFY_AI_ALLOW_MUTATIONS=false.
  • Trate kubeconfigs importados como conteúdo confiável (podem conter credenciais e comandos exec).
  • Se você regenerar/rotacionar o token, recarregue as abas abertas (a UI mostra um aviso "Sessão de dispositivo inválida → Recarregar" quando isso acontece).

Configuração (variáveis de ambiente)

Todas com prefixo LENSFY_. Veja backend/.env.example (lista comentada de todas). Onde definir:

  • App instalado: ~/.config/lensfy/env (lido pelo launcher lensfy e pelo serviço systemd).
  • Desenvolvimento: backend/.env (copie de backend/.env.example) ou variáveis exportadas no shell.

Variáveis do ambiente sempre têm precedência sobre os arquivos.

Variável Default Descrição
LENSFY_HOST 127.0.0.1 Interface de bind. 0.0.0.0 requer LENSFY_ALLOW_REMOTE=true — veja Segurança.
LENSFY_PORT 8645 Porta.
LENSFY_RELOAD 0 1 para auto-reload (dev).
LENSFY_DEBUG false Cria as tabelas do banco no startup (dispensa migrations no dev).
LENSFY_DATABASE_URL sqlite em ~/.lensfy/lensfy.db Override do banco.
LENSFY_SECURITY_ENABLED true Liga/desliga o controle de acesso local.
LENSFY_ALLOW_REMOTE false Permite acesso não-loopback (token continua exigido).
LENSFY_ALLOWED_HOSTS [] Hosts extras aceitos no header Host.
LENSFY_ANTHROPIC_API_KEY — Habilita o assistente de IA (Claude API).
LENSFY_ANTHROPIC_MODEL claude-sonnet-4-6 Modelo do assistente.
LENSFY_AI_ALLOW_MUTATIONS true false deixa a IA só diagnosticar.

Exemplos:

LENSFY_PORT=9000 ./start.sh
LENSFY_ANTHROPIC_API_KEY=sk-ant-... ./start.sh   # liga o assistente IA

Primeiros passos na UI

  1. (Primeira execução) uma tela de onboarding gera o token deste equipamento — clique em “Gerar token e começar” e depois “Entrar”.
  2. Importar cluster — no seletor de clusters (topo da sidebar) → “+ Importar cluster”:
    • Caminho / Arquivo / Colar um kubeconfig, ou
    • gcloud → escolher projeto → listar e importar clusters GKE.
  3. Navegue pela árvore de recursos (Pods, Deployments, Services, Secrets, etc.).
  4. O Dashboard mostra a saúde do cluster; Problemas, Recursos e Mapa ficam no topo.
  5. Assistente IA (botão 🤖 no header) — peça um diagnóstico ou uma ação; ações que alteram o cluster pedem Aprovar/Negar.

Instalar como app (PWA)

No Chrome/Edge, clique no ícone de instalar na barra de endereço (ou no botão Instalar do header). Abre em janela própria, com ícone no sistema.

Service workers exigem contexto seguro: localhost (ok) ou HTTPS.


Testes

cd backend
source .venv/bin/activate
pytest                    # suíte completa
pytest --cov              # com cobertura
pytest tests/test_ai.py   # um arquivo específico

Estrutura

lensfy/
├── lensfy.sh, start.sh, stop.sh   # controle da aplicação (modo dev)
├── install.sh, uninstall.sh       # instalador desktop (Linux, por usuário)
├── packaging/
│   ├── lensfy                     # launcher instalado
│   └── rpm/                       # spec + build-rpm.sh (pacote .rpm)
├── PROJECT.md                     # especificação (pt-BR)
├── CLAUDE.md                      # guia de arquitetura p/ contribuir
├── pyproject.toml                 # metadados do pacote PyPI (hatchling)
└── backend/
    ├── lensfy/                    # pacote Python publicado no PyPI
    │   ├── api/          # rotas REST (/api)
    │   ├── websocket/    # canais em tempo real (/ws): logs, terminal, watch, events, metrics, ai, kubectl
    │   ├── services/     # regras de negócio
    │   ├── repositories/ # acesso a dados
    │   ├── models/       # SQLAlchemy
    │   ├── kubernetes/   # integração com o SDK do Kubernetes, helm, gcloud
    │   ├── ai/           # assistente de IA (Claude API)
    │   ├── core/         # config + segurança (token de dispositivo)
    │   ├── web/          # serve a UI (Jinja2) + PWA
    │   ├── cli.py        # comando `lensfy`
    │   ├── migrations/   # Alembic
    │   ├── templates/    # index.html (app shell)
    │   └── static/       # css/, js/, icons/, manifest.webmanifest, sw.js
    ├── tests/
    └── requirements.txt, requirements-dev.txt   # runtime / dev+testes

Arquitetura em camadas: api/ → services/ → repositories/ → models/. Persistência local em SQLite (migrations via Alembic). Detalhes em CLAUDE.md e a especificação em PROJECT.md.


Roadmap

  • Empacotamento .deb / AppImage e wrapper desktop nativo (Tauri) para Linux/Windows/macOS.
  • Rotação de token pela UI.
  • Testes E2E (Playwright).

Publicando uma versão (PyPI)

A publicação é feita pelo CI do GitLab com Trusted Publishing (OIDC — nenhum token do PyPI fica guardado):

  1. Atualize __version__ em backend/lensfy/__init__.py (ex.: 0.2.0).
  2. Faça commit e crie a tag correspondente: git tag v0.2.0 && git push --tags.
  3. O pipeline roda lint + testes, gera sdist/wheel (python -m build, twine check) e o job publish:pypi envia ao PyPI. Ele falha se a tag não bater com __version__.

Configuração única no pypi.org (Your account → Publishing → Add a new pending publisher → GitLab): projeto lensfy, namespace fabiocax, projeto lensfy, arquivo .gitlab-ci.yml, ambiente pypi.

Build local para conferir: python -m build && twine check dist/*.


Licença

Apache License 2.0.

Metadata

Release files for lensfy 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lensfy 0.1.1
File Size Uploaded
lensfy-0.1.1.tar.gz 412.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lensfy 0.1.1
File Interpreter ABI Platform
lensfy-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 903.3 kB

Release files / lensfy-0.1.1.tar.gz

Download URL lensfy-0.1.1.tar.gz
Size 412.4 kB
Tags Source
SHA-256 checksum
How to use checksums
42f9273160f8b19ee761b1617a70d4b685f74b77166fb0648d303eaa6c5d4bb2
BLAKE2b-256 checksum
How to use checksums
f5bb04c1df8cb643b1833c17ec9af2864272c819f6044a946073c5ae4a8d9fdb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / lensfy-0.1.1-py3-none-any.whl

Download URL lensfy-0.1.1-py3-none-any.whl
Size 490.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ccc276da900ce984578a3f223b5e51bd8ddc23e338f9fe9d3967c7cef527dd63
BLAKE2b-256 checksum
How to use checksums
15becae3e72fccef4d56b0bf7fcd880274e5aa42d6cb840a216b41b658ad1ac8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page