static-code-analysis
About
This skill implements static code analysis using linters, formatters, and security scanners to automatically detect bugs, security vulnerabilities, and style violations. It is ideal for enforcing coding standards, automating code reviews, and integrating quality checks into CI/CD pipelines. Use it to catch issues early and maintain consistent, secure code.
Documentation
Static Code Analysis
Overview
Use automated tools to analyze code without executing it, catching bugs, security issues, and style violations early.
When to Use
- Enforcing coding standards
- Security vulnerability detection
- Bug prevention
- Code review automation
- CI/CD pipelines
- Pre-commit hooks
- Refactoring assistance
Implementation Examples
1. ESLint Configuration
// .eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:security/recommended'
],
plugins: ['@typescript-eslint', 'security', 'import'],
rules: {
'no-console': ['warn', { allow: ['error', 'warn'] }],
'no-unused-vars': 'error',
'prefer-const': 'error',
'eqeqeq': ['error', 'always'],
'no-eval': 'error',
'security/detect-object-injection': 'warn',
'security/detect-non-literal-regexp': 'warn',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/explicit-function-return-type': 'error',
'import/order': ['error', {
'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
'newlines-between': 'always'
}]
}
};
2. Python Linting (pylint + mypy)
# .pylintrc
[MASTER]
ignore=venv,.git,__pycache__
jobs=4
[MESSAGES CONTROL]
disable=
missing-docstring,
too-few-public-methods
[FORMAT]
max-line-length=100
max-module-lines=1000
[DESIGN]
max-args=5
max-locals=15
max-returns=6
max-branches=12
max-statements=50
# mypy.ini
[mypy]
python_version = 3.10
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True
disallow_incomplete_defs = True
check_untyped_defs = True
disallow_untyped_calls = True
warn_redundant_casts = True
warn_unused_ignores = True
strict_equality = True
3. Pre-commit Hooks
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-merge-conflict
- id: detect-private-key
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.50.0
hooks:
- id: eslint
files: \.[jt]sx?$
types: [file]
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black
- repo: https://github.com/PyCQA/pylint
rev: v3.0.0
hooks:
- id: pylint
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.5.1
hooks:
- id: mypy
additional_dependencies: [types-requests]
- repo: https://github.com/trufflesecurity/trufflehog
rev: v3.58.0
hooks:
- id: trufflehog
entry: trufflehog filesystem --directory .
4. SonarQube Integration
# sonar-project.properties
sonar.projectKey=my-project
sonar.projectName=My Project
sonar.projectVersion=1.0
sonar.sources=src
sonar.tests=tests
sonar.exclusions=**/node_modules/**,**/*.test.ts
sonar.typescript.lcov.reportPaths=coverage/lcov.info
sonar.qualitygate.wait=true
# Quality gates
sonar.coverage.exclusions=**/*.test.ts
# .github/workflows/sonar.yml
name: SonarQube Analysis
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
sonar:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: SonarQube Scan
uses: sonarsource/sonarqube-scan-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
- name: Quality Gate Check
uses: sonarsource/sonarqube-quality-gate-action@master
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
5. Custom AST Analysis
import * as ts from 'typescript';
import * as fs from 'fs';
interface Issue {
file: string;
line: number;
column: number;
message: string;
severity: 'error' | 'warning' | 'info';
rule: string;
}
class CustomLinter {
private issues: Issue[] = [];
lintFile(filePath: string): Issue[] {
this.issues = [];
const sourceCode = fs.readFileSync(filePath, 'utf-8');
const sourceFile = ts.createSourceFile(
filePath,
sourceCode,
ts.ScriptTarget.Latest,
true
);
this.visit(sourceFile, filePath);
return this.issues;
}
private visit(node: ts.Node, filePath: string): void {
// Check for console.log
if (
ts.isCallExpression(node) &&
ts.isPropertyAccessExpression(node.expression) &&
node.expression.expression.getText() === 'console' &&
node.expression.name.getText() === 'log'
) {
const { line, character } = ts.getLineAndCharacterOfPosition(
node.getSourceFile(),
node.getStart()
);
this.issues.push({
file: filePath,
line: line + 1,
column: character + 1,
message: 'Unexpected console.log statement',
severity: 'warning',
rule: 'no-console'
});
}
// Check for any type
if (
ts.isTypeReferenceNode(node) &&
node.typeName.getText() === 'any'
) {
const { line, character } = ts.getLineAndCharacterOfPosition(
node.getSourceFile(),
node.getStart()
);
this.issues.push({
file: filePath,
line: line + 1,
column: character + 1,
message: 'Avoid using any type',
severity: 'warning',
rule: 'no-any'
});
}
// Check for long functions
if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) {
const body = node.body;
if (body && body.getFullText().split('\n').length > 50) {
const { line, character } = ts.getLineAndCharacterOfPosition(
node.getSourceFile(),
node.getStart()
);
this.issues.push({
file: filePath,
line: line + 1,
column: character + 1,
message: 'Function is too long (>50 lines)',
severity: 'warning',
rule: 'max-lines-per-function'
});
}
}
ts.forEachChild(node, child => this.visit(child, filePath));
}
formatIssues(issues: Issue[]): string {
if (issues.length === 0) {
return 'No issues found.';
}
return issues.map(issue =>
`${issue.file}:${issue.line}:${issue.column} - ${issue.severity}: ${issue.message} (${issue.rule})`
).join('\n');
}
}
// Usage
const linter = new CustomLinter();
const issues = linter.lintFile('./src/example.ts');
console.log(linter.formatIssues(issues));
6. Security Scanning
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
interface SecurityIssue {
severity: 'critical' | 'high' | 'medium' | 'low';
title: string;
description: string;
file?: string;
line?: number;
remediation?: string;
}
class SecurityScanner {
async scanDependencies(): Promise<SecurityIssue[]> {
try {
const { stdout } = await execAsync('npm audit --json');
const auditResult = JSON.parse(stdout);
const issues: SecurityIssue[] = [];
for (const [name, advisory] of Object.entries(auditResult.vulnerabilities || {})) {
const vuln = advisory as any;
issues.push({
severity: vuln.severity,
title: vuln.via[0]?.title || name,
description: vuln.via[0]?.url || '',
remediation: `Update ${name} to ${vuln.fixAvailable || 'latest'}`
});
}
return issues;
} catch (error) {
console.error('Dependency scan failed:', error);
return [];
}
}
async scanSecrets(directory: string): Promise<SecurityIssue[]> {
const issues: SecurityIssue[] = [];
// Simple regex-based secret detection
const patterns = [
{ name: 'API Key', pattern: /api[_-]?key['"]?\s*[:=]\s*['"]([a-zA-Z0-9]{32,})['"]/ },
{ name: 'AWS Key', pattern: /(AKIA[0-9A-Z]{16})/ },
{ name: 'Private Key', pattern: /-----BEGIN (RSA |EC )?PRIVATE KEY-----/ },
{ name: 'Password', pattern: /password['"]?\s*[:=]\s*['"]((?!<%= ).{8,})['"]/ }
];
// Scan files
const files = this.getFiles(directory);
for (const file of files) {
const content = fs.readFileSync(file, 'utf-8');
const lines = content.split('\n');
for (let i = 0; i < lines.length; i++) {
for (const { name, pattern } of patterns) {
if (pattern.test(lines[i])) {
issues.push({
severity: 'critical',
title: `Potential ${name} detected`,
description: `Found in ${file}:${i + 1}`,
file,
line: i + 1,
remediation: 'Remove secret and use environment variables'
});
}
}
}
}
return issues;
}
private getFiles(dir: string): string[] {
// Implementation to recursively get files
return [];
}
generateReport(issues: SecurityIssue[]): string {
let report = '# Security Scan Report\n\n';
const grouped = issues.reduce((acc, issue) => {
acc[issue.severity] = acc[issue.severity] || [];
acc[issue.severity].push(issue);
return acc;
}, {} as Record<string, SecurityIssue[]>);
for (const [severity, items] of Object.entries(grouped)) {
report += `## ${severity.toUpperCase()} (${items.length})\n\n`;
for (const issue of items) {
report += `### ${issue.title}\n`;
report += `${issue.description}\n`;
if (issue.remediation) {
report += `**Remediation:** ${issue.remediation}\n`;
}
report += '\n';
}
}
return report;
}
}
// Usage
const scanner = new SecurityScanner();
const depIssues = await scanner.scanDependencies();
const secretIssues = await scanner.scanSecrets('./src');
const allIssues = [...depIssues, ...secretIssues];
console.log(scanner.generateReport(allIssues));
Best Practices
✅ DO
- Run linters in CI/CD
- Use pre-commit hooks
- Configure IDE integration
- Fix issues incrementally
- Document custom rules
- Share configuration across team
- Automate security scanning
❌ DON'T
- Ignore all warnings
- Skip linter setup
- Commit lint violations
- Use overly strict rules initially
- Skip security scans
- Disable rules without reason
Tools
- JavaScript/TypeScript: ESLint, TSLint, Prettier
- Python: Pylint, Flake8, Black, Bandit
- Java: PMD, Checkstyle, SpotBugs
- Security: Snyk, Semgrep, Bandit, TruffleHog
- Multi-language: SonarQube, CodeQL
Resources
Quick Install
/plugin add https://github.com/aj-geddes/useful-ai-prompts/tree/main/static-code-analysisCopy and paste this command in Claude Code to install this skill
GitHub 仓库
Related Skills
sglang
MetaSGLang is a high-performance LLM serving framework that specializes in fast, structured generation for JSON, regex, and agentic workflows using its RadixAttention prefix caching. It delivers significantly faster inference, especially for tasks with repeated prefixes, making it ideal for complex, structured outputs and multi-turn conversations. Choose SGLang over alternatives like vLLM when you need constrained decoding or are building applications with extensive prefix sharing.
Algorithmic Art Generation
MetaThis skill helps developers create algorithmic art using p5.js, focusing on generative art, computational aesthetics, and interactive visualizations. It automatically activates for topics like "generative art" or "p5.js visualization" and guides you through creating unique algorithms with features like seeded randomness, flow fields, and particle systems. Use it when you need to build reproducible, code-driven artistic patterns.
business-rule-documentation
MetaThis skill provides standardized templates for systematically documenting business logic and domain knowledge following Domain-Driven Design principles. It helps developers capture business rules, process flows, decision trees, and terminology glossaries to maintain consistency between requirements and implementation. Use it when documenting domain models, creating business rule repositories, or bridging communication between business and technical teams.
huggingface-accelerate
DevelopmentHuggingFace Accelerate provides the simplest API for adding distributed training to PyTorch scripts with just 4 lines of code. It offers a unified interface for multiple distributed training frameworks like DeepSpeed, FSDP, and DDP while handling automatic device placement and mixed precision. This makes it ideal for developers who want to quickly scale their PyTorch training across multiple GPUs or nodes without complex configuration.
