@neyugn/agent-kits 0.1.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.
Files changed (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +514 -0
  3. package/README.vi.md +410 -0
  4. package/README.zh.md +410 -0
  5. package/dist/cli.d.ts +1 -0
  6. package/dist/cli.js +422 -0
  7. package/kits/coder/ARCHITECTURE.md +289 -0
  8. package/kits/coder/agents/ai-engineer.md +344 -0
  9. package/kits/coder/agents/backend-specialist.md +270 -0
  10. package/kits/coder/agents/cloud-architect.md +363 -0
  11. package/kits/coder/agents/code-reviewer.md +284 -0
  12. package/kits/coder/agents/data-engineer.md +401 -0
  13. package/kits/coder/agents/database-specialist.md +251 -0
  14. package/kits/coder/agents/debugger.md +209 -0
  15. package/kits/coder/agents/devops-engineer.md +281 -0
  16. package/kits/coder/agents/documentation-writer.md +296 -0
  17. package/kits/coder/agents/frontend-specialist.md +298 -0
  18. package/kits/coder/agents/i18n-specialist.md +348 -0
  19. package/kits/coder/agents/integration-specialist.md +314 -0
  20. package/kits/coder/agents/mobile-developer.md +271 -0
  21. package/kits/coder/agents/multi-tenant-architect.md +281 -0
  22. package/kits/coder/agents/orchestrator.md +263 -0
  23. package/kits/coder/agents/performance-analyst.md +327 -0
  24. package/kits/coder/agents/project-planner.md +277 -0
  25. package/kits/coder/agents/queue-specialist.md +282 -0
  26. package/kits/coder/agents/realtime-specialist.md +267 -0
  27. package/kits/coder/agents/security-auditor.md +253 -0
  28. package/kits/coder/agents/test-engineer.md +315 -0
  29. package/kits/coder/agents/ux-researcher.md +388 -0
  30. package/kits/coder/rules/.cursorrules +287 -0
  31. package/kits/coder/rules/CLAUDE.md +287 -0
  32. package/kits/coder/rules/CODEX.md +287 -0
  33. package/kits/coder/rules/GEMINI.md +287 -0
  34. package/kits/coder/scripts/checklist.py +318 -0
  35. package/kits/coder/scripts/kit_status.py +292 -0
  36. package/kits/coder/scripts/skills_manager.py +243 -0
  37. package/kits/coder/scripts/verify_all.py +391 -0
  38. package/kits/coder/skills/accessibility-patterns/SKILL.md +372 -0
  39. package/kits/coder/skills/accessibility-patterns/scripts/a11y_checker.py +211 -0
  40. package/kits/coder/skills/ai-rag-patterns/SKILL.md +444 -0
  41. package/kits/coder/skills/api-patterns/SKILL.md +316 -0
  42. package/kits/coder/skills/api-patterns/assets/.gitkeep +1 -0
  43. package/kits/coder/skills/api-patterns/references/deep-dive.md +21 -0
  44. package/kits/coder/skills/api-patterns/scripts/api_validator.py +253 -0
  45. package/kits/coder/skills/api-patterns/scripts/validate.py +56 -0
  46. package/kits/coder/skills/auth-patterns/SKILL.md +267 -0
  47. package/kits/coder/skills/aws-patterns/SKILL.md +576 -0
  48. package/kits/coder/skills/brainstorming/SKILL.md +370 -0
  49. package/kits/coder/skills/brainstorming/assets/.gitkeep +1 -0
  50. package/kits/coder/skills/brainstorming/references/deep-dive.md +21 -0
  51. package/kits/coder/skills/brainstorming/scripts/validate.py +56 -0
  52. package/kits/coder/skills/clean-code/SKILL.md +240 -0
  53. package/kits/coder/skills/clean-code/assets/.gitkeep +1 -0
  54. package/kits/coder/skills/clean-code/references/deep-dive.md +21 -0
  55. package/kits/coder/skills/clean-code/scripts/lint_runner.py +186 -0
  56. package/kits/coder/skills/clean-code/scripts/validate.py +56 -0
  57. package/kits/coder/skills/database-design/SKILL.md +255 -0
  58. package/kits/coder/skills/database-design/assets/.gitkeep +1 -0
  59. package/kits/coder/skills/database-design/references/deep-dive.md +21 -0
  60. package/kits/coder/skills/database-design/scripts/schema_validator.py +272 -0
  61. package/kits/coder/skills/database-design/scripts/validate.py +56 -0
  62. package/kits/coder/skills/docker-patterns/SKILL.md +240 -0
  63. package/kits/coder/skills/documentation-templates/SKILL.md +441 -0
  64. package/kits/coder/skills/e2e-testing/SKILL.md +457 -0
  65. package/kits/coder/skills/flutter-patterns/SKILL.md +330 -0
  66. package/kits/coder/skills/frontend-design/SKILL.md +127 -0
  67. package/kits/coder/skills/github-actions/SKILL.md +349 -0
  68. package/kits/coder/skills/gitlab-ci-patterns/SKILL.md +466 -0
  69. package/kits/coder/skills/graphql-patterns/SKILL.md +558 -0
  70. package/kits/coder/skills/i18n-localization/SKILL.md +345 -0
  71. package/kits/coder/skills/i18n-localization/scripts/i18n_checker.py +267 -0
  72. package/kits/coder/skills/kubernetes-patterns/SKILL.md +357 -0
  73. package/kits/coder/skills/mermaid-diagrams/SKILL.md +351 -0
  74. package/kits/coder/skills/mobile-design/SKILL.md +305 -0
  75. package/kits/coder/skills/monitoring-observability/SKILL.md +458 -0
  76. package/kits/coder/skills/multi-tenancy/SKILL.md +317 -0
  77. package/kits/coder/skills/multi-tenancy/assets/.gitkeep +1 -0
  78. package/kits/coder/skills/multi-tenancy/references/deep-dive.md +21 -0
  79. package/kits/coder/skills/multi-tenancy/scripts/validate.py +56 -0
  80. package/kits/coder/skills/nodejs-best-practices/SKILL.md +220 -0
  81. package/kits/coder/skills/performance-profiling/SKILL.md +333 -0
  82. package/kits/coder/skills/performance-profiling/assets/.gitkeep +1 -0
  83. package/kits/coder/skills/performance-profiling/references/deep-dive.md +21 -0
  84. package/kits/coder/skills/performance-profiling/scripts/validate.py +56 -0
  85. package/kits/coder/skills/plan-writing/SKILL.md +360 -0
  86. package/kits/coder/skills/plan-writing/assets/.gitkeep +1 -0
  87. package/kits/coder/skills/plan-writing/references/deep-dive.md +21 -0
  88. package/kits/coder/skills/plan-writing/scripts/validate.py +56 -0
  89. package/kits/coder/skills/postgres-patterns/SKILL.md +361 -0
  90. package/kits/coder/skills/prompt-engineering/SKILL.md +277 -0
  91. package/kits/coder/skills/queue-patterns/SKILL.md +359 -0
  92. package/kits/coder/skills/queue-patterns/assets/.gitkeep +1 -0
  93. package/kits/coder/skills/queue-patterns/references/deep-dive.md +21 -0
  94. package/kits/coder/skills/queue-patterns/scripts/validate.py +56 -0
  95. package/kits/coder/skills/react-native-patterns/SKILL.md +393 -0
  96. package/kits/coder/skills/react-patterns/SKILL.md +319 -0
  97. package/kits/coder/skills/realtime-patterns/SKILL.md +506 -0
  98. package/kits/coder/skills/realtime-patterns/assets/.gitkeep +1 -0
  99. package/kits/coder/skills/realtime-patterns/references/deep-dive.md +21 -0
  100. package/kits/coder/skills/realtime-patterns/scripts/validate.py +56 -0
  101. package/kits/coder/skills/redis-patterns/SKILL.md +484 -0
  102. package/kits/coder/skills/security-fundamentals/SKILL.md +363 -0
  103. package/kits/coder/skills/security-fundamentals/assets/.gitkeep +1 -0
  104. package/kits/coder/skills/security-fundamentals/references/deep-dive.md +21 -0
  105. package/kits/coder/skills/security-fundamentals/scripts/security_scan.py +326 -0
  106. package/kits/coder/skills/security-fundamentals/scripts/validate.py +56 -0
  107. package/kits/coder/skills/seo-patterns/SKILL.md +262 -0
  108. package/kits/coder/skills/seo-patterns/scripts/seo_checker.py +211 -0
  109. package/kits/coder/skills/systematic-debugging/SKILL.md +478 -0
  110. package/kits/coder/skills/systematic-debugging/assets/.gitkeep +1 -0
  111. package/kits/coder/skills/systematic-debugging/references/deep-dive.md +21 -0
  112. package/kits/coder/skills/systematic-debugging/scripts/validate.py +56 -0
  113. package/kits/coder/skills/tailwind-patterns/SKILL.md +395 -0
  114. package/kits/coder/skills/terraform-patterns/SKILL.md +470 -0
  115. package/kits/coder/skills/testing-patterns/SKILL.md +285 -0
  116. package/kits/coder/skills/testing-patterns/assets/.gitkeep +1 -0
  117. package/kits/coder/skills/testing-patterns/references/deep-dive.md +21 -0
  118. package/kits/coder/skills/testing-patterns/scripts/test_runner.py +219 -0
  119. package/kits/coder/skills/testing-patterns/scripts/validate.py +56 -0
  120. package/kits/coder/skills/typescript-patterns/SKILL.md +417 -0
  121. package/kits/coder/skills/ui-ux-pro-max/SKILL.md +364 -0
  122. package/kits/coder/skills/ui-ux-pro-max/data/charts.csv +26 -0
  123. package/kits/coder/skills/ui-ux-pro-max/data/colors.csv +97 -0
  124. package/kits/coder/skills/ui-ux-pro-max/data/icons.csv +101 -0
  125. package/kits/coder/skills/ui-ux-pro-max/data/landing.csv +31 -0
  126. package/kits/coder/skills/ui-ux-pro-max/data/products.csv +97 -0
  127. package/kits/coder/skills/ui-ux-pro-max/data/prompts.csv +24 -0
  128. package/kits/coder/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  129. package/kits/coder/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  130. package/kits/coder/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  131. package/kits/coder/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  132. package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  133. package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  134. package/kits/coder/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  135. package/kits/coder/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  136. package/kits/coder/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  137. package/kits/coder/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  138. package/kits/coder/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  139. package/kits/coder/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  140. package/kits/coder/skills/ui-ux-pro-max/data/styles.csv +59 -0
  141. package/kits/coder/skills/ui-ux-pro-max/data/typography.csv +58 -0
  142. package/kits/coder/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  143. package/kits/coder/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  144. package/kits/coder/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  145. package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
  146. package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
  147. package/kits/coder/skills/ui-ux-pro-max/scripts/core.py +257 -0
  148. package/kits/coder/skills/ui-ux-pro-max/scripts/design_system.py +488 -0
  149. package/kits/coder/skills/ui-ux-pro-max/scripts/search.py +76 -0
  150. package/kits/coder/workflows/.gitkeep +20 -0
  151. package/kits/coder/workflows/create.md +152 -0
  152. package/kits/coder/workflows/debug.md +223 -0
  153. package/kits/coder/workflows/deploy.md +283 -0
  154. package/kits/coder/workflows/orchestrate.md +243 -0
  155. package/kits/coder/workflows/plan.md +134 -0
  156. package/kits/coder/workflows/test.md +237 -0
  157. package/kits/coder/workflows/ui-ux-pro-max.md +109 -0
  158. package/package.json +49 -0
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ AGT-Kit Status Reporter
4
+ ========================
5
+
6
+ Reports the status of the AGT-Kit installation:
7
+ - Lists all agents and their assigned skills
8
+ - Lists all available skills
9
+ - Lists all workflows
10
+ - Validates kit integrity
11
+
12
+ Usage:
13
+ python .agent/scripts/kit_status.py
14
+ python .agent/scripts/kit_status.py --validate
15
+ python .agent/scripts/kit_status.py --json
16
+ """
17
+
18
+ import sys
19
+ import argparse
20
+ import json
21
+ import re
22
+ from pathlib import Path
23
+ from typing import Dict, List, Any
24
+
25
+ # ANSI colors
26
+ class Colors:
27
+ HEADER = '\033[95m'
28
+ BLUE = '\033[94m'
29
+ CYAN = '\033[96m'
30
+ GREEN = '\033[92m'
31
+ YELLOW = '\033[93m'
32
+ RED = '\033[91m'
33
+ ENDC = '\033[0m'
34
+ BOLD = '\033[1m'
35
+
36
+
37
+ def print_header(text: str):
38
+ print(f"\n{Colors.BOLD}{Colors.CYAN}{'='*60}{Colors.ENDC}")
39
+ print(f"{Colors.BOLD}{Colors.CYAN}{text.center(60)}{Colors.ENDC}")
40
+ print(f"{Colors.BOLD}{Colors.CYAN}{'='*60}{Colors.ENDC}\n")
41
+
42
+
43
+ def print_success(text: str):
44
+ print(f"{Colors.GREEN}āœ… {text}{Colors.ENDC}")
45
+
46
+
47
+ def print_warning(text: str):
48
+ print(f"{Colors.YELLOW}āš ļø {text}{Colors.ENDC}")
49
+
50
+
51
+ def print_error(text: str):
52
+ print(f"{Colors.RED}āŒ {text}{Colors.ENDC}")
53
+
54
+
55
+ def find_kit_root() -> Path:
56
+ """Find the .agent directory from current location or script location."""
57
+ # Try from script location
58
+ script_dir = Path(__file__).parent
59
+ agent_dir = script_dir.parent
60
+
61
+ if (agent_dir / "ARCHITECTURE.md").exists():
62
+ return agent_dir
63
+
64
+ # Try from current working directory
65
+ cwd = Path.cwd()
66
+ for parent in [cwd, *cwd.parents]:
67
+ agent_dir = parent / ".agent"
68
+ if agent_dir.exists() and (agent_dir / "ARCHITECTURE.md").exists():
69
+ return agent_dir
70
+
71
+ return None
72
+
73
+
74
+ def parse_frontmatter(file_path: Path) -> Dict[str, Any]:
75
+ """Parse YAML frontmatter from a markdown file."""
76
+ try:
77
+ content = file_path.read_text()
78
+ if content.startswith('---'):
79
+ parts = content.split('---', 2)
80
+ if len(parts) >= 3:
81
+ frontmatter = parts[1].strip()
82
+ result = {}
83
+ for line in frontmatter.split('\n'):
84
+ if ':' in line:
85
+ key, value = line.split(':', 1)
86
+ result[key.strip()] = value.strip()
87
+ return result
88
+ except:
89
+ pass
90
+ return {}
91
+
92
+
93
+ def get_agents(agent_dir: Path) -> List[Dict[str, Any]]:
94
+ """Get list of agents with their metadata."""
95
+ agents = []
96
+ agents_path = agent_dir / "agents"
97
+
98
+ if not agents_path.exists():
99
+ return agents
100
+
101
+ for agent_file in agents_path.glob("*.md"):
102
+ frontmatter = parse_frontmatter(agent_file)
103
+ skills = frontmatter.get("skills", "").replace("[", "").replace("]", "").split(",")
104
+ skills = [s.strip() for s in skills if s.strip()]
105
+
106
+ agents.append({
107
+ "name": agent_file.stem,
108
+ "file": str(agent_file.relative_to(agent_dir)),
109
+ "description": frontmatter.get("description", ""),
110
+ "skills": skills,
111
+ })
112
+
113
+ return sorted(agents, key=lambda x: x["name"])
114
+
115
+
116
+ def get_skills(agent_dir: Path) -> List[Dict[str, Any]]:
117
+ """Get list of skills with their metadata."""
118
+ skills = []
119
+ skills_path = agent_dir / "skills"
120
+
121
+ if not skills_path.exists():
122
+ return skills
123
+
124
+ for skill_dir in skills_path.iterdir():
125
+ if not skill_dir.is_dir():
126
+ continue
127
+
128
+ skill_md = skill_dir / "SKILL.md"
129
+ if not skill_md.exists():
130
+ continue
131
+
132
+ frontmatter = parse_frontmatter(skill_md)
133
+
134
+ # Check for scripts
135
+ scripts_path = skill_dir / "scripts"
136
+ has_scripts = scripts_path.exists() and any(scripts_path.glob("*.py"))
137
+
138
+ skills.append({
139
+ "name": skill_dir.name,
140
+ "file": str(skill_md.relative_to(agent_dir)),
141
+ "description": frontmatter.get("description", ""),
142
+ "has_scripts": has_scripts,
143
+ })
144
+
145
+ return sorted(skills, key=lambda x: x["name"])
146
+
147
+
148
+ def get_workflows(agent_dir: Path) -> List[Dict[str, Any]]:
149
+ """Get list of workflows."""
150
+ workflows = []
151
+ workflows_path = agent_dir / "workflows"
152
+
153
+ if not workflows_path.exists():
154
+ return workflows
155
+
156
+ for workflow_file in workflows_path.glob("*.md"):
157
+ frontmatter = parse_frontmatter(workflow_file)
158
+
159
+ workflows.append({
160
+ "name": workflow_file.stem,
161
+ "command": f"/{workflow_file.stem}",
162
+ "file": str(workflow_file.relative_to(agent_dir)),
163
+ "description": frontmatter.get("description", ""),
164
+ })
165
+
166
+ return sorted(workflows, key=lambda x: x["name"])
167
+
168
+
169
+ def validate_kit(agent_dir: Path, agents: List, skills: List, workflows: List) -> Dict[str, Any]:
170
+ """Validate kit integrity."""
171
+ issues = []
172
+ warnings = []
173
+
174
+ skill_names = {s["name"] for s in skills}
175
+
176
+ # Check agent skill references
177
+ for agent in agents:
178
+ for skill in agent.get("skills", []):
179
+ if skill and skill not in skill_names:
180
+ issues.append(f"Agent '{agent['name']}' references missing skill: {skill}")
181
+
182
+ # Check for skills without SKILL.md
183
+ skills_path = agent_dir / "skills"
184
+ if skills_path.exists():
185
+ for skill_dir in skills_path.iterdir():
186
+ if skill_dir.is_dir() and not (skill_dir / "SKILL.md").exists():
187
+ warnings.append(f"Skill directory '{skill_dir.name}' missing SKILL.md")
188
+
189
+ # Check ARCHITECTURE.md exists
190
+ if not (agent_dir / "ARCHITECTURE.md").exists():
191
+ issues.append("Missing ARCHITECTURE.md")
192
+
193
+ # Check required files
194
+ required_files = ["ARCHITECTURE.md"]
195
+ for rf in required_files:
196
+ if not (agent_dir / rf).exists():
197
+ issues.append(f"Missing required file: {rf}")
198
+
199
+ return {
200
+ "valid": len(issues) == 0,
201
+ "issues": issues,
202
+ "warnings": warnings,
203
+ }
204
+
205
+
206
+ def print_report(agents: List, skills: List, workflows: List, validation: Dict):
207
+ """Print formatted status report."""
208
+ print_header("šŸ¤– AGT-KIT STATUS REPORT")
209
+
210
+ # Statistics
211
+ print(f"{Colors.BOLD}šŸ“Š Statistics{Colors.ENDC}")
212
+ print(f" Agents: {len(agents)}")
213
+ print(f" Skills: {len(skills)}")
214
+ print(f" Workflows: {len(workflows)}")
215
+ print()
216
+
217
+ # Agents
218
+ print(f"{Colors.BOLD}šŸ¤– Agents ({len(agents)}){Colors.ENDC}")
219
+ for agent in agents:
220
+ skill_count = len(agent.get("skills", []))
221
+ print(f" • {agent['name']} ({skill_count} skills)")
222
+ print()
223
+
224
+ # Skills with scripts
225
+ skills_with_scripts = [s for s in skills if s.get("has_scripts")]
226
+ print(f"{Colors.BOLD}🧩 Skills with Scripts ({len(skills_with_scripts)}/{len(skills)}){Colors.ENDC}")
227
+ for skill in skills_with_scripts:
228
+ print(f" • {skill['name']} āœ“")
229
+ print()
230
+
231
+ # Workflows
232
+ print(f"{Colors.BOLD}šŸ”„ Workflows ({len(workflows)}){Colors.ENDC}")
233
+ for workflow in workflows:
234
+ print(f" • {workflow['command']} - {workflow.get('description', 'No description')[:50]}")
235
+ print()
236
+
237
+ # Validation
238
+ print(f"{Colors.BOLD}āœ… Validation{Colors.ENDC}")
239
+ if validation["valid"]:
240
+ print_success("Kit integrity check passed")
241
+ else:
242
+ for issue in validation["issues"]:
243
+ print_error(issue)
244
+
245
+ for warning in validation.get("warnings", []):
246
+ print_warning(warning)
247
+
248
+
249
+ def main():
250
+ parser = argparse.ArgumentParser(
251
+ description="AGT-Kit Status Reporter",
252
+ formatter_class=argparse.RawDescriptionHelpFormatter,
253
+ )
254
+ parser.add_argument("--validate", action="store_true", help="Run validation checks")
255
+ parser.add_argument("--json", action="store_true", help="Output as JSON")
256
+
257
+ args = parser.parse_args()
258
+
259
+ agent_dir = find_kit_root()
260
+
261
+ if not agent_dir:
262
+ print_error("Could not find .agent directory")
263
+ sys.exit(1)
264
+
265
+ # Gather data
266
+ agents = get_agents(agent_dir)
267
+ skills = get_skills(agent_dir)
268
+ workflows = get_workflows(agent_dir)
269
+ validation = validate_kit(agent_dir, agents, skills, workflows)
270
+
271
+ if args.json:
272
+ output = {
273
+ "kit_path": str(agent_dir),
274
+ "statistics": {
275
+ "agents": len(agents),
276
+ "skills": len(skills),
277
+ "workflows": len(workflows),
278
+ },
279
+ "agents": agents,
280
+ "skills": skills,
281
+ "workflows": workflows,
282
+ "validation": validation,
283
+ }
284
+ print(json.dumps(output, indent=2))
285
+ else:
286
+ print_report(agents, skills, workflows, validation)
287
+
288
+ sys.exit(0 if validation["valid"] else 1)
289
+
290
+
291
+ if __name__ == "__main__":
292
+ main()
@@ -0,0 +1,243 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Skills Manager - Manage AGT-Kit skills dynamically
4
+ ===================================================
5
+
6
+ Enable/disable skills without deleting them.
7
+
8
+ Usage:
9
+ python3 .agent/scripts/skills_manager.py list # List active skills
10
+ python3 .agent/scripts/skills_manager.py disabled # List disabled skills
11
+ python3 .agent/scripts/skills_manager.py enable SKILL # Enable a skill
12
+ python3 .agent/scripts/skills_manager.py disable SKILL # Disable a skill
13
+ python3 .agent/scripts/skills_manager.py search QUERY # Search skills
14
+ python3 .agent/scripts/skills_manager.py info SKILL # Show skill details
15
+ """
16
+
17
+ import sys
18
+ import os
19
+ import re
20
+ from pathlib import Path
21
+
22
+ # Fix console encoding
23
+ try:
24
+ sys.stdout.reconfigure(encoding='utf-8', errors='replace')
25
+ except:
26
+ pass
27
+
28
+ # Paths
29
+ SCRIPT_DIR = Path(__file__).parent
30
+ AGENT_DIR = SCRIPT_DIR.parent
31
+ SKILLS_DIR = AGENT_DIR / "skills"
32
+ DISABLED_DIR = SKILLS_DIR / ".disabled"
33
+
34
+
35
+ def parse_frontmatter(content: str) -> dict:
36
+ """Parse YAML frontmatter from SKILL.md."""
37
+ fm_match = re.search(r'^---\s*\n(.*?)\n---', content, re.DOTALL)
38
+ if not fm_match:
39
+ return {}
40
+
41
+ metadata = {}
42
+ for line in fm_match.group(1).split('\n'):
43
+ if ':' in line:
44
+ key, val = line.split(':', 1)
45
+ metadata[key.strip()] = val.strip().strip('"').strip("'")
46
+ return metadata
47
+
48
+
49
+ def get_skill_info(skill_path: Path) -> dict:
50
+ """Get information about a skill."""
51
+ skill_md = skill_path / "SKILL.md"
52
+ info = {
53
+ "name": skill_path.name,
54
+ "path": str(skill_path),
55
+ "has_skill_md": skill_md.exists(),
56
+ "has_scripts": (skill_path / "scripts").exists(),
57
+ "description": "",
58
+ }
59
+
60
+ if skill_md.exists():
61
+ try:
62
+ content = skill_md.read_text(encoding='utf-8')
63
+ metadata = parse_frontmatter(content)
64
+ info["description"] = metadata.get("description", "")[:80]
65
+ except:
66
+ pass
67
+
68
+ return info
69
+
70
+
71
+ def list_active():
72
+ """List all active skills."""
73
+ print("\n🟢 Active Skills\n" + "="*50)
74
+
75
+ skills = sorted([
76
+ d for d in SKILLS_DIR.iterdir()
77
+ if d.is_dir() and not d.name.startswith('.')
78
+ ], key=lambda x: x.name)
79
+
80
+ with_scripts = 0
81
+ for skill in skills:
82
+ info = get_skill_info(skill)
83
+ script_icon = "šŸ“œ" if info["has_scripts"] else " "
84
+ desc = f" - {info['description']}" if info["description"] else ""
85
+ print(f" {script_icon} {skill.name}{desc}")
86
+ if info["has_scripts"]:
87
+ with_scripts += 1
88
+
89
+ print(f"\nāœ… Total: {len(skills)} skills ({with_scripts} with scripts)")
90
+
91
+
92
+ def list_disabled():
93
+ """List all disabled skills."""
94
+ if not DISABLED_DIR.exists():
95
+ print("āŒ No disabled skills")
96
+ return
97
+
98
+ print("\n⚪ Disabled Skills\n" + "="*50)
99
+
100
+ disabled = sorted([d for d in DISABLED_DIR.iterdir() if d.is_dir()])
101
+
102
+ for skill in disabled:
103
+ print(f" • {skill.name}")
104
+
105
+ print(f"\nšŸ“Š Total: {len(disabled)} disabled skills")
106
+
107
+
108
+ def enable_skill(skill_name: str):
109
+ """Enable a disabled skill."""
110
+ source = DISABLED_DIR / skill_name
111
+ target = SKILLS_DIR / skill_name
112
+
113
+ if not source.exists():
114
+ print(f"āŒ Skill '{skill_name}' not found in .disabled/")
115
+ return False
116
+
117
+ if target.exists():
118
+ print(f"āš ļø Skill '{skill_name}' already active")
119
+ return False
120
+
121
+ source.rename(target)
122
+ print(f"āœ… Enabled: {skill_name}")
123
+ return True
124
+
125
+
126
+ def disable_skill(skill_name: str):
127
+ """Disable an active skill."""
128
+ source = SKILLS_DIR / skill_name
129
+ target = DISABLED_DIR / skill_name
130
+
131
+ if not source.exists():
132
+ print(f"āŒ Skill '{skill_name}' not found")
133
+ return False
134
+
135
+ if source.name.startswith('.'):
136
+ print(f"āš ļø Cannot disable system directory")
137
+ return False
138
+
139
+ DISABLED_DIR.mkdir(exist_ok=True)
140
+ source.rename(target)
141
+ print(f"āœ… Disabled: {skill_name}")
142
+ return True
143
+
144
+
145
+ def search_skills(query: str):
146
+ """Search skills by name or description."""
147
+ print(f"\nšŸ” Searching for '{query}'\n" + "="*50)
148
+
149
+ query_lower = query.lower()
150
+ matches = []
151
+
152
+ for skill_path in SKILLS_DIR.iterdir():
153
+ if not skill_path.is_dir() or skill_path.name.startswith('.'):
154
+ continue
155
+
156
+ info = get_skill_info(skill_path)
157
+
158
+ # Search in name and description
159
+ if query_lower in skill_path.name.lower() or query_lower in info["description"].lower():
160
+ matches.append(info)
161
+
162
+ if matches:
163
+ for info in matches:
164
+ script_icon = "šŸ“œ" if info["has_scripts"] else " "
165
+ desc = f" - {info['description']}" if info["description"] else ""
166
+ print(f" {script_icon} {info['name']}{desc}")
167
+ print(f"\nāœ… Found {len(matches)} matching skills")
168
+ else:
169
+ print(" No skills found matching your query")
170
+
171
+
172
+ def show_skill_info(skill_name: str):
173
+ """Show detailed info about a skill."""
174
+ skill_path = SKILLS_DIR / skill_name
175
+
176
+ if not skill_path.exists():
177
+ print(f"āŒ Skill '{skill_name}' not found")
178
+ return
179
+
180
+ info = get_skill_info(skill_path)
181
+ skill_md = skill_path / "SKILL.md"
182
+
183
+ print(f"\nšŸ“¦ Skill: {skill_name}\n" + "="*50)
184
+ print(f"Path: {info['path']}")
185
+ print(f"Has SKILL.md: {'āœ…' if info['has_skill_md'] else 'āŒ'}")
186
+ print(f"Has Scripts: {'āœ…' if info['has_scripts'] else 'āŒ'}")
187
+
188
+ if info['has_scripts']:
189
+ scripts_dir = skill_path / "scripts"
190
+ scripts = list(scripts_dir.glob("*.py"))
191
+ print(f"\nScripts ({len(scripts)}):")
192
+ for script in scripts:
193
+ print(f" • {script.name}")
194
+
195
+ if skill_md.exists():
196
+ try:
197
+ content = skill_md.read_text(encoding='utf-8')
198
+ metadata = parse_frontmatter(content)
199
+ if metadata.get("description"):
200
+ print(f"\nDescription:\n {metadata['description']}")
201
+ except:
202
+ pass
203
+
204
+
205
+ def main():
206
+ if len(sys.argv) < 2:
207
+ print(__doc__)
208
+ sys.exit(1)
209
+
210
+ command = sys.argv[1].lower()
211
+
212
+ if command == "list":
213
+ list_active()
214
+ elif command == "disabled":
215
+ list_disabled()
216
+ elif command == "enable":
217
+ if len(sys.argv) < 3:
218
+ print("āŒ Usage: skills_manager.py enable SKILL_NAME")
219
+ sys.exit(1)
220
+ enable_skill(sys.argv[2])
221
+ elif command == "disable":
222
+ if len(sys.argv) < 3:
223
+ print("āŒ Usage: skills_manager.py disable SKILL_NAME")
224
+ sys.exit(1)
225
+ disable_skill(sys.argv[2])
226
+ elif command == "search":
227
+ if len(sys.argv) < 3:
228
+ print("āŒ Usage: skills_manager.py search QUERY")
229
+ sys.exit(1)
230
+ search_skills(sys.argv[2])
231
+ elif command == "info":
232
+ if len(sys.argv) < 3:
233
+ print("āŒ Usage: skills_manager.py info SKILL_NAME")
234
+ sys.exit(1)
235
+ show_skill_info(sys.argv[2])
236
+ else:
237
+ print(f"āŒ Unknown command: {command}")
238
+ print(__doc__)
239
+ sys.exit(1)
240
+
241
+
242
+ if __name__ == "__main__":
243
+ main()