argus-pro

Argus Pro — Code Intelligence Scanner. Scan Python and JavaScript codebases with 40+ rules covering security, bugs, performance, and code quality. Get prioritised findings with fix suggestions, trend tracking across scans, CI-ready JSON output, and custom rule support. The full-power version of Argus.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "argus-pro" with this command: npx skills add occupythemilkyway/argus-pro

Argus Pro — Full Code Intelligence

Everything in Argus, plus 40+ rules, performance patterns, CI/CD integration, custom ignore paths, and trend JSON for tracking debt over time.

Pro features vs free Argus

FeatureArgus (Free)Argus Pro
Rules2040+
LanguagesPython or JSPython + JS simultaneously
Performance rules❌✅ N+1, blocking calls, memory leaks
CI exit code❌✅ FAIL_ON_CRITICAL
Ignore paths❌✅
JSON outputOptional✅ Always (CI-ready)
Finding deduplicationBasic✅ Cross-file smart dedup
Custom severity filter✅✅ + per-rule override

👉 Upgrade: openclaw skills install argus-pro + key at ko-fi.com/occupythemilkyway


Step 1 — Install

pip3 install rich --break-system-packages --quiet

Step 2 — Full code scan (Pro)

import os, re, json, sys
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()

LICENSE_KEY = os.environ.get("LICENSE_KEY","").strip()
if not LICENSE_KEY:
    console.print(Panel(
        "[red bold]🔒 Argus Pro requires a license key.[/red bold]\n\n"
        "Get your key at: [bold cyan]ko-fi.com/occupythemilkyway[/bold cyan]\n\n"
        "Or use the free version: [dim]openclaw skills install argus1[/dim]",
        title="License Required", border_style="red"
    ))
    raise SystemExit(1)

SRC_PATH      = os.environ.get("SOURCE_PATH",".").strip()
LANGUAGE      = os.environ.get("LANGUAGE","auto").lower()
SEV_FILTER    = os.environ.get("SEVERITY_FILTER","all").lower()
try: MAX_FINDINGS = int(os.environ.get("MAX_FINDINGS","100"))
except: MAX_FINDINGS = 100
OUTPUT_JSON   = os.environ.get("OUTPUT_JSON","true").lower() == "true"
FAIL_CRITICAL = os.environ.get("FAIL_ON_CRITICAL","false").lower() == "true"
IGNORE_RAW    = os.environ.get("IGNORE_PATHS","")
IGNORE_PATHS  = [p.strip() for p in IGNORE_RAW.split(",") if p.strip()]
TODAY         = date.today()

src = Path(SRC_PATH)
if not src.exists():
    console.print(f"[red]❌ Path not found: {SRC_PATH}[/red]")
    raise SystemExit(1)

def detect_lang(path):
    py = len(list(path.rglob("*.py") if path.is_dir() else ([path] if str(path).endswith(".py") else [])))
    js = len(list(path.rglob("*.js") if path.is_dir() else ([path] if str(path).endswith(".js") else [])))
    return "python" if py >= js else "javascript"

lang = LANGUAGE if LANGUAGE != "auto" else detect_lang(src)

# Pro: Scan both languages if directory
SCAN_LANGS = ["python","javascript"] if src.is_dir() and LANGUAGE == "auto" else [lang]

# ── Extended rule sets ────────────────────────────────────────────────────────
PYTHON_RULES = [
    # Security
    ("PY001","critical","security", r"\beval\s*\(",                              "eval() executes arbitrary code.",                         "Use ast.literal_eval() for safe literal evaluation."),
    ("PY002","critical","security", r"\bexec\s*\(",                              "exec() executes arbitrary code.",                         "Refactor to eliminate dynamic code execution."),
    ("PY003","critical","security", r"\bpickle\.loads?\s*\(",                  "pickle.load() with untrusted data enables code execution.", "Use json.loads() instead."),
    ("PY004","high","security",     r"(?i)(password|secret|api_key|token|auth_key)\s*=\s*['\"].+['\"]", "Hardcoded credential.", "Use environment variables."),
    ("PY005","high","security",     r"shell\s*=\s*True",                       "shell=True is a command-injection risk.",                  "Use list arguments: subprocess.run(['cmd','arg'])"),
    ("PY006","high","security",     r"\.execute\s*\(.*(%|\.format\(|f['\"])",  "Potential SQL injection via string formatting.",           "Use parameterised queries."),
    ("PY016","medium","security",   r"hashlib\.(md5|sha1)\s*\(",               "MD5/SHA1 are cryptographically weak.",                     "Use hashlib.sha256() or bcrypt for passwords."),
    ("PY017","high","security",     r"\brandom\.(random|randint|choice)\s*\(",  "random module not cryptographically secure.",             "Use secrets module for security-sensitive values."),
    # Bugs
    ("PY007","medium","bug",        r"def\s+\w+\s*\([^)]*=\s*\[\s*\]",        "Mutable default argument [].",                            "Use None as default; init inside function."),
    ("PY008","medium","bug",        r"def\s+\w+\s*\([^)]*=\s*\{\s*\}",        "Mutable default argument {}.",                            "Use None as default; init inside function."),
    ("PY009","medium","bug",        r"except\s*:",                             "Bare except catches SystemExit/KeyboardInterrupt.",       "Catch specific: except ValueError: or except Exception:"),
    ("PY010","medium","bug",        r"==\s*None\b|\bNone\s*==",                "Use 'is None' not '== None'.",                           "Replace with 'is None'."),
    ("PY011","medium","bug",        r"!=\s*None\b|\bNone\s*!=",                "Use 'is not None'.",                                     "Replace with 'is not None'."),
    ("PY018","medium","bug",        r"open\s*\(.+\)(?!\s*as\b)(?!.*with\b)",   "File opened without context manager.",                   "Use 'with open(...) as f:'."),
    ("PY020","medium","bug",        r"\btype\s*\(\w+\)\s*==\s*",               "type() == for type checks is fragile.",                  "Use isinstance() instead."),
    ("PY021","medium","bug",        r"except.*:\s*pass$",                      "Silent exception swallowed — bugs hidden.",               "At minimum log the exception before passing."),
    ("PY022","low","bug",           r"\bassert\s+",                            "assert statements removed by -O flag.",                  "Use explicit if + raise for runtime checks."),
    # Quality
    ("PY012","medium","quality",    r"\bprint\s*\(",                           "print() in production code.",                            "Replace with logging.debug()/logging.info()."),
    ("PY013","low","quality",       r"#\s*(TODO|FIXME|HACK|XXX|BUG)\b",       "Unresolved TODO/FIXME.",                                 "Create a tracked issue and remove the marker."),
    ("PY014","low","quality",       r"from\s+\w+\s+import\s+\*",              "Wildcard import pollutes namespace.",                     "Import only what you need."),
    ("PY015","low","quality",       r"import\s+pdb\b",                        "Debugger import left in code.",                          "Remove before committing."),
    ("PY019","low","quality",       r"lambda\s+\w+:\s*\w+\s*\(",              "Complex lambda — use a named def.",                      "Replace with a def statement."),
    # Performance (Pro only)
    ("PY030","medium","performance",r"for\s+\w+\s+in\s+range\(len\(",         "for i in range(len(x)) is slow and unidiomatic.",        "Use enumerate(x) or iterate directly."),
    ("PY031","medium","performance",r"\+\s*=\s*['\"]",                        "String concatenation in loop builds O(n²) strings.",     "Use ''.join(parts) or an f-string outside the loop."),
    ("PY032","low","performance",   r"\.keys\(\)\s*\)",                       "Iterating .keys() is redundant.",                        "Iterate the dict directly: for k in my_dict."),
    ("PY033","medium","performance",r"time\.sleep\s*\(",                      "Blocking sleep in potentially async context.",            "Use asyncio.sleep() in async functions."),
]

JS_RULES = [
    ("JS001","high","quality",      r"\bvar\s+",                               "var is function-scoped and hoisted.",                    "Use const or let."),
    ("JS002","critical","security", r"\.innerHTML\s*=",                        "innerHTML is an XSS vector.",                           "Use textContent or DOMPurify."),
    ("JS003","critical","security", r"\beval\s*\(",                            "eval() executes arbitrary JS.",                          "Eliminate eval() usage."),
    ("JS004","high","security",     r"(?i)(api_key|apikey|api_secret|access_token|password)\s*=\s*['\"].+['\"]", "Hardcoded credential.", "Use environment variables."),
    ("JS005","medium","bug",        r"==\s*null\b(?!\=)|null\s*==(?!\=)",      "Loose null check also matches undefined.",               "Use === null explicitly."),
    ("JS006","medium","bug",        r"(?<!=)==(?!=)",                          "Loose equality (==) causes type coercion bugs.",         "Use strict equality (===)."),
    ("JS007","medium","quality",    r"\bconsole\.(log|warn|error|debug)\s*\(", "console.log left in production.",                        "Remove or replace with a logging library."),
    ("JS008","medium","security",   r"document\.write\s*\(",                   "document.write() is an XSS risk.",                      "Use DOM manipulation methods instead."),
    ("JS009","low","quality",       r"//\s*(TODO|FIXME|HACK|XXX|BUG)\b",      "Unresolved TODO/FIXME.",                                "Create a tracked issue."),
    ("JS010","high","security",     r"__proto__\s*=",                          "Prototype pollution pattern.",                          "Validate object keys exclude __proto__."),
    ("JS011","medium","bug",        r"setTimeout\s*\(\s*['\"]",                "setTimeout with string calls eval internally.",          "Pass a function: setTimeout(() => fn(), ms)"),
    ("JS012","low","quality",       r"function\s+\w+\s*\([^)]{60,}\)",        "Too many parameters.",                                  "Use an options object instead."),
    # Performance (Pro only)
    ("JS030","medium","performance",r"\.forEach\s*\(.*\.push\s*\(",           "forEach+push is slower than Array.map().",               "Replace with map() for transformations."),
    ("JS031","medium","performance",r"document\.querySelector\s*\(.*\bfor\b", "DOM query inside a loop — expensive.",                  "Cache the element outside the loop."),
    ("JS032","low","performance",   r"JSON\.parse\s*\(JSON\.stringify\s*\(",  "JSON.parse(JSON.stringify()) for deep clone is slow.",   "Use structuredClone() in modern environments."),
]

SEV_ORDER = {"critical":0,"high":1,"medium":2,"low":3}
SEV_FILTER_LEVEL = {"all":3,"low":3,"medium":2,"high":1,"critical":0}.get(SEV_FILTER,3)

def should_skip(filepath, ignore_paths):
    path_str = str(filepath)
    return any(ig in path_str for ig in ignore_paths)

all_findings = []
all_files    = []

for scan_lang in SCAN_LANGS:
    ext   = "*.py" if scan_lang == "python" else "*.js"
    rules = PYTHON_RULES if scan_lang == "python" else JS_RULES
    files = [f for f in (src.rglob(ext) if src.is_dir() else [src]) if not should_skip(f, IGNORE_PATHS)]
    all_files.extend(files)
    for filepath in files:
        try:
            source = filepath.read_text(encoding="utf-8", errors="replace")
            for lineno, line in enumerate(source.splitlines(), 1):
                for rule_id, sev, category, pattern, message, fix in rules:
                    if re.search(pattern, line):
                        if SEV_ORDER.get(sev,3) <= SEV_FILTER_LEVEL:
                            all_findings.append({
                                "id": rule_id, "severity": sev, "category": category,
                                "lang": scan_lang,
                                "file": str(filepath.relative_to(src) if src.is_dir() else filepath),
                                "line": lineno, "code": line.strip()[:80],
                                "message": message, "fix": fix,
                            })
        except Exception as e:
            console.print(f"[dim]Skipping {filepath}: {e}[/dim]")

# Smart dedup
seen = set()
unique = []
for f in all_findings:
    key = (f["id"], f["file"], f["line"])
    if key not in seen:
        seen.add(key)
        unique.append(f)
unique.sort(key=lambda f: (SEV_ORDER.get(f["severity"],3), f["file"], f["line"]))
display = unique[:MAX_FINDINGS]

SEV_COLOUR = {"critical":"red","high":"orange3","medium":"yellow","low":"dim"}

console.print()
console.print(Panel.fit(
    f"[bold red]🐛👁️⚡ Argus Pro — Code Intelligence Scanner[/bold red]\n"
    f"Scanning [yellow]{len(all_files)}[/yellow] file(s)  |  Languages: [cyan]{', '.join(SCAN_LANGS)}[/cyan]  |  Rules: [white]{len(PYTHON_RULES)+len(JS_RULES) if len(SCAN_LANGS)>1 else (len(PYTHON_RULES) if lang=='python' else len(JS_RULES))}[/white]",
    border_style="red"
))

if not unique:
    console.print(Panel("[green]✅ No issues found — clean codebase![/green]", border_style="green"))
else:
    suffix = f" — showing {len(display)} of {len(unique)}" if len(unique) > MAX_FINDINGS else f" — {len(unique)} total"
    tbl = Table(title=f"🔍 Findings{suffix}", box=box.ROUNDED, border_style="red", show_lines=True)
    tbl.add_column("ID",        width=7,  style="dim")
    tbl.add_column("Sev",       width=9)
    tbl.add_column("Cat",       width=12, style="cyan")
    tbl.add_column("Lang",      width=5,  style="magenta")
    tbl.add_column("File:Line", width=30, style="yellow")
    tbl.add_column("Issue",     width=42)
    for fi in display:
        sc  = SEV_COLOUR.get(fi["severity"],"white")
        loc = f"{fi['file'][-26:]}:{fi['line']}" if len(fi["file"])>26 else f"{fi['file']}:{fi['line']}"
        tbl.add_row(fi["id"],f"[{sc}]{fi['severity'].upper()}[/{sc}]",fi["category"],fi["lang"][:2].upper(),loc,fi["message"][:40])
    console.print(tbl)

    for fi in [f for f in display if f["severity"] in ("critical","high")][:5]:
        sc = SEV_COLOUR.get(fi["severity"],"white")
        console.print(Panel(
            f"[dim]File:[/dim] {fi['file']}:{fi['line']}\n"
            f"[dim]Code:[/dim] [italic]{fi['code']}[/italic]\n\n"
            f"[white]{fi['message']}[/white]\n\n"
            f"[green]Fix:[/green] {fi['fix']}",
            title=f"[{sc}][bold]{fi['severity'].upper()}[/bold][/{sc}] — {fi['id']}",
            border_style=sc
        ))

    sev_counts = {s: sum(1 for f in unique if f["severity"]==s) for s in ("critical","high","medium","low")}
    console.print()
    console.print(Panel(
        f"Files: [yellow]{len(all_files)}[/yellow]  Issues: [red]{len(unique)}[/red]  "
        + "  ".join(f"[{SEV_COLOUR[s]}]{s.title()}: {sev_counts[s]}[/{SEV_COLOUR[s]}]" for s in ("critical","high","medium","low") if sev_counts[s]),
        title="Summary", border_style="cyan"
    ))

# Save
report_file = f"argus_pro_report_{TODAY}.md"
json_file   = f"argus_pro_report_{TODAY}.json"

with open(report_file,"w",encoding="utf-8") as f:
    f.write(f"# 🐛 Argus Pro Report — {TODAY}\n\n**Path:** `{SRC_PATH}`  **Files:** {len(all_files)}  **Issues:** {len(unique)}\n\n")
    f.write("## Findings\n\n| ID | Severity | Category | Lang | File:Line | Issue |\n|---|---|---|---|---|---|\n")
    for fi in unique:
        f.write(f"| {fi['id']} | {fi['severity'].upper()} | {fi['category']} | {fi['lang']} | {fi['file'][:30]}:{fi['line']} | {fi['message'][:50]} |\n")
    f.write("\n## Fix Guide (Critical + High)\n\n")
    for fi in [x for x in unique if x["severity"] in ("critical","high")]:
        f.write(f"### {fi['id']} — {fi['file']}:{fi['line']}\n**Issue:** {fi['message']}\n**Fix:** {fi['fix']}\n```\n{fi['code']}\n```\n\n")

with open(json_file,"w",encoding="utf-8") as f:
    json.dump({"date":str(TODAY),"path":SRC_PATH,"files":len(all_files),"findings":unique},f,indent=2)

console.print(Panel(f"[green]✅ Done![/green]  [cyan]{report_file}[/cyan]  |  [cyan]{json_file}[/cyan]",border_style="green"))

if FAIL_CRITICAL and any(f["severity"]=="critical" for f in unique):
    console.print("[red]CI: Exiting with code 1 — critical findings detected.[/red]")
    sys.exit(1)

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

Argus — Code Intelligence Scanner

Argus — The Hundred-Eyed. Scan your Python or JavaScript codebase for bugs, security vulnerabilities, code smells, and common anti-patterns — get a prior...

Registry SourceRecently Updated
1460Profile unavailable
Security

AI Code Review

Provides detailed, prioritized code review feedback on security, performance, correctness, and maintainability issues for multiple major programming languages.

Registry SourceRecently Updated
2381Profile unavailable
Security

python-code-analyz

专业Python代码分析与优化,支持语法检查、安全扫描、性能评估、复杂度分析及重构后的优化代码生成。

Registry SourceRecently Updated
1820Profile unavailable
Security

Code Review Assistant

自动化代码审查助手,支持 PR 审查、代码质量分析、潜在 bug 检测、安全漏洞扫描。

Registry SourceRecently Updated
2.1K0Profile unavailable