super-opencode 1.1.2 → 1.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.
Files changed (48) hide show
  1. package/.opencode/agents/architect.md +54 -31
  2. package/.opencode/agents/backend.md +61 -34
  3. package/.opencode/agents/data-agent.md +422 -0
  4. package/.opencode/agents/devops-agent.md +331 -0
  5. package/.opencode/agents/frontend.md +63 -36
  6. package/.opencode/agents/mobile-agent.md +636 -0
  7. package/.opencode/agents/optimizer.md +25 -18
  8. package/.opencode/agents/pm-agent.md +114 -50
  9. package/.opencode/agents/quality.md +36 -29
  10. package/.opencode/agents/researcher.md +30 -21
  11. package/.opencode/agents/reviewer.md +39 -32
  12. package/.opencode/agents/security.md +42 -34
  13. package/.opencode/agents/writer.md +42 -31
  14. package/.opencode/commands/soc-analyze.md +55 -31
  15. package/.opencode/commands/soc-brainstorm.md +48 -26
  16. package/.opencode/commands/soc-cleanup.md +47 -25
  17. package/.opencode/commands/soc-deploy.md +271 -0
  18. package/.opencode/commands/soc-design.md +51 -26
  19. package/.opencode/commands/soc-explain.md +46 -23
  20. package/.opencode/commands/soc-git.md +47 -25
  21. package/.opencode/commands/soc-help.md +35 -14
  22. package/.opencode/commands/soc-implement.md +59 -29
  23. package/.opencode/commands/soc-improve.md +42 -20
  24. package/.opencode/commands/soc-onboard.md +329 -0
  25. package/.opencode/commands/soc-plan.md +215 -0
  26. package/.opencode/commands/soc-pm.md +40 -18
  27. package/.opencode/commands/soc-research.md +43 -20
  28. package/.opencode/commands/soc-review.md +39 -18
  29. package/.opencode/commands/soc-test.md +43 -21
  30. package/.opencode/commands/soc-validate.md +221 -0
  31. package/.opencode/commands/soc-workflow.md +38 -17
  32. package/.opencode/skills/confidence-check/SKILL.md +26 -19
  33. package/.opencode/skills/debug-protocol/SKILL.md +27 -17
  34. package/.opencode/skills/decision-log/SKILL.md +236 -0
  35. package/.opencode/skills/doc-sync/SKILL.md +345 -0
  36. package/.opencode/skills/package-manager/SKILL.md +502 -0
  37. package/.opencode/skills/package-manager/scripts/README.md +106 -0
  38. package/.opencode/skills/package-manager/scripts/detect-package-manager.sh +796 -0
  39. package/.opencode/skills/reflexion/SKILL.md +18 -11
  40. package/.opencode/skills/security-audit/SKILL.md +19 -14
  41. package/.opencode/skills/self-check/SKILL.md +30 -14
  42. package/.opencode/skills/simplification/SKILL.md +19 -5
  43. package/.opencode/skills/tech-debt/SKILL.md +245 -0
  44. package/LICENSE +1 -1
  45. package/README.md +126 -9
  46. package/dist/cli.js +143 -41
  47. package/package.json +27 -12
  48. package/.opencode/settings.json +0 -3
@@ -0,0 +1,796 @@
1
+ #!/bin/bash
2
+ #
3
+ # Multi-Language Package Manager Detection Script (Bash 3.2 Compatible)
4
+ # Detects package managers for JavaScript, Python, Go, Rust, Java, Ruby, PHP, .NET, and more
5
+ #
6
+ # Usage:
7
+ # ./detect-package-manager.sh [options] [language]
8
+ #
9
+ # Options:
10
+ # --json Output results as JSON
11
+ # --quiet Only output errors
12
+ # --recommend Show recommendation only
13
+ # --all Detect for all languages found
14
+ # --help Show this help message
15
+ #
16
+ # Language (optional, auto-detected if not specified):
17
+ # javascript, python, go, rust, java, ruby, php, dotnet, elixir, haskell, etc.
18
+ #
19
+ # Exit codes:
20
+ # 0 - Success
21
+ # 1 - No package manager detected
22
+ # 2 - Error reading project files
23
+ #
24
+
25
+ # Colors for output (only in non-JSON mode)
26
+ RED='\033[0;31m'
27
+ GREEN='\033[0;32m'
28
+ YELLOW='\033[1;33m'
29
+ BLUE='\033[0;34m'
30
+ CYAN='\033[0;36m'
31
+ NC='\033[0m' # No Color
32
+
33
+ # Parse arguments
34
+ JSON_OUTPUT=false
35
+ QUIET=false
36
+ RECOMMEND_ONLY=false
37
+ DETECT_ALL=false
38
+ SPECIFIED_LANGUAGE=""
39
+
40
+ while [[ $# -gt 0 ]]; do
41
+ case $1 in
42
+ --json)
43
+ JSON_OUTPUT=true
44
+ shift
45
+ ;;
46
+ --quiet)
47
+ QUIET=true
48
+ shift
49
+ ;;
50
+ --recommend)
51
+ RECOMMEND_ONLY=true
52
+ shift
53
+ ;;
54
+ --all)
55
+ DETECT_ALL=true
56
+ shift
57
+ ;;
58
+ --help)
59
+ echo "Multi-Language Package Manager Detection Script"
60
+ echo ""
61
+ echo "Usage: $0 [options] [language]"
62
+ echo ""
63
+ echo "Options:"
64
+ echo " --json Output results as JSON"
65
+ echo " --quiet Only output errors"
66
+ echo " --recommend Show recommendation only"
67
+ echo " --all Detect for all languages found"
68
+ echo " --help Show this help message"
69
+ echo ""
70
+ echo "Languages (auto-detected if not specified):"
71
+ echo " javascript - npm, yarn, pnpm, bun"
72
+ echo " python - pip, poetry, uv, conda, pipenv"
73
+ echo " go - go modules"
74
+ echo " rust - cargo"
75
+ echo " java - maven, gradle"
76
+ echo " ruby - bundler"
77
+ echo " php - composer"
78
+ echo " dotnet - nuget"
79
+ echo " elixir - mix"
80
+ echo " haskell - cabal, stack"
81
+ echo " c/cpp - cmake, conan, vcpkg"
82
+ echo " swift - swift package manager"
83
+ echo " kotlin - gradle"
84
+ echo " scala - sbt"
85
+ echo " clojure - leiningen, deps.edn"
86
+ echo " julia - pkg"
87
+ echo " r - renv, packrat"
88
+ echo ""
89
+ echo "Examples:"
90
+ echo " $0 # Auto-detect language and PM"
91
+ echo " $0 --json # JSON output"
92
+ echo " $0 python # Detect Python PM only"
93
+ echo " $0 --all --json # Detect all languages in project"
94
+ exit 0
95
+ ;;
96
+ --*)
97
+ echo "Unknown option: $1"
98
+ echo "Use --help for usage information"
99
+ exit 1
100
+ ;;
101
+ *)
102
+ # Assume it's a language specification
103
+ SPECIFIED_LANGUAGE="$1"
104
+ shift
105
+ ;;
106
+ esac
107
+ done
108
+
109
+ # Logging function
110
+ log() {
111
+ if [[ "$QUIET" == false && "$JSON_OUTPUT" == false && "$RECOMMEND_ONLY" == false ]]; then
112
+ echo -e "$1"
113
+ fi
114
+ }
115
+
116
+ # Error function
117
+ error() {
118
+ if [[ "$JSON_OUTPUT" == false ]]; then
119
+ echo -e "${RED}Error: $1${NC}" >&2
120
+ else
121
+ echo "{\"error\": \"$1\"}" >&2
122
+ fi
123
+ exit 2
124
+ }
125
+
126
+ # Get project root
127
+ PROJECT_ROOT="${PWD}"
128
+
129
+ # Initialize results list
130
+ DETECTED_LANGS=""
131
+
132
+ # ============================================
133
+ # LANGUAGE DETECTION FUNCTIONS
134
+ # Each function outputs: pm|version|method|lockfile|confidence|config|field
135
+ # ============================================
136
+
137
+ # JavaScript/TypeScript
138
+ detect_javascript() {
139
+ local pm=""
140
+ local ver=""
141
+ local meth=""
142
+ local lock=""
143
+ local conf=0
144
+ local cfg=""
145
+ local field=""
146
+
147
+ # Check lockfiles
148
+ if [[ -f "${PROJECT_ROOT}/pnpm-lock.yaml" ]]; then
149
+ pm="pnpm"; lock="pnpm-lock.yaml"; meth="lockfile"; conf=95
150
+ elif [[ -f "${PROJECT_ROOT}/yarn.lock" ]]; then
151
+ pm="yarn"; lock="yarn.lock"; meth="lockfile"; conf=90
152
+ elif [[ -f "${PROJECT_ROOT}/package-lock.json" ]]; then
153
+ pm="npm"; lock="package-lock.json"; meth="lockfile"; conf=90
154
+ elif [[ -f "${PROJECT_ROOT}/bun.lockb" ]]; then
155
+ pm="bun"; lock="bun.lockb"; meth="lockfile"; conf=95
156
+ fi
157
+
158
+ # Check package.json for packageManager field
159
+ if [[ -f "${PROJECT_ROOT}/package.json" ]]; then
160
+ field=$(cat "${PROJECT_ROOT}/package.json" 2>/dev/null | grep -o '"packageManager"[^,]*' | head -1 || true)
161
+ if [[ -n "$field" ]]; then
162
+ local pm_from=$(echo "$field" | grep -o 'npm\|yarn\|pnpm\|bun' | head -1 || true)
163
+ local ver_from=$(echo "$field" | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || true)
164
+ if [[ -n "$pm_from" ]]; then
165
+ pm="$pm_from"; ver="$ver_from"; meth="package.json"; conf=100
166
+ fi
167
+ fi
168
+ fi
169
+
170
+ # Check for monorepo
171
+ if [[ -z "$pm" ]]; then
172
+ if [[ -f "${PROJECT_ROOT}/pnpm-workspace.yaml" || -d "${PROJECT_ROOT}/packages" ]]; then
173
+ pm="pnpm"; meth="monorepo"; conf=80
174
+ elif [[ -f "${PROJECT_ROOT}/package.json" ]]; then
175
+ pm="npm"; meth="default"; conf=60
176
+ fi
177
+ fi
178
+
179
+ # Get installed version
180
+ if [[ -z "$ver" ]]; then
181
+ case "$pm" in
182
+ npm) ver=$(npm --version 2>/dev/null || echo "") ;;
183
+ yarn) ver=$(yarn --version 2>/dev/null || echo "") ;;
184
+ pnpm) ver=$(pnpm --version 2>/dev/null || echo "") ;;
185
+ bun) ver=$(bun --version 2>/dev/null || echo "") ;;
186
+ esac
187
+ fi
188
+
189
+ if [[ -n "$pm" ]]; then
190
+ echo "javascript|$pm|$ver|$meth|$lock|$conf|$cfg|$field"
191
+ return 0
192
+ fi
193
+ return 1
194
+ }
195
+
196
+ # Python
197
+ detect_python() {
198
+ local pm=""
199
+ local ver=""
200
+ local meth=""
201
+ local lock=""
202
+ local conf=0
203
+ local cfg=""
204
+
205
+ if [[ -f "${PROJECT_ROOT}/uv.lock" ]]; then
206
+ pm="uv"; lock="uv.lock"; meth="lockfile"; conf=95
207
+ elif [[ -f "${PROJECT_ROOT}/poetry.lock" ]]; then
208
+ pm="poetry"; lock="poetry.lock"; meth="lockfile"; conf=95
209
+ elif [[ -f "${PROJECT_ROOT}/Pipfile.lock" ]]; then
210
+ pm="pipenv"; lock="Pipfile.lock"; meth="lockfile"; conf=95
211
+ elif [[ -f "${PROJECT_ROOT}/conda-lock.yml" || -f "${PROJECT_ROOT}/environment.yml" ]]; then
212
+ pm="conda"; cfg="environment.yml"; meth="environment file"; conf=90
213
+ elif [[ -f "${PROJECT_ROOT}/requirements.txt" ]]; then
214
+ pm="pip"; lock="requirements.txt"; meth="requirements file"; conf=85
215
+ elif [[ -f "${PROJECT_ROOT}/pyproject.toml" ]]; then
216
+ if grep -q "\[tool.poetry\]" "${PROJECT_ROOT}/pyproject.toml" 2>/dev/null; then
217
+ pm="poetry"; meth="pyproject.toml"; conf=90
218
+ elif grep -q "\[tool.uv\]" "${PROJECT_ROOT}/pyproject.toml" 2>/dev/null; then
219
+ pm="uv"; meth="pyproject.toml"; conf=90
220
+ elif grep -q "\[build-system\]" "${PROJECT_ROOT}/pyproject.toml" 2>/dev/null; then
221
+ pm="pip"; meth="pyproject.toml"; conf=70
222
+ fi
223
+ elif [[ -f "${PROJECT_ROOT}/setup.py" || -f "${PROJECT_ROOT}/setup.cfg" ]]; then
224
+ pm="pip"; meth="legacy setup"; conf=70
225
+ fi
226
+
227
+ if [[ -z "$ver" ]]; then
228
+ case "$pm" in
229
+ pip) ver=$(pip --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || echo "") ;;
230
+ poetry) ver=$(poetry --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || echo "") ;;
231
+ uv) ver=$(uv --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || echo "") ;;
232
+ conda) ver=$(conda --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || echo "") ;;
233
+ pipenv) ver=$(pipenv --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || echo "") ;;
234
+ esac
235
+ fi
236
+
237
+ if [[ -n "$pm" ]]; then
238
+ echo "python|$pm|$ver|$meth|$lock|$conf|$cfg|"
239
+ return 0
240
+ fi
241
+ return 1
242
+ }
243
+
244
+ # Go
245
+ detect_go() {
246
+ if [[ -f "${PROJECT_ROOT}/go.mod" || -f "${PROJECT_ROOT}/go.sum" ]]; then
247
+ local ver=$(go version 2>/dev/null | grep -o 'go[0-9]\+\.[0-9]\+' || echo "")
248
+ echo "go|go modules|$ver|go.mod|go.sum|95||"
249
+ return 0
250
+ fi
251
+ return 1
252
+ }
253
+
254
+ # Rust
255
+ detect_rust() {
256
+ if [[ -f "${PROJECT_ROOT}/Cargo.toml" || -f "${PROJECT_ROOT}/Cargo.lock" ]]; then
257
+ local ver=$(cargo --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "")
258
+ echo "rust|cargo|$ver|Cargo.toml|Cargo.lock|95||"
259
+ return 0
260
+ fi
261
+ return 1
262
+ }
263
+
264
+ # Java
265
+ detect_java() {
266
+ local pm=""
267
+ local lock=""
268
+ local conf=0
269
+
270
+ if [[ -f "${PROJECT_ROOT}/pom.xml" ]]; then
271
+ pm="maven"; conf=95
272
+ elif [[ -f "${PROJECT_ROOT}/build.gradle" || -f "${PROJECT_ROOT}/build.gradle.kts" ]]; then
273
+ pm="gradle"; conf=95
274
+ elif [[ -f "${PROJECT_ROOT}/gradle.lockfile" ]]; then
275
+ pm="gradle"; lock="gradle.lockfile"; conf=95
276
+ fi
277
+
278
+ if [[ -n "$pm" ]]; then
279
+ local ver=""
280
+ if [[ "$pm" == "maven" ]]; then
281
+ ver=$(mvn --version 2>/dev/null | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || echo "")
282
+ else
283
+ ver=$(gradle --version 2>/dev/null | grep "Gradle" | grep -o '[0-9]\+\.[0-9]\+' | head -1 || echo "")
284
+ fi
285
+ echo "java|$pm|$ver|build file|$lock|$conf||"
286
+ return 0
287
+ fi
288
+ return 1
289
+ }
290
+
291
+ # Ruby
292
+ detect_ruby() {
293
+ if [[ -f "${PROJECT_ROOT}/Gemfile" || -f "${PROJECT_ROOT}/Gemfile.lock" ]]; then
294
+ local ver=$(bundle --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "")
295
+ echo "ruby|bundler|$ver|Gemfile|Gemfile.lock|95||"
296
+ return 0
297
+ fi
298
+ return 1
299
+ }
300
+
301
+ # PHP
302
+ detect_php() {
303
+ if [[ -f "${PROJECT_ROOT}/composer.json" || -f "${PROJECT_ROOT}/composer.lock" ]]; then
304
+ local ver=$(composer --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || echo "")
305
+ echo "php|composer|$ver|composer.json|composer.lock|95||"
306
+ return 0
307
+ fi
308
+ return 1
309
+ }
310
+
311
+ # .NET
312
+ detect_dotnet() {
313
+ local found=false
314
+ for f in "${PROJECT_ROOT}"/*.csproj "${PROJECT_ROOT}"/*.fsproj "${PROJECT_ROOT}"/*.vbproj; do
315
+ [[ -f "$f" ]] && found=true && break
316
+ done
317
+
318
+ if [[ "$found" == true || -n "$(ls "${PROJECT_ROOT}"/*.sln 2>/dev/null)" || -f "${PROJECT_ROOT}/packages.config" ]]; then
319
+ local ver=$(dotnet --version 2>/dev/null || echo "")
320
+ echo "dotnet|nuget|$ver|project file|packages.lock.json|90||"
321
+ return 0
322
+ fi
323
+ return 1
324
+ }
325
+
326
+ # Elixir
327
+ detect_elixir() {
328
+ if [[ -f "${PROJECT_ROOT}/mix.exs" || -f "${PROJECT_ROOT}/mix.lock" ]]; then
329
+ local ver=$(mix --version 2>/dev/null | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "")
330
+ echo "elixir|mix|$ver|mix.exs|mix.lock|95||"
331
+ return 0
332
+ fi
333
+ return 1
334
+ }
335
+
336
+ # Haskell
337
+ detect_haskell() {
338
+ local pm=""
339
+ local lock=""
340
+
341
+ if [[ -f "${PROJECT_ROOT}/stack.yaml" || -f "${PROJECT_ROOT}/stack.yaml.lock" ]]; then
342
+ pm="stack"; lock="stack.yaml.lock"
343
+ else
344
+ for f in "${PROJECT_ROOT}"/*.cabal; do
345
+ [[ -f "$f" ]] && pm="cabal" && lock="cabal.project.freeze" && break
346
+ done
347
+ fi
348
+
349
+ if [[ -n "$pm" ]]; then
350
+ local ver=""
351
+ if [[ "$pm" == "stack" ]]; then
352
+ ver=$(stack --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || echo "")
353
+ else
354
+ ver=$(cabal --version 2>/dev/null | head -1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "")
355
+ fi
356
+ echo "haskell|$pm|$ver|config file|$lock|90||"
357
+ return 0
358
+ fi
359
+ return 1
360
+ }
361
+
362
+ # C/C++
363
+ detect_cpp() {
364
+ local pm=""
365
+
366
+ if [[ -f "${PROJECT_ROOT}/conanfile.txt" || -f "${PROJECT_ROOT}/conanfile.py" ]]; then
367
+ pm="conan"
368
+ elif [[ -f "${PROJECT_ROOT}/vcpkg.json" ]]; then
369
+ pm="vcpkg"
370
+ fi
371
+
372
+ if [[ -n "$pm" ]]; then
373
+ echo "cpp|$pm||config file||85||"
374
+ return 0
375
+ fi
376
+ return 1
377
+ }
378
+
379
+ # Swift
380
+ detect_swift() {
381
+ if [[ -f "${PROJECT_ROOT}/Package.swift" || -f "${PROJECT_ROOT}/Package.resolved" ]]; then
382
+ local ver=$(swift --version 2>/dev/null | head -1 | grep -o '[0-9]\+\.[0-9]\+' | head -1 || echo "")
383
+ echo "swift|swift package manager|$ver|Package.swift|Package.resolved|95||"
384
+ return 0
385
+ fi
386
+ return 1
387
+ }
388
+
389
+ # Scala
390
+ detect_scala() {
391
+ if [[ -f "${PROJECT_ROOT}/build.sbt" ]]; then
392
+ local ver=""
393
+ if command -v sbt &> /dev/null; then
394
+ ver=$(sbt sbtVersion 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1 || echo "")
395
+ fi
396
+ echo "scala|sbt|$ver|build.sbt||95||"
397
+ return 0
398
+ fi
399
+ return 1
400
+ }
401
+
402
+ # Clojure
403
+ detect_clojure() {
404
+ local pm=""
405
+
406
+ if [[ -f "${PROJECT_ROOT}/project.clj" ]]; then
407
+ pm="leiningen"
408
+ elif [[ -f "${PROJECT_ROOT}/deps.edn" ]]; then
409
+ pm="tools.deps"
410
+ fi
411
+
412
+ if [[ -n "$pm" ]]; then
413
+ echo "clojure|$pm||project file||90||"
414
+ return 0
415
+ fi
416
+ return 1
417
+ }
418
+
419
+ # Julia
420
+ detect_julia() {
421
+ if [[ -f "${PROJECT_ROOT}/Project.toml" || -f "${PROJECT_ROOT}/Manifest.toml" || -f "${PROJECT_ROOT}/JuliaProject.toml" ]]; then
422
+ local ver=$(julia --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "")
423
+ echo "julia|Pkg|$ver|Project.toml|Manifest.toml|95||"
424
+ return 0
425
+ fi
426
+ return 1
427
+ }
428
+
429
+ # R
430
+ detect_r() {
431
+ if [[ -f "${PROJECT_ROOT}/renv.lock" || -d "${PROJECT_ROOT}/renv" || -f "${PROJECT_ROOT}/packrat.lock" ]]; then
432
+ local pm="renv"
433
+ [[ -f "${PROJECT_ROOT}/packrat.lock" ]] && pm="packrat"
434
+ echo "r|$pm||lockfile|${pm}.lock|95||"
435
+ return 0
436
+ fi
437
+ return 1
438
+ }
439
+
440
+ # ============================================
441
+ # DETECT ALL LANGUAGES
442
+ # ============================================
443
+ detect_all() {
444
+ local result=""
445
+
446
+ if [[ -n "$SPECIFIED_LANGUAGE" ]]; then
447
+ # Detect specific language only
448
+ case "$SPECIFIED_LANGUAGE" in
449
+ javascript|js|node|nodejs) result=$(detect_javascript) ;;
450
+ python|py) result=$(detect_python) ;;
451
+ go|golang) result=$(detect_go) ;;
452
+ rust|rs) result=$(detect_rust) ;;
453
+ java) result=$(detect_java) ;;
454
+ ruby|rb) result=$(detect_ruby) ;;
455
+ php) result=$(detect_php) ;;
456
+ dotnet|csharp|cs|fsharp|fs|vb) result=$(detect_dotnet) ;;
457
+ elixir|ex|exs) result=$(detect_elixir) ;;
458
+ haskell|hs|cabal|stack) result=$(detect_haskell) ;;
459
+ cpp|c++|c|conan|vcpkg|cmake) result=$(detect_cpp) ;;
460
+ swift) result=$(detect_swift) ;;
461
+ scala) result=$(detect_scala) ;;
462
+ clojure|clj) result=$(detect_clojure) ;;
463
+ julia|jl) result=$(detect_julia) ;;
464
+ r) result=$(detect_r) ;;
465
+ *) error "Unknown language: $SPECIFIED_LANGUAGE" ;;
466
+ esac
467
+ [[ -n "$result" ]] && DETECTED_LANGS="$result"
468
+ else
469
+ # Auto-detect all languages
470
+ result=$(detect_javascript); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
471
+ result=$(detect_python); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
472
+ result=$(detect_go); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
473
+ result=$(detect_rust); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
474
+ result=$(detect_java); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
475
+ result=$(detect_ruby); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
476
+ result=$(detect_php); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
477
+ result=$(detect_dotnet); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
478
+ result=$(detect_elixir); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
479
+ result=$(detect_haskell); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
480
+ result=$(detect_cpp); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
481
+ result=$(detect_swift); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
482
+ result=$(detect_scala); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
483
+ result=$(detect_clojure); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
484
+ result=$(detect_julia); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
485
+ result=$(detect_r); [[ -n "$result" ]] && DETECTED_LANGS="${DETECTED_LANGS}${DETECTED_LANGS:+,}$result"
486
+ fi
487
+ }
488
+
489
+ # ============================================
490
+ # OUTPUT FORMATTING
491
+ # ============================================
492
+ get_lang_display() {
493
+ case "$1" in
494
+ javascript) echo "JavaScript/TypeScript" ;;
495
+ python) echo "Python" ;;
496
+ go) echo "Go" ;;
497
+ rust) echo "Rust" ;;
498
+ java) echo "Java" ;;
499
+ ruby) echo "Ruby" ;;
500
+ php) echo "PHP" ;;
501
+ dotnet) echo ".NET" ;;
502
+ elixir) echo "Elixir" ;;
503
+ haskell) echo "Haskell" ;;
504
+ cpp) echo "C/C++" ;;
505
+ swift) echo "Swift" ;;
506
+ scala) echo "Scala" ;;
507
+ clojure) echo "Clojure" ;;
508
+ julia) echo "Julia" ;;
509
+ r) echo "R" ;;
510
+ esac
511
+ }
512
+
513
+ get_recommendation() {
514
+ local lang=$1 pm=$2
515
+ case "$lang" in
516
+ javascript)
517
+ case "$pm" in
518
+ npm) echo "npm is a safe, universal choice. Consider migrating to pnpm for better performance." ;;
519
+ yarn) echo "yarn is reliable. For new projects, consider pnpm for disk efficiency." ;;
520
+ pnpm) echo "pnpm is excellent—fast, disk-efficient, and strict. Perfect choice." ;;
521
+ bun) echo "bun is very fast but newer. Ensure your team is comfortable with it." ;;
522
+ esac
523
+ ;;
524
+ python)
525
+ case "$pm" in
526
+ pip) echo "pip is the standard. Consider poetry or uv for modern Python projects." ;;
527
+ poetry) echo "poetry provides excellent dependency resolution and packaging." ;;
528
+ uv) echo "uv is extremely fast and modern. Great for performance-critical projects." ;;
529
+ conda) echo "conda is ideal for data science and scientific computing." ;;
530
+ pipenv) echo "pipenv combines pip and virtualenv. Consider poetry for new projects." ;;
531
+ esac
532
+ ;;
533
+ go) echo "Go modules is the standard. Ensure you have go.mod committed." ;;
534
+ rust) echo "Cargo is Rust's excellent package manager. Crates.io has great ecosystem coverage." ;;
535
+ java)
536
+ case "$pm" in
537
+ maven) echo "Maven is stable and widely used. Great for enterprise projects." ;;
538
+ gradle) echo "Gradle offers flexibility and performance. Popular for Android and modern Java." ;;
539
+ esac
540
+ ;;
541
+ ruby) echo "Bundler is the standard. Ensure Gemfile.lock is committed for reproducibility." ;;
542
+ php) echo "Composer is excellent. Packagist has great package coverage." ;;
543
+ dotnet) echo "NuGet is the standard for .NET. Ensure packages.lock.json for reproducibility." ;;
544
+ elixir) echo "Mix is powerful. Hex.pm has excellent Elixir package ecosystem." ;;
545
+ haskell)
546
+ case "$pm" in
547
+ stack) echo "Stack is recommended for reproducible builds and LTS snapshots." ;;
548
+ cabal) echo "Cabal is the traditional choice. Consider stack for easier setup." ;;
549
+ esac
550
+ ;;
551
+ cpp)
552
+ case "$pm" in
553
+ conan) echo "Conan is modern and cross-platform. Great for C++ dependency management." ;;
554
+ vcpkg) echo "vcpkg has excellent Microsoft ecosystem integration." ;;
555
+ esac
556
+ ;;
557
+ swift) echo "Swift Package Manager is modern and well-integrated with Xcode." ;;
558
+ scala) echo "sbt is the standard. Maven Central has good Scala coverage." ;;
559
+ clojure)
560
+ case "$pm" in
561
+ leiningen) echo "Leiningen is mature and widely used in Clojure community." ;;
562
+ tools.deps) echo "tools.deps is modern and simpler. Consider for new projects." ;;
563
+ esac
564
+ ;;
565
+ julia) echo "Julia's Pkg is excellent. General registry has good coverage." ;;
566
+ r)
567
+ case "$pm" in
568
+ renv) echo "renv is the modern standard for R reproducibility." ;;
569
+ packrat) echo "packrat is older. Consider migrating to renv." ;;
570
+ esac
571
+ ;;
572
+ esac
573
+ }
574
+
575
+ get_commands() {
576
+ local lang=$1 pm=$2
577
+ case "$lang" in
578
+ javascript)
579
+ case "$pm" in
580
+ npm) echo "install:npm ci|add:npm install|add_dev:npm install --save-dev|run:npm run|exec:npx" ;;
581
+ yarn) echo "install:yarn install --frozen-lockfile|add:yarn add|add_dev:yarn add --dev|run:yarn|exec:yarn dlx" ;;
582
+ pnpm) echo "install:pnpm install --frozen-lockfile|add:pnpm add|add_dev:pnpm add -D|run:pnpm|exec:pnpm dlx" ;;
583
+ bun) echo "install:bun install|add:bun add|add_dev:bun add -d|run:bun run|exec:bunx" ;;
584
+ esac
585
+ ;;
586
+ python)
587
+ case "$pm" in
588
+ pip) echo "install:pip install -r requirements.txt|add:pip install|add_dev:pip install|run:python|exec:python" ;;
589
+ poetry) echo "install:poetry install|add:poetry add|add_dev:poetry add --group dev|run:poetry run|exec:poetry run" ;;
590
+ uv) echo "install:uv sync|add:uv add|add_dev:uv add --dev|run:uv run|exec:uv run" ;;
591
+ conda) echo "install:conda env create -f environment.yml|add:conda install|add_dev:conda install|run:conda run|exec:conda run" ;;
592
+ pipenv) echo "install:pipenv install|add:pipenv install|add_dev:pipenv install --dev|run:pipenv run|exec:pipenv run" ;;
593
+ esac
594
+ ;;
595
+ go) echo "install:go mod download|add:go get|add_dev:go get|run:go run|exec:go run" ;;
596
+ rust) echo "install:cargo fetch|add:cargo add|add_dev:cargo add --dev|run:cargo run|exec:cargo run" ;;
597
+ java)
598
+ case "$pm" in
599
+ maven) echo "install:mvn dependency:resolve|add:pom.xml edit|add_dev:pom.xml edit|run:mvn exec:java|exec:mvn exec:java" ;;
600
+ gradle) echo "install:gradle dependencies|add:build.gradle edit|add_dev:build.gradle edit|run:gradle run|exec:gradle run" ;;
601
+ esac
602
+ ;;
603
+ ruby) echo "install:bundle install|add:bundle add|add_dev:bundle add --group development|run:bundle exec|exec:bundle exec" ;;
604
+ php) echo "install:composer install|add:composer require|add_dev:composer require --dev|run:php|exec:php" ;;
605
+ dotnet) echo "install:dotnet restore|add:dotnet add package|add_dev:dotnet add package|run:dotnet run|exec:dotnet run" ;;
606
+ elixir) echo "install:mix deps.get|add:mix deps.add|add_dev:mix deps.add|run:mix run|exec:mix run" ;;
607
+ haskell)
608
+ case "$pm" in
609
+ stack) echo "install:stack build|add:stack add|add_dev:stack add|run:stack run|exec:stack exec" ;;
610
+ cabal) echo "install:cabal build|add:cabal add|add_dev:cabal add|run:cabal run|exec:cabal exec" ;;
611
+ esac
612
+ ;;
613
+ cpp)
614
+ case "$pm" in
615
+ conan) echo "install:conan install|add:conanfile.txt edit|add_dev:conanfile.txt edit|run:cmake|exec:cmake" ;;
616
+ vcpkg) echo "install:vcpkg install|add:vcpkg add|add_dev:vcpkg add|run:cmake|exec:cmake" ;;
617
+ esac
618
+ ;;
619
+ swift) echo "install:swift package resolve|add:Package.swift edit|add_dev:Package.swift edit|run:swift run|exec:swift run" ;;
620
+ scala) echo "install:sbt update|add:build.sbt edit|add_dev:build.sbt edit|run:sbt run|exec:sbt run" ;;
621
+ clojure)
622
+ case "$pm" in
623
+ leiningen) echo "install:lein deps|add:project.clj edit|add_dev:project.clj edit|run:lein run|exec:lein exec" ;;
624
+ tools.deps) echo "install:clj -P|add:deps.edn edit|add_dev:deps.edn edit|run:clj -M|exec:clj -X" ;;
625
+ esac
626
+ ;;
627
+ julia) echo "install:julia -e 'using Pkg; Pkg.instantiate()'|add:julia -e 'using Pkg; Pkg.add()'|add_dev:julia -e 'using Pkg; Pkg.add()'|run:julia|exec:julia" ;;
628
+ r)
629
+ case "$pm" in
630
+ renv) echo "install:renv::restore()|add:renv::install()|add_dev:renv::install()|run:Rscript|exec:Rscript" ;;
631
+ packrat) echo "install:packrat::restore()|add:packrat::install()|add_dev:packrat::install()|run:Rscript|exec:Rscript" ;;
632
+ esac
633
+ ;;
634
+ esac
635
+ }
636
+
637
+ # Output JSON format
638
+ output_json() {
639
+ local first=true
640
+ echo "{"
641
+ echo " \"project_root\": \"${PROJECT_ROOT}\","
642
+ echo " \"languages\": ["
643
+
644
+ # Parse each detected language
645
+ local IFS=','
646
+ for entry in $DETECTED_LANGS; do
647
+ [[ -z "$entry" ]] && continue
648
+
649
+ if [[ "$first" == false ]]; then
650
+ echo ","
651
+ fi
652
+ first=false
653
+
654
+ # Parse pipe-delimited fields
655
+ local IFS='|'
656
+ local fields=($entry)
657
+ local lang="${fields[0]}"
658
+ local pm="${fields[1]}"
659
+ local ver="${fields[2]}"
660
+ local meth="${fields[3]}"
661
+ local lock="${fields[4]}"
662
+ local conf="${fields[5]}"
663
+ local cfg="${fields[6]}"
664
+ local field="${fields[7]}"
665
+
666
+ local rec=$(get_recommendation "$lang" "$pm" | sed 's/"/\\"/g')
667
+ local cmds=$(get_commands "$lang" "$pm")
668
+
669
+ echo " {"
670
+ echo " \"language\": \"$lang\","
671
+ echo " \"package_manager\": \"$pm\","
672
+ echo " \"version\": \"${ver:-}\","
673
+ echo " \"detection_method\": \"$meth\","
674
+ echo " \"confidence\": ${conf:-0},"
675
+ echo " \"lockfile\": \"${lock:-}\","
676
+ echo " \"config_file\": \"${cfg:-}\","
677
+ echo " \"package_manager_field\": \"${field:-}\","
678
+ echo " \"recommendation\": \"$rec\","
679
+ echo -n " \"commands\": {"
680
+
681
+ # Parse commands
682
+ local IFS='|'
683
+ local cmd_array=($cmds)
684
+ local first_cmd=true
685
+ for cmd in "${cmd_array[@]}"; do
686
+ local key=$(echo "$cmd" | cut -d':' -f1)
687
+ local val=$(echo "$cmd" | cut -d':' -f2)
688
+ if [[ "$first_cmd" == false ]]; then
689
+ echo -n ", "
690
+ fi
691
+ first_cmd=false
692
+ echo -n "\"$key\": \"$val\""
693
+ done
694
+ echo -n "}"
695
+ echo ""
696
+ echo -n " }"
697
+ done
698
+
699
+ echo ""
700
+ echo " ]"
701
+ echo "}"
702
+ }
703
+
704
+ # Output human-readable format
705
+ output_human() {
706
+ if [[ "$RECOMMEND_ONLY" == true ]]; then
707
+ # Get first language's package manager
708
+ local first_entry=$(echo "$DETECTED_LANGS" | cut -d',' -f1)
709
+ echo "$first_entry" | cut -d'|' -f2
710
+ return
711
+ fi
712
+
713
+ echo ""
714
+ echo "╔════════════════════════════════════════════════════════════╗"
715
+ echo "║ Multi-Language Package Manager Detection Report ║"
716
+ echo "╚════════════════════════════════════════════════════════════╝"
717
+ echo ""
718
+ echo "Project: ${PROJECT_ROOT}"
719
+ echo ""
720
+
721
+ if [[ -z "$DETECTED_LANGS" ]]; then
722
+ echo "${RED}No package managers detected for any language!${NC}"
723
+ echo ""
724
+ echo "This project may be new or use an unsupported build system."
725
+ return
726
+ fi
727
+
728
+ # Parse each detected language
729
+ local IFS=','
730
+ for entry in $DETECTED_LANGS; do
731
+ [[ -z "$entry" ]] && continue
732
+
733
+ # Parse pipe-delimited fields
734
+ local IFS='|'
735
+ local fields=($entry)
736
+ local lang="${fields[0]}"
737
+ local pm="${fields[1]}"
738
+ local ver="${fields[2]}"
739
+ local meth="${fields[3]}"
740
+ local lock="${fields[4]}"
741
+ local conf="${fields[5]}"
742
+
743
+ local display=$(get_lang_display "$lang")
744
+ local rec=$(get_recommendation "$lang" "$pm")
745
+
746
+ echo "${CYAN}${display}${NC}"
747
+ echo " ${GREEN}Recommended: ${pm}${NC}"
748
+ [[ -n "$ver" ]] && echo " Version: ${ver}"
749
+ echo " Detection: ${meth}"
750
+ echo " Confidence: ${conf}%"
751
+ [[ -n "$lock" ]] && echo " Lockfile: ${lock}"
752
+ echo ""
753
+ echo " ${BLUE}Recommendation:${NC}"
754
+ echo " ${rec}"
755
+ echo ""
756
+
757
+ # Show commands
758
+ local cmds=$(get_commands "$lang" "$pm")
759
+ echo " ${BLUE}Quick Commands:${NC}"
760
+ local IFS='|'
761
+ local cmd_array=($cmds)
762
+ for cmd in "${cmd_array[@]}"; do
763
+ local key=$(echo "$cmd" | cut -d':' -f1)
764
+ local val=$(echo "$cmd" | cut -d':' -f2)
765
+ printf " %-12s %s\n" "${key}:" "$val"
766
+ done
767
+ echo ""
768
+ done
769
+ }
770
+
771
+ # ============================================
772
+ # MAIN EXECUTION
773
+ # ============================================
774
+ main() {
775
+ detect_all
776
+
777
+ if [[ -z "$DETECTED_LANGS" ]]; then
778
+ if [[ "$JSON_OUTPUT" == true ]]; then
779
+ echo '{"languages": [], "error": "No package managers detected"}'
780
+ else
781
+ error "No package managers detected for any language"
782
+ fi
783
+ exit 1
784
+ fi
785
+
786
+ if [[ "$JSON_OUTPUT" == true ]]; then
787
+ output_json
788
+ else
789
+ output_human
790
+ fi
791
+
792
+ exit 0
793
+ }
794
+
795
+ # Run
796
+ main