monomind 1.10.18 → 1.10.20
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/package.json +3 -1
- package/packages/@monomind/cli/package.json +1 -1
- package/packages/@monomind/cli/scripts/understand-analyze.mjs +68 -10
- package/scripts/install.sh +392 -0
- package/scripts/ua-enrich.mjs +228 -0
- package/scripts/ua-import.mjs +288 -0
- package/scripts/verify-appliance.sh +592 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "monomind",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.20",
|
|
4
4
|
"description": "Monomind - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
"packages/@monomind/cli/scripts/**/*.js",
|
|
28
28
|
"packages/@monomind/cli/scripts/**/*.sh",
|
|
29
29
|
"packages/@monomind/cli/package.json",
|
|
30
|
+
"scripts/*.mjs",
|
|
31
|
+
"scripts/*.sh",
|
|
30
32
|
"packages/@monomind/shared/dist/**/*.js",
|
|
31
33
|
"packages/@monomind/shared/dist/**/*.d.ts",
|
|
32
34
|
"!packages/@monomind/shared/dist/**/*.map",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monoes/monomindcli",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Monomind CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -30,7 +30,7 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
|
30
30
|
import { resolve, join, dirname, basename, relative } from 'node:path';
|
|
31
31
|
import { createRequire } from 'node:module';
|
|
32
32
|
import { fileURLToPath } from 'node:url';
|
|
33
|
-
import { execFileSync } from 'node:child_process';
|
|
33
|
+
import { execFileSync, execSync, spawn } from 'node:child_process';
|
|
34
34
|
|
|
35
35
|
const __dir = dirname(fileURLToPath(import.meta.url));
|
|
36
36
|
const CWD = process.cwd();
|
|
@@ -128,12 +128,60 @@ function detectLayersHeuristic(fileNodes) {
|
|
|
128
128
|
return layers;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
// ── Anthropic API helpers
|
|
131
|
+
// ── Anthropic API helpers ─────────────────────────────────────────────────────
|
|
132
|
+
// Two paths:
|
|
133
|
+
// 1. Direct API via ANTHROPIC_API_KEY (fastest, parallel-safe, requires key)
|
|
134
|
+
// 2. `claude -p` CLI passthrough (reuses Claude Code's auth — no key needed)
|
|
135
|
+
// Slower (CLI cold-start per call), but works inside any Claude Code
|
|
136
|
+
// session without extra setup.
|
|
132
137
|
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
|
|
133
138
|
const ANTHROPIC_URL = 'https://api.anthropic.com/v1/messages';
|
|
134
139
|
const MODEL = 'claude-haiku-4-5-20251001'; // cheapest for bulk analysis
|
|
135
140
|
|
|
136
|
-
|
|
141
|
+
// Detect `claude` CLI once at startup.
|
|
142
|
+
let _claudeCliPath = null;
|
|
143
|
+
function _detectClaudeCli() {
|
|
144
|
+
if (_claudeCliPath !== null) return _claudeCliPath;
|
|
145
|
+
try {
|
|
146
|
+
const out = execSync('command -v claude 2>/dev/null', { encoding: 'utf-8' }).trim();
|
|
147
|
+
_claudeCliPath = out || '';
|
|
148
|
+
} catch { _claudeCliPath = ''; }
|
|
149
|
+
return _claudeCliPath;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const USE_CLAUDE_CLI = !ANTHROPIC_API_KEY && !!_detectClaudeCli();
|
|
153
|
+
|
|
154
|
+
async function callClaudeViaCli(systemPrompt, userPrompt, maxTokens = 1024) {
|
|
155
|
+
return new Promise((resolveP, reject) => {
|
|
156
|
+
const args = [
|
|
157
|
+
'-p',
|
|
158
|
+
'--model', 'haiku',
|
|
159
|
+
'--output-format', 'text',
|
|
160
|
+
'--bare', // skip hooks/skills/auto-memory — we want a fast, clean call
|
|
161
|
+
// Combine system + user into a single prompt argument
|
|
162
|
+
`${systemPrompt}\n\n---\n\n${userPrompt}`,
|
|
163
|
+
];
|
|
164
|
+
const child = spawn(_claudeCliPath, args, {
|
|
165
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
166
|
+
env: { ...process.env },
|
|
167
|
+
});
|
|
168
|
+
let out = '', err = '';
|
|
169
|
+
child.stdout.on('data', d => out += d.toString());
|
|
170
|
+
child.stderr.on('data', d => err += d.toString());
|
|
171
|
+
const timeout = setTimeout(() => {
|
|
172
|
+
child.kill('SIGKILL');
|
|
173
|
+
reject(new Error('claude -p timed out after 60s'));
|
|
174
|
+
}, 60000);
|
|
175
|
+
child.on('close', code => {
|
|
176
|
+
clearTimeout(timeout);
|
|
177
|
+
if (code !== 0) return reject(new Error(`claude -p exited ${code}: ${err.slice(0, 200)}`));
|
|
178
|
+
resolveP(out.trim());
|
|
179
|
+
});
|
|
180
|
+
child.on('error', e => { clearTimeout(timeout); reject(e); });
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function callClaudeViaApi(systemPrompt, userPrompt, maxTokens = 1024) {
|
|
137
185
|
const body = JSON.stringify({
|
|
138
186
|
model: MODEL,
|
|
139
187
|
max_tokens: maxTokens,
|
|
@@ -153,7 +201,6 @@ async function callClaude(systemPrompt, userPrompt, maxTokens = 1024) {
|
|
|
153
201
|
const data = await resp.json();
|
|
154
202
|
return data.content?.[0]?.text ?? '';
|
|
155
203
|
}
|
|
156
|
-
// Retry on 429 (rate limit) and 5xx; fail fast on 4xx
|
|
157
204
|
if (resp.status === 429 || resp.status >= 500) {
|
|
158
205
|
const retryAfter = parseInt(resp.headers.get('retry-after') || '0', 10);
|
|
159
206
|
const backoff = retryAfter > 0 ? retryAfter * 1000 : Math.min(2 ** attempt * 1000, 8000);
|
|
@@ -172,6 +219,16 @@ async function callClaude(systemPrompt, userPrompt, maxTokens = 1024) {
|
|
|
172
219
|
throw lastError || new Error('Anthropic API failed after 3 attempts');
|
|
173
220
|
}
|
|
174
221
|
|
|
222
|
+
async function callClaude(systemPrompt, userPrompt, maxTokens = 1024) {
|
|
223
|
+
if (ANTHROPIC_API_KEY) {
|
|
224
|
+
return callClaudeViaApi(systemPrompt, userPrompt, maxTokens);
|
|
225
|
+
}
|
|
226
|
+
if (USE_CLAUDE_CLI) {
|
|
227
|
+
return callClaudeViaCli(systemPrompt, userPrompt, maxTokens);
|
|
228
|
+
}
|
|
229
|
+
throw new Error('No LLM path available: set ANTHROPIC_API_KEY or install `claude` CLI');
|
|
230
|
+
}
|
|
231
|
+
|
|
175
232
|
function parseJson(text) {
|
|
176
233
|
try {
|
|
177
234
|
const fenceMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
|
|
@@ -640,12 +697,13 @@ async function main() {
|
|
|
640
697
|
const batch = toAnalyze.slice(0, limit);
|
|
641
698
|
console.log(`[understand] Analyzing ${batch.length} files (${toAnalyze.length - batch.length} skipped/already enriched)`);
|
|
642
699
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
700
|
+
const llmPath = ANTHROPIC_API_KEY ? 'api' : (USE_CLAUDE_CLI ? 'claude-cli' : 'none');
|
|
701
|
+
if (llmPath === 'none' && !noLlm) {
|
|
702
|
+
console.warn('[understand] No LLM path available (no ANTHROPIC_API_KEY and no `claude` CLI) — falling back to --no-llm heuristic mode');
|
|
703
|
+
} else if (llmPath === 'claude-cli' && !noLlm) {
|
|
704
|
+
console.log('[understand] Using `claude -p` CLI passthrough (no API key needed; reusing Claude Code auth)');
|
|
646
705
|
}
|
|
647
|
-
|
|
648
|
-
const useLlm = !noLlm && !!ANTHROPIC_API_KEY;
|
|
706
|
+
const useLlm = !noLlm && llmPath !== 'none';
|
|
649
707
|
|
|
650
708
|
// ── Get project context for better prompts ────────────────────────────────
|
|
651
709
|
let projectContext = `Project directory: ${basename(projectDir)}`;
|
|
@@ -798,7 +856,7 @@ async function main() {
|
|
|
798
856
|
async function detectAndWriteLayers(db, fileNodes, forceHeuristic, dryRun, dir) {
|
|
799
857
|
let layers;
|
|
800
858
|
|
|
801
|
-
if (!forceHeuristic && ANTHROPIC_API_KEY) {
|
|
859
|
+
if (!forceHeuristic && (ANTHROPIC_API_KEY || USE_CLAUDE_CLI)) {
|
|
802
860
|
console.log('[understand] Detecting architectural layers via LLM...');
|
|
803
861
|
const filePaths = fileNodes.map(n => n.file_path).filter(Boolean);
|
|
804
862
|
try {
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Monomind Installer (formerly Monomind)
|
|
4
|
+
# https://github.com/nokhodian/monomind
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# curl -fsSL https://cdn.jsdelivr.net/gh/nokhodian/monomind@main/scripts/install.sh | bash
|
|
8
|
+
# curl -fsSL https://cdn.jsdelivr.net/gh/nokhodian/monomind@main/scripts/install.sh | bash -s -- --full
|
|
9
|
+
# curl -fsSL https://cdn.jsdelivr.net/gh/nokhodian/monomind@main/scripts/install.sh | bash -s -- --global
|
|
10
|
+
# curl -fsSL https://cdn.jsdelivr.net/gh/nokhodian/monomind@main/scripts/install.sh | bash -s -- --minimal
|
|
11
|
+
#
|
|
12
|
+
# Options (via arguments):
|
|
13
|
+
# --global Global install (npm install -g)
|
|
14
|
+
# --minimal Minimal install (no optional deps)
|
|
15
|
+
# --full Full setup (global + MCP + doctor + init)
|
|
16
|
+
# --version=X.X.X Specific version
|
|
17
|
+
#
|
|
18
|
+
# Options (via environment - requires export):
|
|
19
|
+
# export MONOMIND_VERSION=alpha
|
|
20
|
+
# export MONOMIND_MINIMAL=1
|
|
21
|
+
# export MONOMIND_GLOBAL=1
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
set -euo pipefail
|
|
25
|
+
|
|
26
|
+
# Colors
|
|
27
|
+
RED='\033[0;31m'
|
|
28
|
+
GREEN='\033[0;32m'
|
|
29
|
+
YELLOW='\033[1;33m'
|
|
30
|
+
BLUE='\033[0;34m'
|
|
31
|
+
CYAN='\033[0;36m'
|
|
32
|
+
BOLD='\033[1m'
|
|
33
|
+
DIM='\033[2m'
|
|
34
|
+
NC='\033[0m' # No Color
|
|
35
|
+
|
|
36
|
+
# Default configuration (can be overridden by env vars)
|
|
37
|
+
VERSION="${MONOMIND_VERSION:-${MONOMIND_VERSION:-latest}}"
|
|
38
|
+
MINIMAL="${MONOMIND_MINIMAL:-0}"
|
|
39
|
+
GLOBAL="${MONOMIND_GLOBAL:-0}"
|
|
40
|
+
SETUP_MCP="${MONOMIND_SETUP_MCP:-0}"
|
|
41
|
+
RUN_DOCTOR="${MONOMIND_DOCTOR:-0}"
|
|
42
|
+
RUN_INIT="${MONOMIND_INIT:-1}"
|
|
43
|
+
|
|
44
|
+
# Parse command line arguments
|
|
45
|
+
while [[ $# -gt 0 ]]; do
|
|
46
|
+
case $1 in
|
|
47
|
+
--global|-g)
|
|
48
|
+
GLOBAL="1"
|
|
49
|
+
shift
|
|
50
|
+
;;
|
|
51
|
+
--minimal|-m)
|
|
52
|
+
MINIMAL="1"
|
|
53
|
+
shift
|
|
54
|
+
;;
|
|
55
|
+
--setup-mcp|--mcp)
|
|
56
|
+
SETUP_MCP="1"
|
|
57
|
+
shift
|
|
58
|
+
;;
|
|
59
|
+
--doctor|-d)
|
|
60
|
+
RUN_DOCTOR="1"
|
|
61
|
+
shift
|
|
62
|
+
;;
|
|
63
|
+
--init|-i)
|
|
64
|
+
RUN_INIT="1"
|
|
65
|
+
shift
|
|
66
|
+
;;
|
|
67
|
+
--no-init)
|
|
68
|
+
RUN_INIT="0"
|
|
69
|
+
shift
|
|
70
|
+
;;
|
|
71
|
+
--full|-f)
|
|
72
|
+
GLOBAL="1"
|
|
73
|
+
SETUP_MCP="1"
|
|
74
|
+
RUN_DOCTOR="1"
|
|
75
|
+
RUN_INIT="1"
|
|
76
|
+
shift
|
|
77
|
+
;;
|
|
78
|
+
--version=*)
|
|
79
|
+
VERSION="${1#*=}"
|
|
80
|
+
shift
|
|
81
|
+
;;
|
|
82
|
+
--help|-h)
|
|
83
|
+
echo "Monomind Installer"
|
|
84
|
+
echo ""
|
|
85
|
+
echo "Usage: curl -fsSL .../install.sh | bash -s -- [OPTIONS]"
|
|
86
|
+
echo ""
|
|
87
|
+
echo "Options:"
|
|
88
|
+
echo " --global, -g Install globally (npm install -g monomind)"
|
|
89
|
+
echo " --minimal, -m Minimal install (skip optional deps)"
|
|
90
|
+
echo " --setup-mcp Auto-configure MCP server for Claude Code"
|
|
91
|
+
echo " --doctor, -d Run diagnostics after install"
|
|
92
|
+
echo " --no-init Skip project initialization (enabled by default)"
|
|
93
|
+
echo " --full, -f Full setup (global + mcp + doctor + init)"
|
|
94
|
+
echo " --version=X.X.X Install specific version (default: alpha)"
|
|
95
|
+
echo " --help, -h Show this help"
|
|
96
|
+
exit 0
|
|
97
|
+
;;
|
|
98
|
+
*)
|
|
99
|
+
shift
|
|
100
|
+
;;
|
|
101
|
+
esac
|
|
102
|
+
done
|
|
103
|
+
|
|
104
|
+
PACKAGE="monomind@${VERSION}"
|
|
105
|
+
|
|
106
|
+
# Progress animation
|
|
107
|
+
SPINNER_CHARS="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
|
|
108
|
+
SPINNER_INDEX=0
|
|
109
|
+
|
|
110
|
+
spinner() {
|
|
111
|
+
printf "\r${CYAN}${SPINNER_CHARS:SPINNER_INDEX++:1}${NC} $1"
|
|
112
|
+
SPINNER_INDEX=$((SPINNER_INDEX % 10))
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
print_banner() {
|
|
116
|
+
echo ""
|
|
117
|
+
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════╗${NC}"
|
|
118
|
+
echo -e "${CYAN}║${NC} ${BOLD}Monomind${NC} — AI Agent Orchestration for Claude Code ${CYAN}║${NC}"
|
|
119
|
+
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════╝${NC}"
|
|
120
|
+
echo ""
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
print_step() {
|
|
124
|
+
echo -e "${GREEN}▸${NC} $1"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
print_substep() {
|
|
128
|
+
echo -e " ${DIM}├─${NC} $1"
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
print_success() {
|
|
132
|
+
echo -e "${GREEN}✓${NC} $1"
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
print_warning() {
|
|
136
|
+
echo -e "${YELLOW}⚠${NC} $1"
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
print_error() {
|
|
140
|
+
echo -e "${RED}✗${NC} $1"
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
print_info() {
|
|
144
|
+
echo -e "${BLUE}ℹ${NC} $1"
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
check_requirements() {
|
|
148
|
+
print_step "Checking requirements..."
|
|
149
|
+
|
|
150
|
+
# Check Node.js
|
|
151
|
+
if command -v node &> /dev/null; then
|
|
152
|
+
NODE_VERSION=$(node -v | sed 's/v//')
|
|
153
|
+
NODE_MAJOR=$(echo "$NODE_VERSION" | cut -d. -f1)
|
|
154
|
+
if [ "$NODE_MAJOR" -ge 20 ]; then
|
|
155
|
+
print_substep "Node.js ${GREEN}v${NODE_VERSION}${NC} ✓"
|
|
156
|
+
else
|
|
157
|
+
print_error "Node.js 20+ required (found v${NODE_VERSION})"
|
|
158
|
+
echo ""
|
|
159
|
+
echo "Install Node.js 20+:"
|
|
160
|
+
echo " curl -fsSL https://fnm.vercel.app/install | bash"
|
|
161
|
+
echo " fnm install 20"
|
|
162
|
+
exit 1
|
|
163
|
+
fi
|
|
164
|
+
else
|
|
165
|
+
print_error "Node.js not found"
|
|
166
|
+
echo ""
|
|
167
|
+
echo "Install Node.js 20+:"
|
|
168
|
+
echo " curl -fsSL https://fnm.vercel.app/install | bash"
|
|
169
|
+
echo " fnm install 20"
|
|
170
|
+
exit 1
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
# Check npm
|
|
174
|
+
if command -v npm &> /dev/null; then
|
|
175
|
+
NPM_VERSION=$(npm -v)
|
|
176
|
+
print_substep "npm ${GREEN}v${NPM_VERSION}${NC} ✓"
|
|
177
|
+
else
|
|
178
|
+
print_error "npm not found"
|
|
179
|
+
exit 1
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
# Check Claude Code CLI
|
|
183
|
+
if command -v claude &> /dev/null; then
|
|
184
|
+
CLAUDE_VERSION=$(claude --version 2>/dev/null | head -1 || echo "installed")
|
|
185
|
+
print_substep "Claude Code ${GREEN}${CLAUDE_VERSION}${NC} ✓"
|
|
186
|
+
else
|
|
187
|
+
print_warning "Claude Code CLI not found"
|
|
188
|
+
print_substep "Installing Claude Code CLI via npm..."
|
|
189
|
+
if npm install -g @anthropic-ai/claude-code 2>/dev/null; then
|
|
190
|
+
if command -v claude &> /dev/null; then
|
|
191
|
+
CLAUDE_VERSION=$(claude --version 2>/dev/null | head -1 || echo "installed")
|
|
192
|
+
print_substep "Claude Code ${GREEN}${CLAUDE_VERSION}${NC} ✓"
|
|
193
|
+
else
|
|
194
|
+
print_substep "Installed. Restart terminal to use 'claude' command"
|
|
195
|
+
fi
|
|
196
|
+
else
|
|
197
|
+
print_warning "npm install failed. Try manually:"
|
|
198
|
+
print_substep "${BOLD}npm install -g @anthropic-ai/claude-code${NC}"
|
|
199
|
+
fi
|
|
200
|
+
fi
|
|
201
|
+
|
|
202
|
+
echo ""
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
show_install_options() {
|
|
206
|
+
print_step "Installation options:"
|
|
207
|
+
print_substep "Package: ${BOLD}${PACKAGE}${NC}"
|
|
208
|
+
if [ "$GLOBAL" = "1" ]; then
|
|
209
|
+
print_substep "Mode: ${BOLD}Global${NC} (npm install -g)"
|
|
210
|
+
else
|
|
211
|
+
print_substep "Mode: ${BOLD}npx${NC} (on-demand)"
|
|
212
|
+
fi
|
|
213
|
+
if [ "$MINIMAL" = "1" ]; then
|
|
214
|
+
print_substep "Profile: ${BOLD}Minimal${NC} (--omit=optional)"
|
|
215
|
+
else
|
|
216
|
+
print_substep "Profile: ${BOLD}Full${NC} (all features)"
|
|
217
|
+
fi
|
|
218
|
+
echo ""
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
install_package() {
|
|
222
|
+
local START_TIME=$(date +%s)
|
|
223
|
+
|
|
224
|
+
if [ "$GLOBAL" = "1" ]; then
|
|
225
|
+
print_step "Installing globally..."
|
|
226
|
+
|
|
227
|
+
if [ "$MINIMAL" = "1" ]; then
|
|
228
|
+
npm install -g "$PACKAGE" --omit=optional 2>&1 | while read -r line; do
|
|
229
|
+
if [[ "$line" == *"added"* ]]; then
|
|
230
|
+
print_substep "$line"
|
|
231
|
+
fi
|
|
232
|
+
done
|
|
233
|
+
else
|
|
234
|
+
npm install -g "$PACKAGE" 2>&1 | while read -r line; do
|
|
235
|
+
if [[ "$line" == *"added"* ]]; then
|
|
236
|
+
print_substep "$line"
|
|
237
|
+
fi
|
|
238
|
+
done
|
|
239
|
+
fi
|
|
240
|
+
else
|
|
241
|
+
print_step "Installing for npx usage..."
|
|
242
|
+
# Actually run npx to pre-install the package
|
|
243
|
+
npx -y "$PACKAGE" --version >/dev/null 2>&1 || true
|
|
244
|
+
print_substep "Package installed for npx"
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
local END_TIME=$(date +%s)
|
|
248
|
+
local DURATION=$((END_TIME - START_TIME))
|
|
249
|
+
|
|
250
|
+
echo ""
|
|
251
|
+
print_success "Installed in ${BOLD}${DURATION}s${NC}"
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
verify_installation() {
|
|
255
|
+
print_step "Verifying installation..."
|
|
256
|
+
|
|
257
|
+
local VERSION_OUTPUT
|
|
258
|
+
if [ "$GLOBAL" = "1" ]; then
|
|
259
|
+
VERSION_OUTPUT=$(monomind --version 2>/dev/null || monomind --version 2>/dev/null || echo "")
|
|
260
|
+
if [ -z "$VERSION_OUTPUT" ]; then
|
|
261
|
+
print_warning "Global command not found in PATH"
|
|
262
|
+
print_substep "Try: ${BOLD}npm install -g monomind@${VERSION}${NC}"
|
|
263
|
+
return 0 # Don't fail - npm might need PATH refresh
|
|
264
|
+
fi
|
|
265
|
+
else
|
|
266
|
+
# For npx mode, package was already installed during install_package
|
|
267
|
+
VERSION_OUTPUT=$(npx "$PACKAGE" --version 2>/dev/null || echo "")
|
|
268
|
+
fi
|
|
269
|
+
|
|
270
|
+
if [ -n "$VERSION_OUTPUT" ]; then
|
|
271
|
+
print_substep "Version: ${GREEN}${VERSION_OUTPUT}${NC}"
|
|
272
|
+
echo ""
|
|
273
|
+
return 0
|
|
274
|
+
else
|
|
275
|
+
print_error "Installation verification failed"
|
|
276
|
+
return 1
|
|
277
|
+
fi
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
show_quickstart() {
|
|
281
|
+
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════╗${NC}"
|
|
282
|
+
echo -e "${CYAN}║${NC} ${BOLD}Quick Start${NC} ${CYAN}║${NC}"
|
|
283
|
+
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════╝${NC}"
|
|
284
|
+
echo ""
|
|
285
|
+
|
|
286
|
+
if [ "$GLOBAL" = "1" ]; then
|
|
287
|
+
echo -e " ${DIM}# Initialize project${NC}"
|
|
288
|
+
echo -e " ${BOLD}monomind init --wizard${NC}"
|
|
289
|
+
echo ""
|
|
290
|
+
echo -e " ${DIM}# Run system diagnostics${NC}"
|
|
291
|
+
echo -e " ${BOLD}monomind doctor${NC}"
|
|
292
|
+
echo ""
|
|
293
|
+
echo -e " ${DIM}# Add as MCP server to Claude Code${NC}"
|
|
294
|
+
echo -e " ${BOLD}claude mcp add monomind -- monomind mcp start${NC}"
|
|
295
|
+
else
|
|
296
|
+
echo -e " ${DIM}# Initialize project${NC}"
|
|
297
|
+
echo -e " ${BOLD}npx monomind@latest init --wizard${NC}"
|
|
298
|
+
echo ""
|
|
299
|
+
echo -e " ${DIM}# Run system diagnostics${NC}"
|
|
300
|
+
echo -e " ${BOLD}npx monomind@latest doctor${NC}"
|
|
301
|
+
echo ""
|
|
302
|
+
echo -e " ${DIM}# Add as MCP server to Claude Code${NC}"
|
|
303
|
+
echo -e " ${BOLD}claude mcp add monomind -- npx -y monomind@latest mcp start${NC}"
|
|
304
|
+
fi
|
|
305
|
+
|
|
306
|
+
echo ""
|
|
307
|
+
echo -e "${DIM}Documentation: https://github.com/nokhodian/monomind${NC}"
|
|
308
|
+
echo -e "${DIM}Issues: https://github.com/nokhodian/monomind/issues${NC}"
|
|
309
|
+
echo ""
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
setup_mcp_server() {
|
|
313
|
+
if [ "$SETUP_MCP" != "1" ]; then
|
|
314
|
+
return 0
|
|
315
|
+
fi
|
|
316
|
+
|
|
317
|
+
print_step "Setting up MCP server..."
|
|
318
|
+
|
|
319
|
+
if ! command -v claude &> /dev/null; then
|
|
320
|
+
print_warning "Claude CLI not found, skipping MCP setup"
|
|
321
|
+
return 0
|
|
322
|
+
fi
|
|
323
|
+
|
|
324
|
+
# Check if already configured
|
|
325
|
+
if claude mcp list 2>/dev/null | grep -q "monomind\|monomind"; then
|
|
326
|
+
print_substep "MCP server already configured ✓"
|
|
327
|
+
return 0
|
|
328
|
+
fi
|
|
329
|
+
|
|
330
|
+
# Add MCP server (pass MONOMIND_CWD so tools resolve paths correctly
|
|
331
|
+
# even when the MCP server is spawned with cwd='/')
|
|
332
|
+
if [ "$GLOBAL" = "1" ]; then
|
|
333
|
+
claude mcp add monomind -e MONOMIND_CWD="$HOME" -- monomind mcp start 2>/dev/null && \
|
|
334
|
+
print_substep "MCP server configured ✓" || \
|
|
335
|
+
print_warning "MCP setup failed - run manually: claude mcp add monomind -e MONOMIND_CWD=\"\$HOME\" -- monomind mcp start"
|
|
336
|
+
else
|
|
337
|
+
claude mcp add monomind -e MONOMIND_CWD="$HOME" -- npx -y monomind@${VERSION} mcp start 2>/dev/null && \
|
|
338
|
+
print_substep "MCP server configured ✓" || \
|
|
339
|
+
print_warning "MCP setup failed - run manually: claude mcp add monomind -e MONOMIND_CWD=\"\$HOME\" -- npx -y monomind@latest mcp start"
|
|
340
|
+
fi
|
|
341
|
+
echo ""
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
run_doctor() {
|
|
345
|
+
if [ "$RUN_DOCTOR" != "1" ]; then
|
|
346
|
+
return 0
|
|
347
|
+
fi
|
|
348
|
+
|
|
349
|
+
print_step "Running diagnostics..."
|
|
350
|
+
echo ""
|
|
351
|
+
|
|
352
|
+
if [ "$GLOBAL" = "1" ]; then
|
|
353
|
+
monomind doctor 2>&1 || true
|
|
354
|
+
else
|
|
355
|
+
npx monomind@${VERSION} doctor 2>&1 || true
|
|
356
|
+
fi
|
|
357
|
+
echo ""
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
run_init() {
|
|
361
|
+
if [ "$RUN_INIT" != "1" ]; then
|
|
362
|
+
return 0
|
|
363
|
+
fi
|
|
364
|
+
|
|
365
|
+
print_step "Initializing project..."
|
|
366
|
+
echo ""
|
|
367
|
+
|
|
368
|
+
if [ "$GLOBAL" = "1" ]; then
|
|
369
|
+
monomind init --yes 2>&1 || true
|
|
370
|
+
else
|
|
371
|
+
npx monomind@${VERSION} init --yes 2>&1 || true
|
|
372
|
+
fi
|
|
373
|
+
echo ""
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
# Main
|
|
377
|
+
main() {
|
|
378
|
+
print_banner
|
|
379
|
+
check_requirements
|
|
380
|
+
show_install_options
|
|
381
|
+
install_package
|
|
382
|
+
verify_installation
|
|
383
|
+
setup_mcp_server
|
|
384
|
+
run_doctor
|
|
385
|
+
run_init
|
|
386
|
+
show_quickstart
|
|
387
|
+
|
|
388
|
+
print_success "${BOLD}Monomind is ready!${NC}"
|
|
389
|
+
echo ""
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
main "$@"
|