specrails-core 4.1.0 → 4.2.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.
- package/README.md +4 -4
- package/VERSION +1 -1
- package/bin/specrails-core.mjs +302 -0
- package/commands/doctor.md +5 -5
- package/commands/enrich.md +9 -9
- package/dist/installer/cli.js +167 -0
- package/dist/installer/cli.js.map +1 -0
- package/dist/installer/commands/doctor.js +144 -0
- package/dist/installer/commands/doctor.js.map +1 -0
- package/dist/installer/commands/init.js +182 -0
- package/dist/installer/commands/init.js.map +1 -0
- package/dist/installer/commands/perf-check.js +16 -0
- package/dist/installer/commands/perf-check.js.map +1 -0
- package/dist/installer/commands/update.js +170 -0
- package/dist/installer/commands/update.js.map +1 -0
- package/dist/installer/phases/install-config.js +120 -0
- package/dist/installer/phases/install-config.js.map +1 -0
- package/dist/installer/phases/manifest.js +93 -0
- package/dist/installer/phases/manifest.js.map +1 -0
- package/dist/installer/phases/prereqs.js +116 -0
- package/dist/installer/phases/prereqs.js.map +1 -0
- package/dist/installer/phases/provider-detect.js +111 -0
- package/dist/installer/phases/provider-detect.js.map +1 -0
- package/dist/installer/phases/scaffold.js +373 -0
- package/dist/installer/phases/scaffold.js.map +1 -0
- package/dist/installer/util/errors.js +79 -0
- package/dist/installer/util/errors.js.map +1 -0
- package/dist/installer/util/exec.js +151 -0
- package/dist/installer/util/exec.js.map +1 -0
- package/dist/installer/util/fs.js +153 -0
- package/dist/installer/util/fs.js.map +1 -0
- package/dist/installer/util/git.js +113 -0
- package/dist/installer/util/git.js.map +1 -0
- package/dist/installer/util/logger.js +55 -0
- package/dist/installer/util/logger.js.map +1 -0
- package/dist/installer/util/paths.js +66 -0
- package/dist/installer/util/paths.js.map +1 -0
- package/dist/installer/util/prompts.js +49 -0
- package/dist/installer/util/prompts.js.map +1 -0
- package/dist/installer/util/template.js +60 -0
- package/dist/installer/util/template.js.map +1 -0
- package/docs/deployment.md +2 -1
- package/docs/installation.md +6 -3
- package/docs/testing/test-matrix-codex.md +19 -11
- package/docs/updating.md +24 -49
- package/docs/user-docs/faq.md +1 -1
- package/docs/windows.md +53 -0
- package/{templates/settings/integration-contract.json → integration-contract.json} +2 -2
- package/package.json +25 -10
- package/pinned-versions.json +4 -0
- package/schemas/profile.v1.json +11 -3
- package/templates/agents/sr-architect.md +1 -1
- package/templates/agents/sr-reviewer.md +1 -1
- package/templates/commands/specrails/compat-check.md +3 -3
- package/templates/commands/specrails/doctor.md +5 -5
- package/templates/commands/specrails/enrich.md +9 -9
- package/templates/commands/specrails/reconfig.md +2 -2
- package/templates/commands/specrails/refactor-recommender.md +2 -2
- package/templates/commands/specrails/vpc-drift.md +1 -1
- package/templates/skills/sr-compat-check/SKILL.md +3 -3
- package/templates/skills/sr-refactor-recommender/SKILL.md +2 -2
- package/bin/doctor.sh +0 -127
- package/bin/perf-check.sh +0 -21
- package/bin/specrails-core.js +0 -262
- package/commands/setup.md +0 -1461
- package/install.sh +0 -1231
- package/update.sh +0 -870
package/bin/doctor.sh
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# specrails doctor — health check for specrails-core installations
|
|
3
|
-
# Usage: specrails doctor
|
|
4
|
-
# Exit 0 if all checks pass, 1 if any check fails.
|
|
5
|
-
|
|
6
|
-
set -uo pipefail
|
|
7
|
-
|
|
8
|
-
# Colors
|
|
9
|
-
GREEN='\033[0;32m'
|
|
10
|
-
RED='\033[0;31m'
|
|
11
|
-
NC='\033[0m'
|
|
12
|
-
BOLD='\033[1m'
|
|
13
|
-
|
|
14
|
-
PASS=0
|
|
15
|
-
FAIL=0
|
|
16
|
-
RESULTS=()
|
|
17
|
-
|
|
18
|
-
pass() { RESULTS+=("$(printf "${GREEN}✅${NC} $1")"); PASS=$((PASS + 1)); }
|
|
19
|
-
fail() { RESULTS+=("$(printf "${RED}❌${NC} $1\n Fix: $2")"); FAIL=$((FAIL + 1)); }
|
|
20
|
-
|
|
21
|
-
echo ""
|
|
22
|
-
echo -e "${BOLD}specrails doctor${NC}"
|
|
23
|
-
echo ""
|
|
24
|
-
|
|
25
|
-
# Determine project root (current working directory)
|
|
26
|
-
PROJECT_ROOT="${PWD}"
|
|
27
|
-
|
|
28
|
-
# ─────────────────────────────────────────────
|
|
29
|
-
# Check 1: Claude Code CLI
|
|
30
|
-
# ─────────────────────────────────────────────
|
|
31
|
-
if CLAUDE_PATH=$(command -v claude 2>/dev/null); then
|
|
32
|
-
pass "Claude Code CLI: found (${CLAUDE_PATH})"
|
|
33
|
-
else
|
|
34
|
-
fail "Claude Code CLI: not found" "Install Claude Code: https://claude.ai/download"
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
|
-
# ─────────────────────────────────────────────
|
|
38
|
-
# Check 2: Claude authentication
|
|
39
|
-
# ─────────────────────────────────────────────
|
|
40
|
-
if command -v claude &>/dev/null; then
|
|
41
|
-
_claude_authed=false
|
|
42
|
-
if claude config list 2>/dev/null | grep -q "api_key"; then
|
|
43
|
-
_claude_authed=true
|
|
44
|
-
elif [[ -n "${ANTHROPIC_API_KEY:-}" ]]; then
|
|
45
|
-
_claude_authed=true
|
|
46
|
-
elif [[ -f "${HOME}/.claude.json" ]] && grep -q '"oauthAccount"' "${HOME}/.claude.json" 2>/dev/null; then
|
|
47
|
-
_claude_authed=true
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
if [[ "$_claude_authed" == "true" ]]; then
|
|
51
|
-
pass "Claude: authenticated"
|
|
52
|
-
else
|
|
53
|
-
fail "Claude: not authenticated" "Option 1: claude config set api_key <your-key> | Option 2: claude auth login"
|
|
54
|
-
fi
|
|
55
|
-
fi
|
|
56
|
-
|
|
57
|
-
# ─────────────────────────────────────────────
|
|
58
|
-
# Check 3: Agent files present
|
|
59
|
-
# ─────────────────────────────────────────────
|
|
60
|
-
AGENTS_DIR="${PROJECT_ROOT}/agents"
|
|
61
|
-
if [[ -d "${AGENTS_DIR}" ]]; then
|
|
62
|
-
AGENT_COUNT=$(find "${AGENTS_DIR}" -name "AGENTS.md" 2>/dev/null | wc -l | tr -d ' ')
|
|
63
|
-
if [[ "${AGENT_COUNT}" -ge 1 ]]; then
|
|
64
|
-
AGENT_NAMES=$(find "${AGENTS_DIR}" -name "AGENTS.md" -exec dirname {} \; | xargs -I{} basename {} | tr '\n' ', ' | sed 's/,$//')
|
|
65
|
-
pass "Agent files: ${AGENT_COUNT} agent(s) found (${AGENT_NAMES})"
|
|
66
|
-
else
|
|
67
|
-
fail "Agent files: agents/ exists but no AGENTS.md found" "Run specrails-core init to set up agents"
|
|
68
|
-
fi
|
|
69
|
-
else
|
|
70
|
-
fail "Agent files: agents/ directory not found" "Run specrails-core init to set up agents"
|
|
71
|
-
fi
|
|
72
|
-
|
|
73
|
-
# ─────────────────────────────────────────────
|
|
74
|
-
# Check 4: CLAUDE.md present
|
|
75
|
-
# ─────────────────────────────────────────────
|
|
76
|
-
if [[ -f "${PROJECT_ROOT}/CLAUDE.md" ]]; then
|
|
77
|
-
pass "CLAUDE.md: present"
|
|
78
|
-
else
|
|
79
|
-
fail "CLAUDE.md: missing" "Run /specrails:setup inside Claude Code to regenerate"
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
# ─────────────────────────────────────────────
|
|
83
|
-
# Check 5: Git initialized
|
|
84
|
-
# ─────────────────────────────────────────────
|
|
85
|
-
if [[ -d "${PROJECT_ROOT}/.git" ]]; then
|
|
86
|
-
pass "Git: initialized"
|
|
87
|
-
else
|
|
88
|
-
fail "Git: not a git repository" "Initialize with: git init"
|
|
89
|
-
fi
|
|
90
|
-
|
|
91
|
-
# ─────────────────────────────────────────────
|
|
92
|
-
# Check 6: npm present
|
|
93
|
-
# ─────────────────────────────────────────────
|
|
94
|
-
if NPM_VERSION=$(npm --version 2>/dev/null); then
|
|
95
|
-
pass "npm: found (v${NPM_VERSION})"
|
|
96
|
-
else
|
|
97
|
-
fail "npm: not found" "Install npm: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm"
|
|
98
|
-
fi
|
|
99
|
-
|
|
100
|
-
# ─────────────────────────────────────────────
|
|
101
|
-
# Output results
|
|
102
|
-
# ─────────────────────────────────────────────
|
|
103
|
-
for line in "${RESULTS[@]}"; do
|
|
104
|
-
echo -e "${line}"
|
|
105
|
-
done
|
|
106
|
-
|
|
107
|
-
echo ""
|
|
108
|
-
|
|
109
|
-
if [[ "${FAIL}" -eq 0 ]]; then
|
|
110
|
-
TOTAL=$((PASS + FAIL))
|
|
111
|
-
echo -e "All ${TOTAL} checks passed. Run ${BOLD}/specrails:get-backlog-specs${NC} to get started."
|
|
112
|
-
else
|
|
113
|
-
echo "${FAIL} check(s) failed."
|
|
114
|
-
fi
|
|
115
|
-
|
|
116
|
-
# ─────────────────────────────────────────────
|
|
117
|
-
# Append to ~/.specrails/doctor.log
|
|
118
|
-
# ─────────────────────────────────────────────
|
|
119
|
-
LOG_DIR="${HOME}/.specrails"
|
|
120
|
-
mkdir -p "${LOG_DIR}"
|
|
121
|
-
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u)
|
|
122
|
-
TOTAL=$((PASS + FAIL))
|
|
123
|
-
echo "${TIMESTAMP} checks=${TOTAL} passed=${PASS} failed=${FAIL}" >> "${LOG_DIR}/doctor.log"
|
|
124
|
-
|
|
125
|
-
echo ""
|
|
126
|
-
|
|
127
|
-
exit $([[ "${FAIL}" -eq 0 ]] && echo 0 || echo 1)
|
package/bin/perf-check.sh
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Performance regression check for specrails-core.
|
|
3
|
-
# This is a template/installer repo — no runtime benchmarks apply.
|
|
4
|
-
# Reports NO_PERF_IMPACT so the CI workflow exits cleanly.
|
|
5
|
-
set -euo pipefail
|
|
6
|
-
|
|
7
|
-
FILES="${MODIFIED_FILES_LIST:-}"
|
|
8
|
-
CONTEXT="${2:-}"
|
|
9
|
-
|
|
10
|
-
# Determine if any performance-sensitive files were modified.
|
|
11
|
-
# For specrails-core (a shell installer + markdown template repo), there are
|
|
12
|
-
# no runtime execution paths to benchmark. All changes are to installer scripts
|
|
13
|
-
# or template files that have no measurable latency or throughput impact.
|
|
14
|
-
|
|
15
|
-
echo "specrails-core performance check"
|
|
16
|
-
echo "Modified files: ${FILES:-<none>}"
|
|
17
|
-
echo ""
|
|
18
|
-
echo "This repository contains shell installer scripts and Markdown templates."
|
|
19
|
-
echo "No runtime benchmarks apply — skipping performance regression analysis."
|
|
20
|
-
echo ""
|
|
21
|
-
echo "PERF_STATUS: NO_PERF_IMPACT"
|
package/bin/specrails-core.js
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { spawnSync } = require("child_process");
|
|
4
|
-
const { resolve } = require("path");
|
|
5
|
-
|
|
6
|
-
const ROOT = resolve(__dirname, "..");
|
|
7
|
-
const COMMANDS = {
|
|
8
|
-
init: "install.sh",
|
|
9
|
-
update: "update.sh",
|
|
10
|
-
doctor: "bin/doctor.sh",
|
|
11
|
-
"perf-check": "bin/perf-check.sh",
|
|
12
|
-
enrich: null,
|
|
13
|
-
version: null,
|
|
14
|
-
profile: null,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const args = process.argv.slice(2);
|
|
18
|
-
const subcommand = args[0];
|
|
19
|
-
|
|
20
|
-
// ─── Global --version / -V flag ──────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
if (args.includes("--version") || args.includes("-V")) {
|
|
23
|
-
const pkg = require(resolve(ROOT, "package.json"));
|
|
24
|
-
console.log(`specrails-core v${pkg.version}`);
|
|
25
|
-
process.exit(0);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!subcommand) {
|
|
29
|
-
console.log(`specrails-core — Agent Workflow System for Claude Code
|
|
30
|
-
|
|
31
|
-
Usage:
|
|
32
|
-
specrails-core init [--root-dir <path>] [--yes|-y] Install into a repository
|
|
33
|
-
specrails-core update [--only <component>] Update an existing installation
|
|
34
|
-
specrails-core doctor Run health checks
|
|
35
|
-
specrails-core perf-check [--files <list>] Performance regression check (CI)
|
|
36
|
-
specrails-core enrich [--from-config <path>] Run /specrails:enrich via Claude CLI
|
|
37
|
-
specrails-core profile <validate|show> [<path>] Validate or pretty-print a profile JSON
|
|
38
|
-
specrails-core version Show installed version
|
|
39
|
-
|
|
40
|
-
Flags for init:
|
|
41
|
-
--root-dir <path> Target repository path (default: current directory)
|
|
42
|
-
--yes | -y Non-interactive; use defaults, skip TUI
|
|
43
|
-
--provider <value> Force provider: claude or codex
|
|
44
|
-
--no-direct Skip TUI; use the legacy interactive bash installer
|
|
45
|
-
--from-config Skip TUI; use existing .specrails/install-config.yaml
|
|
46
|
-
|
|
47
|
-
Global flags:
|
|
48
|
-
--version | -V Show installed version
|
|
49
|
-
|
|
50
|
-
More info: https://github.com/fjpulidop/specrails-core`);
|
|
51
|
-
process.exit(0);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (!(subcommand in COMMANDS)) {
|
|
55
|
-
console.error(`Unknown command: ${subcommand}\n`);
|
|
56
|
-
console.error("Available commands: init, update, doctor, perf-check, enrich, version");
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const script = COMMANDS[subcommand];
|
|
61
|
-
|
|
62
|
-
// Allowlisted flags per subcommand
|
|
63
|
-
const ALLOWED_FLAGS = {
|
|
64
|
-
init: ["--root-dir", "--yes", "-y", "--provider", "--no-direct", "--from-config", "--quick", "--hub-json", "--agent-teams"],
|
|
65
|
-
update: ["--only"],
|
|
66
|
-
doctor: [],
|
|
67
|
-
"perf-check": ["--files", "--context"],
|
|
68
|
-
enrich: ["--from-config", "--quick"],
|
|
69
|
-
version: [],
|
|
70
|
-
profile: [],
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const subargs = args.slice(1);
|
|
74
|
-
const allowed = ALLOWED_FLAGS[subcommand] ?? [];
|
|
75
|
-
|
|
76
|
-
for (const arg of subargs) {
|
|
77
|
-
if (arg.startsWith("-") && !allowed.includes(arg)) {
|
|
78
|
-
console.error(`Unknown flag: ${arg}`);
|
|
79
|
-
process.exit(1);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// ─── version subcommand ──────────────────────────────────────────────────────
|
|
84
|
-
|
|
85
|
-
if (subcommand === "version") {
|
|
86
|
-
const pkg = require(resolve(ROOT, "package.json"));
|
|
87
|
-
console.log(`specrails-core v${pkg.version}`);
|
|
88
|
-
process.exit(0);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// ─── profile subcommand ──────────────────────────────────────────────────────
|
|
92
|
-
// `specrails-core profile validate [path]` — validate a profile JSON against v1 schema
|
|
93
|
-
// `specrails-core profile show [path]` — pretty-print the resolved profile
|
|
94
|
-
// Resolution order when no path: $SPECRAILS_PROFILE_PATH → .specrails/profiles/project-default.json
|
|
95
|
-
|
|
96
|
-
if (subcommand === "profile") {
|
|
97
|
-
const { existsSync, readFileSync } = require("fs");
|
|
98
|
-
const action = subargs[0];
|
|
99
|
-
const pathArg = subargs[1];
|
|
100
|
-
|
|
101
|
-
if (!action || (action !== "validate" && action !== "show")) {
|
|
102
|
-
console.error("Usage: specrails-core profile validate [<path>]");
|
|
103
|
-
console.error(" specrails-core profile show [<path>]");
|
|
104
|
-
process.exit(1);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const resolveProfilePath = () => {
|
|
108
|
-
if (pathArg) return resolve(pathArg);
|
|
109
|
-
if (process.env.SPECRAILS_PROFILE_PATH) return resolve(process.env.SPECRAILS_PROFILE_PATH);
|
|
110
|
-
const projectDefault = resolve(process.cwd(), ".specrails/profiles/project-default.json");
|
|
111
|
-
if (existsSync(projectDefault)) return projectDefault;
|
|
112
|
-
return null;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const profilePath = resolveProfilePath();
|
|
116
|
-
if (!profilePath) {
|
|
117
|
-
console.error("No profile path given and none could be resolved.");
|
|
118
|
-
console.error("Pass an explicit path or set SPECRAILS_PROFILE_PATH, or place a profile at");
|
|
119
|
-
console.error(" .specrails/profiles/project-default.json");
|
|
120
|
-
process.exit(1);
|
|
121
|
-
}
|
|
122
|
-
if (!existsSync(profilePath)) {
|
|
123
|
-
console.error(`Profile file not found: ${profilePath}`);
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
let profile;
|
|
128
|
-
try {
|
|
129
|
-
profile = JSON.parse(readFileSync(profilePath, "utf8"));
|
|
130
|
-
} catch (e) {
|
|
131
|
-
console.error(`Profile is not valid JSON: ${e.message}`);
|
|
132
|
-
process.exit(1);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (action === "show") {
|
|
136
|
-
console.log(JSON.stringify(profile, null, 2));
|
|
137
|
-
process.exit(0);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// action === "validate"
|
|
141
|
-
const schemaPath = resolve(ROOT, "schemas/profile.v1.json");
|
|
142
|
-
if (!existsSync(schemaPath)) {
|
|
143
|
-
console.error(`Schema not found at ${schemaPath} — install may be corrupt`);
|
|
144
|
-
process.exit(1);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
let Ajv;
|
|
148
|
-
try {
|
|
149
|
-
Ajv = require("ajv/dist/2020.js").default;
|
|
150
|
-
} catch {
|
|
151
|
-
console.error("'ajv' is not installed. Run `npm install` in the specrails-core package directory first,");
|
|
152
|
-
console.error("or rely on the hub's own validator for user-facing flows.");
|
|
153
|
-
process.exit(1);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const schema = JSON.parse(readFileSync(schemaPath, "utf8"));
|
|
157
|
-
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
158
|
-
const validate = ajv.compile(schema);
|
|
159
|
-
|
|
160
|
-
if (validate(profile)) {
|
|
161
|
-
console.log(`✓ ${profilePath} is a valid v1 profile.`);
|
|
162
|
-
process.exit(0);
|
|
163
|
-
} else {
|
|
164
|
-
console.error(`✗ ${profilePath} failed validation:`);
|
|
165
|
-
for (const err of validate.errors || []) {
|
|
166
|
-
console.error(` ${err.instancePath || "/"} ${err.message} (${JSON.stringify(err.params)})`);
|
|
167
|
-
}
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// ─── enrich subcommand ───────────────────────────────────────────────────────
|
|
173
|
-
// Launches `claude --command "/specrails:enrich [flags]"` so the AI-powered
|
|
174
|
-
// enrichment runs inside Claude Code with full model access.
|
|
175
|
-
|
|
176
|
-
if (subcommand === "enrich") {
|
|
177
|
-
const enrichFlags = subargs.join(" ");
|
|
178
|
-
const claudeCmd = `/specrails:enrich${enrichFlags ? " " + enrichFlags : ""}`;
|
|
179
|
-
const claudeResult = spawnSync("claude", ["--command", claudeCmd, "--dangerously-skip-permissions"], {
|
|
180
|
-
stdio: "inherit",
|
|
181
|
-
cwd: process.cwd(),
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
if (claudeResult.error) {
|
|
185
|
-
console.error(
|
|
186
|
-
"\nFailed to launch Claude CLI for enrich:",
|
|
187
|
-
claudeResult.error.message,
|
|
188
|
-
"\nEnsure Claude Code is installed: npm install -g @anthropic-ai/claude-code\n"
|
|
189
|
-
);
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
process.exit(claudeResult.status ?? (claudeResult.error ? 1 : 0));
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// ─── Direct mode (TUI) for `init` ─────────────────────────────────────────────
|
|
197
|
-
//
|
|
198
|
-
// Default behaviour: run the Node.js TUI to collect agent/model configuration,
|
|
199
|
-
// write .specrails/install-config.yaml, then hand off to install.sh.
|
|
200
|
-
//
|
|
201
|
-
// Opt-out with: --no-direct (legacy interactive bash installer)
|
|
202
|
-
// --from-config (config already on disk; skip TUI)
|
|
203
|
-
// --yes / -y (write default config, no prompts)
|
|
204
|
-
|
|
205
|
-
const isInit = subcommand === "init";
|
|
206
|
-
const hasNoTui = subargs.includes("--no-direct") || subargs.includes("--from-config");
|
|
207
|
-
const autoYes = subargs.includes("--yes") || subargs.includes("-y");
|
|
208
|
-
const useTui = isInit && !hasNoTui;
|
|
209
|
-
|
|
210
|
-
if (useTui) {
|
|
211
|
-
// Resolve the target directory for the TUI
|
|
212
|
-
const rootDirIdx = subargs.indexOf("--root-dir");
|
|
213
|
-
const rootDir = rootDirIdx >= 0 ? resolve(subargs[rootDirIdx + 1]) : process.cwd();
|
|
214
|
-
|
|
215
|
-
// Build TUI args: pass rootDir + --yes if set
|
|
216
|
-
const tuiArgs = [resolve(ROOT, "bin/tui-installer.mjs"), rootDir];
|
|
217
|
-
if (autoYes) tuiArgs.push("--yes");
|
|
218
|
-
|
|
219
|
-
const tuiResult = spawnSync("node", tuiArgs, {
|
|
220
|
-
stdio: "inherit",
|
|
221
|
-
cwd: process.cwd(),
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
if (tuiResult.error) {
|
|
225
|
-
// @inquirer/prompts not installed (e.g. during development without npm install)
|
|
226
|
-
console.error(
|
|
227
|
-
"\nFailed to launch TUI installer:",
|
|
228
|
-
tuiResult.error.message,
|
|
229
|
-
"\nRun: npm install or use --no-direct for the legacy installer.\n"
|
|
230
|
-
);
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (tuiResult.status !== 0) {
|
|
235
|
-
process.exit(tuiResult.status ?? 1);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// TUI succeeded — run install.sh with --from-config so it reads provider/
|
|
239
|
-
// agent_teams from install-config.yaml rather than prompting interactively.
|
|
240
|
-
const installArgs = subargs
|
|
241
|
-
.filter(a => a !== "--no-direct") // strip internal flags
|
|
242
|
-
.concat(["--yes", "--from-config"]);
|
|
243
|
-
|
|
244
|
-
const result = spawnSync("bash", [resolve(ROOT, script), ...installArgs], {
|
|
245
|
-
stdio: "inherit",
|
|
246
|
-
cwd: process.cwd(),
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
process.exit(result.status ?? (result.error ? 1 : 0));
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// ─── Legacy / non-TUI path ────────────────────────────────────────────────────
|
|
253
|
-
|
|
254
|
-
// Strip only --no-direct (internal flag) before passing args to the shell script
|
|
255
|
-
const cleanArgs = subargs.filter(a => a !== "--no-direct");
|
|
256
|
-
|
|
257
|
-
const result = spawnSync("bash", [resolve(ROOT, script), ...cleanArgs], {
|
|
258
|
-
stdio: "inherit",
|
|
259
|
-
cwd: process.cwd(),
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
process.exit(result.status ?? (result.error ? 1 : 0));
|