oden-forge 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.claude/CLAUDE.md +75 -0
  2. package/.claude/commands/oden/architect.md +204 -0
  3. package/.claude/commands/oden/checklist.md +199 -0
  4. package/.claude/commands/oden/daily.md +223 -0
  5. package/.claude/commands/oden/debug.md +203 -0
  6. package/.claude/commands/oden/epic.md +224 -0
  7. package/.claude/commands/oden/git.md +259 -0
  8. package/.claude/commands/oden/help.md +304 -0
  9. package/.claude/commands/oden/init-agents.md +268 -0
  10. package/.claude/commands/oden/init-mcp.md +460 -0
  11. package/.claude/commands/oden/init.md +495 -0
  12. package/.claude/commands/oden/mcp.md +585 -0
  13. package/.claude/commands/oden/prd.md +134 -0
  14. package/.claude/commands/oden/research.md +207 -0
  15. package/.claude/commands/oden/review.md +146 -0
  16. package/.claude/commands/oden/spec.md +539 -0
  17. package/.claude/commands/oden/sync.md +286 -0
  18. package/.claude/commands/oden/tasks.md +156 -0
  19. package/.claude/commands/oden/test.md +200 -0
  20. package/.claude/commands/oden/work.md +791 -0
  21. package/.claude/epics/.gitkeep +0 -0
  22. package/.claude/hooks/README.md +130 -0
  23. package/.claude/hooks/bash-worktree-fix.sh +189 -0
  24. package/.claude/prds/.gitkeep +0 -0
  25. package/.claude/rules/agent-coordination.md +224 -0
  26. package/.claude/rules/branch-operations.md +147 -0
  27. package/.claude/rules/datetime.md +118 -0
  28. package/.claude/rules/frontmatter-operations.md +58 -0
  29. package/.claude/rules/github-operations.md +89 -0
  30. package/.claude/rules/oden-methodology.md +111 -0
  31. package/.claude/rules/path-standards.md +155 -0
  32. package/.claude/rules/standard-patterns.md +174 -0
  33. package/.claude/rules/strip-frontmatter.md +82 -0
  34. package/.claude/rules/worktree-operations.md +136 -0
  35. package/.claude/scripts/oden/blocked.sh +72 -0
  36. package/.claude/scripts/oden/epic-list.sh +101 -0
  37. package/.claude/scripts/oden/epic-show.sh +91 -0
  38. package/.claude/scripts/oden/epic-status.sh +90 -0
  39. package/.claude/scripts/oden/help.sh +71 -0
  40. package/.claude/scripts/oden/in-progress.sh +74 -0
  41. package/.claude/scripts/oden/init.sh +192 -0
  42. package/.claude/scripts/oden/next.sh +65 -0
  43. package/.claude/scripts/oden/prd-list.sh +89 -0
  44. package/.claude/scripts/oden/prd-status.sh +63 -0
  45. package/.claude/scripts/oden/search.sh +71 -0
  46. package/.claude/scripts/oden/standup.sh +89 -0
  47. package/.claude/scripts/oden/status.sh +42 -0
  48. package/.claude/scripts/oden/validate.sh +101 -0
  49. package/.claude/settings.json +27 -0
  50. package/MIGRATION.md +217 -0
  51. package/README.md +368 -0
  52. package/bin/install.js +155 -0
  53. package/bin/migrate.js +191 -0
  54. package/bin/oden-forge.js +114 -0
  55. package/bin/post-install.js +47 -0
  56. package/bin/pre-uninstall.js +108 -0
  57. package/install.sh +231 -0
  58. package/package.json +76 -0
package/bin/migrate.js ADDED
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+
3
+ const chalk = require('chalk');
4
+ const fs = require('fs-extra');
5
+ const path = require('path');
6
+ const inquirer = require('inquirer');
7
+
8
+ async function migrate() {
9
+ console.log('\n' + chalk.blue('πŸ”„ Oden Forge Migration Tool'));
10
+ console.log(chalk.blue('═'.repeat(50)));
11
+
12
+ const claudeDir = path.join(process.env.HOME, '.claude');
13
+
14
+ // Detect what needs migration
15
+ const migrationPlan = await analyzeMigrationNeeds(claudeDir);
16
+
17
+ if (migrationPlan.items.length === 0) {
18
+ console.log(chalk.green('βœ… No migration needed - you\'re already on v2!'));
19
+ return;
20
+ }
21
+
22
+ console.log(chalk.yellow(`Found ${migrationPlan.items.length} items to migrate:\n`));
23
+
24
+ migrationPlan.items.forEach(item => {
25
+ console.log(chalk.white(`πŸ“ ${item.type}:`));
26
+ console.log(chalk.gray(` From: ${item.from}`));
27
+ console.log(chalk.gray(` Action: ${item.action}`));
28
+ console.log('');
29
+ });
30
+
31
+ const { proceed } = await inquirer.prompt([{
32
+ type: 'confirm',
33
+ name: 'proceed',
34
+ message: 'Proceed with migration?',
35
+ default: true
36
+ }]);
37
+
38
+ if (!proceed) {
39
+ console.log(chalk.blue('❌ Migration cancelled'));
40
+ return;
41
+ }
42
+
43
+ // Execute migration
44
+ await executeMigration(migrationPlan);
45
+ }
46
+
47
+ async function analyzeMigrationNeeds(claudeDir) {
48
+ const migrationItems = [];
49
+
50
+ // Check for old command structures
51
+ const oldCommands = [
52
+ path.join(claudeDir, 'commands', 'pm'),
53
+ path.join(claudeDir, 'commands', 'ccpm')
54
+ ];
55
+
56
+ oldCommands.forEach(dir => {
57
+ if (fs.existsSync(dir)) {
58
+ migrationItems.push({
59
+ type: 'Legacy Commands',
60
+ from: dir,
61
+ action: 'Remove (replaced by /oden:* commands)',
62
+ priority: 'high'
63
+ });
64
+ }
65
+ });
66
+
67
+ // Check for old scripts
68
+ const oldScripts = [
69
+ path.join(claudeDir, 'scripts', 'pm'),
70
+ path.join(claudeDir, 'scripts', 'ccpm')
71
+ ];
72
+
73
+ oldScripts.forEach(dir => {
74
+ if (fs.existsSync(dir)) {
75
+ migrationItems.push({
76
+ type: 'Legacy Scripts',
77
+ from: dir,
78
+ action: 'Remove (replaced by new scripts)',
79
+ priority: 'high'
80
+ });
81
+ }
82
+ });
83
+
84
+ // Check for CCPM installations
85
+ const ccpmPath = path.join(process.env.HOME, '.ccpm');
86
+ if (fs.existsSync(ccpmPath)) {
87
+ migrationItems.push({
88
+ type: 'CCMP Installation',
89
+ from: ccpmPath,
90
+ action: 'Archive and remove (now native)',
91
+ priority: 'medium'
92
+ });
93
+ }
94
+
95
+ // Check for old PRD/Epic structures
96
+ const oldStructures = [
97
+ path.join(claudeDir, 'pm'),
98
+ path.join(claudeDir, 'ccpm')
99
+ ];
100
+
101
+ oldStructures.forEach(dir => {
102
+ if (fs.existsSync(dir)) {
103
+ migrationItems.push({
104
+ type: 'Old Data Structure',
105
+ from: dir,
106
+ action: 'Migrate to new structure',
107
+ priority: 'low'
108
+ });
109
+ }
110
+ });
111
+
112
+ return {
113
+ items: migrationItems,
114
+ hasHighPriority: migrationItems.some(i => i.priority === 'high'),
115
+ hasData: migrationItems.some(i => i.priority === 'low')
116
+ };
117
+ }
118
+
119
+ async function executeMigration(migrationPlan) {
120
+ console.log(chalk.yellow('\nπŸ”„ Executing migration...\n'));
121
+
122
+ let completed = 0;
123
+ let failed = 0;
124
+
125
+ for (const item of migrationPlan.items) {
126
+ try {
127
+ console.log(chalk.white(`Processing: ${item.type}`));
128
+
129
+ switch (item.priority) {
130
+ case 'high':
131
+ await removeOldInstallation(item);
132
+ break;
133
+ case 'medium':
134
+ await archiveAndRemove(item);
135
+ break;
136
+ case 'low':
137
+ await migrateDataStructure(item);
138
+ break;
139
+ }
140
+
141
+ console.log(chalk.green(` βœ… ${item.action}`));
142
+ completed++;
143
+
144
+ } catch (error) {
145
+ console.log(chalk.red(` ❌ Failed: ${error.message}`));
146
+ failed++;
147
+ }
148
+ console.log('');
149
+ }
150
+
151
+ // Summary
152
+ console.log(chalk.green('πŸŽ‰ Migration Complete!'));
153
+ console.log(chalk.green('═'.repeat(30)));
154
+ console.log(chalk.white(`βœ… Completed: ${completed}`));
155
+ if (failed > 0) {
156
+ console.log(chalk.red(`❌ Failed: ${failed}`));
157
+ }
158
+ console.log('');
159
+ console.log(chalk.blue('Next Steps:'));
160
+ console.log(chalk.white(' 1. Open Claude Code'));
161
+ console.log(chalk.white(' 2. Run: /oden:init'));
162
+ console.log(chalk.white(' 3. Enjoy Oden Forge 2.0!'));
163
+ console.log('');
164
+ }
165
+
166
+ async function removeOldInstallation(item) {
167
+ if (fs.existsSync(item.from)) {
168
+ fs.removeSync(item.from);
169
+ }
170
+ }
171
+
172
+ async function archiveAndRemove(item) {
173
+ if (fs.existsSync(item.from)) {
174
+ const archivePath = item.from + '.bak.' + Date.now();
175
+ fs.moveSync(item.from, archivePath);
176
+ console.log(chalk.gray(` Archived to: ${path.basename(archivePath)}`));
177
+ }
178
+ }
179
+
180
+ async function migrateDataStructure(item) {
181
+ // For now, just archive old data structures
182
+ // In the future, we could implement smart migration of PRDs/Epics
183
+ if (fs.existsSync(item.from)) {
184
+ const backupPath = item.from + '.backup.' + Date.now();
185
+ fs.copySync(item.from, backupPath);
186
+ console.log(chalk.gray(` Backed up to: ${path.basename(backupPath)}`));
187
+ fs.removeSync(item.from);
188
+ }
189
+ }
190
+
191
+ module.exports = { migrate };
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+
3
+ const chalk = require('chalk');
4
+ const { program } = require('commander');
5
+ const fs = require('fs-extra');
6
+ const path = require('path');
7
+ const { execSync } = require('child_process');
8
+
9
+ program
10
+ .name('oden-forge')
11
+ .description('Documentation-First Development Toolkit for Claude Code')
12
+ .version('2.0.0');
13
+
14
+ program
15
+ .command('install')
16
+ .description('Install Oden Forge skills to Claude Code')
17
+ .option('-f, --force', 'Force reinstall, overwriting existing')
18
+ .action(async (options) => {
19
+ const { install } = require('./install.js');
20
+ await install(options);
21
+ });
22
+
23
+ program
24
+ .command('uninstall')
25
+ .description('Remove Oden Forge skills from Claude Code')
26
+ .action(async () => {
27
+ const { uninstall } = require('./pre-uninstall.js');
28
+ await uninstall();
29
+ });
30
+
31
+ program
32
+ .command('status')
33
+ .description('Check installation status')
34
+ .action(() => {
35
+ const claudeDir = path.join(process.env.HOME, '.claude');
36
+ const odenCommands = path.join(claudeDir, 'commands', 'oden');
37
+
38
+ console.log('\n' + chalk.blue('πŸ“‹ Oden Forge Status'));
39
+ console.log(chalk.blue('═'.repeat(50)));
40
+
41
+ if (fs.existsSync(odenCommands)) {
42
+ const commands = fs.readdirSync(odenCommands).filter(f => f.endsWith('.md'));
43
+ console.log(chalk.green(`βœ… Installed: ${commands.length} commands`));
44
+ console.log(chalk.gray(` Location: ${odenCommands}`));
45
+ } else {
46
+ console.log(chalk.red('❌ Not installed'));
47
+ console.log(chalk.yellow(' Run: oden-forge install'));
48
+ }
49
+
50
+ // Check for legacy v1
51
+ const legacyPaths = [
52
+ path.join(claudeDir, 'commands', 'pm'),
53
+ path.join(claudeDir, 'commands', 'ccpm'),
54
+ path.join(process.env.HOME, '.ccpm')
55
+ ];
56
+
57
+ const legacyFound = legacyPaths.filter(p => fs.existsSync(p));
58
+ if (legacyFound.length > 0) {
59
+ console.log(chalk.yellow('\n⚠️ Legacy installations found:'));
60
+ legacyFound.forEach(p => console.log(chalk.gray(` ${p}`)));
61
+ console.log(chalk.yellow(' Run: oden-forge migrate'));
62
+ }
63
+
64
+ console.log('\n' + chalk.blue('πŸ’‘ Quick Start:'));
65
+ console.log(chalk.white(' 1. cd your-project'));
66
+ console.log(chalk.white(' 2. claude-code (or your Claude Code command)'));
67
+ console.log(chalk.white(' 3. /oden:init'));
68
+ console.log('');
69
+ });
70
+
71
+ program
72
+ .command('migrate')
73
+ .description('Migrate from Oden Forge v1 or CCPM')
74
+ .action(async () => {
75
+ const { migrate } = require('./migrate.js');
76
+ await migrate();
77
+ });
78
+
79
+ program
80
+ .command('update')
81
+ .description('Update to latest version')
82
+ .action(() => {
83
+ console.log(chalk.yellow('πŸ”„ Updating Oden Forge...'));
84
+ try {
85
+ execSync('npm update -g oden-forge', { stdio: 'inherit' });
86
+ console.log(chalk.green('βœ… Updated successfully!'));
87
+ } catch (error) {
88
+ console.log(chalk.red('❌ Update failed:'), error.message);
89
+ }
90
+ });
91
+
92
+ // Default action
93
+ program
94
+ .action(() => {
95
+ console.log('\n' + chalk.blue('πŸ”¨ Oden Forge - Documentation-First Development'));
96
+ console.log(chalk.blue('═'.repeat(50)));
97
+ console.log(chalk.white('Usage: oden-forge <command>'));
98
+ console.log('');
99
+ console.log(chalk.yellow('Commands:'));
100
+ console.log(' install Install skills to Claude Code');
101
+ console.log(' status Check installation status');
102
+ console.log(' migrate Migrate from v1 or CCPM');
103
+ console.log(' update Update to latest version');
104
+ console.log(' help Show help');
105
+ console.log('');
106
+ console.log(chalk.gray('After installation, use /oden:init in Claude Code'));
107
+ console.log('');
108
+ });
109
+
110
+ if (process.argv.length === 2) {
111
+ program.outputHelp();
112
+ }
113
+
114
+ program.parse();
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+
3
+ async function postInstall() {
4
+ // Only run auto-install for global installs
5
+ if (!process.env.npm_config_global) {
6
+ return; // Skip for local installs
7
+ }
8
+
9
+ try {
10
+ // Check if dependencies are available
11
+ const chalk = require('chalk');
12
+ const { install } = require('./install.js');
13
+
14
+ console.log(chalk.blue('\nπŸ”„ Running post-install setup...'));
15
+
16
+ await install({ force: false });
17
+
18
+ console.log(chalk.blue('\nπŸ’‘ Next Steps:'));
19
+ console.log(chalk.white(' 1. Open Claude Code in your project'));
20
+ console.log(chalk.white(' 2. Run: /oden:init'));
21
+ console.log(chalk.white(' 3. Follow the wizard'));
22
+ console.log('');
23
+ console.log(chalk.gray(' πŸ“– Documentation: https://javikin.github.io/oden-forge'));
24
+ console.log(chalk.gray(' πŸ†˜ Help: oden-forge --help'));
25
+ console.log('');
26
+
27
+ } catch (error) {
28
+ // Fallback if dependencies aren't ready yet
29
+ console.log('\nπŸ”„ Oden Forge 2.0 installed!');
30
+ console.log('');
31
+ console.log('πŸ’‘ Next Steps:');
32
+ console.log(' 1. Run: oden-forge install');
33
+ console.log(' 2. Open Claude Code in your project');
34
+ console.log(' 3. Run: /oden:init');
35
+ console.log('');
36
+ console.log('πŸ“– Documentation: https://javikin.github.io/oden-forge');
37
+ console.log('πŸ†˜ Help: oden-forge --help');
38
+ console.log('');
39
+ }
40
+ }
41
+
42
+ // Only run if called directly
43
+ if (require.main === module) {
44
+ postInstall();
45
+ }
46
+
47
+ module.exports = { postInstall };
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+
3
+ const chalk = require('chalk');
4
+ const fs = require('fs-extra');
5
+ const path = require('path');
6
+ const inquirer = require('inquirer');
7
+
8
+ async function uninstall() {
9
+ console.log('\n' + chalk.yellow('πŸ—‘οΈ Uninstalling Oden Forge'));
10
+ console.log(chalk.yellow('═'.repeat(40)));
11
+
12
+ const claudeDir = path.join(process.env.HOME, '.claude');
13
+ const pathsToRemove = [
14
+ path.join(claudeDir, 'commands', 'oden'),
15
+ path.join(claudeDir, 'scripts', 'oden'),
16
+ path.join(claudeDir, 'prds'),
17
+ path.join(claudeDir, 'epics')
18
+ ];
19
+
20
+ // Check what exists
21
+ const existingPaths = pathsToRemove.filter(p => fs.existsSync(p));
22
+
23
+ if (existingPaths.length === 0) {
24
+ console.log(chalk.green('βœ… Oden Forge is not installed'));
25
+ return;
26
+ }
27
+
28
+ console.log(chalk.white('The following will be removed:'));
29
+ existingPaths.forEach(p => {
30
+ console.log(chalk.gray(` ${p}`));
31
+ });
32
+
33
+ // Ask for confirmation in interactive mode
34
+ if (process.stdout.isTTY) {
35
+ const { confirm } = await inquirer.prompt([{
36
+ type: 'confirm',
37
+ name: 'confirm',
38
+ message: 'Are you sure you want to remove Oden Forge?',
39
+ default: false
40
+ }]);
41
+
42
+ if (!confirm) {
43
+ console.log(chalk.blue('❌ Uninstall cancelled'));
44
+ return;
45
+ }
46
+ }
47
+
48
+ // Remove files
49
+ console.log(chalk.yellow('\nπŸ—‘οΈ Removing files...'));
50
+ let removed = 0;
51
+
52
+ for (const p of existingPaths) {
53
+ try {
54
+ if (fs.existsSync(p)) {
55
+ fs.removeSync(p);
56
+ console.log(chalk.green(` βœ… Removed: ${path.basename(p)}`));
57
+ removed++;
58
+ }
59
+ } catch (error) {
60
+ console.log(chalk.red(` ❌ Failed to remove ${p}: ${error.message}`));
61
+ }
62
+ }
63
+
64
+ // Don't remove ~/.claude/rules as other tools might use it
65
+ // Just remove our specific rules
66
+ const rulesDir = path.join(claudeDir, 'rules');
67
+ if (fs.existsSync(rulesDir)) {
68
+ try {
69
+ const odenRules = [
70
+ 'oden-methodology.md',
71
+ 'worktree-operations.md',
72
+ 'agent-coordination.md',
73
+ 'standard-patterns.md',
74
+ 'github-operations.md',
75
+ 'frontmatter-operations.md',
76
+ 'datetime.md',
77
+ 'path-standards.md',
78
+ 'strip-frontmatter.md'
79
+ ];
80
+
81
+ let rulesRemoved = 0;
82
+ odenRules.forEach(rule => {
83
+ const rulePath = path.join(rulesDir, rule);
84
+ if (fs.existsSync(rulePath)) {
85
+ fs.removeSync(rulePath);
86
+ rulesRemoved++;
87
+ }
88
+ });
89
+
90
+ if (rulesRemoved > 0) {
91
+ console.log(chalk.green(` βœ… Removed: ${rulesRemoved} rules`));
92
+ }
93
+ } catch (error) {
94
+ console.log(chalk.yellow(` ⚠️ Could not clean rules: ${error.message}`));
95
+ }
96
+ }
97
+
98
+ console.log(chalk.green(`\nβœ… Uninstall complete (${removed + 1} items removed)`));
99
+ console.log(chalk.gray('Your project files remain untouched.'));
100
+ console.log('');
101
+ }
102
+
103
+ // Only run if called directly (not during npm uninstall)
104
+ if (require.main === module) {
105
+ uninstall();
106
+ }
107
+
108
+ module.exports = { uninstall };
package/install.sh ADDED
@@ -0,0 +1,231 @@
1
+ #!/bin/bash
2
+
3
+ # ============================================================================
4
+ # ODEN FORGE - INSTALLER
5
+ # ============================================================================
6
+ # Instala todo lo necesario para usar Oden Forge:
7
+ # - Comandos /oden:* (52 comandos unificados)
8
+ # - Scripts de soporte
9
+ # - Hooks
10
+ # - Rules de Claude
11
+ # - Carpetas para PRDs y Epics
12
+ # - Agentes de desarrollo (opcional)
13
+ # ============================================================================
14
+
15
+ set -e
16
+
17
+ # Colors
18
+ RED='\033[0;31m'
19
+ GREEN='\033[0;32m'
20
+ YELLOW='\033[1;33m'
21
+ BLUE='\033[0;34m'
22
+ NC='\033[0m' # No Color
23
+
24
+ # Get script directory
25
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
26
+
27
+ echo ""
28
+ echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
29
+ echo -e "${BLUE}β•‘ ODEN FORGE INSTALLER β•‘${NC}"
30
+ echo -e "${BLUE}β•‘ Documentation-First Development Toolkit β•‘${NC}"
31
+ echo -e "${BLUE}β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•${NC}"
32
+ echo ""
33
+
34
+ # ============================================================================
35
+ # CHECK PREREQUISITES
36
+ # ============================================================================
37
+
38
+ echo -e "${YELLOW}Verificando requisitos...${NC}"
39
+
40
+ # Check if Claude directory exists
41
+ if [ ! -d "$HOME/.claude" ]; then
42
+ echo -e "${YELLOW}Creando directorio ~/.claude...${NC}"
43
+ mkdir -p "$HOME/.claude"
44
+ fi
45
+
46
+ # Check for git
47
+ if ! command -v git &> /dev/null; then
48
+ echo -e "${RED}❌ Git no estÑ instalado. Por favor instala git primero.${NC}"
49
+ exit 1
50
+ fi
51
+ echo -e "${GREEN}βœ“ Git instalado${NC}"
52
+
53
+ # Check for GitHub CLI
54
+ if ! command -v gh &> /dev/null; then
55
+ echo -e "${YELLOW}⚠ GitHub CLI (gh) no estÑ instalado.${NC}"
56
+ echo -e " Para sync con GitHub, instala: https://cli.github.com/"
57
+ GH_INSTALLED=false
58
+ else
59
+ echo -e "${GREEN}βœ“ GitHub CLI instalado${NC}"
60
+ GH_INSTALLED=true
61
+ fi
62
+
63
+ echo ""
64
+
65
+ # ============================================================================
66
+ # INSTALL COMMANDS
67
+ # ============================================================================
68
+
69
+ echo -e "${YELLOW}Instalando comandos /oden:*...${NC}"
70
+
71
+ mkdir -p "$HOME/.claude/commands/oden"
72
+
73
+ if [ -d "$SCRIPT_DIR/.claude/commands/oden" ]; then
74
+ cp -r "$SCRIPT_DIR/.claude/commands/oden/"* "$HOME/.claude/commands/oden/"
75
+ ODEN_COUNT=$(ls "$HOME/.claude/commands/oden/"*.md 2>/dev/null | wc -l | tr -d ' ')
76
+ echo -e "${GREEN}βœ“ $ODEN_COUNT comandos /oden:* instalados${NC}"
77
+ else
78
+ echo -e "${RED}❌ No se encontraron comandos${NC}"
79
+ exit 1
80
+ fi
81
+
82
+ echo ""
83
+
84
+ # ============================================================================
85
+ # INSTALL SCRIPTS
86
+ # ============================================================================
87
+
88
+ echo -e "${YELLOW}Instalando scripts...${NC}"
89
+
90
+ mkdir -p "$HOME/.claude/scripts/oden"
91
+
92
+ if [ -d "$SCRIPT_DIR/.claude/scripts/oden" ]; then
93
+ cp -r "$SCRIPT_DIR/.claude/scripts/oden/"* "$HOME/.claude/scripts/oden/"
94
+ chmod +x "$HOME/.claude/scripts/oden/"*.sh 2>/dev/null || true
95
+ SCRIPT_COUNT=$(ls "$HOME/.claude/scripts/oden/"*.sh 2>/dev/null | wc -l | tr -d ' ')
96
+ echo -e "${GREEN}βœ“ $SCRIPT_COUNT scripts instalados${NC}"
97
+ else
98
+ echo -e "${YELLOW}⚠ No se encontraron scripts${NC}"
99
+ fi
100
+
101
+ echo ""
102
+
103
+ # ============================================================================
104
+ # INSTALL HOOKS
105
+ # ============================================================================
106
+
107
+ echo -e "${YELLOW}Instalando hooks...${NC}"
108
+
109
+ mkdir -p "$HOME/.claude/hooks"
110
+
111
+ if [ -d "$SCRIPT_DIR/.claude/hooks" ]; then
112
+ cp -r "$SCRIPT_DIR/.claude/hooks/"* "$HOME/.claude/hooks/"
113
+ chmod +x "$HOME/.claude/hooks/"*.sh 2>/dev/null || true
114
+ echo -e "${GREEN}βœ“ Hooks instalados${NC}"
115
+ else
116
+ echo -e "${YELLOW}⚠ No se encontraron hooks${NC}"
117
+ fi
118
+
119
+ echo ""
120
+
121
+ # ============================================================================
122
+ # INSTALL RULES
123
+ # ============================================================================
124
+
125
+ echo -e "${YELLOW}Instalando rules...${NC}"
126
+
127
+ mkdir -p "$HOME/.claude/rules"
128
+
129
+ if [ -d "$SCRIPT_DIR/.claude/rules" ]; then
130
+ cp -r "$SCRIPT_DIR/.claude/rules/"* "$HOME/.claude/rules/"
131
+ RULES_COUNT=$(ls "$HOME/.claude/rules/"*.md 2>/dev/null | wc -l | tr -d ' ')
132
+ echo -e "${GREEN}βœ“ $RULES_COUNT rules instaladas${NC}"
133
+ else
134
+ echo -e "${YELLOW}⚠ No se encontraron rules${NC}"
135
+ fi
136
+
137
+ echo ""
138
+
139
+ # ============================================================================
140
+ # CREATE FOLDERS
141
+ # ============================================================================
142
+
143
+ echo -e "${YELLOW}Creando carpetas de trabajo...${NC}"
144
+
145
+ mkdir -p "$HOME/.claude/prds"
146
+ mkdir -p "$HOME/.claude/epics"
147
+ touch "$HOME/.claude/prds/.gitkeep" 2>/dev/null || true
148
+ touch "$HOME/.claude/epics/.gitkeep" 2>/dev/null || true
149
+ echo -e "${GREEN}βœ“ Carpetas prds/ y epics/ creadas${NC}"
150
+
151
+ echo ""
152
+
153
+ # ============================================================================
154
+ # INSTALL AGENTS (OPTIONAL)
155
+ # ============================================================================
156
+
157
+ echo -e "${YELLOW}ΒΏDeseas instalar los agentes de desarrollo? (y/n)${NC}"
158
+ read -r INSTALL_AGENTS
159
+
160
+ if [[ "$INSTALL_AGENTS" =~ ^[Yy]$ ]]; then
161
+ echo -e "${YELLOW}Instalando agentes...${NC}"
162
+
163
+ mkdir -p "$HOME/.claude/agents"
164
+
165
+ if [ -d "$SCRIPT_DIR/.claude/agents" ]; then
166
+ cp -r "$SCRIPT_DIR/.claude/agents/"* "$HOME/.claude/agents/"
167
+ AGENTS_COUNT=$(ls "$HOME/.claude/agents/"*.md 2>/dev/null | wc -l | tr -d ' ')
168
+ echo -e "${GREEN}βœ“ $AGENTS_COUNT agentes instalados${NC}"
169
+ else
170
+ echo -e "${YELLOW}⚠ No se encontraron agentes en el repo.${NC}"
171
+ echo -e " Usa /oden:init-agents dentro de Claude Code para instalarlos.${NC}"
172
+ fi
173
+ else
174
+ echo -e "${BLUE}Agentes no instalados. Usa /oden:init-agents despuΓ©s.${NC}"
175
+ fi
176
+
177
+ echo ""
178
+
179
+ # ============================================================================
180
+ # GITHUB CLI SETUP
181
+ # ============================================================================
182
+
183
+ if [ "$GH_INSTALLED" = true ]; then
184
+ # Check if already authenticated
185
+ if gh auth status &> /dev/null; then
186
+ echo -e "${GREEN}βœ“ GitHub CLI ya estΓ‘ autenticado${NC}"
187
+ else
188
+ echo -e "${YELLOW}ΒΏDeseas configurar GitHub CLI ahora? (y/n)${NC}"
189
+ read -r SETUP_GH
190
+
191
+ if [[ "$SETUP_GH" =~ ^[Yy]$ ]]; then
192
+ echo -e "${YELLOW}Iniciando autenticaciΓ³n de GitHub...${NC}"
193
+ gh auth login
194
+ fi
195
+ fi
196
+ fi
197
+
198
+ echo ""
199
+
200
+ # ============================================================================
201
+ # SUMMARY
202
+ # ============================================================================
203
+
204
+ echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
205
+ echo -e "${GREEN}β•‘ INSTALACIΓ“N COMPLETADA β•‘${NC}"
206
+ echo -e "${GREEN}β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•${NC}"
207
+ echo ""
208
+ echo -e "${BLUE}COMANDOS INSTALADOS (/oden:*):${NC}"
209
+ echo -e " Setup: init, init-agents, init-mcp, help"
210
+ echo -e " Pre-Dev: architect, analyze, spec, plan, checklist"
211
+ echo -e " GitHub: prd-new, epic-sync, issue-start, ..."
212
+ echo -e " Desarrollo: dev, test, debug, research, daily"
213
+ echo -e " Git: git start, git pr, git finish"
214
+ echo ""
215
+ echo -e "${BLUE}ESTRUCTURA CREADA:${NC}"
216
+ echo -e " ~/.claude/commands/oden/ β†’ Comandos"
217
+ echo -e " ~/.claude/scripts/oden/ β†’ Scripts"
218
+ echo -e " ~/.claude/hooks/ β†’ Hooks"
219
+ echo -e " ~/.claude/rules/ β†’ Rules"
220
+ echo -e " ~/.claude/prds/ β†’ PRDs"
221
+ echo -e " ~/.claude/epics/ β†’ Epics"
222
+ echo ""
223
+ echo -e "${BLUE}PRΓ“XIMOS PASOS:${NC}"
224
+ echo -e " 1. Abre Claude Code en tu proyecto"
225
+ echo -e " 2. Ejecuta: /oden:init"
226
+ echo -e " 3. Sigue el wizard"
227
+ echo ""
228
+ echo -e "${YELLOW}DOCUMENTACIΓ“N:${NC}"
229
+ echo -e " README: $SCRIPT_DIR/README.md"
230
+ echo -e " Help: /oden:help"
231
+ echo ""