@cristiancorreau/forge 2.9.6 → 2.9.8

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 (53) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/doctor.d.ts.map +1 -1
  3. package/dist/commands/doctor.js +4 -3
  4. package/dist/commands/doctor.js.map +1 -1
  5. package/dist/commands/generate.js +1 -1
  6. package/dist/commands/generate.js.map +1 -1
  7. package/dist/commands/init.js +2 -2
  8. package/dist/commands/init.js.map +1 -1
  9. package/dist/lib/generators/codex.d.ts.map +1 -1
  10. package/dist/lib/generators/codex.js +10 -8
  11. package/dist/lib/generators/codex.js.map +1 -1
  12. package/dist/lib/generators/kiro.d.ts +1 -1
  13. package/dist/lib/generators/kiro.d.ts.map +1 -1
  14. package/dist/lib/generators/kiro.js +15 -16
  15. package/dist/lib/generators/kiro.js.map +1 -1
  16. package/dist/lib/generators/opencode.d.ts.map +1 -1
  17. package/dist/lib/generators/opencode.js +13 -12
  18. package/dist/lib/generators/opencode.js.map +1 -1
  19. package/dist/lib/paths.d.ts +1 -2
  20. package/dist/lib/paths.d.ts.map +1 -1
  21. package/dist/lib/paths.js +12 -16
  22. package/dist/lib/paths.js.map +1 -1
  23. package/dist/version.d.ts +1 -1
  24. package/dist/version.js +1 -1
  25. package/package.json +2 -2
  26. package/assets/adapters/claude-code/generate-claude-md.py +0 -304
  27. package/assets/adapters/codex/generate-codex-config.py +0 -269
  28. package/assets/adapters/codex/hooks/codex.yaml.tpl +0 -43
  29. package/assets/adapters/codex/hooks/forge-codex-finish.sh +0 -158
  30. package/assets/adapters/codex/hooks/forge-codex-start.sh +0 -186
  31. package/assets/adapters/kiro/generate-steering.py +0 -367
  32. package/assets/adapters/opencode/generate-agents-md.py +0 -262
  33. package/assets/core/hooks/pre-bash-check.py +0 -202
  34. package/assets/core/hooks/pre-edit-check.py +0 -317
  35. package/assets/forge.py +0 -1265
  36. package/assets/requirements.txt +0 -2
  37. package/assets/scripts/aitmpl-search.py +0 -808
  38. package/assets/scripts/forge-add-opportunities.py +0 -92
  39. package/assets/scripts/forge-audit.py +0 -1061
  40. package/assets/scripts/forge-generate-all.py +0 -283
  41. package/assets/scripts/forge-init.py +0 -900
  42. package/assets/scripts/forge-migrate-project-yaml.py +0 -397
  43. package/assets/scripts/forge-scaffold-profile.py +0 -181
  44. package/assets/scripts/forge-teardown.py +0 -193
  45. package/assets/scripts/forge-validate-project-yaml.py +0 -457
  46. package/assets/scripts/forge-wizard.py +0 -1003
  47. package/assets/scripts/setup-codex.sh +0 -229
  48. package/assets/scripts/team-install.sh +0 -147
  49. package/assets/scripts/token-stats.py +0 -201
  50. package/dist/lib/python.d.ts +0 -4
  51. package/dist/lib/python.d.ts.map +0 -1
  52. package/dist/lib/python.js +0 -46
  53. package/dist/lib/python.js.map +0 -1
@@ -1,808 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- template-search.py — Busca templates y recursos para desarrollo con agentes IA.
4
-
5
- Catálogo curado de frameworks, servidores MCP, skills y herramientas.
6
- Funciona offline. Opcionalmente extiende con búsqueda en GitHub (--github).
7
-
8
- Usage:
9
- python3 .agentic/scripts/aitmpl-search.py "fastapi"
10
- python3 .agentic/scripts/aitmpl-search.py "mcp postgres"
11
- python3 .agentic/scripts/aitmpl-search.py --category mcp-server
12
- python3 .agentic/scripts/aitmpl-search.py --list-categories
13
- python3 .agentic/scripts/aitmpl-search.py "rails" --github
14
- python3 .agentic/scripts/aitmpl-search.py --json "claude"
15
- """
16
- from __future__ import annotations
17
-
18
- import argparse
19
- import json
20
- import os
21
- import sys
22
- import time
23
- import textwrap
24
- import urllib.error
25
- import urllib.parse
26
- import urllib.request
27
- from pathlib import Path
28
- from typing import Optional
29
-
30
- # ---------------------------------------------------------------------------
31
- # Catálogo curado
32
- # Campos: name, description, category, tags, url, language
33
- #
34
- # Categorías:
35
- # framework — frameworks de desarrollo con agentes IA
36
- # mcp-server — servidores Model Context Protocol
37
- # skill — skills/comandos para Claude Code
38
- # tool — herramientas de CLI o automatización
39
- # profile — profiles de stack para forge
40
- # resource — documentación, listas y guías
41
- # ---------------------------------------------------------------------------
42
-
43
- CATALOG: list[dict] = [
44
-
45
- # ── Frameworks ──────────────────────────────────────────────────────────
46
-
47
- {
48
- "name": "cristiancorreau/forge",
49
- "description": "Framework de desarrollo con agentes IA para equipos. Profiles para Next.js, Astro, FastAPI, Rails, NestJS, Express, Expo y más. Wizard CLI interactivo.",
50
- "category": "framework",
51
- "tags": ["claude-code", "agents", "typescript", "python", "ruby", "nextjs", "astro", "fastapi", "rails", "nestjs", "express", "expo"],
52
- "url": "https://github.com/cristiancorreau/forge",
53
- "language": "Python",
54
- },
55
- {
56
- "name": "paul-gauthier/aider",
57
- "description": "Pair programming con LLMs en la terminal. Soporta Claude, GPT-4, Gemini. Edita archivos directamente y hace commits automáticos.",
58
- "category": "framework",
59
- "tags": ["claude", "gpt4", "pair-programming", "git", "terminal"],
60
- "url": "https://github.com/paul-gauthier/aider",
61
- "language": "Python",
62
- },
63
- {
64
- "name": "BuilderIO/micro-agent",
65
- "description": "Agente IA que escribe código hasta que los tests pasan. TDD automático: genera código iterativamente hasta lograr green tests.",
66
- "category": "framework",
67
- "tags": ["tdd", "testing", "code-generation", "claude", "openai"],
68
- "url": "https://github.com/BuilderIO/micro-agent",
69
- "language": "TypeScript",
70
- },
71
- {
72
- "name": "anthropics/anthropic-quickstarts",
73
- "description": "Quickstarts oficiales de Anthropic: customer support agent, computer use, multi-agent portfolio. Ejemplos de referencia.",
74
- "category": "framework",
75
- "tags": ["claude", "anthropic", "multi-agent", "computer-use", "quickstart"],
76
- "url": "https://github.com/anthropics/anthropic-quickstarts",
77
- "language": "Python",
78
- },
79
- {
80
- "name": "anthropics/claude-code-action",
81
- "description": "GitHub Action oficial para usar Claude Code en CI/CD. Permite que Claude revise PRs, corrija bugs y responda issues automáticamente.",
82
- "category": "framework",
83
- "tags": ["claude-code", "github-actions", "ci-cd", "pr-review"],
84
- "url": "https://github.com/anthropics/claude-code-action",
85
- "language": "TypeScript",
86
- },
87
-
88
- # ── MCP Servers — oficiales ──────────────────────────────────────────────
89
-
90
- {
91
- "name": "MCP — filesystem",
92
- "description": "Acceso seguro al sistema de archivos local con control de directorios permitidos. Leer, escribir, listar y buscar archivos.",
93
- "category": "mcp-server",
94
- "tags": ["filesystem", "files", "read", "write", "mcp", "oficial"],
95
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem",
96
- "language": "TypeScript",
97
- "install": {
98
- "slug": "filesystem",
99
- "command": "npx",
100
- "args": ["-y", "@modelcontextprotocol/server-filesystem", "{ALLOWED_DIR}"],
101
- "params": [{"key": "ALLOWED_DIR", "label": "Directorio permitido", "default": "."}],
102
- "env": [],
103
- },
104
- },
105
- {
106
- "name": "MCP — git",
107
- "description": "Operaciones git: leer historial, diffs, commits, branches y status. Integración completa con repositorios git locales.",
108
- "category": "mcp-server",
109
- "tags": ["git", "version-control", "commits", "diff", "mcp", "oficial"],
110
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/git",
111
- "language": "Python",
112
- "install": {
113
- "slug": "git",
114
- "command": "uvx",
115
- "args": ["mcp-server-git", "--repository", "{REPO_PATH}"],
116
- "params": [{"key": "REPO_PATH", "label": "Ruta del repositorio git", "default": "."}],
117
- "env": [],
118
- },
119
- },
120
- {
121
- "name": "MCP — github",
122
- "description": "Integración con la API de GitHub: repos, issues, PRs, branches, commits, búsqueda de código. Requiere GITHUB_TOKEN.",
123
- "category": "mcp-server",
124
- "tags": ["github", "issues", "pull-requests", "api", "mcp", "oficial"],
125
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/github",
126
- "language": "TypeScript",
127
- "install": {
128
- "slug": "github",
129
- "command": "npx",
130
- "args": ["-y", "@modelcontextprotocol/server-github"],
131
- "params": [],
132
- "env": [{"key": "GITHUB_TOKEN", "label": "GitHub personal access token (ghp_...)"}],
133
- },
134
- },
135
- {
136
- "name": "MCP — postgres",
137
- "description": "Acceso read-only a bases de datos PostgreSQL. Ejecutar queries, explorar schemas y tablas. Ideal para análisis de datos.",
138
- "category": "mcp-server",
139
- "tags": ["postgres", "postgresql", "database", "sql", "mcp", "oficial"],
140
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/postgres",
141
- "language": "TypeScript",
142
- "install": {
143
- "slug": "postgres",
144
- "command": "npx",
145
- "args": ["-y", "@modelcontextprotocol/server-postgres", "{CONNECTION_STRING}"],
146
- "params": [{"key": "CONNECTION_STRING", "label": "PostgreSQL connection string", "default": "postgresql://localhost/mydb"}],
147
- "env": [],
148
- },
149
- },
150
- {
151
- "name": "MCP — sqlite",
152
- "description": "Interacción con bases de datos SQLite: queries, introspección de schema, gestión de datos. Memo de conocimiento incorporado.",
153
- "category": "mcp-server",
154
- "tags": ["sqlite", "database", "sql", "local", "mcp", "oficial"],
155
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/sqlite",
156
- "language": "Python",
157
- "install": {
158
- "slug": "sqlite",
159
- "command": "uvx",
160
- "args": ["mcp-server-sqlite", "--db-path", "{DB_PATH}"],
161
- "params": [{"key": "DB_PATH", "label": "Ruta del archivo SQLite", "default": "./data.db"}],
162
- "env": [],
163
- },
164
- },
165
- {
166
- "name": "MCP — fetch",
167
- "description": "Fetch de URLs y conversión a Markdown. Permite a Claude leer páginas web, documentación y APIs HTTP.",
168
- "category": "mcp-server",
169
- "tags": ["http", "fetch", "web", "scraping", "markdown", "mcp", "oficial"],
170
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/fetch",
171
- "language": "Python",
172
- "install": {
173
- "slug": "fetch",
174
- "command": "uvx",
175
- "args": ["mcp-server-fetch"],
176
- "params": [],
177
- "env": [],
178
- },
179
- },
180
- {
181
- "name": "MCP — brave-search",
182
- "description": "Búsqueda web con Brave Search API. Web search y local search con privacidad. Requiere BRAVE_API_KEY.",
183
- "category": "mcp-server",
184
- "tags": ["search", "web-search", "brave", "internet", "mcp", "oficial"],
185
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/brave-search",
186
- "language": "TypeScript",
187
- "install": {
188
- "slug": "brave-search",
189
- "command": "npx",
190
- "args": ["-y", "@modelcontextprotocol/server-brave-search"],
191
- "params": [],
192
- "env": [{"key": "BRAVE_API_KEY", "label": "Brave Search API key"}],
193
- },
194
- },
195
- {
196
- "name": "MCP — slack",
197
- "description": "Integración con Slack: enviar mensajes, leer canales, gestionar usuarios. Requiere Slack Bot Token.",
198
- "category": "mcp-server",
199
- "tags": ["slack", "messaging", "communication", "mcp", "oficial"],
200
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/slack",
201
- "language": "TypeScript",
202
- "install": {
203
- "slug": "slack",
204
- "command": "npx",
205
- "args": ["-y", "@modelcontextprotocol/server-slack"],
206
- "params": [],
207
- "env": [
208
- {"key": "SLACK_BOT_TOKEN", "label": "Slack Bot Token (xoxb-...)"},
209
- {"key": "SLACK_TEAM_ID", "label": "Slack Team ID"},
210
- ],
211
- },
212
- },
213
- {
214
- "name": "MCP — puppeteer",
215
- "description": "Automatización de browser con Puppeteer: navegar, hacer screenshots, rellenar formularios y ejecutar JavaScript.",
216
- "category": "mcp-server",
217
- "tags": ["puppeteer", "browser", "automation", "screenshot", "scraping", "mcp", "oficial"],
218
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/puppeteer",
219
- "language": "TypeScript",
220
- "install": {
221
- "slug": "puppeteer",
222
- "command": "npx",
223
- "args": ["-y", "@modelcontextprotocol/server-puppeteer"],
224
- "params": [],
225
- "env": [],
226
- },
227
- },
228
- {
229
- "name": "MCP — sequential-thinking",
230
- "description": "Herramienta de razonamiento paso a paso con revisión y backtracking. Para problemas complejos que requieren análisis estructurado.",
231
- "category": "mcp-server",
232
- "tags": ["reasoning", "thinking", "analysis", "chain-of-thought", "mcp", "oficial"],
233
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/sequentialthinking",
234
- "language": "TypeScript",
235
- "install": {
236
- "slug": "sequential-thinking",
237
- "command": "npx",
238
- "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"],
239
- "params": [],
240
- "env": [],
241
- },
242
- },
243
- {
244
- "name": "MCP — memory",
245
- "description": "Grafo de conocimiento persistente. Claude puede guardar y recuperar información entre conversaciones con entidades y relaciones.",
246
- "category": "mcp-server",
247
- "tags": ["memory", "knowledge-graph", "persistence", "mcp", "oficial"],
248
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/memory",
249
- "language": "TypeScript",
250
- "install": {
251
- "slug": "memory",
252
- "command": "npx",
253
- "args": ["-y", "@modelcontextprotocol/server-memory"],
254
- "params": [],
255
- "env": [],
256
- },
257
- },
258
- {
259
- "name": "MCP — everything",
260
- "description": "Servidor MCP de referencia con prompts, tools y resources de ejemplo. Útil para probar clientes MCP y aprender el protocolo.",
261
- "category": "mcp-server",
262
- "tags": ["reference", "testing", "demo", "mcp", "oficial"],
263
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/everything",
264
- "language": "TypeScript",
265
- "install": {
266
- "slug": "everything",
267
- "command": "npx",
268
- "args": ["-y", "@modelcontextprotocol/server-everything"],
269
- "params": [],
270
- "env": [],
271
- },
272
- },
273
-
274
- # ── MCP Servers — comunidad ───────────────────────────────────────────────
275
-
276
- {
277
- "name": "MCP — supabase (comunidad)",
278
- "description": "Integración con Supabase: ejecutar queries SQL, gestionar tablas, auth y storage via MCP.",
279
- "category": "mcp-server",
280
- "tags": ["supabase", "postgres", "database", "auth", "storage", "mcp"],
281
- "url": "https://github.com/supabase-community/supabase-mcp",
282
- "language": "TypeScript",
283
- "install": {
284
- "slug": "supabase",
285
- "command": "npx",
286
- "args": ["-y", "@supabase/mcp-server-supabase", "--access-token", "{ACCESS_TOKEN}"],
287
- "params": [{"key": "ACCESS_TOKEN", "label": "Supabase personal access token"}],
288
- "env": [],
289
- },
290
- },
291
- {
292
- "name": "MCP — Cloudflare",
293
- "description": "Gestión de Workers, KV, R2, D1, AI Gateway y Vectorize de Cloudflare via MCP. Oficial de Cloudflare.",
294
- "category": "mcp-server",
295
- "tags": ["cloudflare", "workers", "kv", "r2", "d1", "edge", "mcp"],
296
- "url": "https://github.com/cloudflare/mcp-server-cloudflare",
297
- "language": "TypeScript",
298
- "install": {
299
- "slug": "cloudflare",
300
- "command": "npx",
301
- "args": ["-y", "@cloudflare/mcp-server-cloudflare"],
302
- "params": [],
303
- "env": [{"key": "CLOUDFLARE_API_TOKEN", "label": "Cloudflare API token"}],
304
- },
305
- },
306
- {
307
- "name": "MCP — Vercel",
308
- "description": "Gestión de proyectos, deploys, dominios y logs de Vercel via MCP. Integración oficial.",
309
- "category": "mcp-server",
310
- "tags": ["vercel", "deploy", "serverless", "hosting", "mcp"],
311
- "url": "https://github.com/vercel/mcp-server",
312
- "language": "TypeScript",
313
- "install": {
314
- "slug": "vercel",
315
- "command": "npx",
316
- "args": ["-y", "@vercel/mcp-adapter"],
317
- "params": [],
318
- "env": [{"key": "VERCEL_TOKEN", "label": "Vercel API token"}],
319
- },
320
- },
321
- {
322
- "name": "MCP — Linear",
323
- "description": "Integración con Linear: crear y consultar issues, proyectos y cycles. Para equipos que usan Linear como tracker.",
324
- "category": "mcp-server",
325
- "tags": ["linear", "project-management", "issues", "mcp"],
326
- "url": "https://github.com/linear/linear-mcp",
327
- "language": "TypeScript",
328
- "install": {
329
- "slug": "linear",
330
- "command": "npx",
331
- "args": ["-y", "@linear/mcp-server"],
332
- "params": [],
333
- "env": [{"key": "LINEAR_API_KEY", "label": "Linear API key"}],
334
- },
335
- },
336
- {
337
- "name": "MCP — Playwright",
338
- "description": "Automatización de browser con Playwright via MCP. Navegación, screenshots, testing E2E e interacción con páginas web.",
339
- "category": "mcp-server",
340
- "tags": ["playwright", "browser", "e2e", "testing", "automation", "mcp"],
341
- "url": "https://github.com/microsoft/playwright-mcp",
342
- "language": "TypeScript",
343
- "install": {
344
- "slug": "playwright",
345
- "command": "npx",
346
- "args": ["-y", "@playwright/mcp@latest"],
347
- "params": [],
348
- "env": [],
349
- },
350
- },
351
- {
352
- "name": "MCP — Sentry",
353
- "description": "Consulta issues, eventos y trazas de Sentry. Permite a Claude diagnosticar errores de producción directamente.",
354
- "category": "mcp-server",
355
- "tags": ["sentry", "errors", "monitoring", "debugging", "mcp"],
356
- "url": "https://github.com/getsentry/sentry-mcp",
357
- "language": "Python",
358
- "install": {
359
- "slug": "sentry",
360
- "command": "uvx",
361
- "args": ["mcp-server-sentry"],
362
- "params": [],
363
- "env": [{"key": "SENTRY_AUTH_TOKEN", "label": "Sentry auth token"}],
364
- },
365
- },
366
- {
367
- "name": "MCP — Docker",
368
- "description": "Gestión de contenedores, imágenes y volúmenes Docker via MCP. Ejecutar y gestionar el ciclo de vida de containers.",
369
- "category": "mcp-server",
370
- "tags": ["docker", "containers", "devops", "infrastructure", "mcp"],
371
- "url": "https://github.com/ckreiling/mcp-server-docker",
372
- "language": "Python",
373
- "install": {
374
- "slug": "docker",
375
- "command": "uvx",
376
- "args": ["mcp-server-docker"],
377
- "params": [],
378
- "env": [],
379
- },
380
- },
381
- {
382
- "name": "MCP — AWS (aws-kb-retrieval)",
383
- "description": "Retrieval desde AWS Knowledge Base. Para proyectos en AWS que usan Bedrock Knowledge Bases.",
384
- "category": "mcp-server",
385
- "tags": ["aws", "bedrock", "knowledge-base", "rag", "mcp", "oficial"],
386
- "url": "https://github.com/modelcontextprotocol/servers/tree/main/src/aws-kb-retrieval-server",
387
- "language": "TypeScript",
388
- "install": {
389
- "slug": "aws-kb",
390
- "command": "npx",
391
- "args": ["-y", "@modelcontextprotocol/server-aws-kb-retrieval"],
392
- "params": [],
393
- "env": [
394
- {"key": "AWS_ACCESS_KEY_ID", "label": "AWS Access Key ID"},
395
- {"key": "AWS_SECRET_ACCESS_KEY", "label": "AWS Secret Access Key"},
396
- {"key": "AWS_REGION", "label": "AWS Region", "default": "us-east-1"},
397
- ],
398
- },
399
- },
400
-
401
- # ── Profiles de forge ─────────────────────────────────────────────────────
402
-
403
- {
404
- "name": "forge profile — hono-drizzle",
405
- "description": "Agente api-engineer especializado en Hono + Drizzle ORM + TypeScript. Incluye rutas, schemas, migraciones y tests.",
406
- "category": "profile",
407
- "tags": ["hono", "drizzle", "typescript", "api", "orm", "edge"],
408
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/hono-drizzle",
409
- "language": "TypeScript",
410
- },
411
- {
412
- "name": "forge profile — nextjs-admin",
413
- "description": "Agente admin-engineer para dashboards con Next.js 15 + shadcn/ui. Componentes, tablas de datos y gestión interna.",
414
- "category": "profile",
415
- "tags": ["nextjs", "shadcn", "react", "dashboard", "admin", "typescript"],
416
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/nextjs-admin",
417
- "language": "TypeScript",
418
- },
419
- {
420
- "name": "forge profile — astro",
421
- "description": "Agente frontend-engineer para sitios con Astro. SSG/SSR, islands architecture, Content Collections y Tailwind.",
422
- "category": "profile",
423
- "tags": ["astro", "ssg", "ssr", "islands", "typescript", "tailwind", "static"],
424
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/astro",
425
- "language": "TypeScript",
426
- },
427
- {
428
- "name": "forge profile — fastapi",
429
- "description": "Agente api-engineer para FastAPI + Python. Endpoints async, Pydantic schemas, SQLAlchemy y pytest.",
430
- "category": "profile",
431
- "tags": ["fastapi", "python", "async", "pydantic", "sqlalchemy", "pytest"],
432
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/fastapi",
433
- "language": "Python",
434
- },
435
- {
436
- "name": "forge profile — rails",
437
- "description": "Agente fullstack-engineer para Ruby on Rails. Modelos, migraciones, controllers, views y RSpec.",
438
- "category": "profile",
439
- "tags": ["rails", "ruby", "activerecord", "rspec", "fullstack"],
440
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/rails",
441
- "language": "Ruby",
442
- },
443
- {
444
- "name": "forge profile — nestjs",
445
- "description": "Agente api-engineer para NestJS + TypeScript. Módulos, guards, decorators y arquitectura escalable.",
446
- "category": "profile",
447
- "tags": ["nestjs", "typescript", "node", "api", "modules", "guards"],
448
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/nestjs",
449
- "language": "TypeScript",
450
- },
451
- {
452
- "name": "forge profile — express",
453
- "description": "Agente api-engineer para Express + Node.js + TypeScript. Middleware, rutas, validación y Jest.",
454
- "category": "profile",
455
- "tags": ["express", "nodejs", "typescript", "middleware", "api"],
456
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/express",
457
- "language": "TypeScript",
458
- },
459
- {
460
- "name": "forge profile — expo",
461
- "description": "Agente mobile-engineer para React Native con Expo. Navegación, componentes nativos y EAS.",
462
- "category": "profile",
463
- "tags": ["expo", "react-native", "mobile", "ios", "android", "typescript"],
464
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/expo",
465
- "language": "TypeScript",
466
- },
467
- {
468
- "name": "forge profile — playwright-crawler",
469
- "description": "Agente scanner-engineer para scraping y crawling con Playwright. Extracción de datos, screenshots y automatización.",
470
- "category": "profile",
471
- "tags": ["playwright", "scraping", "crawler", "browser", "automation", "typescript"],
472
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/playwright-crawler",
473
- "language": "TypeScript",
474
- },
475
- {
476
- "name": "forge profile — django",
477
- "description": "Agente api-engineer para Django 4.x + DRF + PostgreSQL + pytest-django. Modelos, migraciones, serializers, viewsets y tests.",
478
- "category": "profile",
479
- "tags": ["django", "python", "drf", "postgresql", "rest-api", "pytest"],
480
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/django",
481
- "language": "Python",
482
- },
483
- {
484
- "name": "forge profile — vuenuxt",
485
- "description": "Agente frontend-engineer para Nuxt 3 + Vue 3 + Pinia + TypeScript. Pages, componentes, composables y SSR.",
486
- "category": "profile",
487
- "tags": ["nuxt", "vue", "typescript", "pinia", "ssr", "tailwind"],
488
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/vuenuxt",
489
- "language": "TypeScript",
490
- },
491
- {
492
- "name": "forge profile — go-gin",
493
- "description": "Agente api-engineer para Go + Gin/Echo + sqlc + PostgreSQL + testify. Handlers, services, repositories e migrations.",
494
- "category": "profile",
495
- "tags": ["go", "golang", "gin", "echo", "sqlc", "postgresql", "rest-api"],
496
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/go-gin",
497
- "language": "Go",
498
- },
499
- {
500
- "name": "forge profile — sveltekit",
501
- "description": "Agente frontend-engineer para SvelteKit 2 + Svelte 5 + TypeScript + Tailwind. Routes, components, load functions y form actions.",
502
- "category": "profile",
503
- "tags": ["sveltekit", "svelte", "typescript", "tailwind", "ssr", "vite"],
504
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/sveltekit",
505
- "language": "TypeScript",
506
- },
507
- {
508
- "name": "forge profile — laravel",
509
- "description": "Tres agentes para proyectos Laravel: api-engineer (Sanctum + Eloquent + Form Requests), fullstack-engineer (Blade + Livewire 3 o Inertia) y migration-specialist (upgrade L6→L13 paso a paso con breaking changes por versión).",
510
- "category": "profile",
511
- "tags": ["laravel", "php", "eloquent", "sanctum", "livewire", "blade", "inertia", "migration", "upgrade"],
512
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/laravel",
513
- "language": "PHP",
514
- },
515
- {
516
- "name": "forge profile — wordpress",
517
- "description": "Tres agentes para proyectos WordPress: wp-engineer (FSE + bloques Gutenberg + Interactivity API + WP REST API), divi-engineer (Divi Theme Builder + módulos ET_Builder_Module + Dynamic Content) y elementor-engineer (Elementor Pro + widgets personalizados + Dynamic Tags + Loop Grid).",
518
- "category": "profile",
519
- "tags": ["wordpress", "php", "gutenberg", "fse", "divi", "elementor", "page-builder", "blocks", "theme-builder"],
520
- "url": "https://github.com/cristiancorreau/forge/tree/main/profiles/wordpress",
521
- "language": "PHP",
522
- },
523
-
524
- # ── Tools ────────────────────────────────────────────────────────────────
525
-
526
- {
527
- "name": "anthropics/claude-code (CLI)",
528
- "description": "Claude Code oficial — CLI para desarrollo con agentes IA directamente en la terminal. Instalación: npm i -g @anthropic-ai/claude-code",
529
- "category": "tool",
530
- "tags": ["claude-code", "cli", "terminal", "official"],
531
- "url": "https://docs.anthropic.com/claude-code",
532
- "language": "TypeScript",
533
- },
534
- {
535
- "name": "modelcontextprotocol/inspector",
536
- "description": "Inspector visual para servidores MCP. Permite probar y depurar servers MCP en una interfaz web interactiva.",
537
- "category": "tool",
538
- "tags": ["mcp", "debugging", "inspector", "testing", "development"],
539
- "url": "https://github.com/modelcontextprotocol/inspector",
540
- "language": "TypeScript",
541
- },
542
-
543
- # ── Resources ─────────────────────────────────────────────────────────────
544
-
545
- {
546
- "name": "modelcontextprotocol/servers (todos)",
547
- "description": "Repositorio oficial con todos los servers MCP de referencia: filesystem, git, github, postgres, sqlite, fetch, slack, puppeteer, memory y más.",
548
- "category": "resource",
549
- "tags": ["mcp", "servers", "reference", "official"],
550
- "url": "https://github.com/modelcontextprotocol/servers",
551
- "language": "TypeScript",
552
- },
553
- {
554
- "name": "punkpeye/awesome-mcp-servers",
555
- "description": "Lista curada de servidores MCP de la comunidad. Cubre bases de datos, APIs, herramientas de desarrollo, comunicación y más.",
556
- "category": "resource",
557
- "tags": ["mcp", "awesome", "curated", "list", "community"],
558
- "url": "https://github.com/punkpeye/awesome-mcp-servers",
559
- "language": "",
560
- },
561
- {
562
- "name": "Documentación oficial MCP",
563
- "description": "Documentación del Model Context Protocol: guías para construir servers y clients, especificación del protocolo y ejemplos.",
564
- "category": "resource",
565
- "tags": ["mcp", "docs", "specification", "protocol", "official"],
566
- "url": "https://modelcontextprotocol.io",
567
- "language": "",
568
- },
569
- {
570
- "name": "Documentación Claude Code",
571
- "description": "Docs oficiales de Claude Code: hooks, slash commands, configuración de agentes, CLAUDE.md, MCP y más.",
572
- "category": "resource",
573
- "tags": ["claude-code", "docs", "hooks", "agents", "official"],
574
- "url": "https://docs.anthropic.com/claude-code",
575
- "language": "",
576
- },
577
- ]
578
-
579
- CATEGORIES = sorted(set(t["category"] for t in CATALOG))
580
-
581
- # ---------------------------------------------------------------------------
582
- # Búsqueda local
583
- # ---------------------------------------------------------------------------
584
-
585
- def _search_local(query: str, category: Optional[str] = None) -> list[dict]:
586
- terms = query.lower().split() if query else []
587
- results = []
588
- for item in CATALOG:
589
- if category and item["category"] != category:
590
- continue
591
- if not terms:
592
- results.append((0, item))
593
- continue
594
- haystack = " ".join([
595
- item["name"],
596
- item["description"],
597
- item["category"],
598
- " ".join(item["tags"]),
599
- item.get("language", ""),
600
- ]).lower()
601
- score = sum(1 for t in terms if t in haystack)
602
- if score > 0:
603
- results.append((score, item))
604
-
605
- results.sort(key=lambda x: x[0], reverse=True)
606
- return [x[1] for x in results]
607
-
608
-
609
- # ---------------------------------------------------------------------------
610
- # GitHub API (opcional, --github)
611
- # ---------------------------------------------------------------------------
612
-
613
- CACHE_FILE = Path.home() / ".forge" / "template-search-cache.json"
614
- CACHE_TTL = 1800
615
-
616
-
617
- def _cache_load() -> dict:
618
- if not CACHE_FILE.exists():
619
- return {}
620
- try:
621
- with open(CACHE_FILE) as f:
622
- data = json.load(f)
623
- if time.time() - data.get("_ts", 0) > CACHE_TTL:
624
- return {}
625
- return data
626
- except (json.JSONDecodeError, OSError):
627
- return {}
628
-
629
-
630
- def _cache_save(data: dict) -> None:
631
- CACHE_FILE.parent.mkdir(parents=True, exist_ok=True)
632
- data["_ts"] = time.time()
633
- try:
634
- with open(CACHE_FILE, "w") as f:
635
- json.dump(data, f)
636
- except OSError:
637
- pass
638
-
639
-
640
- def _fetch_github(query: str, limit: int) -> list[dict]:
641
- cache = _cache_load()
642
- cache_key = f"gh_{query}_{limit}"
643
- if cache_key in cache:
644
- return cache[cache_key]
645
-
646
- topic_q = "topic:claude-code OR topic:mcp-server OR topic:ai-agent"
647
- full_q = urllib.parse.urlencode({
648
- "q": f"{query} ({topic_q})",
649
- "sort": "stars",
650
- "order": "desc",
651
- "per_page": min(limit, 20),
652
- })
653
- url = f"https://api.github.com/search/repositories?{full_q}"
654
- headers = {
655
- "Accept": "application/vnd.github+json",
656
- "User-Agent": "forge-template-search/2.0",
657
- }
658
- token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
659
- if token:
660
- headers["Authorization"] = f"Bearer {token}"
661
-
662
- req = urllib.request.Request(url, headers=headers)
663
- try:
664
- with urllib.request.urlopen(req, timeout=10) as resp:
665
- data = json.loads(resp.read().decode("utf-8"))
666
- except urllib.error.HTTPError as e:
667
- if e.code == 403:
668
- print(" Límite de GitHub alcanzado. Exporta GITHUB_TOKEN para más requests.", file=sys.stderr)
669
- return []
670
- except (urllib.error.URLError, json.JSONDecodeError, OSError):
671
- return []
672
-
673
- results = []
674
- for item in data.get("items", []):
675
- results.append({
676
- "name": item.get("full_name", ""),
677
- "description": item.get("description") or "",
678
- "category": "github",
679
- "tags": item.get("topics", []),
680
- "url": item.get("html_url", ""),
681
- "language": item.get("language") or "",
682
- "stars": item.get("stargazers_count", 0),
683
- })
684
-
685
- cache[cache_key] = results
686
- _cache_save(cache)
687
- return results
688
-
689
-
690
- # ---------------------------------------------------------------------------
691
- # Output
692
- # ---------------------------------------------------------------------------
693
-
694
- CATEGORY_LABELS = {
695
- "framework": "Framework",
696
- "mcp-server": "MCP Server",
697
- "skill": "Skill",
698
- "tool": "Herramienta",
699
- "profile": "Profile forge",
700
- "resource": "Recurso",
701
- "github": "GitHub",
702
- }
703
-
704
-
705
- def _print_results(results: list[dict], as_json: bool) -> None:
706
- if as_json:
707
- print(json.dumps(results, ensure_ascii=False, indent=2))
708
- return
709
- if not results:
710
- print("Sin resultados. Prueba con otro término o usa --list-categories.")
711
- return
712
- for i, t in enumerate(results, 1):
713
- cat = CATEGORY_LABELS.get(t.get("category", ""), t.get("category", ""))
714
- name = t.get("name", "")
715
- desc = t.get("description", "")
716
- tags = t.get("tags", [])
717
- url = t.get("url", "")
718
- lang = t.get("language", "")
719
- stars = t.get("stars")
720
-
721
- meta_parts = [f"[{cat}]"]
722
- if lang:
723
- meta_parts.append(lang)
724
- if stars:
725
- meta_parts.append(f"★ {stars:,}")
726
- meta = " ".join(meta_parts)
727
-
728
- print(f"{i:>2}. {name}")
729
- if desc:
730
- for line in textwrap.wrap(desc, width=68, initial_indent=" ",
731
- subsequent_indent=" "):
732
- print(line)
733
- if tags:
734
- tag_str = " ".join(f"#{t}" for t in tags[:8])
735
- print(f" {tag_str}")
736
- print(f" {meta}")
737
- print(f" {url}")
738
- print()
739
-
740
-
741
- # ---------------------------------------------------------------------------
742
- # CLI
743
- # ---------------------------------------------------------------------------
744
-
745
- def main() -> None:
746
- parser = argparse.ArgumentParser(
747
- description="Busca templates y recursos para desarrollo con agentes IA.",
748
- formatter_class=argparse.RawDescriptionHelpFormatter,
749
- epilog=textwrap.dedent("""\
750
- Ejemplos:
751
- %(prog)s "fastapi"
752
- %(prog)s "mcp postgres"
753
- %(prog)s --category mcp-server
754
- %(prog)s --category profile
755
- %(prog)s "rails" --github
756
- %(prog)s --list-categories
757
- """),
758
- )
759
- parser.add_argument("query", nargs="?", default="",
760
- help="Término de búsqueda")
761
- parser.add_argument("--limit", type=int, default=20, metavar="N",
762
- help="Máximo de resultados (default: 20)")
763
- parser.add_argument("--json", dest="as_json", action="store_true",
764
- help="Salida en JSON")
765
- parser.add_argument("--category", "-c", metavar="CAT",
766
- help=f"Filtrar por categoría: {', '.join(CATEGORIES)}")
767
- parser.add_argument("--github", action="store_true",
768
- help="Extender con búsqueda en GitHub API (requiere red)")
769
- parser.add_argument("--list-categories", action="store_true",
770
- help="Listar categorías disponibles y cantidad de items")
771
-
772
- args = parser.parse_args()
773
-
774
- if args.list_categories:
775
- print("Categorías disponibles:\n")
776
- for cat in CATEGORIES:
777
- count = sum(1 for t in CATALOG if t["category"] == cat)
778
- label = CATEGORY_LABELS.get(cat, cat)
779
- print(f" {cat:<16} {label} ({count} items)")
780
- print(f"\nTotal catálogo: {len(CATALOG)} items\n")
781
- return
782
-
783
- if not args.query and not args.category:
784
- parser.print_help()
785
- sys.exit(1)
786
-
787
- results = _search_local(args.query, args.category)
788
-
789
- if args.github and args.query:
790
- print("Buscando en GitHub...", file=sys.stderr)
791
- gh = _fetch_github(args.query, args.limit)
792
- seen = {r["url"] for r in results}
793
- for item in gh:
794
- if item["url"] not in seen:
795
- results.append(item)
796
- seen.add(item["url"])
797
-
798
- results = results[: args.limit]
799
-
800
- if not args.as_json:
801
- source = "catálogo local" + (" + GitHub" if args.github else "")
802
- print(f"Resultados: {len(results)} ({source})\n", file=sys.stderr)
803
-
804
- _print_results(results, args.as_json)
805
-
806
-
807
- if __name__ == "__main__":
808
- main()