| name | argus |
| description | Argus — The Hundred-Eyed. Scan your Python or JavaScript codebase for bugs, security vulnerabilities, code smells, and common anti-patterns — get a prioritised fix list with line numbers, severity ratings, and suggested corrections for every issue found. Nothing escapes Argus. |
| version | 1.0.0 |
| metadata | {"openclaw":{"requires":{"env":[],"bins":["python3","pip3"]},"primaryEnv":"SOURCE_PATH","homepage":"https://clawhub.ai/skills/argus","emoji":"👁️","tags":["code","bugs","security","scanner","python","javascript","argus","debugging","linting"],"envVars":[{"name":"SOURCE_PATH","description":"File or directory to scan","required":true},{"name":"LANGUAGE","description":"Language to scan: python / javascript / auto","required":false,"default":"auto"},{"name":"SEVERITY_FILTER","description":"Minimum severity to show: critical / high / medium / all","required":false,"default":"all"}]}} |
🐛 👁️ Argus — Code Intelligence Scanner
Static analysis for your codebase — finds real bugs, security holes, and code smells before
they hit production. No external API needed. Works on Python and JavaScript files.
What you get:
- Hardcoded passwords, API keys, and tokens flagged as Critical
- SQL injection and prototype pollution detection
- Bare excepts, mutable defaults, wildcard imports, and 13 other patterns
- Severity-filtered output: focus on Critical first, drill down from there
bug_report_[DATE].md + bug_report_[DATE].json with full fix suggestions
Quick Start
SOURCE_PATH="./src" LANGUAGE="python" SEVERITY_FILTER="high" python skill.py
Security
Reads local files only. Nothing transmitted.
Step 1 — Install dependencies
import subprocess, sys
subprocess.run([sys.executable,"-m","pip","install","rich","--break-system-packages","--quiet"], check=True)
Step 2 — Scan for Bugs
import os, re, json
from pathlib import Path
from datetime import date
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich import box
console = Console()
SRC_PATH = os.environ.get("SOURCE_PATH", ".")
LANGUAGE = os.environ.get("LANGUAGE", "auto").lower()
SEV_FILTER = os.environ.get("SEVERITY_FILTER", "all").lower()
TODAY = date.today()
src = Path(SRC_PATH)
if not src.exists():
console.print(Panel(f"[red]Path not found: {SRC_PATH}[/red]", border_style="red")); raise SystemExit(1)
console.print(Panel.fit(f"[bold red]🐛 👁️ Argus — Code Intelligence Scanner[/bold red]\nScanning: [cyan]{SRC_PATH}[/cyan] | Language: [yellow]{LANGUAGE}[/yellow] | Filter: [green]{SEV_FILTER}[/green]", border_style="red"))
def detect_lang(path: Path) -> str:
py = len(list(path.rglob("*.py") if path.is_dir() else [path] if str(path).endswith(".py") else []))
js = ((path.rglob() path.is_dir() [path] (path).endswith() []))
py == js == :
py >= js
lang = LANGUAGE LANGUAGE != detect_lang(src)
PYTHON_RULES = [
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
]
JS_RULES = [
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
(, , , , , ),
]
RULES = PYTHON_RULES lang == JS_RULES
SEV_ORDER = {: , : , : , : }
SEV_SHOW = {: , : , : , : }.get(SEV_FILTER, )
ext = lang ==
files = (src.rglob(ext) src.is_dir() [src])
files = [f f files (f) (f) (f)][:]
console.()
findings = []
fpath files:
:
lines = fpath.read_text(encoding=, errors=).splitlines()
i, line (lines, ):
rule_id, sev, category, pattern, message, fix RULES:
SEV_ORDER.get(sev, ) <= SEV_SHOW re.search(pattern, line):
findings.append({: rule_id, : sev, : category,
: (fpath.relative_to(src) src.is_dir() fpath),
: i, : line.strip()[:], : message, : fix})
Exception:
seen = (); unique = []
f findings:
key = (f[], f[], f[])
key seen: seen.add(key); unique.append(f)
unique.sort(key= x: (SEV_ORDER.get(x[],), x[], x[]))
collections Counter
sev_counts = Counter(f[] f unique)
cat_counts = Counter(f[] f unique)
console.()
console.(Panel(
,
title=, border_style= sev_counts[] >
))
unique:
console.()
display_count = ((unique), )
title_suffix = (unique) >
t = Table(title=, box=box.ROUNDED, show_lines=, border_style=)
t.add_column(, width=, style=); t.add_column(, width=); t.add_column(, style=, width=)
t.add_column(, style=, width=); t.add_column(, style=, width=)
SEV_COLOR = {:,:,:,:}
f unique[:]:
col = SEV_COLOR.get(f[],)
t.add_row(f[], , , f[][:], f[][:])
console.(t)
:
console.(Panel(, border_style=))
out_path =
(out_path,, encoding=) f:
json.dump({: (files), : lang, : unique, : (TODAY)}, f, indent=)
md_path =
(md_path,, encoding=) f:
f.write()
f.write()
fi unique: f.write()
console.()
console.(Panel(,title=,border_style=))