claude-all-config 3.7.7 → 3.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +1 -1
- package/codex +49 -0
- package/codex-all +42 -0
- package/kiro-all +38 -0
- package/package.json +7 -2
- package/postinstall.js +215 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.8.1
|
package/codex
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# codex — ClaudeAll shim that:
|
|
4
|
+
# 1. Sources ~/.codex/.env (and ~/.claude/.env as fallback) so MCP servers
|
|
5
|
+
# see CONTEXT7_API_KEY / EXA_API_KEY / Z_AI_API_KEY / TELEGRAM_* / etc.
|
|
6
|
+
# 2. Forwards all args to the REAL codex binary further down PATH.
|
|
7
|
+
#
|
|
8
|
+
# Bypass this shim entirely:
|
|
9
|
+
# command -v codex -a # see all codex binaries
|
|
10
|
+
# /usr/local/bin/codex ... # call the real one directly
|
|
11
|
+
|
|
12
|
+
set -u
|
|
13
|
+
|
|
14
|
+
# ─── Source env files (most-specific first) ───────────────────────────────
|
|
15
|
+
load_env() {
|
|
16
|
+
local f="$1"
|
|
17
|
+
if [ -f "$f" ]; then
|
|
18
|
+
set -a
|
|
19
|
+
# shellcheck disable=SC1090
|
|
20
|
+
. "$f" 2>/dev/null || true
|
|
21
|
+
set +a
|
|
22
|
+
fi
|
|
23
|
+
}
|
|
24
|
+
load_env "$HOME/.claude/.env"
|
|
25
|
+
load_env "$HOME/.codex/.env"
|
|
26
|
+
|
|
27
|
+
# ─── Find the REAL codex binary (skip ourselves) ──────────────────────────
|
|
28
|
+
SELF="$(readlink -f "$0" 2>/dev/null || realpath "$0" 2>/dev/null || echo "$0")"
|
|
29
|
+
|
|
30
|
+
REAL_CODEX=""
|
|
31
|
+
IFS=':' read -ra DIRS <<< "$PATH"
|
|
32
|
+
for dir in "${DIRS[@]}"; do
|
|
33
|
+
candidate="$dir/codex"
|
|
34
|
+
[ -x "$candidate" ] || continue
|
|
35
|
+
candidate_real="$(readlink -f "$candidate" 2>/dev/null || realpath "$candidate" 2>/dev/null || echo "$candidate")"
|
|
36
|
+
if [ "$candidate_real" = "$SELF" ]; then
|
|
37
|
+
continue
|
|
38
|
+
fi
|
|
39
|
+
REAL_CODEX="$candidate"
|
|
40
|
+
break
|
|
41
|
+
done
|
|
42
|
+
|
|
43
|
+
if [ -z "$REAL_CODEX" ]; then
|
|
44
|
+
echo "❌ ClaudeAll codex shim: real codex binary not found in PATH." >&2
|
|
45
|
+
echo " Install: npm install -g @openai/codex" >&2
|
|
46
|
+
exit 127
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
exec "$REAL_CODEX" "$@"
|
package/codex-all
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# codex-all — Codex CLI launcher with ClaudeAll superpowers loaded.
|
|
4
|
+
#
|
|
5
|
+
# What it does:
|
|
6
|
+
# 1. Source ~/.codex/.env (and ~/.claude/.env as fallback) so MCP servers
|
|
7
|
+
# see CONTEXT7_API_KEY / EXA_API_KEY / Z_AI_API_KEY / TELEGRAM_* / etc.
|
|
8
|
+
# 2. Forward all args to the codex binary further down PATH.
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
# codex-all # interactive session
|
|
12
|
+
# codex-all "your prompt" # one-shot
|
|
13
|
+
# codex-all exec ... # subcommands
|
|
14
|
+
#
|
|
15
|
+
# Override:
|
|
16
|
+
# CODEX_BIN=/path/to/codex codex-all
|
|
17
|
+
|
|
18
|
+
set -u
|
|
19
|
+
|
|
20
|
+
# ─── Source env files (most-specific first) ───────────────────────────────
|
|
21
|
+
load_env() {
|
|
22
|
+
local f="$1"
|
|
23
|
+
if [ -f "$f" ]; then
|
|
24
|
+
set -a
|
|
25
|
+
# shellcheck disable=SC1090
|
|
26
|
+
. "$f" 2>/dev/null || true
|
|
27
|
+
set +a
|
|
28
|
+
fi
|
|
29
|
+
}
|
|
30
|
+
load_env "$HOME/.claude/.env"
|
|
31
|
+
load_env "$HOME/.codex/.env"
|
|
32
|
+
|
|
33
|
+
# ─── Locate codex binary ──────────────────────────────────────────────────
|
|
34
|
+
CODEX_CMD="${CODEX_BIN:-codex}"
|
|
35
|
+
if ! command -v "$CODEX_CMD" &>/dev/null; then
|
|
36
|
+
echo "❌ codex CLI not found in PATH." >&2
|
|
37
|
+
echo " Install: npm install -g @openai/codex" >&2
|
|
38
|
+
echo " Or set CODEX_BIN=/path/to/codex" >&2
|
|
39
|
+
exit 127
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
exec "$CODEX_CMD" "$@"
|
package/kiro-all
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# kiro-all — Kiro CLI launcher with ClaudeAll secrets loaded.
|
|
4
|
+
#
|
|
5
|
+
# Sources ~/.kiro/.env (and ~/.claude/.env as fallback), then forwards to the
|
|
6
|
+
# real kiro-cli (or `kiro` if your install uses that name).
|
|
7
|
+
|
|
8
|
+
set -u
|
|
9
|
+
|
|
10
|
+
load_env() {
|
|
11
|
+
local f="$1"
|
|
12
|
+
if [ -f "$f" ]; then
|
|
13
|
+
set -a
|
|
14
|
+
# shellcheck disable=SC1090
|
|
15
|
+
. "$f" 2>/dev/null || true
|
|
16
|
+
set +a
|
|
17
|
+
fi
|
|
18
|
+
}
|
|
19
|
+
load_env "$HOME/.claude/.env"
|
|
20
|
+
load_env "$HOME/.kiro/.env"
|
|
21
|
+
|
|
22
|
+
# Locate kiro binary (prefer kiro-cli; fall back to kiro)
|
|
23
|
+
KIRO_CMD=""
|
|
24
|
+
for cand in "${KIRO_BIN:-}" kiro-cli kiro; do
|
|
25
|
+
[ -z "$cand" ] && continue
|
|
26
|
+
if command -v "$cand" &>/dev/null; then
|
|
27
|
+
KIRO_CMD="$cand"
|
|
28
|
+
break
|
|
29
|
+
fi
|
|
30
|
+
done
|
|
31
|
+
|
|
32
|
+
if [ -z "$KIRO_CMD" ]; then
|
|
33
|
+
echo "❌ kiro-cli not found in PATH." >&2
|
|
34
|
+
echo " See https://kiro.dev for install instructions." >&2
|
|
35
|
+
exit 127
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
exec "$KIRO_CMD" "$@"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-all-config",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.1",
|
|
4
4
|
"description": "🦾 MONSTER ENGINEER v2 - Ultimate AI CLI with 63 Skills, 12 Superpowers, 14 Agents. Multi-Agent Orchestration, Cost-Aware, Security Scorecard, Parallel-First.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
"claude-all-skills": "./bin/skills-cli.js",
|
|
9
9
|
"claude-all-update": "./update.sh",
|
|
10
10
|
"claude-all-mcp": "./bin/mcp-install.js",
|
|
11
|
-
"gemini-all": "./gemini-all"
|
|
11
|
+
"gemini-all": "./gemini-all",
|
|
12
|
+
"codex-all": "./codex-all",
|
|
13
|
+
"kiro-all": "./kiro-all"
|
|
12
14
|
},
|
|
13
15
|
"scripts": {
|
|
14
16
|
"postinstall": "node postinstall.js || bash install.sh",
|
|
@@ -89,6 +91,9 @@
|
|
|
89
91
|
"claude-all",
|
|
90
92
|
"gemini-all",
|
|
91
93
|
"gemini",
|
|
94
|
+
"codex-all",
|
|
95
|
+
"codex",
|
|
96
|
+
"kiro-all",
|
|
92
97
|
"install.sh",
|
|
93
98
|
"install-termux.sh",
|
|
94
99
|
"install-universal.sh",
|
package/postinstall.js
CHANGED
|
@@ -147,12 +147,16 @@ function mergeEnvFile(srcPath, destPath) {
|
|
|
147
147
|
|
|
148
148
|
const hasClaude = commandExists('claude');
|
|
149
149
|
const hasGemini = commandExists('gemini');
|
|
150
|
+
const hasCodex = commandExists('codex');
|
|
151
|
+
const hasKiro = commandExists('kiro') || commandExists('kiro-cli');
|
|
150
152
|
|
|
151
153
|
console.log('🤖 ClaudeAll - Installing configurations...\n');
|
|
152
154
|
|
|
153
155
|
if (hasClaude) console.log('✅ Claude CLI detected');
|
|
154
156
|
if (hasGemini) console.log('✅ Gemini CLI detected');
|
|
155
|
-
if (
|
|
157
|
+
if (hasCodex) console.log('✅ Codex CLI detected');
|
|
158
|
+
if (hasKiro) console.log('✅ Kiro CLI detected');
|
|
159
|
+
if (!hasClaude && !hasGemini && !hasCodex && !hasKiro) {
|
|
156
160
|
console.log('⚠️ No CLI detected, installing configs anyway...');
|
|
157
161
|
}
|
|
158
162
|
console.log('');
|
|
@@ -428,6 +432,200 @@ function installGemini() {
|
|
|
428
432
|
console.log(` ⚙️ settings.json (MONSTER ENGINEER + auto-approve)`);
|
|
429
433
|
}
|
|
430
434
|
|
|
435
|
+
// Install to Codex (~/.codex/) — Codex CLI from OpenAI uses TOML config and
|
|
436
|
+
// AGENTS.md for global instructions (analogous to CLAUDE.md / GEMINI.md).
|
|
437
|
+
function installCodex() {
|
|
438
|
+
const CODEX_DIR = path.join(HOME, '.codex');
|
|
439
|
+
console.log('📦 Installing to Codex (~/.codex/)...');
|
|
440
|
+
|
|
441
|
+
// Create directories — Codex looks for skills directly under ~/.codex/skills/
|
|
442
|
+
const dirs = ['agents', 'skills', 'commands', 'hooks', 'lib'];
|
|
443
|
+
dirs.forEach(dir => {
|
|
444
|
+
const targetDir = path.join(CODEX_DIR, dir);
|
|
445
|
+
try {
|
|
446
|
+
if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true });
|
|
447
|
+
} catch {}
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// Copy content (resilient to root-owned existing files)
|
|
451
|
+
const agentCount = copyDir(path.join(PKG_DIR, 'agents'), path.join(CODEX_DIR, 'agents'));
|
|
452
|
+
console.log(` 🤖 ${agentCount} agents`);
|
|
453
|
+
|
|
454
|
+
const skillCount = copyDir(path.join(PKG_DIR, 'skills'), path.join(CODEX_DIR, 'skills'));
|
|
455
|
+
console.log(` ⚡ ${skillCount} skill files`);
|
|
456
|
+
|
|
457
|
+
const cmdCount = copyDir(path.join(PKG_DIR, 'commands'), path.join(CODEX_DIR, 'commands'));
|
|
458
|
+
console.log(` 📝 ${cmdCount} commands`);
|
|
459
|
+
|
|
460
|
+
const hookCount = copyDir(path.join(PKG_DIR, 'hooks'), path.join(CODEX_DIR, 'hooks'));
|
|
461
|
+
console.log(` 🔗 ${hookCount} hooks`);
|
|
462
|
+
|
|
463
|
+
if (fs.existsSync(path.join(PKG_DIR, 'lib'))) {
|
|
464
|
+
copyDir(path.join(PKG_DIR, 'lib'), path.join(CODEX_DIR, 'lib'));
|
|
465
|
+
console.log(` 📚 lib`);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// AGENTS.md — Codex's equivalent of CLAUDE.md, generated from CLAUDE.md
|
|
469
|
+
// (single source of truth) with surface substitutions.
|
|
470
|
+
const claudeMdInPkg = path.join(PKG_DIR, 'CLAUDE.md');
|
|
471
|
+
const agentsMdDest = path.join(CODEX_DIR, 'AGENTS.md');
|
|
472
|
+
if (fs.existsSync(claudeMdInPkg)) {
|
|
473
|
+
try {
|
|
474
|
+
let content = fs.readFileSync(claudeMdInPkg, 'utf8');
|
|
475
|
+
content = content
|
|
476
|
+
.replace(/# ClaudeAll Global Instructions/, '# Codex Agent Instructions (ClaudeAll Global Instructions)')
|
|
477
|
+
.replace(/Claude Code enhanced with ClaudeAll superpowers\./, 'OpenAI Codex CLI enhanced with ClaudeAll superpowers.\n\n**Bypass mode**: configure approval policy in ~/.codex/config.toml (default: never).')
|
|
478
|
+
.replace(/~\/\.claude\//g, '~/.codex/')
|
|
479
|
+
.replace(/CLAUDE\.md/g, 'AGENTS.md');
|
|
480
|
+
fs.writeFileSync(agentsMdDest, content);
|
|
481
|
+
console.log(` 📄 AGENTS.md (synced from CLAUDE.md, ${content.split('\n').length} lines)`);
|
|
482
|
+
} catch (e) {
|
|
483
|
+
console.log(` ⚠️ AGENTS.md write skipped (${e.code || 'error'})`);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// config.toml — translate mcp.json into Codex's TOML schema for MCP servers.
|
|
488
|
+
const mcpSrc = path.join(PKG_DIR, 'mcp.json');
|
|
489
|
+
const codexConfigDest = path.join(CODEX_DIR, 'config.toml');
|
|
490
|
+
if (fs.existsSync(mcpSrc)) {
|
|
491
|
+
try {
|
|
492
|
+
const mcpRaw = fs.readFileSync(mcpSrc, 'utf8').replace(/\$\{HOME\}/g, HOME);
|
|
493
|
+
const mcp = JSON.parse(mcpRaw);
|
|
494
|
+
let toml = '# ClaudeAll-managed Codex config (auto-generated from mcp.json)\n';
|
|
495
|
+
toml += '# Edit ~/.codex/.env for secrets. Re-run `npm install -g claude-all-config@latest`\n';
|
|
496
|
+
toml += '# to regenerate this file from the latest mcp.json.\n\n';
|
|
497
|
+
|
|
498
|
+
// Sandbox-friendly defaults so codex on a fresh proot/container works
|
|
499
|
+
toml += '# Default approval — match ClaudeAll style: autonomous unless overridden.\n';
|
|
500
|
+
toml += 'approval_policy = "never"\n\n';
|
|
501
|
+
|
|
502
|
+
for (const [name, cfg] of Object.entries(mcp.mcpServers || {})) {
|
|
503
|
+
const safeName = name.includes('-') ? `"${name}"` : name;
|
|
504
|
+
toml += `[mcp_servers.${safeName}]\n`;
|
|
505
|
+
if (cfg.type === 'http' || cfg.url) {
|
|
506
|
+
toml += `url = ${JSON.stringify(cfg.url)}\n`;
|
|
507
|
+
if (cfg.headers && cfg.headers.Authorization) {
|
|
508
|
+
// Pull env var name out of "Bearer ${VAR_NAME}"
|
|
509
|
+
const m = cfg.headers.Authorization.match(/\$\{([A-Z_][A-Z0-9_]*)\}/);
|
|
510
|
+
if (m) toml += `bearer_token_env_var = "${m[1]}"\n`;
|
|
511
|
+
}
|
|
512
|
+
} else if (cfg.command) {
|
|
513
|
+
toml += `command = ${JSON.stringify(cfg.command)}\n`;
|
|
514
|
+
if (Array.isArray(cfg.args)) {
|
|
515
|
+
toml += `args = ${JSON.stringify(cfg.args)}\n`;
|
|
516
|
+
}
|
|
517
|
+
if (cfg.env && Object.keys(cfg.env).length > 0) {
|
|
518
|
+
toml += `\n[mcp_servers.${safeName}.env]\n`;
|
|
519
|
+
for (const [k, v] of Object.entries(cfg.env)) {
|
|
520
|
+
toml += `${k} = ${JSON.stringify(v)}\n`;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
toml += '\n';
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Preserve any existing user customization above ours? For now we
|
|
528
|
+
// overwrite — the user's secrets are in .env, not in this file.
|
|
529
|
+
fs.writeFileSync(codexConfigDest, toml);
|
|
530
|
+
const serverCount = Object.keys(mcp.mcpServers || {}).length;
|
|
531
|
+
console.log(` ⚙️ config.toml (${serverCount} MCP servers, approval_policy=never)`);
|
|
532
|
+
} catch (e) {
|
|
533
|
+
console.log(` ⚠️ config.toml write skipped (${e.code || e.message || 'error'})`);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// .env merge — same template as Claude/Gemini
|
|
538
|
+
const envSrc = path.join(PKG_DIR, '.env.example');
|
|
539
|
+
const envDest = path.join(CODEX_DIR, '.env');
|
|
540
|
+
if (fs.existsSync(envSrc)) {
|
|
541
|
+
try {
|
|
542
|
+
const r = mergeEnvFile(envSrc, envDest);
|
|
543
|
+
try { fs.chmodSync(envDest, 0o600); } catch {}
|
|
544
|
+
console.log(` 🔐 .env ${r.action} (${r.filled} filled, ${r.preserved} preserved)`);
|
|
545
|
+
} catch (e) {
|
|
546
|
+
console.log(` ⚠️ .env merge skipped (${e.code || 'error'})`);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Install to Kiro (~/.kiro/) — Kiro CLI uses skills in SKILL.md format
|
|
552
|
+
// (compatible with Claude), AGENTS.md for global instructions, and stores MCP
|
|
553
|
+
// config under ~/.kiro/settings/mcp.json. Agents in Kiro use a JSON schema
|
|
554
|
+
// that's auto-generated by Kiro itself, so we don't ship those.
|
|
555
|
+
function installKiro() {
|
|
556
|
+
const KIRO_DIR = path.join(HOME, '.kiro');
|
|
557
|
+
console.log('📦 Installing to Kiro (~/.kiro/)...');
|
|
558
|
+
|
|
559
|
+
const dirs = ['skills', 'commands', 'hooks', 'lib', 'settings', 'prompts'];
|
|
560
|
+
dirs.forEach(dir => {
|
|
561
|
+
const targetDir = path.join(KIRO_DIR, dir);
|
|
562
|
+
try {
|
|
563
|
+
if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true });
|
|
564
|
+
} catch {}
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
// Skills are SKILL.md format — fully compatible with Kiro
|
|
568
|
+
const skillCount = copyDir(path.join(PKG_DIR, 'skills'), path.join(KIRO_DIR, 'skills'));
|
|
569
|
+
console.log(` ⚡ ${skillCount} skill files`);
|
|
570
|
+
|
|
571
|
+
// Commands & hooks (in case Kiro adopts them)
|
|
572
|
+
const cmdCount = copyDir(path.join(PKG_DIR, 'commands'), path.join(KIRO_DIR, 'commands'));
|
|
573
|
+
console.log(` 📝 ${cmdCount} commands`);
|
|
574
|
+
|
|
575
|
+
const hookCount = copyDir(path.join(PKG_DIR, 'hooks'), path.join(KIRO_DIR, 'hooks'));
|
|
576
|
+
console.log(` 🔗 ${hookCount} hooks`);
|
|
577
|
+
|
|
578
|
+
if (fs.existsSync(path.join(PKG_DIR, 'lib'))) {
|
|
579
|
+
copyDir(path.join(PKG_DIR, 'lib'), path.join(KIRO_DIR, 'lib'));
|
|
580
|
+
console.log(` 📚 lib`);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// AGENTS.md — synced from CLAUDE.md (single source of truth)
|
|
584
|
+
const claudeMdInPkg = path.join(PKG_DIR, 'CLAUDE.md');
|
|
585
|
+
const agentsMdDest = path.join(KIRO_DIR, 'AGENTS.md');
|
|
586
|
+
if (fs.existsSync(claudeMdInPkg)) {
|
|
587
|
+
try {
|
|
588
|
+
let content = fs.readFileSync(claudeMdInPkg, 'utf8');
|
|
589
|
+
content = content
|
|
590
|
+
.replace(/# ClaudeAll Global Instructions/, '# Kiro Agent Instructions (ClaudeAll Global Instructions)')
|
|
591
|
+
.replace(/Claude Code enhanced with ClaudeAll superpowers\./, 'Kiro CLI enhanced with ClaudeAll superpowers.\n\nKiro uses its own JSON-format agents under ~/.kiro/agents/ (auto-managed). The skills, hooks, and MCP servers below are shared with Claude/Gemini/Codex.')
|
|
592
|
+
.replace(/~\/\.claude\//g, '~/.kiro/')
|
|
593
|
+
.replace(/CLAUDE\.md/g, 'AGENTS.md');
|
|
594
|
+
fs.writeFileSync(agentsMdDest, content);
|
|
595
|
+
console.log(` 📄 AGENTS.md (synced from CLAUDE.md, ${content.split('\n').length} lines)`);
|
|
596
|
+
} catch (e) {
|
|
597
|
+
console.log(` ⚠️ AGENTS.md write skipped (${e.code || 'error'})`);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// MCP config under ~/.kiro/settings/mcp.json with ${HOME} expanded
|
|
602
|
+
const mcpSrc = path.join(PKG_DIR, 'mcp.json');
|
|
603
|
+
const mcpDest = path.join(KIRO_DIR, 'settings', 'mcp.json');
|
|
604
|
+
if (fs.existsSync(mcpSrc)) {
|
|
605
|
+
try {
|
|
606
|
+
let mcpContent = fs.readFileSync(mcpSrc, 'utf8').replace(/\$\{HOME\}/g, HOME);
|
|
607
|
+
fs.writeFileSync(mcpDest, mcpContent);
|
|
608
|
+
try { fs.chmodSync(mcpDest, 0o600); } catch {}
|
|
609
|
+
console.log(` 🔧 MCP config (11 servers, settings/mcp.json)`);
|
|
610
|
+
} catch (e) {
|
|
611
|
+
console.log(` ⚠️ MCP config skipped (${e.code || 'error'})`);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// .env merge
|
|
616
|
+
const envSrc = path.join(PKG_DIR, '.env.example');
|
|
617
|
+
const envDest = path.join(KIRO_DIR, '.env');
|
|
618
|
+
if (fs.existsSync(envSrc)) {
|
|
619
|
+
try {
|
|
620
|
+
const r = mergeEnvFile(envSrc, envDest);
|
|
621
|
+
try { fs.chmodSync(envDest, 0o600); } catch {}
|
|
622
|
+
console.log(` 🔐 .env ${r.action} (${r.filled} filled, ${r.preserved} preserved)`);
|
|
623
|
+
} catch (e) {
|
|
624
|
+
console.log(` ⚠️ .env merge skipped (${e.code || 'error'})`);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
431
629
|
// Install uvx for MiniMax MCP support
|
|
432
630
|
function installUvx() {
|
|
433
631
|
const hasUvx = commandExists('uvx');
|
|
@@ -476,6 +674,10 @@ function setupLocalBinSymlinks() {
|
|
|
476
674
|
// 'gemini' shim shadows the real `gemini` binary so plain `gemini` runs
|
|
477
675
|
// in YOLO mode by default with .env loaded. Opt out with --no-yolo.
|
|
478
676
|
'gemini': path.join(PKG_DIR, 'gemini'),
|
|
677
|
+
'codex-all': path.join(PKG_DIR, 'codex-all'),
|
|
678
|
+
// 'codex' shim shadows the real `codex` so plain `codex` auto-loads .env.
|
|
679
|
+
'codex': path.join(PKG_DIR, 'codex'),
|
|
680
|
+
'kiro-all': path.join(PKG_DIR, 'kiro-all'),
|
|
479
681
|
};
|
|
480
682
|
|
|
481
683
|
let created = 0;
|
|
@@ -543,6 +745,16 @@ if (hasGemini) {
|
|
|
543
745
|
installGemini();
|
|
544
746
|
}
|
|
545
747
|
|
|
748
|
+
if (hasCodex) {
|
|
749
|
+
console.log('');
|
|
750
|
+
installCodex();
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
if (hasKiro) {
|
|
754
|
+
console.log('');
|
|
755
|
+
installKiro();
|
|
756
|
+
}
|
|
757
|
+
|
|
546
758
|
setupLocalBinSymlinks();
|
|
547
759
|
|
|
548
760
|
// If we ran under sudo, hand ownership back to the original user so that a
|
|
@@ -551,6 +763,8 @@ if (SUDO_USER) {
|
|
|
551
763
|
console.log(`\n🔒 Restoring ownership to ${SUDO_USER}...`);
|
|
552
764
|
fixOwnership(path.join(HOME, '.claude'));
|
|
553
765
|
fixOwnership(path.join(HOME, '.gemini'));
|
|
766
|
+
fixOwnership(path.join(HOME, '.codex'));
|
|
767
|
+
fixOwnership(path.join(HOME, '.kiro'));
|
|
554
768
|
fixOwnership(path.join(HOME, '.mcp.json'));
|
|
555
769
|
fixOwnership(path.join(HOME, '.local'));
|
|
556
770
|
console.log(' ✅ Ownership fixed.');
|