loki-mode 6.30.2 → 6.31.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 +1 -1
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/loki +544 -0
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/web-app/dist/assets/index-Bxk-CzWn.js +65 -0
- package/web-app/dist/index.html +1 -1
- package/web-app/dist/assets/index-BTtIHGw7.js +0 -65
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
[](https://www.autonomi.dev/)
|
|
11
11
|
[](https://hub.docker.com/r/asklokesh/loki-mode)
|
|
12
12
|
|
|
13
|
-
**Current Version: v6.
|
|
13
|
+
**Current Version: v6.31.0**
|
|
14
14
|
|
|
15
15
|
### Traction
|
|
16
16
|
|
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes PRD to deployed product with minimal human intervention. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v6.
|
|
6
|
+
# Loki Mode v6.31.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -267,4 +267,4 @@ The following features are documented in skill modules but not yet fully automat
|
|
|
267
267
|
| Quality gates 3-reviewer system | Implemented (v5.35.0) | 5 specialist reviewers in `skills/quality-gates.md`; execution in run.sh |
|
|
268
268
|
| Benchmarks (HumanEval, SWE-bench) | Infrastructure only | Runner scripts and datasets exist in `benchmarks/`; no published results |
|
|
269
269
|
|
|
270
|
-
**v6.
|
|
270
|
+
**v6.31.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
6.
|
|
1
|
+
6.31.0
|
package/autonomy/loki
CHANGED
|
@@ -438,6 +438,7 @@ show_help() {
|
|
|
438
438
|
echo " trigger Event-driven autonomous execution (schedules, webhooks)"
|
|
439
439
|
echo " failover [cmd] Cross-provider auto-failover (status|--enable|--test|--chain)"
|
|
440
440
|
echo " onboard [path] Analyze a repo and generate CLAUDE.md (structure, conventions, commands)"
|
|
441
|
+
echo ' explain [path] Analyze any codebase and explain its architecture in plain English'
|
|
441
442
|
echo " plan <PRD> Dry-run PRD analysis: complexity, cost, and execution plan"
|
|
442
443
|
echo " ci [opts] CI/CD quality gate integration (--pr, --report, --github-comment)"
|
|
443
444
|
echo " test [opts] AI-powered test generation (--file, --dir, --changed, --dry-run)"
|
|
@@ -9549,6 +9550,9 @@ main() {
|
|
|
9549
9550
|
onboard)
|
|
9550
9551
|
cmd_onboard "$@"
|
|
9551
9552
|
;;
|
|
9553
|
+
explain)
|
|
9554
|
+
cmd_explain "$@"
|
|
9555
|
+
;;
|
|
9552
9556
|
ci)
|
|
9553
9557
|
cmd_ci "$@"
|
|
9554
9558
|
;;
|
|
@@ -15049,6 +15053,546 @@ Generated by loki onboard (depth $depth) on $(date +%Y-%m-%d)"
|
|
|
15049
15053
|
fi
|
|
15050
15054
|
}
|
|
15051
15055
|
|
|
15056
|
+
|
|
15057
|
+
# Analyze any codebase and explain its architecture in plain English (v6.31.0)
|
|
15058
|
+
cmd_explain() {
|
|
15059
|
+
local target_path="."
|
|
15060
|
+
set +e
|
|
15061
|
+
local output_json=false
|
|
15062
|
+
local output_brief=false
|
|
15063
|
+
local output_save=false
|
|
15064
|
+
|
|
15065
|
+
while [[ $# -gt 0 ]]; do
|
|
15066
|
+
case "$1" in
|
|
15067
|
+
--json) output_json=true; shift ;;
|
|
15068
|
+
--brief) output_brief=true; shift ;;
|
|
15069
|
+
--save) output_save=true; shift ;;
|
|
15070
|
+
--help|-h)
|
|
15071
|
+
echo -e "${BOLD}loki explain${NC} - Analyze any codebase and explain its architecture"
|
|
15072
|
+
echo ""
|
|
15073
|
+
echo "Usage: loki explain [path] [options]"
|
|
15074
|
+
echo ""
|
|
15075
|
+
echo "Arguments:"
|
|
15076
|
+
echo " path Path to repository (default: current directory)"
|
|
15077
|
+
echo ""
|
|
15078
|
+
echo "Options:"
|
|
15079
|
+
echo " --json Machine-readable JSON output"
|
|
15080
|
+
echo " --brief Condensed one-pager version"
|
|
15081
|
+
echo " --save Write output to EXPLAIN.md in the analyzed directory"
|
|
15082
|
+
echo " --help Show this help"
|
|
15083
|
+
echo ""
|
|
15084
|
+
echo "Examples:"
|
|
15085
|
+
echo " loki explain # Analyze current directory"
|
|
15086
|
+
echo " loki explain ~/projects/myapp # Analyze specific repo"
|
|
15087
|
+
echo " loki explain --brief # Condensed overview"
|
|
15088
|
+
echo " loki explain --json # JSON output for tooling"
|
|
15089
|
+
echo " loki explain --save # Save as EXPLAIN.md"
|
|
15090
|
+
return 0
|
|
15091
|
+
;;
|
|
15092
|
+
-*)
|
|
15093
|
+
log_error "Unknown option: $1"
|
|
15094
|
+
echo "Run 'loki explain --help' for usage."
|
|
15095
|
+
return 1
|
|
15096
|
+
;;
|
|
15097
|
+
*) target_path="$1"; shift ;;
|
|
15098
|
+
esac
|
|
15099
|
+
done
|
|
15100
|
+
|
|
15101
|
+
if [ ! -d "$target_path" ]; then
|
|
15102
|
+
log_error "Directory not found: $target_path"
|
|
15103
|
+
return 1
|
|
15104
|
+
fi
|
|
15105
|
+
|
|
15106
|
+
target_path="$(cd "$target_path" && pwd)"
|
|
15107
|
+
local project_name
|
|
15108
|
+
project_name="$(basename "$target_path")"
|
|
15109
|
+
|
|
15110
|
+
local languages="" frameworks="" build_system="" test_framework=""
|
|
15111
|
+
local entry_points="" package_manager="" project_description=""
|
|
15112
|
+
local project_version="" detected_patterns="" scripts_info=""
|
|
15113
|
+
|
|
15114
|
+
# --- package.json (JavaScript/TypeScript) ---
|
|
15115
|
+
if [ -f "$target_path/package.json" ]; then
|
|
15116
|
+
languages="$languages JavaScript/TypeScript"
|
|
15117
|
+
package_manager="npm"
|
|
15118
|
+
[ -f "$target_path/yarn.lock" ] && package_manager="yarn"
|
|
15119
|
+
[ -f "$target_path/pnpm-lock.yaml" ] && package_manager="pnpm"
|
|
15120
|
+
[ -f "$target_path/bun.lockb" ] && package_manager="bun"
|
|
15121
|
+
|
|
15122
|
+
if command -v python3 &>/dev/null; then
|
|
15123
|
+
local pkg_meta
|
|
15124
|
+
pkg_meta=$(python3 -c "
|
|
15125
|
+
import json
|
|
15126
|
+
try:
|
|
15127
|
+
d = json.load(open('$target_path/package.json'))
|
|
15128
|
+
print(d.get('name', ''))
|
|
15129
|
+
print(d.get('description', ''))
|
|
15130
|
+
print(d.get('version', ''))
|
|
15131
|
+
main = d.get('main', d.get('module', ''))
|
|
15132
|
+
print(main)
|
|
15133
|
+
s = d.get('scripts', {})
|
|
15134
|
+
for k in sorted(s.keys()):
|
|
15135
|
+
print(f'script:{k}:{s[k]}')
|
|
15136
|
+
for dep in list(d.get('dependencies', {}).keys()):
|
|
15137
|
+
print(f'dep:{dep}')
|
|
15138
|
+
for dep in list(d.get('devDependencies', {}).keys()):
|
|
15139
|
+
print(f'devdep:{dep}')
|
|
15140
|
+
except: pass
|
|
15141
|
+
" 2>/dev/null || true)
|
|
15142
|
+
local pkg_name pkg_desc pkg_ver pkg_main
|
|
15143
|
+
pkg_name=$(echo "$pkg_meta" | sed -n '1p')
|
|
15144
|
+
pkg_desc=$(echo "$pkg_meta" | sed -n '2p')
|
|
15145
|
+
pkg_ver=$(echo "$pkg_meta" | sed -n '3p')
|
|
15146
|
+
pkg_main=$(echo "$pkg_meta" | sed -n '4p')
|
|
15147
|
+
[ -n "$pkg_name" ] && project_name="$pkg_name"
|
|
15148
|
+
[ -n "$pkg_desc" ] && project_description="$pkg_desc"
|
|
15149
|
+
[ -n "$pkg_ver" ] && project_version="$pkg_ver"
|
|
15150
|
+
[ -n "$pkg_main" ] && entry_points="$pkg_main"
|
|
15151
|
+
scripts_info=$(echo "$pkg_meta" | grep '^script:' | sed 's/^script://' || true)
|
|
15152
|
+
local deps_list devdeps_list all_deps
|
|
15153
|
+
deps_list=$(echo "$pkg_meta" | grep '^dep:' | sed 's/^dep://' || true)
|
|
15154
|
+
devdeps_list=$(echo "$pkg_meta" | grep '^devdep:' | sed 's/^devdep://' || true)
|
|
15155
|
+
all_deps="$deps_list
|
|
15156
|
+
$devdeps_list"
|
|
15157
|
+
echo "$deps_list" | grep -q '^react$' && frameworks="$frameworks React" || true
|
|
15158
|
+
echo "$deps_list" | grep -q '^next$' && frameworks="$frameworks Next.js" || true
|
|
15159
|
+
echo "$deps_list" | grep -q '^vue$' && frameworks="$frameworks Vue" || true
|
|
15160
|
+
echo "$deps_list" | grep -q '^express$' && frameworks="$frameworks Express" || true
|
|
15161
|
+
echo "$deps_list" | grep -q '^fastify$' && frameworks="$frameworks Fastify" || true
|
|
15162
|
+
echo "$deps_list" | grep -q '^svelte$' && frameworks="$frameworks Svelte" || true
|
|
15163
|
+
echo "$deps_list" | grep -q '^@angular/core$' && frameworks="$frameworks Angular" || true
|
|
15164
|
+
echo "$deps_list" | grep -q '^hono$' && frameworks="$frameworks Hono" || true
|
|
15165
|
+
echo "$deps_list" | grep -q '^astro$' && frameworks="$frameworks Astro" || true
|
|
15166
|
+
echo "$deps_list" | grep -q '^nuxt$' && frameworks="$frameworks Nuxt" || true
|
|
15167
|
+
echo "$deps_list" | grep -q '^remix$' && frameworks="$frameworks Remix" || true
|
|
15168
|
+
echo "$deps_list" | grep -q '^electron$' && frameworks="$frameworks Electron" || true
|
|
15169
|
+
echo "$all_deps" | grep -q '^tailwindcss$' && frameworks="$frameworks Tailwind" || true
|
|
15170
|
+
echo "$all_deps" | grep -q '^jest$' && test_framework="$test_framework jest" || true
|
|
15171
|
+
echo "$all_deps" | grep -q '^vitest$' && test_framework="$test_framework vitest" || true
|
|
15172
|
+
echo "$all_deps" | grep -q '^mocha$' && test_framework="$test_framework mocha" || true
|
|
15173
|
+
echo "$all_deps" | grep -q '^@playwright/test$' && test_framework="$test_framework playwright" || true
|
|
15174
|
+
echo "$all_deps" | grep -q '^cypress$' && test_framework="$test_framework cypress" || true
|
|
15175
|
+
echo "$all_deps" | grep -q '^webpack$' && build_system="webpack" || true
|
|
15176
|
+
echo "$all_deps" | grep -q '^vite$' && build_system="vite" || true
|
|
15177
|
+
echo "$all_deps" | grep -q '^esbuild$' && build_system="esbuild" || true
|
|
15178
|
+
echo "$all_deps" | grep -q '^rollup$' && build_system="rollup" || true
|
|
15179
|
+
echo "$all_deps" | grep -q '^turbo$' && build_system="turborepo" || true
|
|
15180
|
+
echo "$all_deps" | grep -q '^prisma$' && detected_patterns="$detected_patterns ORM(Prisma)" || true
|
|
15181
|
+
echo "$all_deps" | grep -q '^drizzle-orm$' && detected_patterns="$detected_patterns ORM(Drizzle)" || true
|
|
15182
|
+
echo "$all_deps" | grep -q '^@trpc/server$' && detected_patterns="$detected_patterns tRPC" || true
|
|
15183
|
+
echo "$all_deps" | grep -q '^graphql$' && detected_patterns="$detected_patterns GraphQL" || true
|
|
15184
|
+
echo "$all_deps" | grep -q '^socket.io$' && detected_patterns="$detected_patterns WebSocket" || true
|
|
15185
|
+
echo "$all_deps" | grep -q '^ws$' && detected_patterns="$detected_patterns WebSocket" || true
|
|
15186
|
+
echo "$all_deps" | grep -q '^@nestjs/core$' && frameworks="$frameworks NestJS" || true
|
|
15187
|
+
echo "$all_deps" | grep -q '^redis$\|^ioredis$' && detected_patterns="$detected_patterns Redis" || true
|
|
15188
|
+
echo "$all_deps" | grep -q '^mongoose$' && detected_patterns="$detected_patterns MongoDB" || true
|
|
15189
|
+
echo "$all_deps" | grep -q '^pg$' && detected_patterns="$detected_patterns PostgreSQL" || true
|
|
15190
|
+
echo "$all_deps" | grep -q '^stripe$' && detected_patterns="$detected_patterns Stripe" || true
|
|
15191
|
+
fi
|
|
15192
|
+
fi
|
|
15193
|
+
|
|
15194
|
+
# --- Python ---
|
|
15195
|
+
if [ -f "$target_path/pyproject.toml" ]; then
|
|
15196
|
+
languages="$languages Python"
|
|
15197
|
+
package_manager="pip"
|
|
15198
|
+
grep -q '\[tool.poetry' "$target_path/pyproject.toml" 2>/dev/null && package_manager="poetry" || true
|
|
15199
|
+
grep -q "django" "$target_path/pyproject.toml" 2>/dev/null && frameworks="$frameworks Django" || true
|
|
15200
|
+
grep -q "flask" "$target_path/pyproject.toml" 2>/dev/null && frameworks="$frameworks Flask" || true
|
|
15201
|
+
grep -q "fastapi" "$target_path/pyproject.toml" 2>/dev/null && frameworks="$frameworks FastAPI" || true
|
|
15202
|
+
grep -q "sqlalchemy" "$target_path/pyproject.toml" 2>/dev/null && detected_patterns="$detected_patterns ORM(SQLAlchemy)" || true
|
|
15203
|
+
grep -q "pytest" "$target_path/pyproject.toml" 2>/dev/null && test_framework="$test_framework pytest" || true
|
|
15204
|
+
[ -z "$project_description" ] && project_description=$(grep '^description' "$target_path/pyproject.toml" 2>/dev/null | head -1 | sed 's/^description *= *"//;s/"$//' || true)
|
|
15205
|
+
[ -z "$project_version" ] && project_version=$(grep '^version' "$target_path/pyproject.toml" 2>/dev/null | head -1 | sed 's/^version *= *"//;s/"$//' || true)
|
|
15206
|
+
elif [ -f "$target_path/requirements.txt" ] || [ -f "$target_path/setup.py" ]; then
|
|
15207
|
+
languages="$languages Python"
|
|
15208
|
+
[ -z "$package_manager" ] && package_manager="pip"
|
|
15209
|
+
fi
|
|
15210
|
+
|
|
15211
|
+
# --- Go ---
|
|
15212
|
+
if [ -f "$target_path/go.mod" ]; then
|
|
15213
|
+
languages="$languages Go"
|
|
15214
|
+
package_manager="go-modules"; build_system="go"; test_framework="$test_framework go-test"
|
|
15215
|
+
grep -q "gin-gonic" "$target_path/go.mod" 2>/dev/null && frameworks="$frameworks Gin" || true
|
|
15216
|
+
grep -q "grpc" "$target_path/go.mod" 2>/dev/null && detected_patterns="$detected_patterns gRPC" || true
|
|
15217
|
+
fi
|
|
15218
|
+
|
|
15219
|
+
# --- Rust ---
|
|
15220
|
+
if [ -f "$target_path/Cargo.toml" ]; then
|
|
15221
|
+
languages="$languages Rust"
|
|
15222
|
+
package_manager="cargo"; build_system="cargo"; test_framework="$test_framework cargo-test"
|
|
15223
|
+
grep -q "actix" "$target_path/Cargo.toml" 2>/dev/null && frameworks="$frameworks Actix" || true
|
|
15224
|
+
grep -q "axum" "$target_path/Cargo.toml" 2>/dev/null && frameworks="$frameworks Axum" || true
|
|
15225
|
+
grep -q "tokio" "$target_path/Cargo.toml" 2>/dev/null && detected_patterns="$detected_patterns Async(Tokio)" || true
|
|
15226
|
+
fi
|
|
15227
|
+
|
|
15228
|
+
# --- Ruby ---
|
|
15229
|
+
if [ -f "$target_path/Gemfile" ]; then
|
|
15230
|
+
languages="$languages Ruby"; package_manager="bundler"
|
|
15231
|
+
grep -q "rails" "$target_path/Gemfile" 2>/dev/null && frameworks="$frameworks Rails" || true
|
|
15232
|
+
grep -q "rspec" "$target_path/Gemfile" 2>/dev/null && test_framework="$test_framework rspec" || true
|
|
15233
|
+
fi
|
|
15234
|
+
|
|
15235
|
+
# --- Java/Kotlin ---
|
|
15236
|
+
if [ -f "$target_path/pom.xml" ]; then languages="$languages Java" && build_system="maven" && package_manager="maven"; fi
|
|
15237
|
+
if [ -f "$target_path/build.gradle" ] || [ -f "$target_path/build.gradle.kts" ]; then languages="$languages Java/Kotlin"; build_system="gradle"; fi
|
|
15238
|
+
|
|
15239
|
+
# --- C/C++ ---
|
|
15240
|
+
if [ -f "$target_path/CMakeLists.txt" ]; then languages="$languages C/C++" && build_system="cmake"; fi
|
|
15241
|
+
if [ -f "$target_path/Makefile" ]; then [ -z "$build_system" ] && build_system="make"; fi
|
|
15242
|
+
|
|
15243
|
+
# --- Shell ---
|
|
15244
|
+
local shell_count
|
|
15245
|
+
shell_count=$(find "$target_path" -maxdepth 2 -name "*.sh" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
15246
|
+
[ "$shell_count" -gt 3 ] && languages="$languages Bash"
|
|
15247
|
+
|
|
15248
|
+
# --- Docker / CI ---
|
|
15249
|
+
local has_docker=false
|
|
15250
|
+
if [ -f "$target_path/Dockerfile" ]; then has_docker=true && detected_patterns="$detected_patterns Docker"; fi
|
|
15251
|
+
[ -f "$target_path/docker-compose.yml" ] || [ -f "$target_path/docker-compose.yaml" ] && detected_patterns="$detected_patterns DockerCompose"
|
|
15252
|
+
|
|
15253
|
+
local ci_system=""
|
|
15254
|
+
[ -d "$target_path/.github/workflows" ] && ci_system="GitHub Actions"
|
|
15255
|
+
if [ -f "$target_path/.gitlab-ci.yml" ]; then ci_system="$ci_system GitLab CI"; fi
|
|
15256
|
+
|
|
15257
|
+
# --- Monorepo ---
|
|
15258
|
+
local is_monorepo=false
|
|
15259
|
+
if [ -f "$target_path/lerna.json" ]; then is_monorepo=true && detected_patterns="$detected_patterns Monorepo(Lerna)"; fi
|
|
15260
|
+
if [ -f "$target_path/turbo.json" ]; then is_monorepo=true && detected_patterns="$detected_patterns Monorepo(Turborepo)"; fi
|
|
15261
|
+
if [ -f "$target_path/nx.json" ]; then is_monorepo=true && detected_patterns="$detected_patterns Monorepo(Nx)"; fi
|
|
15262
|
+
if [ -f "$target_path/pnpm-workspace.yaml" ]; then is_monorepo=true && detected_patterns="$detected_patterns Monorepo(pnpm)"; fi
|
|
15263
|
+
if [ -f "$target_path/package.json" ] && grep -q '"workspaces"' "$target_path/package.json" 2>/dev/null; then
|
|
15264
|
+
is_monorepo=true
|
|
15265
|
+
echo "$detected_patterns" | grep -q "Monorepo" || detected_patterns="$detected_patterns Monorepo(npm)"
|
|
15266
|
+
fi
|
|
15267
|
+
|
|
15268
|
+
# Deduplicate
|
|
15269
|
+
languages=$(echo "$languages" | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/^ *//;s/ *$//')
|
|
15270
|
+
frameworks=$(echo "$frameworks" | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/^ *//;s/ *$//')
|
|
15271
|
+
test_framework=$(echo "$test_framework" | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/^ *//;s/ *$//')
|
|
15272
|
+
detected_patterns=$(echo "$detected_patterns" | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/^ *//;s/ *$//')
|
|
15273
|
+
|
|
15274
|
+
# --- README ---
|
|
15275
|
+
local readme_content="" readme_file=""
|
|
15276
|
+
for f in README.md readme.md README.rst README README.txt; do
|
|
15277
|
+
if [ -f "$target_path/$f" ]; then
|
|
15278
|
+
readme_file="$f"
|
|
15279
|
+
readme_content=$(head -80 "$target_path/$f" 2>/dev/null || true)
|
|
15280
|
+
break
|
|
15281
|
+
fi
|
|
15282
|
+
done
|
|
15283
|
+
if [ -z "$project_description" ] && [ -n "$readme_content" ]; then
|
|
15284
|
+
project_description=$(echo "$readme_content" | grep -v '^#' | grep -v '^$' | grep -v '^\[' | grep -v '^!' | grep -v '^---' | head -3 | sed 's/^ *//' | tr '\n' ' ' | sed 's/ */ /g;s/^ *//;s/ *$//')
|
|
15285
|
+
fi
|
|
15286
|
+
|
|
15287
|
+
# --- File counts ---
|
|
15288
|
+
local tree_output=""
|
|
15289
|
+
if command -v git &>/dev/null && [ -d "$target_path/.git" ]; then
|
|
15290
|
+
tree_output=$(cd "$target_path" && git ls-files 2>/dev/null | head -500 || true)
|
|
15291
|
+
else
|
|
15292
|
+
tree_output=$(find "$target_path" -maxdepth 4 -type f \
|
|
15293
|
+
-not -path '*/node_modules/*' -not -path '*/.git/*' \
|
|
15294
|
+
-not -path '*/vendor/*' -not -path '*/__pycache__/*' \
|
|
15295
|
+
-not -path '*/dist/*' -not -path '*/build/*' \
|
|
15296
|
+
-not -path '*/.next/*' -not -path '*/target/*' \
|
|
15297
|
+
2>/dev/null | sed "s|$target_path/||" | sort | head -500)
|
|
15298
|
+
fi
|
|
15299
|
+
local total_files src_count test_count doc_count config_count
|
|
15300
|
+
total_files=$(echo "$tree_output" | { grep -c . || true; })
|
|
15301
|
+
src_count=$(echo "$tree_output" | { grep -cE '\.(js|ts|tsx|jsx|py|rs|go|rb|java|kt|c|cpp|h|hpp|sh|swift|cs|php)$' || true; })
|
|
15302
|
+
test_count=$(echo "$tree_output" | { grep -cE '(\.test\.|\.spec\.|_test\.|_spec\.|tests/|test/|__tests__/)' || true; })
|
|
15303
|
+
doc_count=$(echo "$tree_output" | { grep -cE '\.(md|rst|txt)$' || true; })
|
|
15304
|
+
config_count=$(echo "$tree_output" | { grep -cE '\.(json|yaml|yml|toml|cfg|ini|env)$|Dockerfile|Makefile' || true; })
|
|
15305
|
+
|
|
15306
|
+
local top_dirs
|
|
15307
|
+
top_dirs=$(echo "$tree_output" | sed 's|/.*||' | sort | uniq -c | sort -rn | head -20)
|
|
15308
|
+
|
|
15309
|
+
# Detect patterns from directory structure
|
|
15310
|
+
echo "$tree_output" | grep -qE '^(api|routes|controllers)/' && detected_patterns="$detected_patterns REST"
|
|
15311
|
+
echo "$tree_output" | grep -qE '^(pages|app)/' && detected_patterns="$detected_patterns FileRouting"
|
|
15312
|
+
echo "$tree_output" | grep -q '^components/' && detected_patterns="$detected_patterns ComponentBased" || true
|
|
15313
|
+
echo "$tree_output" | grep -qE '(middleware|middlewares)/' && detected_patterns="$detected_patterns Middleware"
|
|
15314
|
+
echo "$tree_output" | grep -qE '(events|listeners|handlers)/' && detected_patterns="$detected_patterns EventDriven"
|
|
15315
|
+
echo "$tree_output" | grep -qE '(models|entities|schemas)/' && detected_patterns="$detected_patterns MVC"
|
|
15316
|
+
echo "$tree_output" | grep -qE '(services|service)/' && detected_patterns="$detected_patterns ServiceLayer"
|
|
15317
|
+
detected_patterns=$(echo "$detected_patterns" | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/^ *//;s/ *$//')
|
|
15318
|
+
|
|
15319
|
+
# --- Detect commands ---
|
|
15320
|
+
local build_cmd="" run_cmd="" test_cmd="" lint_cmd=""
|
|
15321
|
+
if [ -n "$scripts_info" ]; then
|
|
15322
|
+
local has_build has_dev has_start has_test has_lint
|
|
15323
|
+
has_build=$(echo "$scripts_info" | grep '^build:' | head -1)
|
|
15324
|
+
has_dev=$(echo "$scripts_info" | grep '^dev:' | head -1)
|
|
15325
|
+
has_start=$(echo "$scripts_info" | grep '^start:' | head -1)
|
|
15326
|
+
has_test=$(echo "$scripts_info" | grep '^test:' | head -1)
|
|
15327
|
+
has_lint=$(echo "$scripts_info" | grep '^lint:' | head -1)
|
|
15328
|
+
[ -n "$has_build" ] && build_cmd="${package_manager:-npm} run build"
|
|
15329
|
+
[ -n "$has_dev" ] && run_cmd="${package_manager:-npm} run dev"
|
|
15330
|
+
[ -z "$run_cmd" ] && [ -n "$has_start" ] && run_cmd="${package_manager:-npm} start"
|
|
15331
|
+
[ -n "$has_test" ] && test_cmd="${package_manager:-npm} test"
|
|
15332
|
+
[ -n "$has_lint" ] && lint_cmd="${package_manager:-npm} run lint"
|
|
15333
|
+
fi
|
|
15334
|
+
if [ -f "$target_path/Cargo.toml" ]; then build_cmd="cargo build" && run_cmd="cargo run" && test_cmd="cargo test"; fi
|
|
15335
|
+
if [ -f "$target_path/go.mod" ]; then build_cmd="go build ./..." && run_cmd="go run ." && test_cmd="go test ./..."; fi
|
|
15336
|
+
if [ -f "$target_path/Makefile" ]; then
|
|
15337
|
+
[ -z "$build_cmd" ] && build_cmd="make"
|
|
15338
|
+
grep -q '^test:' "$target_path/Makefile" 2>/dev/null && [ -z "$test_cmd" ] && test_cmd="make test" || true
|
|
15339
|
+
fi
|
|
15340
|
+
if [ -f "$target_path/pyproject.toml" ]; then grep -q '\[tool.pytest' "$target_path/pyproject.toml" 2>/dev/null && [ -z "$test_cmd" ] && test_cmd="pytest" || true; fi
|
|
15341
|
+
|
|
15342
|
+
# --- Key entry point files ---
|
|
15343
|
+
local major_files=""
|
|
15344
|
+
for candidate in \
|
|
15345
|
+
"src/index.ts" "src/index.js" "src/main.ts" "src/main.js" "src/app.ts" "src/app.js" \
|
|
15346
|
+
"index.ts" "index.js" "main.ts" "main.js" "app.ts" "app.js" "server.ts" "server.js" \
|
|
15347
|
+
"src/App.tsx" "src/App.jsx" "pages/index.tsx" "app/page.tsx" \
|
|
15348
|
+
"main.py" "app.py" "manage.py" "src/main.py" "__main__.py" \
|
|
15349
|
+
"main.go" "cmd/main.go" "src/main.rs" "src/lib.rs"; do
|
|
15350
|
+
echo "$tree_output" | grep -q "^${candidate}$" && major_files="$major_files $candidate"
|
|
15351
|
+
done
|
|
15352
|
+
major_files=$(echo "$major_files" | sed 's/^ *//')
|
|
15353
|
+
|
|
15354
|
+
# --- JSON output ---
|
|
15355
|
+
if [ "$output_json" = true ]; then
|
|
15356
|
+
python3 -c "
|
|
15357
|
+
import json
|
|
15358
|
+
data = {
|
|
15359
|
+
'project': {'name': '$project_name', 'description': '''$(echo "$project_description" | sed "s/'/\\\\'/g")''', 'version': '$project_version', 'path': '$target_path'},
|
|
15360
|
+
'stack': {'languages': '${languages}'.split() if '${languages}'.strip() else [], 'frameworks': '${frameworks}'.split() if '${frameworks}'.strip() else [], 'build_system': '$build_system' or None, 'package_manager': '$package_manager' or None, 'test_framework': '${test_framework}'.split() if '${test_framework}'.strip() else [], 'ci': '${ci_system}'.strip() or None},
|
|
15361
|
+
'patterns': '${detected_patterns}'.split() if '${detected_patterns}'.strip() else [],
|
|
15362
|
+
'files': {'total': $total_files, 'source': $src_count, 'test': $test_count, 'docs': $doc_count, 'config': $config_count},
|
|
15363
|
+
'commands': {'build': '${build_cmd}' or None, 'run': '${run_cmd}' or None, 'test': '${test_cmd}' or None, 'lint': '${lint_cmd}' or None},
|
|
15364
|
+
'entry_points': '${major_files}'.split() if '${major_files}'.strip() else [],
|
|
15365
|
+
'monorepo': $( [ "$is_monorepo" = true ] && echo "True" || echo "False" ),
|
|
15366
|
+
'has_docker': $( [ "$has_docker" = true ] && echo "True" || echo "False" )
|
|
15367
|
+
}
|
|
15368
|
+
print(json.dumps(data, indent=2))
|
|
15369
|
+
" 2>/dev/null || echo '{"error": "JSON generation failed"}'
|
|
15370
|
+
return 0
|
|
15371
|
+
fi
|
|
15372
|
+
|
|
15373
|
+
# --- Text output ---
|
|
15374
|
+
local output=""
|
|
15375
|
+
local sep="================================================================================"
|
|
15376
|
+
local sep2="--------------------------------------------------------------------------------"
|
|
15377
|
+
|
|
15378
|
+
if [ "$output_brief" = true ]; then
|
|
15379
|
+
output="${BOLD}$project_name${NC}"
|
|
15380
|
+
[ -n "$project_version" ] && output="$output (v$project_version)"
|
|
15381
|
+
output="$output
|
|
15382
|
+
$sep2"
|
|
15383
|
+
[ -n "$project_description" ] && output="$output
|
|
15384
|
+
$project_description
|
|
15385
|
+
"
|
|
15386
|
+
output="$output
|
|
15387
|
+
${BOLD}Stack:${NC} ${languages:-unknown}"
|
|
15388
|
+
[ -n "$frameworks" ] && output="$output + $frameworks"
|
|
15389
|
+
[ -n "$build_system" ] && output="$output | Build: $build_system"
|
|
15390
|
+
[ -n "$package_manager" ] && output="$output | Pkg: $package_manager"
|
|
15391
|
+
output="$output
|
|
15392
|
+
${BOLD}Scope:${NC} $total_files files ($src_count source, $test_count test, $doc_count docs)"
|
|
15393
|
+
[ -n "$detected_patterns" ] && output="$output
|
|
15394
|
+
${BOLD}Patterns:${NC} $(echo "$detected_patterns" | tr ' ' ', ')"
|
|
15395
|
+
[ -n "$ci_system" ] && output="$output
|
|
15396
|
+
${BOLD}CI/CD:${NC} $(echo "$ci_system" | sed 's/^ *//')"
|
|
15397
|
+
[ -n "$test_framework" ] && output="$output
|
|
15398
|
+
${BOLD}Testing:${NC} $test_framework"
|
|
15399
|
+
if [ -n "$run_cmd" ] || [ -n "$build_cmd" ] || [ -n "$test_cmd" ]; then
|
|
15400
|
+
output="$output
|
|
15401
|
+
"
|
|
15402
|
+
[ -n "$run_cmd" ] && output="$output
|
|
15403
|
+
${BOLD}Run:${NC} $run_cmd"
|
|
15404
|
+
[ -n "$build_cmd" ] && output="$output
|
|
15405
|
+
${BOLD}Build:${NC} $build_cmd"
|
|
15406
|
+
[ -n "$test_cmd" ] && output="$output
|
|
15407
|
+
${BOLD}Test:${NC} $test_cmd"
|
|
15408
|
+
fi
|
|
15409
|
+
[ -n "$major_files" ] && output="$output
|
|
15410
|
+
|
|
15411
|
+
${BOLD}Entry points:${NC} $(echo "$major_files" | tr ' ' ', ')"
|
|
15412
|
+
output="$output
|
|
15413
|
+
$sep2
|
|
15414
|
+
Generated by loki explain --brief on $(date +%Y-%m-%d)"
|
|
15415
|
+
else
|
|
15416
|
+
output="$sep
|
|
15417
|
+
PROJECT ANALYSIS: $project_name"
|
|
15418
|
+
[ -n "$project_version" ] && output="$output (v$project_version)"
|
|
15419
|
+
output="$output
|
|
15420
|
+
$sep
|
|
15421
|
+
|
|
15422
|
+
${BOLD}EXECUTIVE SUMMARY${NC}
|
|
15423
|
+
$sep2
|
|
15424
|
+
"
|
|
15425
|
+
if [ -n "$project_description" ]; then
|
|
15426
|
+
output="$output$project_description"
|
|
15427
|
+
else
|
|
15428
|
+
output="${output}A ${languages:-software} project"
|
|
15429
|
+
[ -n "$frameworks" ] && output="$output built with $frameworks"
|
|
15430
|
+
[ -z "$readme_file" ] && output="$output. No README found -- description derived from project metadata."
|
|
15431
|
+
[ -n "$readme_file" ] && output="$output."
|
|
15432
|
+
fi
|
|
15433
|
+
output="$output
|
|
15434
|
+
|
|
15435
|
+
Scope: $total_files tracked files ($src_count source, $test_count test, $doc_count docs, $config_count config).
|
|
15436
|
+
|
|
15437
|
+
${BOLD}ARCHITECTURE OVERVIEW${NC}
|
|
15438
|
+
$sep2
|
|
15439
|
+
"
|
|
15440
|
+
if [ -n "$major_files" ]; then
|
|
15441
|
+
output="${output}Entry points:"
|
|
15442
|
+
for ef in $major_files; do
|
|
15443
|
+
output="$output
|
|
15444
|
+
- $ef"
|
|
15445
|
+
done
|
|
15446
|
+
output="$output
|
|
15447
|
+
"
|
|
15448
|
+
fi
|
|
15449
|
+
output="${output}
|
|
15450
|
+
Directory structure (by file count):"
|
|
15451
|
+
while IFS= read -r line; do
|
|
15452
|
+
[ -z "$line" ] && continue
|
|
15453
|
+
local dcount dname
|
|
15454
|
+
dcount=$(echo "$line" | awk '{print $1}')
|
|
15455
|
+
dname=$(echo "$line" | awk '{print $2}')
|
|
15456
|
+
if [ -d "$target_path/$dname" ]; then
|
|
15457
|
+
output="$output
|
|
15458
|
+
$dname/ ($dcount files)"
|
|
15459
|
+
else
|
|
15460
|
+
output="$output
|
|
15461
|
+
$dname"
|
|
15462
|
+
fi
|
|
15463
|
+
done <<< "$top_dirs"
|
|
15464
|
+
[ "$is_monorepo" = true ] && output="$output
|
|
15465
|
+
|
|
15466
|
+
This is a monorepo project."
|
|
15467
|
+
output="$output
|
|
15468
|
+
|
|
15469
|
+
${BOLD}TECHNOLOGY STACK${NC}
|
|
15470
|
+
$sep2
|
|
15471
|
+
Languages: ${languages:-N/A}
|
|
15472
|
+
Frameworks: ${frameworks:-N/A}
|
|
15473
|
+
Build system: ${build_system:-N/A}
|
|
15474
|
+
Package manager: ${package_manager:-N/A}
|
|
15475
|
+
Test framework: ${test_framework:-N/A}
|
|
15476
|
+
CI/CD: ${ci_system:-N/A}
|
|
15477
|
+
"
|
|
15478
|
+
if [ -n "$detected_patterns" ]; then
|
|
15479
|
+
output="$output
|
|
15480
|
+
${BOLD}KEY PATTERNS${NC}
|
|
15481
|
+
$sep2"
|
|
15482
|
+
for pattern in $detected_patterns; do
|
|
15483
|
+
case "$pattern" in
|
|
15484
|
+
REST) output="$output
|
|
15485
|
+
- REST API (route/controller directories detected)" ;;
|
|
15486
|
+
GraphQL) output="$output
|
|
15487
|
+
- GraphQL API" ;;
|
|
15488
|
+
gRPC) output="$output
|
|
15489
|
+
- gRPC (protocol buffer based RPC)" ;;
|
|
15490
|
+
tRPC) output="$output
|
|
15491
|
+
- tRPC (end-to-end typesafe APIs)" ;;
|
|
15492
|
+
WebSocket) output="$output
|
|
15493
|
+
- WebSocket (real-time communication)" ;;
|
|
15494
|
+
EventDriven) output="$output
|
|
15495
|
+
- Event-driven architecture" ;;
|
|
15496
|
+
MVC) output="$output
|
|
15497
|
+
- MVC pattern (model/entity directories detected)" ;;
|
|
15498
|
+
ServiceLayer) output="$output
|
|
15499
|
+
- Service layer pattern" ;;
|
|
15500
|
+
ComponentBased) output="$output
|
|
15501
|
+
- Component-based UI architecture" ;;
|
|
15502
|
+
FileRouting) output="$output
|
|
15503
|
+
- File-based routing (pages/app directory)" ;;
|
|
15504
|
+
Middleware) output="$output
|
|
15505
|
+
- Middleware pipeline" ;;
|
|
15506
|
+
Docker) output="$output
|
|
15507
|
+
- Docker containerized" ;;
|
|
15508
|
+
DockerCompose) output="$output
|
|
15509
|
+
- Docker Compose multi-service" ;;
|
|
15510
|
+
Monorepo*) output="$output
|
|
15511
|
+
- $pattern" ;;
|
|
15512
|
+
*) output="$output
|
|
15513
|
+
- $pattern" ;;
|
|
15514
|
+
esac
|
|
15515
|
+
done
|
|
15516
|
+
output="$output
|
|
15517
|
+
"
|
|
15518
|
+
fi
|
|
15519
|
+
output="$output
|
|
15520
|
+
${BOLD}GETTING STARTED${NC}
|
|
15521
|
+
$sep2
|
|
15522
|
+
"
|
|
15523
|
+
if [ -n "$package_manager" ]; then
|
|
15524
|
+
case "$package_manager" in
|
|
15525
|
+
npm) output="${output}Install dependencies: npm install
|
|
15526
|
+
" ;;
|
|
15527
|
+
yarn) output="${output}Install dependencies: yarn install
|
|
15528
|
+
" ;;
|
|
15529
|
+
pnpm) output="${output}Install dependencies: pnpm install
|
|
15530
|
+
" ;;
|
|
15531
|
+
pip|poetry) output="${output}Install dependencies: ${package_manager} install
|
|
15532
|
+
" ;;
|
|
15533
|
+
cargo) output="${output}Build: cargo build
|
|
15534
|
+
" ;;
|
|
15535
|
+
go-modules) output="${output}Download dependencies: go mod download
|
|
15536
|
+
" ;;
|
|
15537
|
+
bundler) output="${output}Install dependencies: bundle install
|
|
15538
|
+
" ;;
|
|
15539
|
+
*) output="${output}Package manager: $package_manager
|
|
15540
|
+
" ;;
|
|
15541
|
+
esac
|
|
15542
|
+
fi
|
|
15543
|
+
[ -n "$run_cmd" ] && output="${output}
|
|
15544
|
+
Run (development): $run_cmd
|
|
15545
|
+
"
|
|
15546
|
+
[ -n "$build_cmd" ] && output="${output}
|
|
15547
|
+
Build: $build_cmd
|
|
15548
|
+
"
|
|
15549
|
+
[ -n "$test_cmd" ] && output="${output}
|
|
15550
|
+
Test: $test_cmd
|
|
15551
|
+
"
|
|
15552
|
+
[ -n "$lint_cmd" ] && output="${output}
|
|
15553
|
+
Lint: $lint_cmd
|
|
15554
|
+
"
|
|
15555
|
+
output="$output
|
|
15556
|
+
${BOLD}FOR NEW CONTRIBUTORS${NC}
|
|
15557
|
+
$sep2
|
|
15558
|
+
"
|
|
15559
|
+
if [ -n "$readme_file" ]; then
|
|
15560
|
+
output="${output}Start by reading $readme_file for project-specific context.
|
|
15561
|
+
"
|
|
15562
|
+
else
|
|
15563
|
+
output="${output}Note: This project has no README. Consider adding one.
|
|
15564
|
+
"
|
|
15565
|
+
fi
|
|
15566
|
+
if [ -n "$major_files" ]; then
|
|
15567
|
+
output="${output}
|
|
15568
|
+
Key files to understand first:"
|
|
15569
|
+
for ef in $major_files; do
|
|
15570
|
+
output="$output
|
|
15571
|
+
- $ef"
|
|
15572
|
+
done
|
|
15573
|
+
output="$output
|
|
15574
|
+
"
|
|
15575
|
+
fi
|
|
15576
|
+
[ "$test_count" -gt 0 ] && [ -n "$test_cmd" ] && output="${output}
|
|
15577
|
+
Tests: $test_count test files found. Run '$test_cmd' to verify your changes.
|
|
15578
|
+
"
|
|
15579
|
+
output="$output
|
|
15580
|
+
$sep
|
|
15581
|
+
Generated by loki explain on $(date +%Y-%m-%d)"
|
|
15582
|
+
fi
|
|
15583
|
+
|
|
15584
|
+
# --- Output ---
|
|
15585
|
+
if [ "$output_save" = true ]; then
|
|
15586
|
+
local clean_output
|
|
15587
|
+
clean_output=$(echo -e "$output" | sed 's/\x1b\[[0-9;]*m//g')
|
|
15588
|
+
echo "$clean_output" > "$target_path/EXPLAIN.md"
|
|
15589
|
+
echo -e "${GREEN}Saved to $target_path/EXPLAIN.md${NC}"
|
|
15590
|
+
else
|
|
15591
|
+
echo -e "$output"
|
|
15592
|
+
fi
|
|
15593
|
+
set -euo pipefail
|
|
15594
|
+
}
|
|
15595
|
+
|
|
15052
15596
|
# CI/CD quality gate integration (v6.22.0)
|
|
15053
15597
|
cmd_ci() {
|
|
15054
15598
|
local ci_pr=false
|
package/dashboard/__init__.py
CHANGED
package/docs/INSTALLATION.md
CHANGED
package/mcp/__init__.py
CHANGED