@qubiit/lmagent 3.1.2 → 3.1.3

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 (46) hide show
  1. package/.agents/docs/commands.md +80 -31
  2. package/.agents/docs/getting-started.md +50 -46
  3. package/.agents/rules/00-master.md +2 -2
  4. package/.agents/skills/ai-agent-engineer/SKILL.md +15 -3
  5. package/.agents/skills/api-designer/SKILL.md +13 -3
  6. package/.agents/skills/architect/SKILL.md +42 -29
  7. package/.agents/skills/automation-engineer/SKILL.md +14 -3
  8. package/.agents/skills/backend-engineer/SKILL.md +17 -3
  9. package/.agents/skills/bmad-methodology/SKILL.md +12 -3
  10. package/.agents/skills/browser-agent/SKILL.md +12 -3
  11. package/.agents/skills/code-reviewer/SKILL.md +13 -3
  12. package/.agents/skills/data-engineer/SKILL.md +14 -3
  13. package/.agents/skills/devops-engineer/SKILL.md +14 -3
  14. package/.agents/skills/document-generator/SKILL.md +14 -3
  15. package/.agents/skills/frontend-engineer/SKILL.md +19 -3
  16. package/.agents/skills/git-workflow/SKILL.md +12 -3
  17. package/.agents/skills/mcp-builder/SKILL.md +14 -3
  18. package/.agents/skills/mobile-engineer/SKILL.md +14 -3
  19. package/.agents/skills/orchestrator/SKILL.md +14 -3
  20. package/.agents/skills/performance-engineer/SKILL.md +14 -3
  21. package/.agents/skills/product-manager/SKILL.md +14 -3
  22. package/.agents/skills/prompt-engineer/SKILL.md +12 -3
  23. package/.agents/skills/qa-engineer/SKILL.md +14 -3
  24. package/.agents/skills/scrum-master/SKILL.md +12 -3
  25. package/.agents/skills/security-analyst/SKILL.md +14 -3
  26. package/.agents/skills/seo-auditor/SKILL.md +13 -3
  27. package/.agents/skills/spec-driven-dev/SKILL.md +14 -3
  28. package/.agents/skills/supabase-expert/SKILL.md +14 -3
  29. package/.agents/skills/swe-agent/SKILL.md +16 -3
  30. package/.agents/skills/systematic-debugger/SKILL.md +13 -3
  31. package/.agents/skills/tech-lead/SKILL.md +14 -3
  32. package/.agents/skills/technical-writer/SKILL.md +14 -3
  33. package/.agents/skills/testing-strategist/SKILL.md +13 -3
  34. package/.agents/skills/ux-ui-designer/SKILL.md +14 -3
  35. package/.agents/templates/agent-configs/_generic.md +20 -0
  36. package/.agents/templates/agent-configs/continuerules.md +17 -0
  37. package/.agents/templates/agent-configs/goosehints.md +19 -0
  38. package/.agents/templates/agent-configs/junie-guidelines.md +22 -0
  39. package/.agents/templates/agent-configs/openclaw.json +17 -0
  40. package/.agents/templates/agent-configs/openhands-repo.md +21 -0
  41. package/AGENTS.md +171 -84
  42. package/CLAUDE.md +2 -2
  43. package/CONTRIBUTING.md +112 -49
  44. package/README.md +211 -242
  45. package/install.js +423 -363
  46. package/package.json +1 -1
package/install.js CHANGED
@@ -10,6 +10,7 @@ const figlet = require('figlet');
10
10
  const gradient = require('gradient-string');
11
11
 
12
12
  const program = new Command();
13
+ const PKG_VERSION = require('./package.json').version;
13
14
 
14
15
  // Configuración: Directorios fuente del paquete
15
16
  const PACKAGE_SKILLS_DIR = path.join(__dirname, '.agents', 'skills');
@@ -21,9 +22,11 @@ const PACKAGE_DOCS_DIR = path.join(__dirname, '.agents', 'docs');
21
22
  const PACKAGE_MEMORY_DIR = path.join(__dirname, '.agents', 'memory');
22
23
 
23
24
  // Archivos de proyecto que init copia a la raíz
25
+ // Usan {{VERSION}} como placeholder; se reemplaza dinámicamente al instalar
24
26
  const INIT_FILES = [
25
- { src: 'CLAUDE.md', desc: 'Instrucciones para Claude Code' },
26
- { src: 'AGENTS.md', desc: 'Catálogo de capacidades LMAgent' },
27
+ { src: 'CLAUDE.md', desc: 'Instrucciones para Claude Code / Antigravity', versionTemplate: true },
28
+ { src: 'GEMINI.md', desc: 'Instrucciones para Gemini CLI / Antigravity', versionTemplate: true },
29
+ { src: 'AGENTS.md', desc: 'Catálogo de capacidades LMAgent', versionTemplate: false },
27
30
  ];
28
31
 
29
32
  const INIT_DIRS = [
@@ -33,322 +36,78 @@ const INIT_DIRS = [
33
36
  { src: 'workflows', desc: 'SOPs y Procedimientos' },
34
37
  ];
35
38
 
36
- // Configuración: IDEs y Agentes soportados
37
- // Configuración: IDEs y Agentes soportados
39
+ // IDE_CONFIGS: Lista ÚNICA y DEDUPLICADA de todos los agentes soportados
38
40
  const IDE_CONFIGS = [
39
- // --- IDEs & Tiers Principales (Auto-Detected) ---
41
+ // --- IDEs Principales (Auto-Detectados) ---
42
+ // Cursor: usa .cursor/rules/*.mdc (formato MDC con frontmatter)
40
43
  { name: 'Cursor', value: 'cursor', rulesDir: '.cursor/rules', skillsDir: '.cursor/skills', workflowsDir: '.cursor/workflows', configFile: '.cursorrules', bridgeFile: 'lmagent.mdc', markerFile: '.cursorrules', forceCopy: true },
41
- { name: 'Windsurf', value: 'windsurf', rulesDir: '.windsurf/rules', skillsDir: '.windsurf/skills', workflowsDir: '.windsurf/workflows', configFile: '.windsurfrules', bridgeFile: 'lmagent.md', markerFile: '.windsurfrules', forceCopy: true },
44
+ // Windsurf Wave 8+: usa .windsurf/rules/*.md (directorio, NO .windsurfrules)
45
+ { name: 'Windsurf', value: 'windsurf', rulesDir: '.windsurf/rules', skillsDir: '.windsurf/skills', workflowsDir: '.windsurf/workflows', configFile: null, bridgeFile: 'lmagent.md', markerFile: '.windsurf', forceCopy: true },
46
+ // Cline: usa .clinerules/ (directorio con .md files)
42
47
  { name: 'Cline', value: 'cline', rulesDir: '.clinerules', skillsDir: '.cline/skills', workflowsDir: '.cline/workflows', configFile: null, bridgeFile: '00-lmagent.md', markerFile: '.clinerules', forceCopy: true },
43
- { name: 'Roo Code', value: 'roo', rulesDir: '.clinerules', skillsDir: '.roo/skills', workflowsDir: '.roo/workflows', configFile: null, bridgeFile: '00-lmagent.md', markerFile: '.roo', forceCopy: true },
44
- { name: 'VSCode Copilot', value: 'vscode', rulesDir: '.github/instructions', skillsDir: '.github/skills', workflowsDir: '.github/workflows', configFile: '.github/copilot-instructions.md', markerFile: '.vscode' },
48
+ // Roo Code: usa .roo/rules/ (NO .clinerules, que es de Cline)
49
+ { name: 'Roo Code', value: 'roo', rulesDir: '.roo/rules', skillsDir: '.roo/skills', workflowsDir: '.roo/workflows', configFile: null, bridgeFile: '00-lmagent.md', markerFile: '.roo', forceCopy: true },
50
+ // GitHub Copilot: usa .github/copilot-instructions.md + .github/instructions/*.md
51
+ { name: 'VSCode Copilot', value: 'vscode', rulesDir: '.github/instructions', skillsDir: '.github/skills', workflowsDir: '.github/workflows', configFile: '.github/copilot-instructions.md', bridgeFile: null, markerFile: '.vscode' },
45
52
  { name: 'Trae', value: 'trae', rulesDir: '.trae/rules', skillsDir: '.trae/skills', workflowsDir: '.trae/workflows', configFile: null, bridgeFile: 'lmagent.md', markerFile: '.trae', forceCopy: true },
46
- { name: 'Claude Code', value: 'claude', rulesDir: '.claude/rules', skillsDir: '.claude/skills', workflowsDir: '.claude/workflows', configFile: 'CLAUDE.md', markerFile: '.claude', forceCopy: true },
47
-
48
- // --- Expanded Agent Support (Manual/Config Injection) ---
49
- { name: 'Amp / Kimi / Replit', value: 'amp', rulesDir: '.agents/rules', skillsDir: '.agents/skills', workflowsDir: '.agents/workflows', configFile: null, markerFile: '.agents' },
50
- { name: 'Antigravity', value: 'antigravity', rulesDir: '.agent/rules', skillsDir: '.agent/skills', workflowsDir: '.agent/workflows', configFile: null, markerFile: '.agent' },
51
- { name: 'Augment', value: 'augment', rulesDir: '.augment/rules', skillsDir: '.augment/skills', workflowsDir: '.augment/workflows', configFile: null, markerFile: '.augment' },
52
- { name: 'OpenClaw', value: 'openclaw', rulesDir: 'rules', skillsDir: 'skills', workflowsDir: 'workflows', configFile: null, markerFile: 'openclaw.yaml' },
53
- { name: 'CodeBuddy', value: 'codebuddy', rulesDir: '.codebuddy/rules', skillsDir: '.codebuddy/skills', workflowsDir: '.codebuddy/workflows', configFile: null, markerFile: '.codebuddy' },
54
- { name: 'Codex', value: 'codex', rulesDir: '.codex/rules', skillsDir: '.codex/skills', workflowsDir: '.codex/workflows', configFile: null, markerFile: '.codex' },
55
- { name: 'Command Code', value: 'command-code', rulesDir: '.commandcode/rules', skillsDir: '.commandcode/skills', workflowsDir: '.commandcode/workflows', configFile: null, markerFile: '.commandcode' },
56
- { name: 'Continue', value: 'continue', rulesDir: '.continue/rules', skillsDir: '.continue/skills', workflowsDir: '.continue/workflows', configFile: null, bridgeFile: '00-lmagent.md', markerFile: '.continue' },
57
- { name: 'Crush', value: 'crush', rulesDir: '.crush/rules', skillsDir: '.crush/skills', workflowsDir: '.crush/workflows', configFile: null, markerFile: '.crush' },
58
- { name: 'Droid', value: 'droid', rulesDir: '.factory/rules', skillsDir: '.factory/skills', workflowsDir: '.factory/workflows', configFile: null, markerFile: '.factory' },
59
- { name: 'Gemini CLI', value: 'gemini', rulesDir: '.agents/rules', skillsDir: '.agents/skills', workflowsDir: '.agents/workflows', configFile: null, markerFile: '.gemini' },
60
- { name: 'Goose', value: 'goose', rulesDir: '.goose/rules', skillsDir: '.goose/skills', workflowsDir: '.goose/workflows', configFile: null, bridgeFile: 'lmagent.md', markerFile: '.goose' },
61
- { name: 'Junie', value: 'junie', rulesDir: '.junie/rules', skillsDir: '.junie/skills', workflowsDir: '.junie/workflows', configFile: null, markerFile: '.junie' },
62
- { name: 'iFlow CLI', value: 'iflow', rulesDir: '.iflow/rules', skillsDir: '.iflow/skills', workflowsDir: '.iflow/workflows', configFile: null, markerFile: '.iflow' },
63
- { name: 'Kilo Code', value: 'kilo', rulesDir: '.kilocode/rules', skillsDir: '.kilocode/skills', workflowsDir: '.kilocode/workflows', configFile: null, markerFile: '.kilocode' },
64
- { name: 'Kiro CLI', value: 'kiro', rulesDir: '.kiro/rules', skillsDir: '.kiro/skills', workflowsDir: '.kiro/workflows', configFile: null, markerFile: '.kiro' },
65
- { name: 'Kode', value: 'kode', rulesDir: '.kode/rules', skillsDir: '.kode/skills', workflowsDir: '.kode/workflows', configFile: null, markerFile: '.kode' },
66
- { name: 'MCPJam', value: 'mcpjam', rulesDir: '.mcpjam/rules', skillsDir: '.mcpjam/skills', workflowsDir: '.mcpjam/workflows', configFile: null, markerFile: '.mcpjam' },
67
- { name: 'Mistral Vibe', value: 'mistral', rulesDir: '.vibe/rules', skillsDir: '.vibe/skills', workflowsDir: '.vibe/workflows', configFile: null, markerFile: '.vibe' },
68
- { name: 'Mux', value: 'mux', rulesDir: '.mux/rules', skillsDir: '.mux/skills', workflowsDir: '.mux/workflows', configFile: null, markerFile: '.mux' },
69
- { name: 'OpenCode', value: 'opencode', rulesDir: '.opencode/rules', skillsDir: '.opencode/skills', workflowsDir: '.opencode/workflows', configFile: null, markerFile: '.opencode' },
70
- { name: 'OpenHands', value: 'openhands', rulesDir: '.openhands/microagents', skillsDir: '.openhands/skills', workflowsDir: '.openhands/workflows', configFile: null, bridgeFile: 'repo.md', markerFile: '.openhands' },
71
- { name: 'Pi', value: 'pi', rulesDir: '.pi/rules', skillsDir: '.pi/skills', workflowsDir: '.pi/workflows', configFile: null, markerFile: '.pi' },
72
- { name: 'Qoder', value: 'qoder', rulesDir: '.qoder/rules', skillsDir: '.qoder/skills', workflowsDir: '.qoder/workflows', configFile: null, markerFile: '.qoder' },
73
- { name: 'Qwen Code', value: 'qwen', rulesDir: '.qwen/rules', skillsDir: '.qwen/skills', workflowsDir: '.qwen/workflows', configFile: null, markerFile: '.qwen' },
53
+ // Claude Code: usa CLAUDE.md (raíz) + .claude/rules/ + .claude/skills/
54
+ { name: 'Claude Code', value: 'claude', rulesDir: '.claude/rules', skillsDir: '.claude/skills', workflowsDir: '.claude/workflows', configFile: 'CLAUDE.md', bridgeFile: null, markerFile: '.claude', forceCopy: true },
55
+ { name: 'Zed', value: 'zed', rulesDir: '.rules', skillsDir: '.rules/skills', workflowsDir: '.rules/workflows', configFile: null, bridgeFile: 'lmagent.md', markerFile: '.zed' },
56
+
57
+ // --- Agentes CLI & Autónomos ---
58
+ { name: 'Amp / Kimi / Replit', value: 'amp', rulesDir: '.agents/rules', skillsDir: '.agents/skills', workflowsDir: '.agents/workflows', configFile: null, bridgeFile: null, markerFile: '.agents' },
59
+ // Antigravity (Google Deepmind): usa GEMINI.md (raíz) + .agent/skills/ + .agent/rules/
60
+ { name: 'Antigravity', value: 'antigravity', rulesDir: '.agent/rules', skillsDir: '.agent/skills', workflowsDir: '.agent/workflows', configFile: 'GEMINI.md', bridgeFile: null, markerFile: '.agent' },
61
+ { name: 'Augment', value: 'augment', rulesDir: '.augment/rules', skillsDir: '.augment/skills', workflowsDir: '.augment/workflows', configFile: null, bridgeFile: null, markerFile: '.augment' },
62
+ // Gemini CLI: usa GEMINI.md (raíz) + .gemini/skills/ (oficial) o .agents/skills/ (fallback)
63
+ { name: 'Gemini CLI', value: 'gemini', rulesDir: '.gemini/rules', skillsDir: '.gemini/skills', workflowsDir: '.gemini/workflows', configFile: 'GEMINI.md', bridgeFile: null, markerFile: '.gemini' },
64
+ { name: 'OpenClaw / Envoid', value: 'openclaw', rulesDir: 'rules', skillsDir: 'skills', workflowsDir: 'workflows', configFile: 'openclaw.json', configTemplate: 'openclaw.json', bridgeFile: null, markerFile: 'openclaw.json' },
65
+ { name: 'CodeBuddy', value: 'codebuddy', rulesDir: '.codebuddy/rules', skillsDir: '.codebuddy/skills', workflowsDir: '.codebuddy/workflows', configFile: null, bridgeFile: null, markerFile: '.codebuddy', forceCopy: true },
66
+ // Codex CLI (OpenAI): usa AGENTS.md en raíz + .codex/ como directorio de config
67
+ { name: 'Codex', value: 'codex', rulesDir: '.codex', skillsDir: '.codex/skills', workflowsDir: '.codex/workflows', configFile: 'AGENTS.md', bridgeFile: null, markerFile: '.codex' },
68
+ { name: 'Command Code', value: 'command-code', rulesDir: '.commandcode/rules', skillsDir: '.commandcode/skills', workflowsDir: '.commandcode/workflows', configFile: null, bridgeFile: null, markerFile: '.commandcode' },
69
+ // Continue: soporta .continuerules (raíz) + .continue/rules/ (directorio)
70
+ { name: 'Continue', value: 'continue', rulesDir: '.continue/rules', skillsDir: '.continue/skills', workflowsDir: '.continue/workflows', configFile: '.continuerules', configTemplate: 'continuerules.md', bridgeFile: '00-lmagent.md', markerFile: '.continue' },
71
+ { name: 'Crush', value: 'crush', rulesDir: '.crush/rules', skillsDir: '.crush/skills', workflowsDir: '.crush/workflows', configFile: null, bridgeFile: null, markerFile: '.crush' },
72
+ { name: 'Droid', value: 'droid', rulesDir: '.factory/rules', skillsDir: '.factory/skills', workflowsDir: '.factory/workflows', configFile: null, bridgeFile: null, markerFile: '.factory' },
73
+ // Goose (Block): usa .goosehints en raíz para instrucciones al agente
74
+ { name: 'Goose', value: 'goose', rulesDir: '.goose', skillsDir: '.goose/skills', workflowsDir: '.goose/workflows', configFile: '.goosehints', configTemplate: 'goosehints.md', bridgeFile: null, markerFile: '.goose' },
75
+ // Junie (JetBrains): usa .junie/guidelines.md como archivo de instrucciones
76
+ { name: 'Junie', value: 'junie', rulesDir: '.junie', skillsDir: '.junie/skills', workflowsDir: '.junie/workflows', configFile: '.junie/guidelines.md', configTemplate: 'junie-guidelines.md', bridgeFile: null, markerFile: '.junie' },
77
+ { name: 'iFlow CLI', value: 'iflow', rulesDir: '.iflow/rules', skillsDir: '.iflow/skills', workflowsDir: '.iflow/workflows', configFile: null, bridgeFile: null, markerFile: '.iflow' },
78
+ { name: 'Kilo Code', value: 'kilo', rulesDir: '.kilocode/rules', skillsDir: '.kilocode/skills', workflowsDir: '.kilocode/workflows', configFile: null, bridgeFile: null, markerFile: '.kilocode' },
79
+ { name: 'Kiro CLI', value: 'kiro', rulesDir: '.kiro/rules', skillsDir: '.kiro/skills', workflowsDir: '.kiro/workflows', configFile: null, bridgeFile: null, markerFile: '.kiro' },
80
+ { name: 'Kode', value: 'kode', rulesDir: '.kode/rules', skillsDir: '.kode/skills', workflowsDir: '.kode/workflows', configFile: null, bridgeFile: null, markerFile: '.kode' },
81
+ { name: 'MCPJam', value: 'mcpjam', rulesDir: '.mcpjam/rules', skillsDir: '.mcpjam/skills', workflowsDir: '.mcpjam/workflows', configFile: null, bridgeFile: null, markerFile: '.mcpjam' },
82
+ { name: 'Mistral Vibe', value: 'mistral', rulesDir: '.vibe/rules', skillsDir: '.vibe/skills', workflowsDir: '.vibe/workflows', configFile: null, bridgeFile: null, markerFile: '.vibe' },
83
+ { name: 'Mux', value: 'mux', rulesDir: '.mux/rules', skillsDir: '.mux/skills', workflowsDir: '.mux/workflows', configFile: null, bridgeFile: null, markerFile: '.mux' },
84
+ { name: 'OpenCode', value: 'opencode', rulesDir: '.opencode/rules', skillsDir: '.opencode/skills', workflowsDir: '.opencode/workflows', configFile: null, bridgeFile: null, markerFile: '.opencode' },
85
+ // OpenHands: usa .openhands/microagents/repo.md para instrucciones del repo
86
+ { name: 'OpenHands', value: 'openhands', rulesDir: '.openhands/microagents', skillsDir: '.openhands/skills', workflowsDir: '.openhands/workflows', configFile: '.openhands/microagents/repo.md', configTemplate: 'openhands-repo.md', bridgeFile: null, markerFile: '.openhands' },
87
+ { name: 'Pi', value: 'pi', rulesDir: '.pi/rules', skillsDir: '.pi/skills', workflowsDir: '.pi/workflows', configFile: null, bridgeFile: null, markerFile: '.pi' },
88
+ { name: 'Qoder', value: 'qoder', rulesDir: '.qoder/rules', skillsDir: '.qoder/skills', workflowsDir: '.qoder/workflows', configFile: null, bridgeFile: null, markerFile: '.qoder' },
89
+ { name: 'Qwen Code', value: 'qwen', rulesDir: '.qwen/rules', skillsDir: '.qwen/skills', workflowsDir: '.qwen/workflows', configFile: null, bridgeFile: null, markerFile: '.qwen' },
74
90
  { name: 'Trae CN', value: 'trae-cn', rulesDir: '.trae-cn/rules', skillsDir: '.trae-cn/skills', workflowsDir: '.trae-cn/workflows', configFile: null, bridgeFile: 'lmagent.md', markerFile: '.trae-cn' },
75
- { name: 'Zencoder', value: 'zencoder', rulesDir: '.zencoder/rules', skillsDir: '.zencoder/skills', workflowsDir: '.zencoder/workflows', configFile: null, markerFile: '.zencoder' },
76
- { name: 'Neovate', value: 'neovate', rulesDir: '.neovate/rules', skillsDir: '.neovate/skills', workflowsDir: '.neovate/workflows', configFile: null, markerFile: '.neovate' },
77
- { name: 'Pochi', value: 'pochi', rulesDir: '.pochi/rules', skillsDir: '.pochi/skills', workflowsDir: '.pochi/workflows', configFile: null, markerFile: '.pochi' },
78
- { name: 'AdaL', value: 'adal', rulesDir: '.adal/rules', skillsDir: '.adal/skills', workflowsDir: '.adal/workflows', configFile: null, markerFile: '.adal' },
79
-
80
- {
81
- name: 'Gemini CLI',
82
- value: 'gemini',
83
- rulesDir: '.agents/rules',
84
- skillsDir: '.gemini/skills',
85
- workflowsDir: '.agents/workflows',
86
- configFile: '.gemini/config',
87
- markerFile: '.gemini'
88
- },
89
- {
90
- name: 'Continue',
91
- value: 'continue',
92
- rulesDir: '.continue/rules',
93
- skillsDir: '.continue/skills',
94
- workflowsDir: '.continue/workflows',
95
- configFile: '.continue/config.json',
96
- markerFile: '.continue'
97
- },
98
- {
99
- name: 'OpenCode',
100
- value: 'opencode',
101
- rulesDir: '.agents/rules',
102
- skillsDir: '.config/opencode/skills',
103
- workflowsDir: '.agents/workflows',
104
- configFile: '.opencode/config',
105
- markerFile: '.opencode'
106
- },
107
- {
108
- name: 'OpenHands',
109
- value: 'openhands',
110
- rulesDir: '.openhands/rules',
111
- skillsDir: '.openhands/skills',
112
- workflowsDir: '.openhands/workflows',
113
- configFile: '.openhands/config',
114
- markerFile: '.openhands'
115
- },
116
- {
117
- name: 'Goose',
118
- value: 'goose',
119
- rulesDir: '.goose/rules',
120
- skillsDir: '.goose/skills',
121
- workflowsDir: '.goose/workflows',
122
- configFile: '.goose/config',
123
- markerFile: '.goose'
124
- },
125
- {
126
- name: 'Mistral Vibe',
127
- value: 'vibe',
128
- rulesDir: '.vibe/rules',
129
- skillsDir: '.vibe/skills',
130
- workflowsDir: '.vibe/workflows',
131
- configFile: '.vibe/config',
132
- markerFile: '.vibe'
133
- },
134
- {
135
- name: 'Zed',
136
- value: 'zed',
137
- rulesDir: '.rules',
138
- skillsDir: '.rules/skills',
139
- workflowsDir: '.rules/workflows',
140
- configFile: '.rules/config',
141
- markerFile: '.zed'
142
- },
143
- {
144
- name: 'Envoid (OpenClaw / Moltbot)',
145
- value: 'openclaw',
146
- rulesDir: 'rules',
147
- skillsDir: 'skills',
148
- workflowsDir: 'workflows',
149
- configFile: 'openclaw.json',
150
- markerFile: 'openclaw.json'
151
- },
152
- {
153
- name: 'CodeBuddy',
154
- value: 'codebuddy',
155
- rulesDir: '.codebuddy/rules',
156
- skillsDir: '.codebuddy/skills',
157
- workflowsDir: '.codebuddy/workflows',
158
- configFile: '.codebuddy/config',
159
- markerFile: '.codebuddy',
160
- forceCopy: true
161
- },
162
- {
163
- name: 'Command Code',
164
- value: 'command-code',
165
- rulesDir: '.commandcode/rules',
166
- skillsDir: '.commandcode/skills',
167
- workflowsDir: '.commandcode/workflows',
168
- configFile: '.commandcode/config',
169
- markerFile: '.commandcode'
170
- },
171
- {
172
- name: 'Crush',
173
- value: 'crush',
174
- rulesDir: '.crush/rules',
175
- skillsDir: '.crush/skills',
176
- workflowsDir: '.crush/workflows',
177
- configFile: '.crush/config',
178
- markerFile: '.crush'
179
- },
180
- {
181
- name: 'Droid',
182
- value: 'droid',
183
- rulesDir: '.factory/rules',
184
- skillsDir: '.factory/skills',
185
- workflowsDir: '.factory/workflows',
186
- configFile: '.factory/config',
187
- markerFile: '.factory'
188
- },
189
- {
190
- name: 'Junie',
191
- value: 'junie',
192
- rulesDir: '.junie/rules',
193
- skillsDir: '.junie/skills',
194
- workflowsDir: '.junie/workflows',
195
- configFile: '.junie/config',
196
- markerFile: '.junie'
197
- },
198
- {
199
- name: 'iFlow',
200
- value: 'iflow',
201
- rulesDir: '.iflow/rules',
202
- skillsDir: '.iflow/skills',
203
- workflowsDir: '.iflow/workflows',
204
- configFile: '.iflow/config',
205
- markerFile: '.iflow'
206
- },
207
- {
208
- name: 'Kilo Code',
209
- value: 'kilo',
210
- rulesDir: '.kilocode/rules',
211
- skillsDir: '.kilocode/skills',
212
- workflowsDir: '.kilocode/workflows',
213
- configFile: '.kilocode/config',
214
- markerFile: '.kilocode'
215
- },
216
- {
217
- name: 'Kiro',
218
- value: 'kiro',
219
- rulesDir: '.kiro/rules',
220
- skillsDir: '.kiro/skills',
221
- workflowsDir: '.kiro/workflows',
222
- configFile: '.kiro/config',
223
- markerFile: '.kiro'
224
- },
225
- {
226
- name: 'Kode',
227
- value: 'kode',
228
- rulesDir: '.kode/rules',
229
- skillsDir: '.kode/skills',
230
- workflowsDir: '.kode/workflows',
231
- configFile: '.kode/config',
232
- markerFile: '.kode'
233
- },
234
- {
235
- name: 'MCPJam',
236
- value: 'mcpjam',
237
- rulesDir: '.mcpjam/rules',
238
- skillsDir: '.mcpjam/skills',
239
- workflowsDir: '.mcpjam/workflows',
240
- configFile: '.mcpjam/config',
241
- markerFile: '.mcpjam'
242
- },
243
- {
244
- name: 'Mux',
245
- value: 'mux',
246
- rulesDir: '.mux/rules',
247
- skillsDir: '.mux/skills',
248
- workflowsDir: '.mux/workflows',
249
- configFile: '.mux/config',
250
- markerFile: '.mux'
251
- },
252
- {
253
- name: 'Pi',
254
- value: 'pi',
255
- rulesDir: '.pi/rules',
256
- skillsDir: '.pi/skills',
257
- workflowsDir: '.pi/workflows',
258
- configFile: '.pi/config',
259
- markerFile: '.pi'
260
- },
261
- {
262
- name: 'Qoder',
263
- value: 'qoder',
264
- rulesDir: '.qoder/rules',
265
- skillsDir: '.qoder/skills',
266
- workflowsDir: '.qoder/workflows',
267
- configFile: '.qoder/config',
268
- markerFile: '.qoder'
269
- },
270
- {
271
- name: 'Qwen Code',
272
- value: 'qwen',
273
- rulesDir: '.qwen/rules',
274
- skillsDir: '.qwen/skills',
275
- workflowsDir: '.qwen/workflows',
276
- configFile: '.qwen/config',
277
- markerFile: '.qwen'
278
- },
279
- {
280
- name: 'Trae CN',
281
- value: 'trae-cn',
282
- rulesDir: '.trae-cn/rules',
283
- skillsDir: '.trae-cn/skills',
284
- workflowsDir: '.trae-cn/workflows',
285
- configFile: '.trae-cn/config',
286
- markerFile: '.trae-cn'
287
- },
288
- {
289
- name: 'Zencoder',
290
- value: 'zencoder',
291
- rulesDir: '.zencoder/rules',
292
- skillsDir: '.zencoder/skills',
293
- workflowsDir: '.zencoder/workflows',
294
- configFile: '.zencoder/config',
295
- markerFile: '.zencoder'
296
- },
297
- {
298
- name: 'Neovate',
299
- value: 'neovate',
300
- rulesDir: '.neovate/rules',
301
- skillsDir: '.neovate/skills',
302
- workflowsDir: '.neovate/workflows',
303
- configFile: '.neovate/config',
304
- markerFile: '.neovate'
305
- },
306
- {
307
- name: 'Pochi',
308
- value: 'pochi',
309
- rulesDir: '.pochi/rules',
310
- skillsDir: '.pochi/skills',
311
- workflowsDir: '.pochi/workflows',
312
- configFile: '.pochi/config',
313
- markerFile: '.pochi'
314
- },
315
- {
316
- name: 'AdaL',
317
- value: 'adal',
318
- rulesDir: '.adal/rules',
319
- skillsDir: '.adal/skills',
320
- workflowsDir: '.adal/workflows',
321
- configFile: '.adal/config',
322
- markerFile: '.adal'
323
- },
324
- {
325
- name: 'Generic/Other',
326
- value: 'generic',
327
- rulesDir: '.agents/rules',
328
- skillsDir: '.agents/skills',
329
- workflowsDir: '.agents/workflows',
330
- configFile: 'AGENTS.md',
331
- markerFile: '.agents'
332
- },
333
- {
334
- name: 'Custom Path (Manual)',
335
- value: 'custom',
336
- rulesDir: '',
337
- skillsDir: '',
338
- workflowsDir: '',
339
- markerFile: ''
340
- }
91
+ { name: 'Zencoder', value: 'zencoder', rulesDir: '.zencoder/rules', skillsDir: '.zencoder/skills', workflowsDir: '.zencoder/workflows', configFile: null, bridgeFile: null, markerFile: '.zencoder' },
92
+ { name: 'Neovate', value: 'neovate', rulesDir: '.neovate/rules', skillsDir: '.neovate/skills', workflowsDir: '.neovate/workflows', configFile: null, bridgeFile: null, markerFile: '.neovate' },
93
+ { name: 'Pochi', value: 'pochi', rulesDir: '.pochi/rules', skillsDir: '.pochi/skills', workflowsDir: '.pochi/workflows', configFile: null, bridgeFile: null, markerFile: '.pochi' },
94
+ { name: 'AdaL', value: 'adal', rulesDir: '.adal/rules', skillsDir: '.adal/skills', workflowsDir: '.adal/workflows', configFile: null, bridgeFile: null, markerFile: '.adal' },
95
+
96
+ // --- Opciones Especiales ---
97
+ { name: 'Generic/Other', value: 'generic', rulesDir: '.agents/rules', skillsDir: '.agents/skills', workflowsDir: '.agents/workflows', configFile: 'AGENTS.md', bridgeFile: null, markerFile: '.agents' },
98
+ { name: 'Custom Path (Manual)', value: 'custom', rulesDir: '', skillsDir: '', workflowsDir: '', configFile: null, bridgeFile: null, markerFile: '' },
341
99
  ];
342
100
 
343
101
  program
344
102
  .name('lmagent')
345
103
  .description('CLI para instalar skills y reglas de LMAgent')
346
- .version('3.1.2');
104
+ .version(PKG_VERSION);
347
105
 
348
106
  program.command('install')
349
107
  .description('Instalar skills, rules y workflows en el IDE del proyecto')
350
108
  .option('-f, --force', 'Forzar instalación')
351
109
  .option('-y, --yes', 'Instalar todo sin preguntar')
110
+ .option('-g, --global', 'También sincronizar al repositorio global (~/.agents/)')
352
111
  .action((options) => {
353
112
  runInstall(options);
354
113
  });
@@ -357,6 +116,7 @@ program.command('update')
357
116
  .description('Actualizar skills y reglas en el proyecto (alias de install)')
358
117
  .option('-f, --force', 'Forzar actualización')
359
118
  .option('-y, --yes', 'Instalar todo sin preguntar')
119
+ .option('-g, --global', 'También sincronizar al repositorio global (~/.agents/)')
360
120
  .action((options) => {
361
121
  console.log(chalk.blue('ℹ Iniciando actualización...'));
362
122
  runInstall(options);
@@ -402,19 +162,226 @@ program.command('create-skill')
402
162
  }
403
163
  });
404
164
 
165
+ program.command('tokens')
166
+ .description('Analizar consumo de tokens del framework instalado en el proyecto')
167
+ .option('--json', 'Salida en formato JSON')
168
+ .option('--report', 'Generar reporte en .agents/token-report.md')
169
+ .action((options) => {
170
+ const { execSync } = require('child_process');
171
+ const scriptPath = path.join(__dirname, 'scripts', 'token-analyzer.js');
172
+ const args = [options.json ? '--json' : '', options.report ? '--report' : ''].filter(Boolean).join(' ');
173
+ try {
174
+ execSync(`node "${scriptPath}" ${args}`, { stdio: 'inherit' });
175
+ } catch (e) {
176
+ process.exit(e.status || 1);
177
+ }
178
+ });
179
+
180
+ program.command('skills')
181
+ .description('Gestionar skills externos desde GitHub (compatible con el estándar skills.sh)')
182
+ .argument('<action>', 'Acción: add')
183
+ .argument('<source>', 'Repositorio GitHub: owner/repo o URL completa')
184
+ .option('--skill <name>', 'Nombre específico del skill a instalar (opcional)')
185
+ .action(async (action, source, opts) => {
186
+ if (action !== 'add') {
187
+ console.error(chalk.red(`❌ Acción desconocida: ${action}. Usa: lmagent skills add <owner/repo>`));
188
+ process.exit(1);
189
+ }
190
+ const { execSync } = require('child_process');
191
+ const repoSlug = source.replace('https://github.com/', '').replace(/\.git$/, '');
192
+ const [owner, repo] = repoSlug.split('/');
193
+ if (!owner || !repo) {
194
+ console.error(chalk.red('❌ Formato inválido. Usa: lmagent skills add owner/repo'));
195
+ process.exit(1);
196
+ }
197
+ const tmpDir = path.join(os.tmpdir(), `lmagent-skill-${Date.now()}`);
198
+ const targetSkillsDir = path.join(process.cwd(), '.agents', 'skills');
199
+ console.log(chalk.cyan(`📦 Descargando skill desde github.com/${owner}/${repo}...`));
200
+ try {
201
+ execSync(`git clone --depth 1 https://github.com/${owner}/${repo} "${tmpDir}"`, { stdio: 'pipe' });
202
+ const skillsPath = fs.existsSync(path.join(tmpDir, 'skills')) ? path.join(tmpDir, 'skills') : tmpDir;
203
+ const items = fs.readdirSync(skillsPath).filter(i => {
204
+ const p = path.join(skillsPath, i);
205
+ return fs.statSync(p).isDirectory() && fs.existsSync(path.join(p, 'SKILL.md'));
206
+ });
207
+ if (items.length === 0) {
208
+ console.log(chalk.yellow('⚠️ No se encontraron skills con SKILL.md en el repositorio.'));
209
+ fs.rmSync(tmpDir, { recursive: true, force: true });
210
+ return;
211
+ }
212
+ const toInstall = opts.skill ? items.filter(i => i.includes(opts.skill)) : items;
213
+ if (!fs.existsSync(targetSkillsDir)) fs.mkdirSync(targetSkillsDir, { recursive: true });
214
+ for (const skill of toInstall) {
215
+ const src = path.join(skillsPath, skill);
216
+ const dest = path.join(targetSkillsDir, skill);
217
+ copyRecursiveSync(src, dest, true);
218
+ console.log(` ${chalk.green('✔')} ${skill}/`);
219
+ }
220
+ fs.rmSync(tmpDir, { recursive: true, force: true });
221
+ console.log(chalk.green(`✨ ${toInstall.length} skill(s) instalado(s) en .agents/skills/`));
222
+ console.log(chalk.dim(' Ejecuta `lmagent install` para sincronizarlos a tu agente.'));
223
+ } catch (e) {
224
+ console.error(chalk.red(`❌ Error al instalar skill: ${e.message}`));
225
+ try { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch (_) { }
226
+ process.exit(1);
227
+ }
228
+ });
229
+
230
+ program.command('uninstall')
231
+ .description('Eliminar todos los archivos instalados por LMAgent del proyecto')
232
+ .option('-f, --force', 'No pedir confirmación, eliminar directamente')
233
+ .option('--all', 'También eliminar entry points raíz (CLAUDE.md, GEMINI.md, AGENTS.md)')
234
+ .action(async (options) => {
235
+ console.clear();
236
+ const branding = figlet.textSync('LMAGENT', { font: 'ANSI Shadow' });
237
+ console.log(gradient.pastel.multiline(branding));
238
+ console.log(gradient.cristal(' Uninstall - Limpieza\n'));
239
+
240
+ const projectRoot = process.cwd();
241
+
242
+ // Detectar qué agentes están instalados en el proyecto
243
+ const installedIdes = IDE_CONFIGS.filter(ide => {
244
+ if (ide.value === 'custom' || ide.value === 'generic') return false;
245
+ const markerInProject = ide.markerFile && fs.existsSync(path.join(projectRoot, ide.markerFile));
246
+ const rulesDirInProject = ide.rulesDir && fs.existsSync(path.join(projectRoot, ide.rulesDir));
247
+ const skillsDirInProject = ide.skillsDir && fs.existsSync(path.join(projectRoot, ide.skillsDir));
248
+ return markerInProject || rulesDirInProject || skillsDirInProject;
249
+ });
250
+
251
+ if (installedIdes.length === 0) {
252
+ console.log(chalk.yellow('⚠️ No se detectó ningún agente instalado en este proyecto.'));
253
+ return;
254
+ }
255
+
256
+ console.log(chalk.bold('🔍 Agentes detectados en este proyecto:\n'));
257
+ for (const ide of installedIdes) {
258
+ const parts = [];
259
+ if (ide.rulesDir && fs.existsSync(path.join(projectRoot, ide.rulesDir))) parts.push(chalk.gray(ide.rulesDir));
260
+ if (ide.skillsDir && fs.existsSync(path.join(projectRoot, ide.skillsDir))) parts.push(chalk.gray(ide.skillsDir));
261
+ if (ide.configFile && fs.existsSync(path.join(projectRoot, ide.configFile))) parts.push(chalk.gray(ide.configFile));
262
+ console.log(` ${chalk.cyan('•')} ${chalk.bold(ide.name)}: ${parts.join(', ')}`);
263
+ }
264
+
265
+ // Entry points raíz
266
+ const rootFiles = ['CLAUDE.md', 'GEMINI.md', 'AGENTS.md', '.cursorrules', '.windsurfrules', '.continuerules', '.goosehints'];
267
+ const existingRootFiles = rootFiles.filter(f => fs.existsSync(path.join(projectRoot, f)));
268
+
269
+ if (options.all && existingRootFiles.length > 0) {
270
+ console.log(chalk.bold('\n📄 Entry points raíz que también se eliminarán:'));
271
+ for (const f of existingRootFiles) {
272
+ console.log(` ${chalk.red('•')} ${f}`);
273
+ }
274
+ }
275
+
276
+ console.log('');
277
+
278
+ if (!options.force) {
279
+ const { confirm } = await inquirer.prompt([{
280
+ type: 'confirm',
281
+ name: 'confirm',
282
+ message: chalk.red(`⚠️ ¿Eliminar todos los archivos de LMAgent de este proyecto? Esta acción no se puede deshacer.`),
283
+ default: false
284
+ }]);
285
+ if (!confirm) {
286
+ console.log(chalk.gray('Cancelado.'));
287
+ return;
288
+ }
289
+ }
290
+
291
+ console.log('');
292
+ let removed = 0;
293
+ let errors = 0;
294
+
295
+ // Eliminar directorios y archivos de cada agente
296
+ for (const ide of installedIdes) {
297
+ const toRemove = [];
298
+
299
+ // Directorios del agente (skills, rules, workflows) — solo si son específicos del agente
300
+ // No eliminar directorios genéricos como .github, rules/, skills/ que pueden tener otros usos
301
+ const agentSpecificDirs = [ide.skillsDir, ide.workflowsDir];
302
+ if (ide.rulesDir && !['rules', '.github/instructions'].includes(ide.rulesDir)) {
303
+ agentSpecificDirs.push(ide.rulesDir);
304
+ }
305
+
306
+ // Determinar el directorio raíz del agente (ej: .cursor, .windsurf, .claude)
307
+ const agentRootDir = ide.markerFile && !ide.markerFile.includes('.') ? null
308
+ : ide.rulesDir ? ide.rulesDir.split('/')[0] : null;
309
+ if (agentRootDir && agentRootDir.startsWith('.') && fs.existsSync(path.join(projectRoot, agentRootDir))) {
310
+ // Eliminar el directorio raíz completo del agente
311
+ toRemove.push({ path: path.join(projectRoot, agentRootDir), type: 'dir', label: agentRootDir + '/' });
312
+ } else {
313
+ // Eliminar subdirectorios individualmente
314
+ for (const dir of agentSpecificDirs) {
315
+ if (dir && fs.existsSync(path.join(projectRoot, dir))) {
316
+ toRemove.push({ path: path.join(projectRoot, dir), type: 'dir', label: dir + '/' });
317
+ }
318
+ }
319
+ }
320
+
321
+ // Archivos de configuración específicos del agente (markerFile si es un archivo)
322
+ if (ide.markerFile && ide.markerFile.includes('.') && fs.existsSync(path.join(projectRoot, ide.markerFile))) {
323
+ const markerStat = fs.statSync(path.join(projectRoot, ide.markerFile));
324
+ if (markerStat.isFile()) {
325
+ toRemove.push({ path: path.join(projectRoot, ide.markerFile), type: 'file', label: ide.markerFile });
326
+ }
327
+ }
328
+
329
+ for (const item of toRemove) {
330
+ try {
331
+ if (item.type === 'dir') {
332
+ fs.rmSync(item.path, { recursive: true, force: true });
333
+ } else {
334
+ fs.unlinkSync(item.path);
335
+ }
336
+ console.log(` ${chalk.red('✘')} ${ide.name}: ${chalk.gray(item.label)} eliminado`);
337
+ removed++;
338
+ } catch (e) {
339
+ console.error(` ${chalk.red('❌')} Error eliminando ${item.label}: ${e.message}`);
340
+ errors++;
341
+ }
342
+ }
343
+ }
344
+
345
+ // Eliminar entry points raíz si --all
346
+ if (options.all) {
347
+ for (const f of existingRootFiles) {
348
+ try {
349
+ fs.unlinkSync(path.join(projectRoot, f));
350
+ console.log(` ${chalk.red('✘')} ${chalk.gray(f)} eliminado`);
351
+ removed++;
352
+ } catch (e) {
353
+ console.error(` ${chalk.red('❌')} Error eliminando ${f}: ${e.message}`);
354
+ errors++;
355
+ }
356
+ }
357
+ }
358
+
359
+ console.log('');
360
+ if (errors === 0) {
361
+ console.log(gradient.pastel(`\n✨ Limpieza completada. ${removed} elemento(s) eliminado(s).\n`));
362
+ if (!options.all) {
363
+ console.log(chalk.dim(' 💡 Usa `lmagent uninstall --all` para también eliminar CLAUDE.md, GEMINI.md y AGENTS.md.'));
364
+ }
365
+ } else {
366
+ console.log(chalk.yellow(`\n⚠️ ${removed} eliminado(s), ${errors} error(es).\n`));
367
+ }
368
+ });
369
+
405
370
  if (process.argv.length === 2) {
406
371
  runInstall({});
407
372
  } else {
408
373
  program.parse();
409
374
  }
410
375
 
376
+
411
377
  // Helper for Windows-proof path comparison
412
378
  function arePathsEqual(p1, p2) {
413
379
  if (!p1 || !p2) return false;
414
380
  return path.resolve(p1).toLowerCase() === path.resolve(p2).toLowerCase();
415
381
  }
416
382
 
417
- // Helper to deploy AGENTS.md and CLAUDE.md to project root
383
+ // Helper to deploy AGENTS.md, CLAUDE.md y GEMINI.md to project root
384
+ // Los archivos con versionTemplate:true tienen {{VERSION}} que se reemplaza dinámicamente
418
385
  async function deployCorePillars(options, projectRoot) {
419
386
  console.log(chalk.bold('\n🚀 Desplegando Pilares de Inteligencia (Contexto Root):'));
420
387
  for (const file of INIT_FILES) {
@@ -427,18 +394,22 @@ async function deployCorePillars(options, projectRoot) {
427
394
  shouldCopy = true;
428
395
  console.log(` ${chalk.green('✔')} ${file.src} (Creado en la raíz)`);
429
396
  } else {
430
- if (options.force) {
397
+ // Si ya existe pero tiene versión vieja, actualizar automáticamente
398
+ const existingContent = fs.readFileSync(destPath, 'utf8');
399
+ const hasOldVersion = existingContent.includes('{{VERSION}}') ||
400
+ (file.versionTemplate && !existingContent.includes(`v${PKG_VERSION}`));
401
+
402
+ if (options.force || hasOldVersion) {
431
403
  shouldCopy = true;
432
- console.log(` ${chalk.yellow('')} ${file.src} (Sobrescribiendo por --force)`);
404
+ const reason = hasOldVersion ? 'Actualizando versión' : 'Sobrescribiendo por --force';
405
+ console.log(` ${chalk.yellow('✎')} ${file.src} (${reason})`);
433
406
  } else if (options.yes) {
434
- // En modo --yes, si ya existe, NO sobrescribimos para no borrar personalización del usuario
435
- // PERO informamos.
436
- console.log(` ${chalk.blue('ℹ')} ${file.src} ya existe (Manteniendo versión local)`);
407
+ console.log(` ${chalk.blue('ℹ')} ${file.src} ya existe v${PKG_VERSION} (OK)`);
437
408
  } else {
438
409
  const answer = await inquirer.prompt([{
439
410
  type: 'confirm',
440
411
  name: 'overwrite',
441
- message: `⚠️ ${file.src} ya existe en la raíz. ¿Deseas actualizarlo/sobrescribirlo?`,
412
+ message: `⚠️ ${file.src} ya existe. ¿Deseas actualizarlo?`,
442
413
  default: false
443
414
  }]);
444
415
  shouldCopy = answer.overwrite;
@@ -447,7 +418,12 @@ async function deployCorePillars(options, projectRoot) {
447
418
  }
448
419
 
449
420
  if (shouldCopy) {
450
- fs.copyFileSync(srcPath, destPath);
421
+ let content = fs.readFileSync(srcPath, 'utf8');
422
+ // Inyectar versión dinámica si el archivo usa template
423
+ if (file.versionTemplate) {
424
+ content = content.replace(/\{\{VERSION\}\}/g, PKG_VERSION);
425
+ }
426
+ fs.writeFileSync(destPath, content, 'utf8');
451
427
  }
452
428
  }
453
429
  }
@@ -464,20 +440,21 @@ async function runInstall(options) {
464
440
  const globalAgentDir = path.join(userHome, '.agents');
465
441
  const globalSkillsDir = path.join(globalAgentDir, 'skills');
466
442
  const globalRulesDir = path.join(globalAgentDir, 'rules');
467
- const globalWorkflowsDir = path.join(globalAgentDir, 'workflows'); // New
468
-
469
- // 1. Sincronizar (Copiar) Package -> Global Repo (~/.agents)
470
- // UX OPTIMIZATION: Silent sync unless error
471
- try {
472
- if (!fs.existsSync(globalAgentDir)) fs.mkdirSync(globalAgentDir, { recursive: true });
473
-
474
- if (fs.existsSync(PACKAGE_SKILLS_DIR)) copyRecursiveSync(PACKAGE_SKILLS_DIR, globalSkillsDir, true);
475
- if (fs.existsSync(PACKAGE_RULES_DIR)) copyRecursiveSync(PACKAGE_RULES_DIR, globalRulesDir, true);
476
- if (fs.existsSync(PACKAGE_WORKFLOWS_DIR)) copyRecursiveSync(PACKAGE_WORKFLOWS_DIR, globalWorkflowsDir, true);
477
- if (fs.existsSync(PACKAGE_MEMORY_DIR)) copyRecursiveSync(PACKAGE_MEMORY_DIR, path.join(globalAgentDir, 'memory'), true);
478
- // console.log(chalk.green('✔ Repositorio global sincronizado.'));
479
- } catch (e) {
480
- // console.error(chalk.red(`❌ Error al sincronizar repositorio global: ${e.message}`));
443
+ const globalWorkflowsDir = path.join(globalAgentDir, 'workflows');
444
+
445
+ // Sync global SOLO si se pasa --global explícitamente (evita doble lectura de contexto)
446
+ if (options.global) {
447
+ console.log(chalk.blue('🌐 Sincronizando al repositorio global (~/.agents/)...'));
448
+ try {
449
+ if (!fs.existsSync(globalAgentDir)) fs.mkdirSync(globalAgentDir, { recursive: true });
450
+ if (fs.existsSync(PACKAGE_SKILLS_DIR)) copyRecursiveSync(PACKAGE_SKILLS_DIR, globalSkillsDir, true);
451
+ if (fs.existsSync(PACKAGE_RULES_DIR)) copyRecursiveSync(PACKAGE_RULES_DIR, globalRulesDir, true);
452
+ if (fs.existsSync(PACKAGE_WORKFLOWS_DIR)) copyRecursiveSync(PACKAGE_WORKFLOWS_DIR, globalWorkflowsDir, true);
453
+ if (fs.existsSync(PACKAGE_MEMORY_DIR)) copyRecursiveSync(PACKAGE_MEMORY_DIR, path.join(globalAgentDir, 'memory'), true);
454
+ console.log(chalk.green('✔ Repositorio global sincronizado.'));
455
+ } catch (e) {
456
+ console.error(chalk.red(`❌ Error al sincronizar repositorio global: ${e.message}`));
457
+ }
481
458
  }
482
459
 
483
460
  await deployCorePillars(options, projectRoot);
@@ -510,10 +487,6 @@ async function runInstall(options) {
510
487
  console.log(chalk.cyan('🔹 Configuración de Instalación'));
511
488
  console.log(chalk.gray('================================================================'));
512
489
 
513
- console.log(chalk.gray('================================================================'));
514
- console.log(chalk.cyan('🔹 Configuración de Instalación'));
515
- console.log(chalk.gray('================================================================'));
516
-
517
490
  // UX OPTIMIZATION: "Project First" & Windows Compat
518
491
  // 1. Detect Environment
519
492
  const isWindows = os.platform() === 'win32';
@@ -527,21 +500,65 @@ async function runInstall(options) {
527
500
  console.log('');
528
501
 
529
502
  // 3. Auto-Detect IDEs
503
+ // Mapa de rutas de instalación global por agente (donde el IDE instala sus archivos en ~/)
504
+ // HOME_PATHS: rutas de instalación global de cada agente en el sistema del usuario
505
+ // Cubre los 37 agentes soportados. Se verifica si alguna de las rutas existe en ~/
506
+ const HOME_PATHS = {
507
+ // IDEs principales
508
+ 'cursor': ['.cursor'],
509
+ 'windsurf': ['.windsurf'],
510
+ 'cline': ['.vscode/extensions', '.cline'],
511
+ 'roo': ['.vscode/extensions', '.roo'],
512
+ 'vscode': ['.vscode'],
513
+ 'trae': ['.trae'],
514
+ 'trae-cn': ['.trae-cn', '.trae'],
515
+ 'claude': ['.claude'],
516
+ 'zed': ['.config/zed', '.zed'],
517
+ // Agentes CLI & autónomos
518
+ 'antigravity': ['.gemini/antigravity'],
519
+ 'gemini': ['.gemini'],
520
+ 'augment': ['.augment'],
521
+ 'continue': ['.continue'],
522
+ 'codex': ['.codex'],
523
+ 'goose': ['.config/goose', '.goose'],
524
+ 'junie': ['.junie'],
525
+ 'kilo': ['.kilocode'],
526
+ 'kiro': ['.kiro'],
527
+ 'opencode': ['.opencode'],
528
+ 'openhands': ['.openhands'],
529
+ 'amp': ['.agents'],
530
+ 'zencoder': ['.zencoder'],
531
+ 'codebuddy': ['.codebuddy'],
532
+ 'crush': ['.crush'],
533
+ 'droid': ['.factory'],
534
+ 'mux': ['.mux'],
535
+ 'qwen': ['.qwen'],
536
+ // Agentes menores / nicho
537
+ 'openclaw': ['.config/openclaw', '.openclaw'],
538
+ 'command-code': ['.commandcode'],
539
+ 'iflow': ['.iflow'],
540
+ 'kode': ['.kode'],
541
+ 'mcpjam': ['.mcpjam'],
542
+ 'mistral': ['.vibe', '.mistral'],
543
+ 'pi': ['.pi'],
544
+ 'qoder': ['.qoder'],
545
+ 'neovate': ['.neovate'],
546
+ 'pochi': ['.pochi'],
547
+ 'adal': ['.adal'],
548
+ };
549
+
530
550
  const detectedIdes = IDE_CONFIGS.filter(ide => {
531
- if (ide.value === 'custom') return false; // Custom is never auto-detected
551
+ if (ide.value === 'custom' || ide.value === 'generic') return false;
532
552
 
533
- // Check Project Root
534
- const inProject = (ide.rulesDir && fs.existsSync(path.join(projectRoot, ide.rulesDir.split('/')[0]))) ||
535
- (ide.markerFile && fs.existsSync(path.join(projectRoot, ide.markerFile)));
553
+ // Check Project Root: usar markerFile primero (más preciso), luego rulesDir como fallback
554
+ const markerInProject = ide.markerFile && fs.existsSync(path.join(projectRoot, ide.markerFile));
555
+ const rulesDirInProject = ide.rulesDir && fs.existsSync(path.join(projectRoot, ide.rulesDir));
556
+ const skillsDirInProject = ide.skillsDir && fs.existsSync(path.join(projectRoot, ide.skillsDir));
557
+ const inProject = markerInProject || rulesDirInProject || skillsDirInProject;
536
558
 
537
- // Check User Home (Heuristic for installed IDEs)
538
- const inHome = (ide.markerFile && fs.existsSync(path.join(userHome, ide.markerFile))) ||
539
- (ide.value === 'vscode' && fs.existsSync(path.join(userHome, '.vscode'))) ||
540
- (ide.value === 'cursor' && fs.existsSync(path.join(userHome, '.cursor'))) ||
541
- (ide.value === 'windsurf' && fs.existsSync(path.join(userHome, '.windsurf'))) ||
542
- (ide.value === 'trae' && fs.existsSync(path.join(userHome, '.trae'))) ||
543
- (ide.value === 'cline' && fs.existsSync(path.join(userHome, '.cline'))) ||
544
- (ide.value === 'roo' && fs.existsSync(path.join(userHome, '.roo')));
559
+ // Check User Home: usar mapa explícito de rutas de instalación global
560
+ const homePaths = HOME_PATHS[ide.value] || [];
561
+ const inHome = homePaths.some(p => fs.existsSync(path.join(userHome, p)));
545
562
 
546
563
  return inProject || inHome;
547
564
  });
@@ -670,6 +687,16 @@ async function runInstall(options) {
670
687
  options.installMemory = memoryAnswer.memory;
671
688
  }
672
689
 
690
+ // Opción global: sincronizar también a ~/.agents/
691
+ console.log('');
692
+ const globalAnswer = await inquirer.prompt([{
693
+ type: 'confirm',
694
+ name: 'global',
695
+ message: '🌐 ¿También sincronizar al repositorio global (~/.agents/)? (Útil para Gemini CLI, Codex y agentes CLI)',
696
+ default: false
697
+ }]);
698
+ if (globalAnswer.global) options.global = true;
699
+
673
700
  console.log('');
674
701
  const { confirm } = await inquirer.prompt([{
675
702
  type: 'confirm',
@@ -729,11 +756,28 @@ async function runInstall(options) {
729
756
  const relativeCatalogPath = getRelLink(ide.configFile, 'AGENTS.md');
730
757
  const relativeContextPath = getRelLink(ide.configFile, 'CLAUDE.md');
731
758
 
732
- // console.log(chalk.bold(`\nConfiguring ${ide.name} auto-detect:`));
733
- try {
734
- let content = `
735
- # 🤖 LMAgent Framework v3.0.0
736
- > Contexto Activo: Este proyecto utiliza el estándar LMAgent V3.
759
+ // Usar template específico del agente si existe, si no usar contenido genérico
760
+ const AGENT_CONFIGS_TEMPLATE_DIR = path.join(__dirname, '.agents', 'templates', 'agent-configs');
761
+ const templateFile = ide.configTemplate
762
+ ? path.join(AGENT_CONFIGS_TEMPLATE_DIR, ide.configTemplate)
763
+ : path.join(AGENT_CONFIGS_TEMPLATE_DIR, '_generic.md');
764
+
765
+ let content;
766
+ if (fs.existsSync(templateFile) && !ide.configFile.endsWith('.json')) {
767
+ // Usar template del archivo, inyectando VERSION
768
+ content = fs.readFileSync(templateFile, 'utf8')
769
+ .replace(/\{\{VERSION\}\}/g, PKG_VERSION)
770
+ .replace(/\{\{MAJOR\}\}/g, PKG_VERSION.split('.')[0]);
771
+ } else if (ide.configFile.endsWith('.json') && fs.existsSync(templateFile)) {
772
+ // JSON: usar template y reemplazar VERSION
773
+ content = fs.readFileSync(templateFile, 'utf8')
774
+ .replace(/\{\{VERSION\}\}/g, PKG_VERSION)
775
+ .replace(/\{\{MAJOR\}\}/g, PKG_VERSION.split('.')[0]);
776
+ } else {
777
+ // Fallback: contenido genérico dinámico
778
+ content = `
779
+ # 🤖 LMAgent Framework v${PKG_VERSION}
780
+ > Contexto Activo: Este proyecto utiliza el estándar LMAgent V${PKG_VERSION.split('.')[0]}.
737
781
 
738
782
  ## 🚨 SOURCE OF TRUTH (CEREBRO)
739
783
  **TU CONTEXTO Y REGLAS VIVEN AQUÍ 👉 [AGENTS.md](${relativeCatalogPath})**
@@ -753,7 +797,9 @@ Use estos comandos para activar su rol. Para detalles, consulte \`AGENTS.md\`.
753
797
 
754
798
  !! SYSTEM NOTE: Read AGENTS.md to understand how to execute these roles. !!
755
799
  `;
756
- // If file exists, check if we need to append
800
+ }
801
+ // If file exists, check if we need to append
802
+ try {
757
803
  if (fs.existsSync(configPath)) {
758
804
  // Check if it's a directory (Edge case: Cline legacy folders)
759
805
  if (fs.statSync(configPath).isDirectory()) {
@@ -785,9 +831,16 @@ Use estos comandos para activar su rol. Para detalles, consulte \`AGENTS.md\`.
785
831
  console.log(` ${bootstrapStatus === 'CREATED' ? chalk.green('✔') : chalk.blue('ℹ')} ${ide.name} Bootstrap: ${bootstrapStatus}`);
786
832
  }
787
833
 
788
- // 4.1 Generate Bridge Rule if supported
789
- const bridgeFile = ide.bridgeFile || 'lmagent.md';
790
- if (ide.rulesDir && bridgeFile) {
834
+ // 4.1 Generate Bridge Rule
835
+ // Si el agente NO tiene configFile, necesita un archivo puente en rulesDir para auto-invocarse.
836
+ // Si tampoco tiene bridgeFile definido, usamos '00-lmagent.md' como default genérico.
837
+ const bridgeFile = ide.bridgeFile || (ide.rulesDir && !ide.configFile ? '00-lmagent.md' : null);
838
+ const needsBridge = bridgeFile && !ide.configFile;
839
+ // Garantizar que rulesDir existe siempre (para que el agente pueda detectar la instalación)
840
+ if (ide.rulesDir && !fs.existsSync(path.join(targetRoot, ide.rulesDir))) {
841
+ fs.mkdirSync(path.join(targetRoot, ide.rulesDir), { recursive: true });
842
+ }
843
+ if (ide.rulesDir && needsBridge) {
791
844
  const bridgePath = path.join(targetRoot, ide.rulesDir, bridgeFile);
792
845
  const relativeBridgeToRoot = path.join(ide.rulesDir, bridgeFile);
793
846
  const relContext = getRelLink(relativeBridgeToRoot, 'CLAUDE.md');
@@ -805,7 +858,7 @@ globs: **/*
805
858
 
806
859
  # 🤖 LMAgent Bridge Rule
807
860
 
808
- Este proyecto está potenciado por **LMAgent v3.0.0**.
861
+ Este proyecto está potenciado por **LMAgent v${PKG_VERSION}**.
809
862
 
810
863
  ## 🚨 SOURCE OF TRUTH (CEREBRO)
811
864
  **TU CONTEXTO Y REGLAS VIVEN AQUÍ 👉 [AGENTS.md](${relCatalog})**
@@ -829,7 +882,7 @@ Use estos comandos para activar su rol. Para detalles, consulte \`AGENTS.md\`.
829
882
  // Standard Markdown (Universal & Cline/Windsurf)
830
883
  bridgeContent = `# 🤖 LMAgent Framework Entry Point
831
884
 
832
- Este proyecto utiliza **LMAgent v3.0.0**.
885
+ Este proyecto utiliza **LMAgent v${PKG_VERSION}**.
833
886
 
834
887
  ## 🚨 SOURCE OF TRUTH (CEREBRO)
835
888
  **TU CONTEXTO Y REGLAS VIVEN AQUÍ 👉 [AGENTS.md](${relCatalog})**
@@ -958,15 +1011,18 @@ Use estos comandos para activar su rol. Para detalles, consulte \`AGENTS.md\`.
958
1011
  console.log(chalk.gray('================================================================'));
959
1012
  console.log(chalk.bold.green('🎉 ¡Todo listo! Aquí tienes cómo usar tus nuevos superpoderes:'));
960
1013
  console.log('');
961
- console.log(chalk.cyan('🤖 Para Cursor / Windsurf / Trae:'));
962
- console.log(chalk.white(' 1. Tus skills aparecen como Reglas (.cursorrules, etc.)'));
963
- console.log(chalk.white(' 2. En el Chat (Ctrl+L) o Composer (Ctrl+I), simplemente pídelo.'));
964
- console.log(chalk.gray(' Ej: "Crea un nuevo componente de React" (El agente usará frontend-engineer automáticamente)'));
1014
+
1015
+ // Mensaje dinámico según agentes instalados
1016
+ const ideNames = targetIdes.map(i => i.name).join(', ');
1017
+ console.log(chalk.cyan(`🤖 Agentes configurados: ${chalk.bold(ideNames)}`));
1018
+ console.log('');
1019
+ console.log(chalk.white(' 1. Abre tu agente en este proyecto — leerá el contexto automáticamente.'));
1020
+ console.log(chalk.white(' 2. Usa los triggers para activar un rol específico:'));
1021
+ console.log(chalk.gray(' /dev → Backend | /front → Frontend | /arch → Arquitecto'));
1022
+ console.log(chalk.gray(' /fix → Debugger | /pm → Product | /orch → Orchestrator'));
965
1023
  console.log('');
966
- console.log(chalk.magenta('🧠 Para Antigravity / Claude Code / Agentes Autónomos:'));
967
- console.log(chalk.white(' 1. El agente lee automáticamente tu carpeta .agent/ o configuración local.'));
968
- console.log(chalk.white(' 2. Escribe tu petición en lenguaje natural.'));
969
- console.log(chalk.gray(' Ej: "Analiza la base de datos" (El agente buscará y usará backend-engineer/data-engineer)'));
1024
+ console.log(chalk.dim(' 💡 Ejecuta `lmagent doctor` para verificar la instalación.'));
1025
+ console.log(chalk.dim(' 💡 Ejecuta `lmagent tokens` para ver el consumo de tokens del framework.'));
970
1026
  console.log(chalk.gray('================================================================'));
971
1027
  }
972
1028
 
@@ -1181,7 +1237,9 @@ async function runInit(options) {
1181
1237
 
1182
1238
  if (fs.existsSync(srcPath)) {
1183
1239
  if (!fs.existsSync(destPath)) {
1184
- fs.copyFileSync(srcPath, destPath);
1240
+ let content = fs.readFileSync(srcPath, 'utf8');
1241
+ if (file.versionTemplate) content = content.replace(/\{\{VERSION\}\}/g, PKG_VERSION);
1242
+ fs.writeFileSync(destPath, content, 'utf8');
1185
1243
  console.log(` ${chalk.green('✔')} ${file.src} (Created)`);
1186
1244
  } else {
1187
1245
  // Exists: Ask to overwrite (unless force/yes)
@@ -1199,7 +1257,9 @@ async function runInit(options) {
1199
1257
  }
1200
1258
 
1201
1259
  if (shouldOverwrite) {
1202
- fs.copyFileSync(srcPath, destPath);
1260
+ let content = fs.readFileSync(srcPath, 'utf8');
1261
+ if (file.versionTemplate) content = content.replace(/\{\{VERSION\}\}/g, PKG_VERSION);
1262
+ fs.writeFileSync(destPath, content, 'utf8');
1203
1263
  console.log(` ${chalk.yellow('✎')} ${file.src} (Overwritten)`);
1204
1264
  } else {
1205
1265
  console.log(` ${chalk.gray('SKIP')} ${file.src} (Kept existing)`);
@@ -1266,7 +1326,7 @@ DEBUG=true
1266
1326
  }
1267
1327
 
1268
1328
  // Resumen
1269
- console.log(gradient.pastel.multiline('\n✨ Proyecto inicializado con LMAgent v3.1.2 ✨'));
1329
+ console.log(gradient.pastel.multiline(`\n✨ Proyecto inicializado con LMAgent v${PKG_VERSION} ✨`));
1270
1330
  console.log('');
1271
1331
  console.log(chalk.cyan('Próximos pasos:'));
1272
1332
  console.log(` 1. ${chalk.bold('lmagent install')} - Instalar skills/rules/workflows en tu IDE`);