New skills covering 10 categories: **Security & Audit**: 007 (STRIDE/PASTA/OWASP), cred-omega (secrets management) **AI Personas**: Karpathy, Hinton, Sutskever, LeCun (4 sub-skills), Altman, Musk, Gates, Jobs, Buffett **Multi-agent Orchestration**: agent-orchestrator, task-intelligence, multi-advisor **Code Analysis**: matematico-tao (Terence Tao-inspired mathematical code analysis) **Social & Messaging**: Instagram Graph API, Telegram Bot, WhatsApp Cloud API, social-orchestrator **Image Generation**: AI Studio (Gemini), Stability AI, ComfyUI Gateway, image-studio router **Brazilian Domain**: 6 auction specialist modules, 2 legal advisors, auctioneers data scraper **Product & Growth**: design, invention, monetization, analytics, growth engine **DevOps & LLM Ops**: Docker/CI-CD/AWS, RAG/embeddings/fine-tuning **Skill Governance**: installer, sentinel auditor, context management Each skill includes: - Standardized YAML frontmatter (name, description, risk, source, tags, tools) - Structured sections (Overview, When to Use, How it Works, Best Practices) - Python scripts and reference documentation where applicable - Cross-platform compatibility (Claude Code, Antigravity, Cursor, Gemini CLI, Codex CLI) Co-authored-by: ProgramadorBrasil <214873561+ProgramadorBrasil@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
363 lines
12 KiB
Python
363 lines
12 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Claude Monitor — Diagnóstico Rápido de Performance
|
|
|
|
Analisa CPU, RAM, browsers, disco e rede em ~3 segundos.
|
|
Identifica o gargalo principal e sugere ações corretivas.
|
|
|
|
Uso:
|
|
python health_check.py # Diagnóstico completo
|
|
python health_check.py --browsers-detail # Detalhe de browsers
|
|
python health_check.py --json # Output JSON puro
|
|
python health_check.py --quick # Só resumo (sem teste de rede)
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import socket
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
# Garante que psutil está disponível
|
|
try:
|
|
import psutil
|
|
except ImportError:
|
|
print("Instalando psutil...")
|
|
subprocess.check_call([sys.executable, "-m", "pip", "install", "psutil", "--quiet"])
|
|
import psutil
|
|
|
|
# Importa config do mesmo diretório
|
|
sys.path.insert(0, str(Path(__file__).parent))
|
|
from config import (
|
|
BROWSER_NAMES, CLAUDE_NAMES, API_ENDPOINT,
|
|
THRESHOLDS, classify
|
|
)
|
|
|
|
|
|
def check_cpu():
|
|
"""Verifica uso de CPU."""
|
|
cpu_percent = psutil.cpu_percent(interval=1)
|
|
cpu_count = psutil.cpu_count()
|
|
per_cpu = psutil.cpu_percent(interval=0, percpu=True)
|
|
|
|
return {
|
|
"percent": cpu_percent,
|
|
"cores": cpu_count,
|
|
"per_core": per_cpu,
|
|
"status": classify(cpu_percent, "cpu"),
|
|
}
|
|
|
|
|
|
def check_ram():
|
|
"""Verifica uso de RAM."""
|
|
ram = psutil.virtual_memory()
|
|
swap = psutil.swap_memory()
|
|
|
|
return {
|
|
"total_gb": round(ram.total / 1024**3, 1),
|
|
"used_gb": round(ram.used / 1024**3, 1),
|
|
"available_gb": round(ram.available / 1024**3, 1),
|
|
"percent": ram.percent,
|
|
"swap_used_gb": round(swap.used / 1024**3, 1),
|
|
"swap_percent": swap.percent,
|
|
"status": classify(ram.percent, "ram_percent"),
|
|
}
|
|
|
|
|
|
def check_browsers(detail=False):
|
|
"""Verifica processos de browser e consumo de RAM."""
|
|
browsers = {}
|
|
all_procs = []
|
|
|
|
for proc in psutil.process_iter(["pid", "name", "memory_info"]):
|
|
try:
|
|
info = proc.info
|
|
name_lower = info["name"].lower()
|
|
ram_mb = info["memory_info"].rss / 1024**2
|
|
|
|
for bname in BROWSER_NAMES:
|
|
if bname in name_lower:
|
|
if bname not in browsers:
|
|
browsers[bname] = {"count": 0, "ram_mb": 0, "pids": []}
|
|
browsers[bname]["count"] += 1
|
|
browsers[bname]["ram_mb"] += ram_mb
|
|
if detail:
|
|
browsers[bname]["pids"].append({
|
|
"pid": info["pid"],
|
|
"ram_mb": round(ram_mb, 0)
|
|
})
|
|
break
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
pass
|
|
|
|
total_ram_gb = sum(b["ram_mb"] for b in browsers.values()) / 1024
|
|
total_procs = sum(b["count"] for b in browsers.values())
|
|
|
|
# Formata para output
|
|
for bname in browsers:
|
|
browsers[bname]["ram_mb"] = round(browsers[bname]["ram_mb"], 0)
|
|
|
|
return {
|
|
"browsers": browsers,
|
|
"total_ram_gb": round(total_ram_gb, 1),
|
|
"total_processes": total_procs,
|
|
"ram_status": classify(total_ram_gb, "browsers_ram_gb"),
|
|
"process_status": classify(total_procs, "browsers_processes"),
|
|
}
|
|
|
|
|
|
def check_claude_processes():
|
|
"""Verifica processos do Claude Code."""
|
|
claude_procs = []
|
|
total_ram = 0
|
|
|
|
for proc in psutil.process_iter(["pid", "name", "memory_info", "cpu_percent"]):
|
|
try:
|
|
info = proc.info
|
|
name_lower = info["name"].lower()
|
|
|
|
for cname in CLAUDE_NAMES:
|
|
if cname in name_lower:
|
|
ram_mb = info["memory_info"].rss / 1024**2
|
|
claude_procs.append({
|
|
"pid": info["pid"],
|
|
"name": info["name"],
|
|
"ram_mb": round(ram_mb, 0),
|
|
})
|
|
total_ram += ram_mb
|
|
break
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
pass
|
|
|
|
claude_procs.sort(key=lambda x: x["ram_mb"], reverse=True)
|
|
|
|
return {
|
|
"count": len(claude_procs),
|
|
"total_ram_gb": round(total_ram / 1024, 1),
|
|
"processes": claude_procs[:10], # Top 10
|
|
}
|
|
|
|
|
|
def check_disk():
|
|
"""Verifica espaço em disco."""
|
|
disk = psutil.disk_usage("C:/")
|
|
free_percent = 100 - disk.percent
|
|
|
|
return {
|
|
"total_gb": round(disk.total / 1024**3, 0),
|
|
"used_gb": round(disk.used / 1024**3, 0),
|
|
"free_gb": round(disk.free / 1024**3, 0),
|
|
"used_percent": disk.percent,
|
|
"free_percent": round(free_percent, 1),
|
|
"status": classify(free_percent, "disk_free_percent"),
|
|
}
|
|
|
|
|
|
def check_network():
|
|
"""Testa latência até a API do Claude."""
|
|
try:
|
|
start = time.time()
|
|
sock = socket.create_connection((API_ENDPOINT, 443), timeout=5)
|
|
latency_ms = round((time.time() - start) * 1000, 0)
|
|
sock.close()
|
|
|
|
return {
|
|
"latency_ms": latency_ms,
|
|
"endpoint": API_ENDPOINT,
|
|
"reachable": True,
|
|
"status": classify(latency_ms, "network_latency_ms"),
|
|
}
|
|
except (socket.timeout, socket.error, OSError) as e:
|
|
return {
|
|
"latency_ms": None,
|
|
"endpoint": API_ENDPOINT,
|
|
"reachable": False,
|
|
"status": "critical",
|
|
"error": str(e),
|
|
}
|
|
|
|
|
|
def check_top_processes(n=10):
|
|
"""Lista os N processos que mais consomem RAM."""
|
|
procs = []
|
|
for proc in psutil.process_iter(["pid", "name", "memory_info"]):
|
|
try:
|
|
info = proc.info
|
|
procs.append({
|
|
"name": info["name"],
|
|
"ram_mb": round(info["memory_info"].rss / 1024**2, 0),
|
|
"pid": info["pid"],
|
|
})
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
pass
|
|
|
|
procs.sort(key=lambda x: x["ram_mb"], reverse=True)
|
|
return procs[:n]
|
|
|
|
|
|
def diagnose(results):
|
|
"""Analisa os resultados e gera diagnóstico."""
|
|
issues = []
|
|
suggestions = []
|
|
bottleneck = "ok"
|
|
severity = "ok"
|
|
|
|
cpu = results["cpu"]
|
|
ram = results["ram"]
|
|
browsers = results["browsers"]
|
|
disk = results["disk"]
|
|
network = results.get("network", {})
|
|
claude = results["claude"]
|
|
|
|
# CPU
|
|
if cpu["status"] == "critical":
|
|
issues.append(f"CPU a {cpu['percent']}% (CRITICO)")
|
|
suggestions.append("Fechar aplicativos pesados ou abas de browser desnecessarias")
|
|
suggestions.append("Verificar se Windows Update ou antivirus esta rodando em background")
|
|
bottleneck = "cpu"
|
|
severity = "critical"
|
|
elif cpu["status"] == "warning":
|
|
issues.append(f"CPU a {cpu['percent']}% (elevada)")
|
|
suggestions.append("Considerar fechar algumas abas de browser")
|
|
if severity != "critical":
|
|
bottleneck = "cpu"
|
|
severity = "warning"
|
|
|
|
# RAM
|
|
if ram["status"] == "critical":
|
|
issues.append(f"RAM a {ram['percent']}% ({ram['used_gb']} de {ram['total_gb']} GB)")
|
|
suggestions.append("Fechar browsers ou aplicativos para liberar memoria")
|
|
if severity != "critical":
|
|
bottleneck = "ram"
|
|
severity = "critical"
|
|
elif ram["status"] == "warning":
|
|
issues.append(f"RAM a {ram['percent']}% (monitorar)")
|
|
|
|
# Browsers
|
|
if browsers["ram_status"] == "critical":
|
|
issues.append(f"Browsers consumindo {browsers['total_ram_gb']} GB ({browsers['total_processes']} processos)")
|
|
suggestions.append("Fechar abas desnecessarias nos browsers")
|
|
browser_detail = []
|
|
for bname, info in browsers["browsers"].items():
|
|
browser_detail.append(f" - {bname}: {info['count']} processos, {info['ram_mb']:.0f} MB")
|
|
suggestions.append("Detalhamento:\n" + "\n".join(browser_detail))
|
|
if bottleneck == "ok":
|
|
bottleneck = "browsers"
|
|
if severity == "ok":
|
|
severity = "warning"
|
|
elif browsers["ram_status"] == "warning":
|
|
issues.append(f"Browsers usando {browsers['total_ram_gb']} GB (moderado)")
|
|
|
|
# Disco
|
|
if disk["status"] == "critical":
|
|
issues.append(f"Disco quase cheio: apenas {disk['free_gb']:.0f} GB livres ({disk['free_percent']}%)")
|
|
suggestions.append("Limpar arquivos temporarios, cache e lixeira")
|
|
suggestions.append("Verificar pasta Downloads e Temp por arquivos grandes")
|
|
if bottleneck == "ok":
|
|
bottleneck = "disk"
|
|
severity = "warning"
|
|
elif disk["status"] == "warning":
|
|
issues.append(f"Disco com {disk['free_gb']:.0f} GB livres ({disk['free_percent']}%)")
|
|
|
|
# Rede
|
|
if network.get("status") == "critical":
|
|
if not network.get("reachable"):
|
|
issues.append("API do Claude INACESSIVEL")
|
|
suggestions.append("Verificar conexao com internet")
|
|
suggestions.append("Verificar se VPN ou proxy esta bloqueando")
|
|
bottleneck = "network"
|
|
severity = "critical"
|
|
else:
|
|
issues.append(f"Latencia alta para API: {network['latency_ms']}ms")
|
|
suggestions.append("Verificar qualidade da conexao WiFi/cabo")
|
|
if bottleneck == "ok":
|
|
bottleneck = "network"
|
|
severity = "warning"
|
|
|
|
# Claude Code RAM
|
|
if claude["total_ram_gb"] > 8:
|
|
issues.append(f"Claude Code usando {claude['total_ram_gb']} GB ({claude['count']} processos)")
|
|
suggestions.append("Considerar fechar sessoes de conversa antigas no Claude Code")
|
|
|
|
# Tudo ok
|
|
if not issues:
|
|
issues.append("Sistema saudavel, sem gargalos detectados")
|
|
suggestions.append("A lentidao pode ser temporaria (pico na API do Claude)")
|
|
suggestions.append("Tente trocar de sessao novamente em alguns segundos")
|
|
|
|
# Gerar resumo em PT-BR
|
|
summary_lines = ["## Diagnostico de Performance\n"]
|
|
|
|
status_emoji = {"critical": "[!!!]", "warning": "[!]", "ok": "[OK]"}
|
|
summary_lines.append(f"**Status geral: {status_emoji[severity]} {severity.upper()}**\n")
|
|
|
|
if bottleneck != "ok":
|
|
summary_lines.append(f"**Gargalo principal: {bottleneck.upper()}**\n")
|
|
|
|
summary_lines.append("### Problemas detectados:")
|
|
for issue in issues:
|
|
summary_lines.append(f"- {issue}")
|
|
|
|
summary_lines.append("\n### Acoes recomendadas:")
|
|
for i, sug in enumerate(suggestions, 1):
|
|
if "\n" in sug:
|
|
summary_lines.append(f"{i}. {sug}")
|
|
else:
|
|
summary_lines.append(f"{i}. {sug}")
|
|
|
|
summary_lines.append(f"\n### Numeros-chave:")
|
|
summary_lines.append(f"- CPU: {cpu['percent']}% | RAM: {ram['percent']}% ({ram['used_gb']}/{ram['total_gb']} GB)")
|
|
summary_lines.append(f"- Browsers: {browsers['total_processes']} processos, {browsers['total_ram_gb']} GB")
|
|
summary_lines.append(f"- Claude Code: {claude['count']} processos, {claude['total_ram_gb']} GB")
|
|
summary_lines.append(f"- Disco C: {disk['free_gb']:.0f} GB livres ({disk['free_percent']}%)")
|
|
if network.get("latency_ms"):
|
|
summary_lines.append(f"- Latencia API: {network['latency_ms']}ms")
|
|
|
|
return {
|
|
"bottleneck": bottleneck,
|
|
"severity": severity,
|
|
"issues": issues,
|
|
"suggestions": suggestions,
|
|
"summary": "\n".join(summary_lines),
|
|
}
|
|
|
|
|
|
def main():
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description="Claude Monitor - Diagnostico Rapido")
|
|
parser.add_argument("--browsers-detail", action="store_true", help="Mostra detalhes por browser")
|
|
parser.add_argument("--json", action="store_true", help="Output em JSON puro")
|
|
parser.add_argument("--quick", action="store_true", help="Pula teste de rede")
|
|
args = parser.parse_args()
|
|
|
|
results = {}
|
|
|
|
# Coleta dados
|
|
results["timestamp"] = datetime.now().isoformat()
|
|
results["cpu"] = check_cpu()
|
|
results["ram"] = check_ram()
|
|
results["browsers"] = check_browsers(detail=args.browsers_detail)
|
|
results["claude"] = check_claude_processes()
|
|
results["disk"] = check_disk()
|
|
results["top_processes"] = check_top_processes(15)
|
|
|
|
if not args.quick:
|
|
results["network"] = check_network()
|
|
|
|
# Diagnóstico
|
|
results["diagnosis"] = diagnose(results)
|
|
|
|
if args.json:
|
|
print(json.dumps(results, indent=2, ensure_ascii=False))
|
|
else:
|
|
print(results["diagnosis"]["summary"])
|
|
print(f"\n(Para output completo em JSON, use: python health_check.py --json)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|