@softspark/ai-toolkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +412 -0
- package/CHANGELOG.md +68 -0
- package/LICENSE +21 -0
- package/README.md +632 -0
- package/action.yml +53 -0
- package/app/.claude-plugin/plugin.json +44 -0
- package/app/ARCHITECTURE.md +306 -0
- package/app/CLAUDE.md.template +23 -0
- package/app/agents/ai-engineer.md +128 -0
- package/app/agents/backend-specialist.md +193 -0
- package/app/agents/business-intelligence.md +54 -0
- package/app/agents/chaos-monkey.md +67 -0
- package/app/agents/chief-of-staff.md +51 -0
- package/app/agents/code-archaeologist.md +127 -0
- package/app/agents/code-reviewer.md +184 -0
- package/app/agents/command-expert.md +131 -0
- package/app/agents/data-analyst.md +205 -0
- package/app/agents/data-scientist.md +151 -0
- package/app/agents/database-architect.md +317 -0
- package/app/agents/debugger.md +238 -0
- package/app/agents/devops-implementer.md +194 -0
- package/app/agents/documenter.md +364 -0
- package/app/agents/explorer-agent.md +145 -0
- package/app/agents/fact-checker.md +172 -0
- package/app/agents/frontend-specialist.md +209 -0
- package/app/agents/game-developer.md +216 -0
- package/app/agents/incident-responder.md +226 -0
- package/app/agents/infrastructure-architect.md +127 -0
- package/app/agents/infrastructure-validator.md +247 -0
- package/app/agents/llm-ops-engineer.md +237 -0
- package/app/agents/mcp-expert.md +228 -0
- package/app/agents/mcp-server-architect.md +195 -0
- package/app/agents/mcp-testing-engineer.md +292 -0
- package/app/agents/meta-architect.md +58 -0
- package/app/agents/ml-engineer.md +136 -0
- package/app/agents/mobile-developer.md +190 -0
- package/app/agents/night-watchman.md +55 -0
- package/app/agents/nlp-engineer.md +154 -0
- package/app/agents/orchestrator.md +437 -0
- package/app/agents/performance-optimizer.md +254 -0
- package/app/agents/predictive-analyst.md +57 -0
- package/app/agents/product-manager.md +194 -0
- package/app/agents/project-planner.md +287 -0
- package/app/agents/prompt-engineer.md +103 -0
- package/app/agents/qa-automation-engineer.md +182 -0
- package/app/agents/rag-engineer.md +201 -0
- package/app/agents/research-synthesizer.md +138 -0
- package/app/agents/search-specialist.md +101 -0
- package/app/agents/security-architect.md +62 -0
- package/app/agents/security-auditor.md +293 -0
- package/app/agents/seo-specialist.md +111 -0
- package/app/agents/system-governor.md +57 -0
- package/app/agents/tech-lead.md +62 -0
- package/app/agents/technical-researcher.md +103 -0
- package/app/agents/test-engineer.md +264 -0
- package/app/constitution.md +38 -0
- package/app/hooks/_profile-check.sh +11 -0
- package/app/hooks/guard-destructive.sh +74 -0
- package/app/hooks/guard-path.sh +73 -0
- package/app/hooks/post-tool-use.sh +35 -0
- package/app/hooks/pre-compact.sh +31 -0
- package/app/hooks/quality-check.sh +22 -0
- package/app/hooks/quality-gate.sh +49 -0
- package/app/hooks/save-session.sh +24 -0
- package/app/hooks/session-end.sh +37 -0
- package/app/hooks/session-start.sh +29 -0
- package/app/hooks/subagent-start.sh +16 -0
- package/app/hooks/subagent-stop.sh +16 -0
- package/app/hooks/track-usage.sh +50 -0
- package/app/hooks/user-prompt-submit.sh +25 -0
- package/app/hooks.json +178 -0
- package/app/mcp-defaults.json +23 -0
- package/app/output-styles/golden-rules.md +43 -0
- package/app/plugins/README.md +19 -0
- package/app/plugins/csharp-pack/README.md +11 -0
- package/app/plugins/csharp-pack/plugin.json +18 -0
- package/app/plugins/enterprise-pack/README.md +16 -0
- package/app/plugins/enterprise-pack/hooks/output-style.sh +6 -0
- package/app/plugins/enterprise-pack/hooks/status-line.sh +8 -0
- package/app/plugins/enterprise-pack/plugin.json +24 -0
- package/app/plugins/frontend-pack/README.md +14 -0
- package/app/plugins/frontend-pack/plugin.json +22 -0
- package/app/plugins/java-pack/README.md +11 -0
- package/app/plugins/java-pack/plugin.json +18 -0
- package/app/plugins/kotlin-pack/README.md +11 -0
- package/app/plugins/kotlin-pack/plugin.json +18 -0
- package/app/plugins/memory-pack/README.md +24 -0
- package/app/plugins/memory-pack/hooks/observation-capture.sh +67 -0
- package/app/plugins/memory-pack/hooks/session-summary.sh +71 -0
- package/app/plugins/memory-pack/plugin.json +22 -0
- package/app/plugins/memory-pack/scripts/init_db.py +81 -0
- package/app/plugins/memory-pack/scripts/strip_private.py +22 -0
- package/app/plugins/memory-pack/skills/mem-search/SKILL.md +70 -0
- package/app/plugins/research-pack/README.md +14 -0
- package/app/plugins/research-pack/plugin.json +22 -0
- package/app/plugins/ruby-pack/README.md +11 -0
- package/app/plugins/ruby-pack/plugin.json +18 -0
- package/app/plugins/rust-pack/README.md +11 -0
- package/app/plugins/rust-pack/plugin.json +18 -0
- package/app/plugins/security-pack/README.md +15 -0
- package/app/plugins/security-pack/plugin.json +23 -0
- package/app/plugins/swift-pack/README.md +11 -0
- package/app/plugins/swift-pack/plugin.json +18 -0
- package/app/rules/claude-toolkit-rules.md +21 -0
- package/app/rules/git-conventions.md +5 -0
- package/app/rules/quality-gates.md +10 -0
- package/app/skills/_lib/__init__.py +1 -0
- package/app/skills/_lib/detect_utils.py +150 -0
- package/app/skills/agent-creator/SKILL.md +82 -0
- package/app/skills/analyze/SKILL.md +92 -0
- package/app/skills/analyze/scripts/complexity.py +165 -0
- package/app/skills/api-patterns/SKILL.md +305 -0
- package/app/skills/app-builder/SKILL.md +187 -0
- package/app/skills/architecture-audit/SKILL.md +141 -0
- package/app/skills/architecture-decision/SKILL.md +55 -0
- package/app/skills/architecture-decision/templates/adr-template.md +36 -0
- package/app/skills/biz-scan/SKILL.md +30 -0
- package/app/skills/briefing/SKILL.md +27 -0
- package/app/skills/build/SKILL.md +97 -0
- package/app/skills/build/scripts/detect-build.py +151 -0
- package/app/skills/chaos/SKILL.md +32 -0
- package/app/skills/ci/SKILL.md +77 -0
- package/app/skills/ci/scripts/ci-detect.py +135 -0
- package/app/skills/ci/templates/github-actions-node.yml +38 -0
- package/app/skills/ci/templates/github-actions-python.yml +42 -0
- package/app/skills/ci-cd-patterns/SKILL.md +299 -0
- package/app/skills/clean-code/SKILL.md +110 -0
- package/app/skills/clean-code/reference/dart.md +18 -0
- package/app/skills/clean-code/reference/go.md +23 -0
- package/app/skills/clean-code/reference/php.md +32 -0
- package/app/skills/clean-code/reference/python.md +180 -0
- package/app/skills/clean-code/reference/typescript.md +26 -0
- package/app/skills/command-creator/SKILL.md +83 -0
- package/app/skills/commit/SKILL.md +98 -0
- package/app/skills/commit/scripts/pre-commit-check.py +87 -0
- package/app/skills/commit/templates/conventional-commit.md +52 -0
- package/app/skills/csharp-patterns/SKILL.md +450 -0
- package/app/skills/database-patterns/SKILL.md +297 -0
- package/app/skills/debug/SKILL.md +154 -0
- package/app/skills/debug/scripts/error-parser.py +187 -0
- package/app/skills/debugging-tactics/SKILL.md +136 -0
- package/app/skills/deploy/SKILL.md +130 -0
- package/app/skills/deploy/scripts/pre_deploy_check.py +171 -0
- package/app/skills/deploy/templates/deployment-checklist.md +31 -0
- package/app/skills/design-an-interface/SKILL.md +105 -0
- package/app/skills/design-engineering/SKILL.md +260 -0
- package/app/skills/docker-devops/SKILL.md +303 -0
- package/app/skills/docs/SKILL.md +145 -0
- package/app/skills/docs/scripts/doc-inventory.py +176 -0
- package/app/skills/docs/templates/adr-template.md +36 -0
- package/app/skills/docs/templates/readme-template.md +67 -0
- package/app/skills/documentation-standards/SKILL.md +191 -0
- package/app/skills/ecommerce-patterns/SKILL.md +209 -0
- package/app/skills/evaluate/SKILL.md +132 -0
- package/app/skills/evolve/SKILL.md +27 -0
- package/app/skills/explain/SKILL.md +54 -0
- package/app/skills/explain/scripts/dependency-graph.py +215 -0
- package/app/skills/explore/SKILL.md +112 -0
- package/app/skills/explore/scripts/visualize.py +117 -0
- package/app/skills/fix/SKILL.md +78 -0
- package/app/skills/fix/scripts/error-classifier.py +191 -0
- package/app/skills/flutter-patterns/SKILL.md +254 -0
- package/app/skills/git-mastery/SKILL.md +70 -0
- package/app/skills/grill-me/SKILL.md +38 -0
- package/app/skills/health/SKILL.md +91 -0
- package/app/skills/health/scripts/health_check.py +162 -0
- package/app/skills/hive-mind/SKILL.md +56 -0
- package/app/skills/hook-creator/SKILL.md +107 -0
- package/app/skills/index/SKILL.md +74 -0
- package/app/skills/instinct-review/SKILL.md +77 -0
- package/app/skills/java-patterns/SKILL.md +442 -0
- package/app/skills/kotlin-patterns/SKILL.md +446 -0
- package/app/skills/lint/SKILL.md +103 -0
- package/app/skills/lint/scripts/detect-linters.py +112 -0
- package/app/skills/mcp-patterns/SKILL.md +270 -0
- package/app/skills/mem-search/SKILL.md +70 -0
- package/app/skills/migrate/SKILL.md +90 -0
- package/app/skills/migrate/scripts/migration-status.py +195 -0
- package/app/skills/migration-patterns/SKILL.md +260 -0
- package/app/skills/night-watch/SKILL.md +28 -0
- package/app/skills/observability-patterns/SKILL.md +203 -0
- package/app/skills/onboard/SKILL.md +76 -0
- package/app/skills/orchestrate/SKILL.md +86 -0
- package/app/skills/panic/SKILL.md +30 -0
- package/app/skills/performance-profiling/SKILL.md +59 -0
- package/app/skills/plan/SKILL.md +110 -0
- package/app/skills/plan/templates/plan-template.md +40 -0
- package/app/skills/plan-writing/SKILL.md +201 -0
- package/app/skills/plugin-creator/SKILL.md +78 -0
- package/app/skills/pr/SKILL.md +129 -0
- package/app/skills/pr/scripts/pr-summary.py +175 -0
- package/app/skills/prd-to-issues/SKILL.md +108 -0
- package/app/skills/prd-to-plan/SKILL.md +120 -0
- package/app/skills/predict/SKILL.md +30 -0
- package/app/skills/qa-session/SKILL.md +110 -0
- package/app/skills/rag-patterns/SKILL.md +203 -0
- package/app/skills/refactor/SKILL.md +124 -0
- package/app/skills/refactor/scripts/refactor-scan.py +210 -0
- package/app/skills/refactor-plan/SKILL.md +112 -0
- package/app/skills/repeat/SKILL.md +149 -0
- package/app/skills/research-mastery/SKILL.md +56 -0
- package/app/skills/review/SKILL.md +141 -0
- package/app/skills/review/scripts/diff-analyzer.py +170 -0
- package/app/skills/rollback/SKILL.md +87 -0
- package/app/skills/rollback/scripts/rollback_info.py +149 -0
- package/app/skills/ruby-patterns/SKILL.md +454 -0
- package/app/skills/rust-patterns/SKILL.md +446 -0
- package/app/skills/search/SKILL.md +64 -0
- package/app/skills/security-patterns/SKILL.md +91 -0
- package/app/skills/security-patterns/reference/authentication.md +37 -0
- package/app/skills/security-patterns/reference/authorization.md +22 -0
- package/app/skills/security-patterns/reference/input-validation.md +30 -0
- package/app/skills/security-patterns/reference/oauth-csrf-audit.md +131 -0
- package/app/skills/skill-creator/SKILL.md +154 -0
- package/app/skills/skill-creator/templates/dashboard/index.html +130 -0
- package/app/skills/skill-creator/templates/reasoning-engine/assets/example.json +12 -0
- package/app/skills/skill-creator/templates/reasoning-engine/search.py +110 -0
- package/app/skills/subagent-development/SKILL.md +225 -0
- package/app/skills/subagent-development/reference/code-quality-reviewer-prompt.md +145 -0
- package/app/skills/subagent-development/reference/implementer-prompt.md +118 -0
- package/app/skills/subagent-development/reference/spec-reviewer-prompt.md +100 -0
- package/app/skills/swarm/SKILL.md +81 -0
- package/app/skills/swift-patterns/SKILL.md +500 -0
- package/app/skills/tdd/SKILL.md +174 -0
- package/app/skills/tdd/reference/deep-modules.md +32 -0
- package/app/skills/tdd/reference/interface-design.md +32 -0
- package/app/skills/tdd/reference/mocking.md +52 -0
- package/app/skills/tdd/reference/refactoring.md +10 -0
- package/app/skills/tdd/reference/tests.md +59 -0
- package/app/skills/teams/SKILL.md +101 -0
- package/app/skills/test/SKILL.md +107 -0
- package/app/skills/test/scripts/detect-runner.py +113 -0
- package/app/skills/testing-patterns/SKILL.md +73 -0
- package/app/skills/testing-patterns/reference/flutter-testing.md +33 -0
- package/app/skills/testing-patterns/reference/go-testing.md +52 -0
- package/app/skills/testing-patterns/reference/php-phpunit.md +39 -0
- package/app/skills/testing-patterns/reference/python-pytest.md +228 -0
- package/app/skills/testing-patterns/reference/typescript-vitest.md +50 -0
- package/app/skills/triage-issue/SKILL.md +120 -0
- package/app/skills/typescript-patterns/SKILL.md +256 -0
- package/app/skills/ubiquitous-language/SKILL.md +74 -0
- package/app/skills/verification-before-completion/SKILL.md +108 -0
- package/app/skills/workflow/SKILL.md +250 -0
- package/app/skills/write-a-prd/SKILL.md +129 -0
- package/app/skills/write-a-prd/reference/visual-companion.md +78 -0
- package/app/skills/write-a-prd/scripts/frame-template.html +111 -0
- package/app/skills/write-a-prd/scripts/visual-server.cjs +79 -0
- package/app/templates/skill/generator/SKILL.md.template +40 -0
- package/app/templates/skill/knowledge/SKILL.md.template +52 -0
- package/app/templates/skill/linter/SKILL.md.template +34 -0
- package/app/templates/skill/reviewer/SKILL.md.template +51 -0
- package/app/templates/skill/workflow/SKILL.md.template +49 -0
- package/benchmarks/README.md +111 -0
- package/benchmarks/ecosystem-dashboard.json +148 -0
- package/benchmarks/ecosystem-harvest.json +148 -0
- package/benchmarks/results.json +38 -0
- package/benchmarks/run.py +351 -0
- package/bin/ai-toolkit.js +345 -0
- package/kb/best-practices/README.md +11 -0
- package/kb/howto/README.md +11 -0
- package/kb/procedures/maintenance-sop.md +306 -0
- package/kb/reference/agents-catalog.md +124 -0
- package/kb/reference/anti-pattern-registry-format.md +221 -0
- package/kb/reference/architecture-overview.md +232 -0
- package/kb/reference/benchmark-config.md +62 -0
- package/kb/reference/ci-integration.md +66 -0
- package/kb/reference/claude-ecosystem-benchmark-snapshot.md +80 -0
- package/kb/reference/claude-ecosystem-expansion-foundations.md +102 -0
- package/kb/reference/commands-catalog.md +21 -0
- package/kb/reference/distribution-model.md +63 -0
- package/kb/reference/global-install-model.md +56 -0
- package/kb/reference/hierarchical-override-pattern.md +200 -0
- package/kb/reference/hooks-catalog.md +306 -0
- package/kb/reference/integrations.md +88 -0
- package/kb/reference/language-packs.md +52 -0
- package/kb/reference/merge-friendly-install-model.md +58 -0
- package/kb/reference/plugin-pack-conventions.md +151 -0
- package/kb/reference/quick-wins-implementation-summary.md +70 -0
- package/kb/reference/skill-templates.md +50 -0
- package/kb/reference/skills-catalog.md +215 -0
- package/kb/reference/skills-unification.md +57 -0
- package/kb/reference/stats.md +69 -0
- package/kb/reference/sync.md +76 -0
- package/kb/troubleshooting/README.md +11 -0
- package/llms-full.txt +3068 -0
- package/llms.txt +39 -0
- package/package.json +75 -0
- package/scripts/_common.py +160 -0
- package/scripts/add_rule.py +50 -0
- package/scripts/benchmark_config.py +127 -0
- package/scripts/benchmark_ecosystem.py +288 -0
- package/scripts/check_deps.py +260 -0
- package/scripts/create_skill.py +118 -0
- package/scripts/doctor.py +504 -0
- package/scripts/eject.py +113 -0
- package/scripts/emission.py +256 -0
- package/scripts/evaluate_skills.py +260 -0
- package/scripts/frontmatter.py +58 -0
- package/scripts/generate_agents_md.py +91 -0
- package/scripts/generate_aider_conf.py +51 -0
- package/scripts/generate_cline.py +35 -0
- package/scripts/generate_copilot.py +30 -0
- package/scripts/generate_cursor_rules.py +35 -0
- package/scripts/generate_gemini.py +28 -0
- package/scripts/generate_llms_txt.py +164 -0
- package/scripts/generate_roo_modes.py +80 -0
- package/scripts/generate_windsurf.py +35 -0
- package/scripts/generator_base.py +140 -0
- package/scripts/harvest_ecosystem.py +50 -0
- package/scripts/inject_rule_cli.py +101 -0
- package/scripts/inject_section_cli.py +47 -0
- package/scripts/injection.py +180 -0
- package/scripts/install.py +236 -0
- package/scripts/install_git_hooks.py +71 -0
- package/scripts/install_steps/__init__.py +5 -0
- package/scripts/install_steps/ai_tools.py +261 -0
- package/scripts/install_steps/hooks.py +90 -0
- package/scripts/install_steps/markers.py +79 -0
- package/scripts/install_steps/symlinks.py +87 -0
- package/scripts/merge-hooks.py +192 -0
- package/scripts/plugin.py +642 -0
- package/scripts/plugin_schema.py +138 -0
- package/scripts/remove_rule.py +58 -0
- package/scripts/stats.py +81 -0
- package/scripts/sync.py +215 -0
- package/scripts/uninstall.py +292 -0
- package/scripts/validate.py +700 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Shared utilities for skill detection scripts.
|
|
2
|
+
|
|
3
|
+
Provides common constants, file helpers, and a standard main() wrapper
|
|
4
|
+
used by detect-linters.py, detect-build.py, detect-runner.py, ci-detect.py,
|
|
5
|
+
and other project-scanning scripts under app/skills/*/scripts/.
|
|
6
|
+
|
|
7
|
+
All functions are stdlib-only.
|
|
8
|
+
|
|
9
|
+
Usage::
|
|
10
|
+
|
|
11
|
+
from _lib.detect_utils import read_json, read_text, IGNORE_DIRS, run_detector
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import os
|
|
17
|
+
import re
|
|
18
|
+
import shutil
|
|
19
|
+
import sys
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
# Directories to skip during project walks
|
|
24
|
+
IGNORE_DIRS: frozenset[str] = frozenset({
|
|
25
|
+
".git", "node_modules", "__pycache__", ".venv", "venv",
|
|
26
|
+
"dist", "build", ".next", "vendor",
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
# Common project markers → project type
|
|
30
|
+
PROJECT_MARKERS: dict[str, list[str]] = {
|
|
31
|
+
"python": ["pyproject.toml", "setup.py", "requirements.txt"],
|
|
32
|
+
"node": ["package.json"],
|
|
33
|
+
"flutter": ["pubspec.yaml"],
|
|
34
|
+
"go": ["go.mod"],
|
|
35
|
+
"rust": ["Cargo.toml"],
|
|
36
|
+
"php": ["composer.json"],
|
|
37
|
+
"docker": ["Dockerfile"],
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
# File I/O helpers
|
|
43
|
+
# ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
def read_json(path: Path) -> dict[str, Any] | None:
|
|
46
|
+
"""Read and parse a JSON file, returning None on failure."""
|
|
47
|
+
try:
|
|
48
|
+
with open(path, "r") as f:
|
|
49
|
+
return json.load(f)
|
|
50
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def read_text(path: Path) -> str | None:
|
|
55
|
+
"""Read a text file, returning None when it does not exist."""
|
|
56
|
+
try:
|
|
57
|
+
with open(path, "r") as f:
|
|
58
|
+
return f.read()
|
|
59
|
+
except FileNotFoundError:
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def is_installed(binary: str) -> bool:
|
|
64
|
+
"""Check whether a binary is available on PATH."""
|
|
65
|
+
return shutil.which(binary) is not None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# ---------------------------------------------------------------------------
|
|
69
|
+
# Project detection
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
def detect_project_type(project_dir: Path) -> str | None:
|
|
73
|
+
"""Detect project type from well-known marker files."""
|
|
74
|
+
for ptype, markers in PROJECT_MARKERS.items():
|
|
75
|
+
for marker in markers:
|
|
76
|
+
if (project_dir / marker).exists():
|
|
77
|
+
return ptype
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def count_files(root: Path, patterns: list[str]) -> int:
|
|
82
|
+
"""Walk root and count files matching any regex pattern.
|
|
83
|
+
|
|
84
|
+
Directories in IGNORE_DIRS are pruned.
|
|
85
|
+
"""
|
|
86
|
+
count = 0
|
|
87
|
+
for dirpath, dirnames, filenames in os.walk(root):
|
|
88
|
+
dirnames[:] = [d for d in dirnames if d not in IGNORE_DIRS]
|
|
89
|
+
for f in filenames:
|
|
90
|
+
for pat in patterns:
|
|
91
|
+
if re.search(pat, f):
|
|
92
|
+
count += 1
|
|
93
|
+
break
|
|
94
|
+
return count
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def parse_makefile_targets(project_dir: Path) -> list[str]:
|
|
98
|
+
"""Extract non-hidden target names from a Makefile."""
|
|
99
|
+
content = read_text(project_dir / "Makefile")
|
|
100
|
+
if not content:
|
|
101
|
+
return []
|
|
102
|
+
targets: list[str] = []
|
|
103
|
+
for line in content.split("\n"):
|
|
104
|
+
m = re.match(r"^([a-zA-Z_][a-zA-Z0-9_-]*)\s*:", line)
|
|
105
|
+
if m and not m.group(1).startswith("."):
|
|
106
|
+
targets.append(m.group(1))
|
|
107
|
+
return targets
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# ---------------------------------------------------------------------------
|
|
111
|
+
# Standard main() wrapper
|
|
112
|
+
# ---------------------------------------------------------------------------
|
|
113
|
+
|
|
114
|
+
def run_detector(
|
|
115
|
+
detect_fn: Any,
|
|
116
|
+
*,
|
|
117
|
+
extra_args: bool = False,
|
|
118
|
+
) -> None:
|
|
119
|
+
"""Standard entry point wrapper for detection scripts.
|
|
120
|
+
|
|
121
|
+
Parses argv for project directory, calls detect_fn(project_dir, ...),
|
|
122
|
+
and prints JSON result to stdout. Handles errors uniformly.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
detect_fn: Callable(project_dir: Path, ...) -> dict
|
|
126
|
+
extra_args: If True, passes remaining argv items to detect_fn
|
|
127
|
+
"""
|
|
128
|
+
project_dir = Path.cwd()
|
|
129
|
+
extra: list[str] = []
|
|
130
|
+
|
|
131
|
+
for arg in sys.argv[1:]:
|
|
132
|
+
if os.path.isdir(arg):
|
|
133
|
+
project_dir = Path(arg).resolve()
|
|
134
|
+
else:
|
|
135
|
+
extra.append(arg)
|
|
136
|
+
|
|
137
|
+
if not project_dir.is_dir():
|
|
138
|
+
print(json.dumps({"error": f"Not a directory: {project_dir}"}))
|
|
139
|
+
sys.exit(1)
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
if extra_args and extra:
|
|
143
|
+
result = detect_fn(project_dir, *extra)
|
|
144
|
+
else:
|
|
145
|
+
result = detect_fn(project_dir)
|
|
146
|
+
result["project_dir"] = str(project_dir)
|
|
147
|
+
print(json.dumps(result, indent=2))
|
|
148
|
+
except Exception as e:
|
|
149
|
+
print(json.dumps({"error": str(e)}))
|
|
150
|
+
sys.exit(1)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-creator
|
|
3
|
+
description: "Creates new specialized agents with frontmatter, tool selection, and delegation guidance"
|
|
4
|
+
effort: high
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
argument-hint: "[agent name or role]"
|
|
7
|
+
allowed-tools: Read, Write, Edit, Bash, Grep, Glob
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Agent Creator
|
|
11
|
+
|
|
12
|
+
$ARGUMENTS
|
|
13
|
+
|
|
14
|
+
Create a new specialized agent following ai-toolkit conventions.
|
|
15
|
+
|
|
16
|
+
## Workflow
|
|
17
|
+
|
|
18
|
+
1. **Capture role** -- what problem space should the agent own?
|
|
19
|
+
2. **Define triggers** -- which keywords or task types should route to this agent?
|
|
20
|
+
3. **Choose tools** -- minimal tool set, least privilege first
|
|
21
|
+
4. **Choose model** -- `opus` for deep reasoning, `sonnet` for lighter pattern work
|
|
22
|
+
5. **Map supporting skills** -- which knowledge skills should the agent reference?
|
|
23
|
+
6. **Write instructions** -- capabilities, constraints, escalation rules, deliverables
|
|
24
|
+
7. **Validate** -- frontmatter, naming, skills references, tool whitelist
|
|
25
|
+
|
|
26
|
+
## Required Frontmatter
|
|
27
|
+
|
|
28
|
+
```yaml
|
|
29
|
+
---
|
|
30
|
+
name: agent-name
|
|
31
|
+
description: "When to use this agent. Triggers: keyword1, keyword2."
|
|
32
|
+
tools: Read, Write, Edit
|
|
33
|
+
model: sonnet
|
|
34
|
+
skills: skill-one, skill-two
|
|
35
|
+
---
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Authoring Rules
|
|
39
|
+
|
|
40
|
+
- Match filename and `name` exactly using lowercase-hyphen format
|
|
41
|
+
- Keep the description trigger-rich and operational
|
|
42
|
+
- Give the agent a clear boundary: what it owns and what it should escalate
|
|
43
|
+
- Prefer specialized, narrow responsibility over generic “do everything” agents
|
|
44
|
+
- Reference only existing skills unless the task also includes creating the missing skill
|
|
45
|
+
- Avoid tool bloat; every extra tool increases risk and ambiguity
|
|
46
|
+
|
|
47
|
+
## Agent Skeleton
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
---
|
|
51
|
+
name: {agent-name}
|
|
52
|
+
description: "When to use this agent. Triggers: keyword1, keyword2."
|
|
53
|
+
tools: Read, Edit
|
|
54
|
+
model: sonnet
|
|
55
|
+
skills: relevant-skill
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
You are a specialized agent for {domain}.
|
|
59
|
+
|
|
60
|
+
## Responsibilities
|
|
61
|
+
- Responsibility one
|
|
62
|
+
- Responsibility two
|
|
63
|
+
|
|
64
|
+
## Constraints
|
|
65
|
+
- Do not edit files outside owned scope unless required
|
|
66
|
+
- Escalate security, data-loss, or architecture risks
|
|
67
|
+
|
|
68
|
+
## Deliverables
|
|
69
|
+
- Clear findings
|
|
70
|
+
- Specific edits or recommendations
|
|
71
|
+
- Validation notes
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Validation Checklist
|
|
75
|
+
|
|
76
|
+
- [ ] Filename matches `name:` in frontmatter
|
|
77
|
+
- [ ] Description includes trigger words and use cases
|
|
78
|
+
- [ ] Tools are from the approved Claude Code tool set
|
|
79
|
+
- [ ] Referenced skills exist
|
|
80
|
+
- [ ] Model choice matches expected complexity
|
|
81
|
+
- [ ] `scripts/validate.py` passes after adding the agent
|
|
82
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: analyze
|
|
3
|
+
description: "Analyze code quality, complexity, and patterns"
|
|
4
|
+
user-invocable: true
|
|
5
|
+
effort: medium
|
|
6
|
+
argument-hint: "[path or pattern]"
|
|
7
|
+
allowed-tools: Read, Grep, Glob
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Code Analysis
|
|
11
|
+
|
|
12
|
+
$ARGUMENTS
|
|
13
|
+
|
|
14
|
+
Analyze code quality, complexity, and patterns.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
/analyze [path] [--type=<type>]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## What This Command Does
|
|
23
|
+
|
|
24
|
+
1. **Scans** codebase or specific path
|
|
25
|
+
2. **Analyzes** code quality metrics
|
|
26
|
+
3. **Identifies** patterns and anti-patterns
|
|
27
|
+
4. **Reports** findings with recommendations
|
|
28
|
+
|
|
29
|
+
## Analysis Types
|
|
30
|
+
|
|
31
|
+
| Type | Description |
|
|
32
|
+
|------|-------------|
|
|
33
|
+
| `quality` | Code quality metrics (default) |
|
|
34
|
+
| `security` | Security vulnerability scan |
|
|
35
|
+
| `complexity` | Cyclomatic complexity |
|
|
36
|
+
| `dependencies` | Dependency analysis |
|
|
37
|
+
| `coverage` | Test coverage gaps |
|
|
38
|
+
|
|
39
|
+
## Output Format
|
|
40
|
+
|
|
41
|
+
```markdown
|
|
42
|
+
## Code Analysis Report
|
|
43
|
+
|
|
44
|
+
### Summary
|
|
45
|
+
- **Files Analyzed**: [count]
|
|
46
|
+
- **Issues Found**: [count]
|
|
47
|
+
- **Quality Score**: [score]/100
|
|
48
|
+
|
|
49
|
+
### Metrics
|
|
50
|
+
| Metric | Value | Threshold |
|
|
51
|
+
|--------|-------|-----------|
|
|
52
|
+
| Complexity | [avg] | <10 |
|
|
53
|
+
| Duplication | [%] | <5% |
|
|
54
|
+
| Coverage | [%] | >70% |
|
|
55
|
+
|
|
56
|
+
### Issues by Severity
|
|
57
|
+
- Critical: [count]
|
|
58
|
+
- High: [count]
|
|
59
|
+
- Medium: [count]
|
|
60
|
+
- Low: [count]
|
|
61
|
+
|
|
62
|
+
### Top Issues
|
|
63
|
+
1. **[Issue]** - [file:line]
|
|
64
|
+
- [Description]
|
|
65
|
+
- Fix: [Recommendation]
|
|
66
|
+
|
|
67
|
+
### Patterns Detected
|
|
68
|
+
- [Pattern 1]: [locations]
|
|
69
|
+
- [Pattern 2]: [locations]
|
|
70
|
+
|
|
71
|
+
### Recommendations
|
|
72
|
+
1. [Recommendation with priority]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Automated Complexity Analysis
|
|
76
|
+
|
|
77
|
+
Run the bundled script for a quick complexity report:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
python3 ${CLAUDE_SKILL_DIR}/scripts/complexity.py .
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Reports file counts by type, largest files, TODO/FIXME counts, and total code lines.
|
|
84
|
+
|
|
85
|
+
## Tools Used
|
|
86
|
+
|
|
87
|
+
| Language | Tools |
|
|
88
|
+
|----------|-------|
|
|
89
|
+
| Python | ruff, mypy, pylint |
|
|
90
|
+
| JavaScript | eslint, tsc |
|
|
91
|
+
| Go | golangci-lint |
|
|
92
|
+
| Rust | clippy |
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Code complexity analysis script.
|
|
3
|
+
|
|
4
|
+
Scans a project directory and reports file counts by extension, largest
|
|
5
|
+
files by line count, TODO/FIXME/HACK/XXX markers, and a summary with
|
|
6
|
+
total file and line counts.
|
|
7
|
+
|
|
8
|
+
Usage::
|
|
9
|
+
|
|
10
|
+
python3 complexity.py [directory]
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
from collections import Counter
|
|
17
|
+
from datetime import datetime, timezone
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
IGNORE_DIRS: set[str] = {
|
|
21
|
+
".git", "node_modules", "__pycache__", ".venv",
|
|
22
|
+
"vendor", "dist", "build",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
IGNORE_DIRS_LARGEST: set[str] = IGNORE_DIRS # same exclusions for largest-file scan
|
|
26
|
+
|
|
27
|
+
IGNORE_LOCK_NAMES: set[str] = {
|
|
28
|
+
"package-lock.json",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
IGNORE_LOCK_EXTENSIONS: set[str] = {
|
|
32
|
+
".lock",
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
CODE_EXTENSIONS: set[str] = {
|
|
36
|
+
".py", ".ts", ".tsx", ".js", ".jsx",
|
|
37
|
+
".go", ".php", ".dart", ".rs", ".rb",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _is_ignored(path: Path, ignored: set[str]) -> bool:
|
|
42
|
+
"""Return True if any component of *path* matches the ignored set."""
|
|
43
|
+
return bool(set(path.parts) & ignored)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _walk_files(root: Path, ignored: set[str]) -> list[Path]:
|
|
47
|
+
"""Collect all regular files under *root*, skipping ignored dirs."""
|
|
48
|
+
files: list[Path] = []
|
|
49
|
+
for dirpath, dirnames, filenames in os.walk(root):
|
|
50
|
+
dirnames[:] = [d for d in dirnames if d not in ignored]
|
|
51
|
+
dp = Path(dirpath)
|
|
52
|
+
for fn in filenames:
|
|
53
|
+
files.append(dp / fn)
|
|
54
|
+
return files
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _count_lines(path: Path) -> int:
|
|
58
|
+
"""Count lines in a file, returning 0 on read errors."""
|
|
59
|
+
try:
|
|
60
|
+
with open(path, "rb") as fh:
|
|
61
|
+
return sum(1 for _ in fh)
|
|
62
|
+
except (OSError, PermissionError):
|
|
63
|
+
return 0
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _file_counts(files: list[Path]) -> list[tuple[int, str]]:
|
|
67
|
+
"""Return (count, extension) pairs sorted descending, top 15."""
|
|
68
|
+
ext_counter: Counter[str] = Counter()
|
|
69
|
+
for f in files:
|
|
70
|
+
ext = f.suffix.lstrip(".") if f.suffix else f.name
|
|
71
|
+
ext_counter[ext] += 1
|
|
72
|
+
return ext_counter.most_common(15)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _largest_files(root: Path) -> list[tuple[int, str]]:
|
|
76
|
+
"""Return (line_count, path) for the 10 largest files."""
|
|
77
|
+
all_files = _walk_files(root, IGNORE_DIRS_LARGEST)
|
|
78
|
+
eligible = [
|
|
79
|
+
f for f in all_files
|
|
80
|
+
if f.suffix not in IGNORE_LOCK_EXTENSIONS
|
|
81
|
+
and f.name not in IGNORE_LOCK_NAMES
|
|
82
|
+
]
|
|
83
|
+
counted: list[tuple[int, str]] = []
|
|
84
|
+
for f in eligible:
|
|
85
|
+
lines = _count_lines(f)
|
|
86
|
+
if lines > 0:
|
|
87
|
+
counted.append((lines, str(f)))
|
|
88
|
+
counted.sort(reverse=True)
|
|
89
|
+
return counted[:10]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _debt_markers(root: Path, files: list[Path]) -> dict[str, int]:
|
|
93
|
+
"""Count files containing each debt marker in code files."""
|
|
94
|
+
code_files = [f for f in files if f.suffix in CODE_EXTENSIONS]
|
|
95
|
+
markers = ["TODO", "FIXME", "HACK", "XXX"]
|
|
96
|
+
results: dict[str, int] = {}
|
|
97
|
+
for marker in markers:
|
|
98
|
+
count = 0
|
|
99
|
+
for cf in code_files:
|
|
100
|
+
try:
|
|
101
|
+
with open(cf, "r", errors="replace") as fh:
|
|
102
|
+
for line in fh:
|
|
103
|
+
if marker in line:
|
|
104
|
+
count += 1
|
|
105
|
+
break
|
|
106
|
+
except (OSError, PermissionError):
|
|
107
|
+
continue
|
|
108
|
+
results[marker] = count
|
|
109
|
+
return results
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _summary(root: Path, all_files: list[Path]) -> tuple[int, int]:
|
|
113
|
+
"""Return (total_files, total_code_lines) for the summary."""
|
|
114
|
+
total_files = len(all_files)
|
|
115
|
+
|
|
116
|
+
code_files = _walk_files(root, IGNORE_DIRS)
|
|
117
|
+
code_only = [f for f in code_files if f.suffix in CODE_EXTENSIONS]
|
|
118
|
+
total_lines = sum(_count_lines(f) for f in code_only)
|
|
119
|
+
return total_files, total_lines
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def main() -> None:
|
|
123
|
+
"""Entry point: analyse directory and print text report to stdout."""
|
|
124
|
+
root = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else Path.cwd().resolve()
|
|
125
|
+
now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
126
|
+
|
|
127
|
+
all_files = _walk_files(root, IGNORE_DIRS)
|
|
128
|
+
|
|
129
|
+
print("=== Code Complexity Report ===")
|
|
130
|
+
print(f"Directory: {root}")
|
|
131
|
+
print(f"Date: {now}")
|
|
132
|
+
print()
|
|
133
|
+
|
|
134
|
+
# File counts by extension
|
|
135
|
+
print("## File Counts")
|
|
136
|
+
for count, ext in _file_counts(all_files):
|
|
137
|
+
print(f" {count} {ext}")
|
|
138
|
+
print()
|
|
139
|
+
|
|
140
|
+
# Largest files
|
|
141
|
+
print("## Largest Files (top 10)")
|
|
142
|
+
largest = _largest_files(root)
|
|
143
|
+
for lines, path in largest:
|
|
144
|
+
print(f" {lines} {path}")
|
|
145
|
+
# Include total line if there are entries (mirrors wc behavior)
|
|
146
|
+
if len(largest) > 1:
|
|
147
|
+
total = sum(lc for lc, _ in largest)
|
|
148
|
+
print(f" {total} total")
|
|
149
|
+
print()
|
|
150
|
+
|
|
151
|
+
# Debt markers
|
|
152
|
+
print("## Code Debt Markers")
|
|
153
|
+
for marker, count in _debt_markers(root, all_files).items():
|
|
154
|
+
print(f" {marker}: {count} files")
|
|
155
|
+
print()
|
|
156
|
+
|
|
157
|
+
# Summary
|
|
158
|
+
print("## Summary")
|
|
159
|
+
total_files, total_lines = _summary(root, all_files)
|
|
160
|
+
print(f" Total files: {total_files}")
|
|
161
|
+
print(f" Total code lines: {total_lines}")
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
if __name__ == "__main__":
|
|
165
|
+
main()
|