karnel-termux 4.7.6 → 4.7.7

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 (81) hide show
  1. package/README.md +230 -225
  2. package/install.sh +30 -9
  3. package/karnel/bin/karnel +2 -2
  4. package/karnel/cli/commands/backup.sh +10 -2
  5. package/karnel/cli/commands/brain.sh +28 -23
  6. package/karnel/cli/commands/cleanup.sh +10 -4
  7. package/karnel/cli/commands/deploy.sh +53 -0
  8. package/karnel/cli/commands/doctor/code.sh +225 -0
  9. package/karnel/cli/commands/doctor/code_detect.sh +184 -0
  10. package/karnel/cli/commands/doctor/code_exec.sh +278 -0
  11. package/karnel/cli/commands/doctor/code_langs.sh +229 -0
  12. package/karnel/cli/commands/doctor/fixes.sh +63 -46
  13. package/karnel/cli/commands/doctor.sh +222 -80
  14. package/karnel/cli/commands/env.sh +2 -0
  15. package/karnel/cli/commands/ia.sh +12 -2
  16. package/karnel/cli/commands/init.sh +17 -9
  17. package/karnel/cli/commands/install.sh +90 -54
  18. package/karnel/cli/commands/list.sh +36 -0
  19. package/karnel/cli/commands/pg.sh +21 -6
  20. package/karnel/cli/commands/reinstall.sh +99 -0
  21. package/karnel/cli/commands/restore.sh +43 -3
  22. package/karnel/cli/commands/search.sh +2 -2
  23. package/karnel/cli/commands/update.sh +6 -1
  24. package/karnel/cli/commands/upgrade.sh +8 -1
  25. package/karnel/cli/commands/voice.sh +2 -1
  26. package/karnel/cli/karnel.sh +11 -5
  27. package/karnel/modules/games.sh +11 -0
  28. package/karnel/tools/ai/all.sh +1 -0
  29. package/karnel/tools/ai/copilot-termux/README.md +40 -0
  30. package/karnel/tools/ai/copilot-termux/install.sh +80 -0
  31. package/karnel/tools/ai/copilot-termux/package.json +20 -0
  32. package/karnel/tools/db/all.sh +2 -0
  33. package/karnel/tools/deploy/railway/install.sh +2 -2
  34. package/karnel/tools/dev/all.sh +8 -0
  35. package/karnel/tools/dev/applaunch/__pycache__/applaunch.cpython-314.pyc +0 -0
  36. package/karnel/tools/dev/applaunch/applaunch.py +434 -0
  37. package/karnel/tools/dev/applaunch/install.sh +51 -0
  38. package/karnel/tools/dev/fconv/__pycache__/fconv.cpython-314.pyc +0 -0
  39. package/karnel/tools/dev/fconv/fconv.py +749 -0
  40. package/karnel/tools/dev/fconv/install.sh +51 -0
  41. package/karnel/tools/dev/filecheck/__pycache__/filecheck.cpython-314.pyc +0 -0
  42. package/karnel/tools/dev/filecheck/filecheck.py +429 -0
  43. package/karnel/tools/dev/filecheck/install.sh +51 -0
  44. package/karnel/tools/dev/notes/__pycache__/notes.cpython-314.pyc +0 -0
  45. package/karnel/tools/dev/notes/install.sh +51 -0
  46. package/karnel/tools/dev/notes/notes.py +849 -0
  47. package/karnel/tools/dev/passman/__pycache__/passman.cpython-314.pyc +0 -0
  48. package/karnel/tools/dev/passman/install.sh +51 -0
  49. package/karnel/tools/dev/passman/passman.py +536 -0
  50. package/karnel/tools/dev/splash/__pycache__/splash.cpython-314.pyc +0 -0
  51. package/karnel/tools/dev/splash/install.sh +51 -0
  52. package/karnel/tools/dev/splash/splash.py +188 -0
  53. package/karnel/tools/dev/treex/install.sh +51 -0
  54. package/karnel/tools/dev/treex/treex.py +2036 -0
  55. package/karnel/tools/dev/websites/__pycache__/websites.cpython-314.pyc +0 -0
  56. package/karnel/tools/dev/websites/install.sh +51 -0
  57. package/karnel/tools/dev/websites/websites.py +844 -0
  58. package/karnel/tools/games/all.sh +62 -0
  59. package/karnel/tools/games/arcade/__pycache__/arcade.cpython-314.pyc +0 -0
  60. package/karnel/tools/games/arcade/arcade.py +193 -0
  61. package/karnel/tools/games/arcade/install.sh +51 -0
  62. package/karnel/tools/games/buzz/__pycache__/buzz.cpython-314.pyc +0 -0
  63. package/karnel/tools/games/buzz/buzz.py +1264 -0
  64. package/karnel/tools/games/buzz/install.sh +51 -0
  65. package/karnel/tools/games/ctfgod/__pycache__/ctfgod.cpython-314.pyc +0 -0
  66. package/karnel/tools/games/ctfgod/ctfgod.py +1576 -0
  67. package/karnel/tools/games/ctfgod/install.sh +51 -0
  68. package/karnel/tools/games/detective/__pycache__/detective.cpython-314.pyc +0 -0
  69. package/karnel/tools/games/detective/detective.py +2091 -0
  70. package/karnel/tools/games/detective/install.sh +51 -0
  71. package/karnel/tools/games/pet-friends/__pycache__/pet-friends.cpython-314.pyc +0 -0
  72. package/karnel/tools/games/pet-friends/install.sh +51 -0
  73. package/karnel/tools/games/pet-friends/pet-friends.py +15802 -0
  74. package/karnel/tools/games/tamagotchi/__pycache__/tamagotchi.cpython-314.pyc +0 -0
  75. package/karnel/tools/games/tamagotchi/install.sh +51 -0
  76. package/karnel/tools/games/tamagotchi/tamagotchi.py +1224 -0
  77. package/karnel/tools/games/terminal-arcade/__pycache__/terminal-arcade.cpython-314.pyc +0 -0
  78. package/karnel/tools/games/terminal-arcade/terminal-arcade.py +193 -0
  79. package/karnel/tools/npm/all.sh +1 -0
  80. package/karnel/utils/log.sh +34 -12
  81. package/package.json +1 -1
@@ -4,18 +4,80 @@ import "@/utils/log"
4
4
  import "@/utils/colors"
5
5
 
6
6
  doctor_main() {
7
+ local subcommand="${1:-termux}"
8
+ case "$subcommand" in
9
+ help|--help|-h)
10
+ doctor_help
11
+ ;;
12
+ termux)
13
+ shift
14
+ doctor_termux "$@"
15
+ ;;
16
+ code)
17
+ shift
18
+ doctor_code "$@"
19
+ ;;
20
+ --quick|-q)
21
+ log_warn "Deprecated: use ${D_CYAN}karnel doctor termux --quick${NC}"
22
+ doctor_termux "$@"
23
+ ;;
24
+ --fix|-f)
25
+ log_warn "Deprecated: use ${D_CYAN}karnel doctor termux --fix${NC}"
26
+ shift
27
+ doctor_termux "--fix" "$@"
28
+ ;;
29
+ *)
30
+ log_error "Unknown doctor subcommand: $subcommand"
31
+ echo
32
+ doctor_help
33
+ return 1
34
+ ;;
35
+ esac
36
+ }
37
+
38
+ doctor_help() {
39
+ echo
40
+ box "◈ KARNEL DOCTOR ◈"
41
+ echo
42
+ log_info "Usage: karnel doctor <subcommand> [options]"
43
+ echo
44
+ log_info "When no subcommand is given, runs termux diagnostics."
45
+ echo
46
+ separator_section "Subcommands"
47
+ echo
48
+ printf " ${D_CYAN}%-16s${NC} %s\n" "termux" "Diagnose Termux environment (full system check)"
49
+ printf " ${D_CYAN}%-16s${NC} %s\n" "code" "Analyze project code structure and tools"
50
+ echo
51
+ separator_section "Termux Options"
52
+ echo
53
+ printf " ${D_CYAN}%-16s${NC} %s\n" "--quick, -q" "Skip slow checks"
54
+ printf " ${D_CYAN}%-16s${NC} %s\n" "--fix, -f" "Auto-apply all fixes without prompt"
55
+ echo
56
+ log_info "Examples:"
57
+ list_item "${D_CYAN}karnel doctor${NC} — Termux diagnostics (default)"
58
+ list_item "${D_CYAN}karnel doctor termux --quick${NC} — Quick diagnostics"
59
+ list_item "${D_CYAN}karnel doctor code${NC} — Analyze current project"
60
+ list_item "${D_CYAN}karnel doctor termux --fix${NC} — Diagnose + auto-fix"
61
+ echo
62
+ }
63
+
64
+ doctor_termux() {
7
65
  local QUICK_MODE=false
8
66
  local FIX_MODE=false
9
67
  for arg in "$@"; do
10
- [[ "$arg" == "--quick" || "$arg" == "-q" ]] && QUICK_MODE=true
11
- [[ "$arg" == "--fix" || "$arg" == "-f" ]] && FIX_MODE=true
68
+ case "$arg" in
69
+ --quick|-q) QUICK_MODE=true ;;
70
+ --fix|-f) FIX_MODE=true ;;
71
+ --help|-h) doctor_help; return ;;
72
+ --*) log_error "Unknown option: $arg"; doctor_help; return 1 ;;
73
+ esac
12
74
  done
13
75
 
14
76
  echo
15
- box "◈ KARNEL DOCTOR ◈"
77
+ box "◈ KARNEL DOCTOR — TERMUX ◈"
16
78
  echo
17
79
  if $QUICK_MODE; then
18
- log_info "Quick mode — skipping slow checks"
80
+ log_info "Quick mode — running essential system and package checks only"
19
81
  fi
20
82
  log_info "Diagnosing your Termux and Karnel environment..."
21
83
  echo
@@ -35,14 +97,13 @@ doctor_main() {
35
97
  android_ver=$(getprop ro.build.version.release 2>/dev/null)
36
98
  android_ver="${android_ver:-Unknown}"
37
99
 
38
- local termux_ver=""
39
- if command -v termux-info &>/dev/null; then
40
- termux_ver=$(timeout 5 termux-info 2>/dev/null | grep -i "termux_version" | head -n1 | cut -d'=' -f2)
100
+ local termux_ver="${TERMUX_VERSION:-}"
101
+ if [[ -z "$termux_ver" ]] && command -v termux-info &>/dev/null; then
102
+ termux_ver=$(timeout 5 termux-info 2>/dev/null | grep -i "termux_version" | head -n1 | cut -d'=' -f2 || true)
41
103
  fi
42
104
  if [[ -z "$termux_ver" ]]; then
43
- termux_ver=$(dpkg -s termux-tools 2>/dev/null | grep -i version | awk '{print $2}')
105
+ termux_ver=$(dpkg -s termux-tools 2>/dev/null | grep -i version | awk '{print $2}' 2>/dev/null || echo "Unknown")
44
106
  fi
45
- termux_ver="${termux_ver:-Unknown}"
46
107
 
47
108
  log_success "Android Version: $android_ver"
48
109
  log_success "Termux Version: $termux_ver"
@@ -127,7 +188,7 @@ doctor_main() {
127
188
  case "$dep" in
128
189
  git) version=$(git --version | awk '{print $3}') ;;
129
190
  node) version=$(node --version) ;;
130
- python) version=$(python3 --version 2>/dev/null || python --version 2>/dev/null | awk '{print $2}') ;;
191
+ python) version=$( (python3 --version 2>/dev/null || python --version 2>/dev/null) | awk '{print $2}' ) ;;
131
192
  rustc) version=$(rustc --version | awk '{print $2}') ;;
132
193
  go) version=$(go version | awk '{print $3}') ;;
133
194
  clang) version=$(clang --version | head -1 | awk '{print $3}') ;;
@@ -153,7 +214,10 @@ doctor_main() {
153
214
  separator_section "Package Manager & System Health"
154
215
  echo
155
216
 
156
- if dpkg --audit &>/dev/null; then
217
+ local dpkg_audit_out
218
+ dpkg_audit_out=$(dpkg --audit 2>&1)
219
+ local dpkg_rc=$?
220
+ if [[ $dpkg_rc -eq 0 ]] && [[ -z "$dpkg_audit_out" ]]; then
157
221
  log_success "dpkg package manager is healthy"
158
222
  else
159
223
  log_error "dpkg has interrupted installations!"
@@ -186,9 +250,55 @@ doctor_main() {
186
250
  fi
187
251
  fi
188
252
 
253
+ # Keyring integrity check (Termux-fixer inspired)
254
+ local keyring_dir="$PREFIX/etc/apt/trusted.gpg.d"
255
+ if [[ -d "$keyring_dir" ]]; then
256
+ local key_count
257
+ key_count=$(find "$keyring_dir" -maxdepth 1 -type f \( -name '*.gpg' -o -name '*.asc' \) -print 2>/dev/null | wc -l)
258
+ if (( key_count == 0 )); then
259
+ log_warn "No APT keyring files found in $keyring_dir"
260
+ ((warnings++))
261
+ fix_commands+=("pkg update -y && pkg install -y termux-keyring")
262
+ fix_descriptions+=("Reinstall termux-keyring")
263
+ fix_callbacks+=("_fix_keyring")
264
+ else
265
+ log_success "APT keyring: $key_count key file(s) present"
266
+ fi
267
+ fi
268
+
269
+ # System clock sanity check (HTTPS cert validation)
270
+ if command -v date &>/dev/null; then
271
+ local current_year
272
+ current_year=$(date +%Y 2>/dev/null)
273
+ if (( current_year < 2024 )); then
274
+ log_error "System clock is incorrect (year: $current_year) — HTTPS/TLS certs will fail!"
275
+ ((errors++))
276
+ else
277
+ log_success "System clock: $current_year"
278
+ fi
279
+ fi
280
+
281
+ # APT cache health check
282
+ local apt_cache_dir="$PREFIX/var/apt/lists"
283
+ if [[ -d "$apt_cache_dir" ]]; then
284
+ local cache_size
285
+ cache_size=$(du -sh "$apt_cache_dir" 2>/dev/null | awk '{print $1}')
286
+ local cache_files
287
+ cache_files=$(find "$apt_cache_dir" -type f 2>/dev/null | wc -l)
288
+ if (( cache_files > 500 )); then
289
+ log_warn "APT lists cache is large: $cache_size ($cache_files files)"
290
+ ((warnings++))
291
+ fix_commands+=("rm -rf $apt_cache_dir/* && pkg update -y")
292
+ fix_descriptions+=("Reset APT lists cache (fixes Hash Sum mismatch)")
293
+ fix_callbacks+=("_fix_apt_cache")
294
+ else
295
+ log_success "APT cache: $cache_size ($cache_files files)"
296
+ fi
297
+ fi
298
+
189
299
  if $QUICK_MODE; then
190
300
  echo
191
- log_info "Quick mode: skipping Node.js, Python, PostgreSQL, AI tools, binary health, I/O, and network checks"
301
+ log_info "Quick mode: skipping extended runtime, AI, shell, process, I/O, and network checks"
192
302
  echo
193
303
  else
194
304
 
@@ -384,10 +494,12 @@ doctor_main() {
384
494
  fi
385
495
 
386
496
  # C extension build capability
387
- local cc_test="$PREFIX/tmp/cext_test.c"
388
- echo '#include <Python.h>' > "$cc_test"
389
- if python3-config --includes &>/dev/null && \
390
- clang $(python3-config --includes) -shared -fPIC -o /dev/null -x c - <<<'#include <Python.h>' &>/dev/null; then
497
+ local python_include_output
498
+ local -a python_include_flags=()
499
+ python_include_output=$(python3-config --includes 2>/dev/null || true)
500
+ read -r -a python_include_flags <<< "$python_include_output"
501
+ if [[ ${#python_include_flags[@]} -gt 0 ]] && \
502
+ clang "${python_include_flags[@]}" -shared -fPIC -o /dev/null -x c - <<<'#include <Python.h>' &>/dev/null; then
391
503
  log_success "C extensions can be compiled (Python.h + clang OK)"
392
504
  else
393
505
  log_warn "C extension build may fail — clang or Python headers issue"
@@ -396,7 +508,6 @@ doctor_main() {
396
508
  fix_descriptions+=("Install C build dependencies for Python extensions")
397
509
  fix_callbacks+=("_fix_pkg_install")
398
510
  fi
399
- rm -f "$cc_test"
400
511
 
401
512
  # uv availability (used by hermes-agent installer)
402
513
  if command -v uv &>/dev/null; then
@@ -406,9 +517,11 @@ doctor_main() {
406
517
  fi
407
518
 
408
519
  # pip check — detect broken dependencies
409
- local pip_check_output
410
- pip_check_output=$(timeout 15 pip check 2>&1 | grep -i "broken\|missing\|conflict\|incompatible" || true)
411
- if [[ -z "$pip_check_output" ]]; then
520
+ local pip_check_output pip_check_rc
521
+ pip_check_output=$(timeout 15 pip check 2>&1) && pip_check_rc=0 || pip_check_rc=$?
522
+ local broken_lines
523
+ broken_lines=$(echo "$pip_check_output" | grep -i "broken\|missing\|conflict\|incompatible" || true)
524
+ if (( pip_check_rc == 0 )) || [[ -z "$broken_lines" ]]; then
412
525
  log_success "pip dependencies: consistent"
413
526
  else
414
527
  log_warn "pip dependency issues detected"
@@ -417,7 +530,7 @@ doctor_main() {
417
530
  done
418
531
  ((warnings++))
419
532
  local broken_pkgs
420
- broken_pkgs=$(timeout 10 pip check 2>&1 | grep -oP '^\S+' | head -3 | tr '\n' ' ')
533
+ broken_pkgs=$(echo "$broken_lines" | grep -oP '^\S+' | head -3 | tr '\n' ' ')
421
534
  if [[ -n "$broken_pkgs" ]]; then
422
535
  fix_commands+=("pip install --upgrade --force-reinstall $broken_pkgs")
423
536
  fix_descriptions+=("Fix pip dependency conflicts: $broken_pkgs")
@@ -467,14 +580,13 @@ doctor_main() {
467
580
  fix_callbacks+=("_fix_banner")
468
581
  fi
469
582
  fi
470
- fi # end QUICK_MODE skip
471
583
 
472
584
  # ===== 10. AI TOOLS STATUS =====
473
585
  echo
474
586
  separator_section "AI Tools Installed"
475
587
  echo
476
588
 
477
- local -a ai_cmds=("opencode" "claude" "gemini" "codex" "qwen" "vibe" "mimo" "hermes" "kimi" "ollama" "freebuff" "pi" "agy" "mmx" "gentle-ai" "gga" "engram" "codegraph" "kilocode" "kiro" "crush" "odysseus" "openclaude" "openclaw" "command-code" "kimchi" "cline" "omni-route" "ctx7" "openspec")
589
+ local -a ai_cmds=("opencode" "claude" "gemini" "codex" "qwen" "vibe" "mimo" "hermes" "kimi" "ollama" "freebuff" "pi" "agy" "mmx" "gentle-ai" "gga" "engram" "codegraph" "kilocode" "kiro" "crush" "odysseus" "openclaude" "openclaw" "command-code" "kimchi" "cline" "omni-route" "ctx7" "openspec" "copilot")
478
590
  local ai_count=0
479
591
 
480
592
  for cmd in "${ai_cmds[@]}"; do
@@ -699,9 +811,7 @@ doctor_main() {
699
811
 
700
812
  if command -v proot-distro &>/dev/null; then
701
813
  log_success "proot-distro: available"
702
- local ubuntu_installed=false
703
- if proot-distro list 2>/dev/null | grep -qi ubuntu; then
704
- ubuntu_installed=true
814
+ if proot-distro list 2>&1 | grep -qi ubuntu; then
705
815
  log_success "Ubuntu proot container: installed"
706
816
  else
707
817
  log_info "Ubuntu proot container: not installed (needed by kimchi)"
@@ -727,8 +837,10 @@ doctor_main() {
727
837
  separator_section "Termux:API"
728
838
  echo
729
839
 
730
- if command -v termux-info &>/dev/null; then
731
- log_success "Termux:API is installed"
840
+ if command -v termux-battery-status &>/dev/null; then
841
+ log_success "Termux:API is installed (termux-battery-status available)"
842
+ elif dpkg -s termux-api 2>/dev/null | grep -q 'Status.*installed'; then
843
+ log_success "Termux:API package installed"
732
844
  else
733
845
  log_warn "Termux:API not installed (needed for voice commands)"
734
846
  ((warnings++))
@@ -775,14 +887,24 @@ doctor_main() {
775
887
  echo
776
888
 
777
889
  # DNS resolution
778
- if nslookup github.com &>/dev/null || host github.com &>/dev/null; then
890
+ local dns_ok=false
891
+ if command -v nslookup &>/dev/null; then
892
+ nslookup github.com &>/dev/null && dns_ok=true
893
+ elif command -v host &>/dev/null; then
894
+ host github.com &>/dev/null && dns_ok=true
895
+ elif command -v curl &>/dev/null; then
896
+ curl -fsSL --max-time 5 https://github.com &>/dev/null && dns_ok=true
897
+ fi
898
+ if $dns_ok; then
779
899
  log_success "DNS resolution: OK"
780
900
  else
781
- log_warn "DNS resolution failed"
901
+ local dns_warn="DNS resolution check failed"
902
+ if ! command -v nslookup &>/dev/null && ! command -v host &>/dev/null; then
903
+ dns_warn="$dns_warn (install dnsutils or whois for detailed check)"
904
+ fi
905
+ log_warn "$dns_warn"
782
906
  ((warnings++))
783
- fix_commands+=("echo 'nameserver 8.8.8.8' > $PREFIX/etc/resolv.conf")
784
- fix_descriptions+=("Set Google DNS (8.8.8.8) for Termux")
785
- fix_callbacks+=("_fix_dns")
907
+
786
908
  fi
787
909
 
788
910
  if curl -fsSL --max-time 5 https://github.com &>/dev/null; then
@@ -843,7 +965,7 @@ doctor_main() {
843
965
  separator_section "Karnel Data Integrity"
844
966
  echo
845
967
 
846
- local karnel_dirs=("$KARNEL_CONFIG" "$KARNEL_CACHE" "$KARNEL_DATA" "$HOME/.local/share/karnel-data")
968
+ local karnel_dirs=("$KARNEL_CONFIG" "$KARNEL_CACHE" "$KARNEL_DATA")
847
969
  for dir in "${karnel_dirs[@]}"; do
848
970
  if [[ -d "$dir" ]]; then
849
971
  local size
@@ -887,7 +1009,7 @@ doctor_main() {
887
1009
 
888
1010
  # Check url-quote-magic for parse errors (Termux zsh bug)
889
1011
  local uqm_file="$PREFIX/share/zsh/functions/Zle/url-quote-magic"
890
- if [[ -f "$uqm_file" ]] && grep -q '((${~localschema})' "$uqm_file" 2>/dev/null; then
1012
+ if [[ -f "$uqm_file" ]] && grep -qF "((\${~localschema})" "$uqm_file" 2>/dev/null; then
891
1013
  log_warn "url-quote-magic: double-paren parse error found (zsh 5.9 bug)"
892
1014
  log_warn "url-quote-magic has known double-paren syntax error"
893
1015
  fix_commands+=("true")
@@ -902,7 +1024,7 @@ doctor_main() {
902
1024
 
903
1025
  if command -v termux-info &>/dev/null; then
904
1026
  local gpu_info
905
- gpu_info=$(termux-info 2>/dev/null | grep -i "gpu\|render\|opengl" | head -3)
1027
+ gpu_info=$(timeout 10 termux-info 2>/dev/null | grep -i "gpu\|render\|opengl" | head -3)
906
1028
  if [[ -n "$gpu_info" ]]; then
907
1029
  log_success "GPU: $(echo "$gpu_info" | tr -s ' ')"
908
1030
  fi
@@ -936,7 +1058,7 @@ doctor_main() {
936
1058
 
937
1059
  if command -v termux-battery-status &>/dev/null; then
938
1060
  local battery_info
939
- battery_info=$(termux-battery-status 2>/dev/null)
1061
+ battery_info=$(timeout 5 termux-battery-status 2>/dev/null || true)
940
1062
  if [[ -n "$battery_info" ]]; then
941
1063
  local battery_pct
942
1064
  battery_pct=$(echo "$battery_info" | python3 -c "import json,sys; print(json.load(sys.stdin).get('percentage',0))" 2>/dev/null || echo "?")
@@ -952,6 +1074,8 @@ doctor_main() {
952
1074
  local charging
953
1075
  charging=$(echo "$battery_info" | python3 -c "import json,sys; print(json.load(sys.stdin).get('status','Unknown'))" 2>/dev/null || echo "?")
954
1076
  log_info "Charging status: $charging"
1077
+ else
1078
+ log_info "Battery status unavailable or timed out"
955
1079
  fi
956
1080
  else
957
1081
  log_info "termux-battery-status not available (install termux-api)"
@@ -1023,7 +1147,7 @@ doctor_main() {
1023
1147
  # Check for orphaned node/python processes
1024
1148
  local orphan_count=0
1025
1149
  orphan_count=$(pgrep -c -f 'node.*karnel\|python.*karnel' 2>/dev/null || echo 0)
1026
- if (( orphan_count > 2 )); then
1150
+ if [[ "$orphan_count" =~ ^[0-9]+$ ]] && (( orphan_count > 2 )); then
1027
1151
  log_warn "$orphan_count Karnel-related processes running (may be stale)"
1028
1152
  ((warnings++))
1029
1153
  fi
@@ -1033,8 +1157,8 @@ doctor_main() {
1033
1157
  separator_section "Storage I/O Health"
1034
1158
  echo
1035
1159
 
1036
- local io_test_file="$HOME/.cache/karnel_io_test"
1037
- mkdir -p "$(dirname "$io_test_file")" 2>/dev/null
1160
+ local io_test_file
1161
+ io_test_file="$(mktemp "$KARNEL_CACHE/karnel_io_test.XXXXXX" 2>/dev/null)" || io_test_file="$KARNEL_CACHE/karnel_io_test.$$"
1038
1162
  local io_start io_end io_time
1039
1163
  io_start=$(date +%s%N 2>/dev/null || echo 0)
1040
1164
  dd if=/dev/zero of="$io_test_file" bs=4096 count=100 2>/dev/null
@@ -1107,8 +1231,13 @@ doctor_main() {
1107
1231
  echo
1108
1232
 
1109
1233
  if [[ -d /storage ]]; then
1110
- local storage_count
1111
- storage_count=$(ls -1 /storage 2>/dev/null | grep -v '^emulated$\|^self$' | wc -l)
1234
+ local storage_count=0 storage_path storage_name
1235
+ for storage_path in /storage/*; do
1236
+ [[ -e "$storage_path" ]] || continue
1237
+ storage_name=$(basename "$storage_path")
1238
+ [[ "$storage_name" == "emulated" || "$storage_name" == "self" ]] && continue
1239
+ storage_count=$((storage_count + 1))
1240
+ done
1112
1241
  if (( storage_count > 0 )); then
1113
1242
  log_success "External storage: $storage_count volume(s) mounted"
1114
1243
  else
@@ -1119,54 +1248,23 @@ doctor_main() {
1119
1248
  # Check USB devices
1120
1249
  if [[ -d /dev/bus/usb ]]; then
1121
1250
  local usb_count
1122
- usb_count=$(ls /dev/bus/usb/ 2>/dev/null | wc -l)
1251
+ usb_count=$(find /dev/bus/usb -mindepth 1 -maxdepth 1 -type d -print 2>/dev/null | wc -l)
1123
1252
  if (( usb_count > 0 )); then
1124
1253
  log_info "USB: $usb_count bus(es) detected"
1125
1254
  fi
1126
1255
  fi
1127
1256
 
1257
+ fi # end QUICK_MODE skip
1258
+
1128
1259
  # ===== GENERATE REPORT =====
1129
1260
  local report_dir="$KARNEL_DATA/doctor_reports"
1130
- mkdir -p "$report_dir"
1261
+ mkdir -p "$report_dir" 2>/dev/null || log_warn "Could not create report directory"
1131
1262
  local report_file="$report_dir/doctor_report_latest.md"
1132
1263
 
1133
- cat >"$report_file" <<EOF
1134
- # Karnel Doctor Diagnostic Report
1135
- Generated: $(date)
1136
-
1137
- ## System Info
1138
- - **Android**: $android_ver
1139
- - **Termux**: $termux_ver
1140
- - **Architecture**: $arch
1141
- - **Karnel Version**: $karnel_ver
1142
-
1143
- ## Resources
1144
- - **Disk Free**: $free_space
1145
- - **RAM Total**: $ram_total
1146
- - **RAM Free**: $ram_free
1147
-
1148
- ## Storage & Permissions
1149
- - **Shared Storage**: $storage_status
1150
- - **Karnel Write Access**: $([ -w "$KARNEL_PATH" ] && echo "Yes" || echo "No")
1151
-
1152
- ## PostgreSQL
1153
- - **Installed**: $pg_installed
1154
- - **Data Found**: ${pg_data_found:-unknown}
1155
-
1156
- ## AI Tools
1157
- - **Count**: $ai_count
1158
-
1159
- ## Summary
1160
- - **Errors**: $errors
1161
- - **Warnings**: $warnings
1162
- - **Fixed**: $fixed
1163
- EOF
1164
-
1165
1264
  # ===== RESULTS =====
1166
1265
  echo
1167
1266
  separator
1168
1267
  log_success "Diagnostics completed!"
1169
- list_item "Report saved: ${D_CYAN}$report_file${D_NC}"
1170
1268
 
1171
1269
  if [[ $errors -gt 0 ]]; then
1172
1270
  log_error "Found $errors error(s) and $warnings warning(s)."
@@ -1201,8 +1299,6 @@ EOF
1201
1299
 
1202
1300
  if [[ -n "$callback" ]] && type "$callback" &>/dev/null 2>&1; then
1203
1301
  "$callback" && success=true
1204
- elif [[ -n "${fix_commands[$i]}" ]]; then
1205
- eval "${fix_commands[$i]}" 2>/dev/null && success=true
1206
1302
  fi
1207
1303
 
1208
1304
  if [[ "$success" == "true" ]]; then
@@ -1220,8 +1316,54 @@ EOF
1220
1316
  fi
1221
1317
  fi
1222
1318
  fi
1319
+
1320
+ if cat >"$report_file" <<EOF
1321
+ # Karnel Doctor Diagnostic Report
1322
+ Generated: $(date)
1323
+
1324
+ ## System Info
1325
+ - **Android**: $android_ver
1326
+ - **Termux**: $termux_ver
1327
+ - **Architecture**: $arch
1328
+ - **Karnel Version**: ${karnel_ver:-skipped}
1329
+
1330
+ ## Resources
1331
+ - **Disk Free**: $free_space
1332
+ - **RAM Total**: $ram_total
1333
+ - **RAM Free**: $ram_free
1334
+
1335
+ ## Storage & Permissions
1336
+ - **Shared Storage**: $storage_status
1337
+ - **Karnel Write Access**: $([ -w "$KARNEL_PATH" ] && echo "Yes" || echo "No")
1338
+
1339
+ ## PostgreSQL
1340
+ - **Installed**: ${pg_installed:-skipped}
1341
+ - **Data Found**: ${pg_data_found:-skipped}
1342
+
1343
+ ## AI Tools
1344
+ - **Count**: ${ai_count:-skipped}
1345
+
1346
+ ## Summary
1347
+ - **Errors**: $errors
1348
+ - **Warnings**: $warnings
1349
+ - **Fixed**: $fixed
1350
+ EOF
1351
+ then
1352
+ list_item "Report saved: ${D_CYAN}$report_file${D_NC}"
1353
+ else
1354
+ log_warn "Failed to save report"
1355
+ fi
1223
1356
  echo
1224
1357
  }
1225
1358
 
1226
- import "@/cli/commands/doctor/fixes"
1359
+ _fix_keyring() {
1360
+ pkg update -y &>/dev/null && pkg install -y termux-keyring &>/dev/null
1361
+ }
1227
1362
 
1363
+ _fix_apt_cache() {
1364
+ rm -rf "$PREFIX/var/apt/lists"/* 2>/dev/null
1365
+ pkg update -y &>/dev/null
1366
+ }
1367
+
1368
+ import "@/cli/commands/doctor/fixes"
1369
+ import "@/cli/commands/doctor/code"
@@ -100,6 +100,7 @@ env_unset() {
100
100
  local -a keys=()
101
101
  local line k
102
102
  while IFS= read -r line; do
103
+ [[ "$line" != *"="* ]] && continue
103
104
  line="${line#export }"
104
105
  k="${line%%=*}"
105
106
  keys+=("$k")
@@ -179,6 +180,7 @@ env_ls() {
179
180
  local line
180
181
 
181
182
  while IFS= read -r line; do
183
+ [[ "$line" != *"="* ]] && continue
182
184
  line="${line#export }"
183
185
  local k="${line%%=*}"
184
186
  local v="${line#*=}"
@@ -353,6 +353,16 @@ ia_sessions() {
353
353
  done
354
354
  fi
355
355
 
356
+ # Copilot-Termux sessions
357
+ if [[ -d "$HOME/.copilot" ]]; then
358
+ while IFS= read -r -d '' f; do
359
+ local basename; basename=$(basename "$f")
360
+ local ts; ts=$(stat -c %Y "$f" 2>/dev/null || echo "unknown")
361
+ local readable_ts; readable_ts=$(date -d "@$ts" +%Y%m%d_%H%M%S 2>/dev/null || echo "unknown")
362
+ sessions+=("[copilot]|$readable_ts|$basename")
363
+ done < <(find "$HOME/.copilot" \( -name 'events.jsonl' -o -name 'command-history-state.json' \) -type f -print0 2>/dev/null)
364
+ fi
365
+
356
366
  if [[ ${#sessions[@]} -eq 0 ]]; then
357
367
  log_warn "No AI sessions found"
358
368
  log_info "Start an AI tool to create your first session"
@@ -371,7 +381,7 @@ ia_sessions() {
371
381
  ts_raw=$(echo "$session" | cut -d'|' -f2)
372
382
  name=$(echo "$session" | cut -d'|' -f3-)
373
383
  local escaped_name
374
- escaped_name=$(printf '%s' "$name" | sed 's/"/\\"/g')
384
+ escaped_name=$(printf '%s' "$name" | sed 's/"/\\"/g' | sed "s/'/\\\\'/g")
375
385
  if [[ $first -eq 1 ]]; then
376
386
  first=0
377
387
  else
@@ -421,7 +431,7 @@ ia_routes() {
421
431
  local -a routes=()
422
432
 
423
433
  # Collect all available AI CLIs (em sincronia com AI_TOOLS_REGISTRY em tools/ai/all.sh)
424
- for cmd in qwen gemini claude vibe openclaude openclaw ollama codex opencode mimo engram codegraph pi agy mmx gentle-ai gga hermes kimi command-code freebuff kilocode kiro cline crush odysseus kimchi omni-route ctx7 openspec; do
434
+ for cmd in qwen gemini claude vibe openclaude openclaw ollama codex opencode mimo engram codegraph pi agy mmx gentle-ai gga hermes kimi command-code freebuff kilocode kiro cline crush odysseus kimchi omni-route ctx7 openspec copilot; do
425
435
  if command -v "$cmd" &>/dev/null; then
426
436
  local path
427
437
  path=$(command -v "$cmd")
@@ -131,7 +131,8 @@ EOF
131
131
  if ! command -v jq &>/dev/null; then
132
132
  log_warn "jq not found — skipping package.json update"
133
133
  else
134
- local temp=$(mktemp)
134
+ local temp
135
+ temp=$(mktemp)
135
136
  jq '.scripts.dev = "next dev --webpack" | .scripts.build = "next build --webpack" | .scripts.start = "next start"' package.json > "$temp" && mv "$temp" package.json
136
137
  log_success "Added --webpack flag to dev and build scripts"
137
138
  fi
@@ -531,7 +532,8 @@ EOF
531
532
  if ! command -v jq &>/dev/null; then
532
533
  log_warn "jq not found — skipping package.json update"
533
534
  else
534
- local temp=$(mktemp)
535
+ local temp
536
+ temp=$(mktemp)
535
537
  jq '.scripts += {
536
538
  "dev": "ts-node-dev --require tsconfig-paths/register --env-file=.env --respawn src/index.ts",
537
539
  "build": "tsc && tsc-alias -p tsconfig.json",
@@ -1005,8 +1007,8 @@ EOF
1005
1007
 
1006
1008
  # Create scripts/run.sh
1007
1009
  cat >scripts/run.sh <<'EOF'
1008
- #!/usr/bin/bash
1009
- go run cmd/api/main.go
1010
+ #!/usr/bin/env bash
1011
+ cargo run
1010
1012
  EOF
1011
1013
  chmod +x scripts/run.sh
1012
1014
 
@@ -1076,8 +1078,13 @@ configure_rust() {
1076
1078
 
1077
1079
  # Append dependencies to Cargo.toml
1078
1080
  if [[ -f "Cargo.toml" ]]; then
1079
- # Reset dependencies block
1080
- sed -i '/\[dependencies\]/q' Cargo.toml
1081
+ # Append after [dependencies] or add it
1082
+ if grep -q '^\[dependencies\]' Cargo.toml; then
1083
+ cat >>Cargo.toml <<EOF
1084
+ EOF
1085
+ else
1086
+ echo -e "\n[dependencies]" >> Cargo.toml
1087
+ fi
1081
1088
  cat >>Cargo.toml <<EOF
1082
1089
  tokio = { version = "1.0", features = ["full"] }
1083
1090
  serde = { version = "1.0", features = ["derive"] }
@@ -1184,8 +1191,8 @@ EOF
1184
1191
 
1185
1192
  # Create scripts/run.sh
1186
1193
  cat >scripts/run.sh <<'EOF'
1187
- #!/usr/bin/bash
1188
- cargo run
1194
+ #!/usr/bin/env bash
1195
+ go run cmd/api/main.go
1189
1196
  EOF
1190
1197
  chmod +x scripts/run.sh
1191
1198
 
@@ -1236,7 +1243,8 @@ init_main() {
1236
1243
  go | gin) configure_go ;;
1237
1244
  rust | axum) configure_rust ;;
1238
1245
  "")
1239
- local detected=$(detect_project_type)
1246
+ local detected
1247
+ detected=$(detect_project_type)
1240
1248
  if [[ "$detected" != "unknown" ]]; then
1241
1249
  log_info "Detected project type: $detected"
1242
1250
  echo