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
@@ -0,0 +1,229 @@
1
+ #!/usr/bin/env bash
2
+
3
+ declare -g _LANG_SETUP=""
4
+
5
+ _init_lang_tools() {
6
+ [[ -n "$_LANG_SETUP" ]] && return
7
+ _LANG_SETUP=1
8
+ declare -gA LANG_TOOLS
9
+
10
+ # JavaScript
11
+ LANG_TOOLS["JavaScript:eslint"]="eslint|lint|npx --no-install eslint .|npx --no-install eslint . --fix|safe|native"
12
+ LANG_TOOLS["JavaScript:prettier"]="prettier|format|npx --no-install prettier . --check|npx --no-install prettier . --write|safe|native"
13
+ LANG_TOOLS["JavaScript:npm_audit"]="npm audit|deps|npm audit --audit-level=high|||native"
14
+ LANG_TOOLS["JavaScript:vitest"]="vitest|test|npx --no-install vitest run|||native"
15
+ LANG_TOOLS["JavaScript:jest"]="jest|test|npx --no-install jest|||native"
16
+ LANG_TOOLS["JavaScript:markdownlint"]="markdownlint-cli2|docs|npx --no-install markdownlint-cli2 \"**/*.md\" --no-missiglob|npx --no-install markdownlint-cli2 --fix \"**/*.md\"|safe|native"
17
+
18
+ # TypeScript
19
+ LANG_TOOLS["TypeScript:tsc"]="tsc|type-check|npx --no-install tsc --noEmit|||native"
20
+ LANG_TOOLS["TypeScript:biome"]="biome|lint+format|npx --no-install biome check .|npx --no-install biome check --write .|safe|native"
21
+ LANG_TOOLS["TypeScript:eslint"]="eslint|lint|npx --no-install eslint . --ext .ts,.tsx|npx --no-install eslint . --ext .ts,.tsx --fix|safe|native"
22
+ LANG_TOOLS["TypeScript:prettier"]="prettier|format|npx --no-install prettier . --check|npx --no-install prettier . --write|safe|native"
23
+
24
+ # Python
25
+ LANG_TOOLS["Python:compileall"]="python|syntax|python -c 'import ast,pathlib; [ast.parse(p.read_text(encoding=\"utf-8\"), filename=str(p)) for p in pathlib.Path(\".\").rglob(\"*.py\") if not any(part in p.parts for part in (\"node_modules\", \".venv\", \"venv\", \"__pycache__\"))]'|||native"
26
+ LANG_TOOLS["Python:ruff"]="ruff|lint+format|ruff check .|ruff check . --fix|safe|native"
27
+ LANG_TOOLS["Python:ruff_format"]="ruff|format|ruff format --check .|ruff format .|safe|native"
28
+ LANG_TOOLS["Python:pyright"]="pyright|type-check|pyright|||community"
29
+ LANG_TOOLS["Python:mypy"]="mypy|type-check|mypy .|||community"
30
+ LANG_TOOLS["Python:bandit"]="bandit|security|bandit -r . -x 'node_modules,.venv,venv,__pycache__'|||community"
31
+ LANG_TOOLS["Python:pip_audit"]="pip-audit|deps|pip-audit|||community"
32
+ LANG_TOOLS["Python:pytest"]="pytest|test|python -m pytest|||native"
33
+ LANG_TOOLS["Python:pytest_cov"]="pytest-cov|coverage|python -m pytest --cov=. --cov-report=term-missing|||community"
34
+ LANG_TOOLS["Python:vulture"]="vulture|dead-code|vulture . --exclude 'node_modules,.venv,venv,__pycache__'|||community"
35
+ LANG_TOOLS["Python:radon"]="radon|complexity|radon cc . -s -a --exclude 'node_modules,.venv,venv,__pycache__'|||community"
36
+
37
+ # Shell
38
+ LANG_TOOLS["Shell:bash_syntax"]="bash|syntax|bash -n {}|||native"
39
+ LANG_TOOLS["Shell:zsh_syntax"]="zsh|syntax|zsh -n {}|||native"
40
+ LANG_TOOLS["Shell:shellcheck"]="shellcheck|lint|shellcheck {}|||community"
41
+ LANG_TOOLS["Shell:shfmt"]="shfmt|format|shfmt -d {}|shfmt -w {}|safe|community"
42
+ LANG_TOOLS["Shell:checkmake"]="checkmake|build|checkmake Makefile|||community"
43
+
44
+ # SQL
45
+ LANG_TOOLS["SQL:sqlfluff"]="sqlfluff|lint|sqlfluff lint {} --dialect ansi|sqlfluff fix {} --dialect ansi|safe|community"
46
+
47
+ # Go
48
+ LANG_TOOLS["Go:gofmt"]="gofmt|format|while IFS= read -r -d '' file; do gofmt -d \"\$file\"; done < <(find . -type f -name '*.go' -not -path './vendor/*' -print0)|while IFS= read -r -d '' file; do gofmt -w \"\$file\"; done < <(find . -type f -name '*.go' -not -path './vendor/*' -print0)|safe|official"
49
+ LANG_TOOLS["Go:go_vet"]="go vet|lint|go vet ./...|||official"
50
+ LANG_TOOLS["Go:staticcheck"]="staticcheck|lint|staticcheck ./...|||community"
51
+ LANG_TOOLS["Go:govulncheck"]="govulncheck|deps|govulncheck ./...|||official"
52
+ LANG_TOOLS["Go:go_test"]="go test|test|go test ./...|||official"
53
+
54
+ # Rust
55
+ LANG_TOOLS["Rust:cargo_check"]="cargo|syntax|cargo check --all-targets --all-features 2>&1 | tail -5|||official"
56
+ LANG_TOOLS["Rust:rustfmt"]="rustfmt|format|cargo fmt --all -- --check|cargo fmt --all|safe|official"
57
+ LANG_TOOLS["Rust:clippy"]="clippy|lint|cargo clippy --all-targets --all-features -- -D warnings|cargo clippy --fix --allow-dirty|safe|official"
58
+ LANG_TOOLS["Rust:cargo_test"]="cargo test|test|cargo test --all-features|||official"
59
+ LANG_TOOLS["Rust:cargo_audit"]="cargo-audit|deps|cargo audit|||community"
60
+
61
+ # C/C++
62
+ LANG_TOOLS["C/C++:clang_syntax"]="clang|syntax|clang -fsyntax-only -Wall {} 2>&1 | head -20|||official"
63
+ LANG_TOOLS["C/C++:clang_format"]="clang-format|format|clang-format --dry-run --Werror {}|clang-format -i {}|safe|official"
64
+ LANG_TOOLS["C/C++:clang_tidy"]="clang-tidy|lint|clang-tidy {} -- -std=c17 2>&1 | head -20|||official"
65
+
66
+ # Java
67
+ LANG_TOOLS["Java:javac"]="javac|syntax|javac -d \"${TMPDIR:-/tmp}\" -Xlint:all {} 2>&1 | head -10|||official"
68
+
69
+ # Docker
70
+ LANG_TOOLS["Docker:hadolint"]="hadolint|lint|hadolint Dockerfile|||community"
71
+ LANG_TOOLS["Docker:docker_compose"]="docker compose|syntax|docker compose config -q|||official"
72
+
73
+ # Terraform
74
+ LANG_TOOLS["Terraform:terraform_fmt"]="terraform|format|terraform fmt -check -recursive|terraform fmt -recursive|safe|official"
75
+ LANG_TOOLS["Terraform:terraform_validate"]="terraform|syntax|terraform validate|||official"
76
+ LANG_TOOLS["Terraform:tflint"]="tflint|lint|tflint --recursive|||community"
77
+
78
+ # PHP
79
+ LANG_TOOLS["PHP:php_lint"]="php|syntax|php -l {}|||official"
80
+ LANG_TOOLS["PHP:phpstan"]="phpstan|type-check|phpstan analyse --no-progress 2>&1 | tail -20|||community"
81
+ LANG_TOOLS["PHP:phpunit"]="phpunit|test|phpunit|||community"
82
+
83
+ # Ruby
84
+ LANG_TOOLS["Ruby:ruby_syntax"]="ruby|syntax|ruby -c {}|||official"
85
+ LANG_TOOLS["Ruby:rubocop"]="rubocop|lint|rubocop|rubocop -a|safe|community"
86
+
87
+ # Dart
88
+ LANG_TOOLS["Dart:dart_analyze"]="dart|lint|dart analyze|||official"
89
+ LANG_TOOLS["Dart:dart_format"]="dart|format|dart format -o none --set-exit-if-changed .|dart format .|safe|official"
90
+
91
+ # Elixir
92
+ LANG_TOOLS["Elixir:mix_compile"]="mix|syntax|mix compile --warnings-as-errors|||official"
93
+ LANG_TOOLS["Elixir:mix_format"]="mix|format|mix format --check-formatted|mix format|safe|official"
94
+ LANG_TOOLS["Elixir:mix_test"]="mix|test|mix test|||official"
95
+
96
+ # Kotlin
97
+ LANG_TOOLS["Kotlin:detekt"]="detekt|lint|detekt|||community"
98
+ LANG_TOOLS["Kotlin:ktlint"]="ktlint|format|ktlint --relative|ktlint --format --relative|safe|community"
99
+
100
+ # Swift
101
+ LANG_TOOLS["Swift:swift_build"]="swift|syntax|swift build|||official"
102
+ LANG_TOOLS["Swift:swiftlint"]="swiftlint|lint|swiftlint lint|swiftlint --fix|safe|community"
103
+
104
+ # Haskell
105
+ LANG_TOOLS["Haskell:hlint"]="hlint|lint|hlint .|||community"
106
+
107
+ # Lua
108
+ LANG_TOOLS["Lua:luac"]="luac|syntax|luac -p {}|||official"
109
+
110
+ # Lua
111
+ LANG_TOOLS["Lua:selene"]="selene|lint|selene .|||community"
112
+ LANG_TOOLS["Lua:stylua"]="stylua|format|stylua --check .|stylua .|safe|community"
113
+
114
+ # Nix
115
+ LANG_TOOLS["Nix:nix_flake"]="nix|syntax|nix flake check|||official"
116
+ LANG_TOOLS["Nix:statix"]="statix|lint|statix check .|||community"
117
+
118
+ # Julia
119
+ LANG_TOOLS["Julia:julia_test"]="julia|test|julia --project -e 'using Pkg; Pkg.test()'|||native"
120
+
121
+ # Zig
122
+ LANG_TOOLS["Zig:zig_build"]="zig|syntax|zig build|||official"
123
+ LANG_TOOLS["Zig:zig_fmt"]="zig|format|zig fmt --check .|zig fmt .|safe|official"
124
+
125
+ # GitHub Actions
126
+ LANG_TOOLS["GitHub Actions:actionlint"]="actionlint|lint|actionlint|||community"
127
+
128
+ # Ansible
129
+ LANG_TOOLS["Ansible:ansible_lint"]="ansible-lint|lint|ansible-lint|||community"
130
+
131
+ # Cross-language tools
132
+ LANG_TOOLS["*:yamllint"]="yamllint|lint|yamllint .|||community"
133
+ LANG_TOOLS["*:jq_json"]="jq|syntax|jq empty {} 2>/dev/null|||native"
134
+ LANG_TOOLS["*:xmllint"]="xmllint|syntax|xmllint --noout {} 2>&1|||official"
135
+ LANG_TOOLS["*:trivy"]="trivy|security|trivy fs --scanners=config,vuln --quiet .|||community"
136
+ LANG_TOOLS["*:semgrep"]="semgrep|security|semgrep --quiet 2>&1 | tail -10|||community"
137
+ }
138
+
139
+ _parse_lang_tool() {
140
+ local entry="$1"
141
+ local parsed_tool parsed_category parsed_run parsed_fix parsed_safety parsed_termux
142
+
143
+ parsed_termux="${entry##*|}"
144
+ entry="${entry%|*}"
145
+ parsed_safety="${entry##*|}"
146
+ entry="${entry%|*}"
147
+ parsed_fix="${entry##*|}"
148
+ entry="${entry%|*}"
149
+ parsed_tool="${entry%%|*}"
150
+ entry="${entry#*|}"
151
+ parsed_category="${entry%%|*}"
152
+ parsed_run="${entry#*|}"
153
+
154
+ declare -g -a PARSED_LANG_TOOL
155
+ PARSED_LANG_TOOL=("$parsed_tool" "$parsed_category" "$parsed_run" "$parsed_fix" "$parsed_safety" "$parsed_termux")
156
+ }
157
+
158
+ _get_lang_tools() {
159
+ local lang="$1" mode="${2:-quick}" include_global="${3:-true}"
160
+ _init_lang_tools
161
+ local results=()
162
+
163
+ for key in "${!LANG_TOOLS[@]}"; do
164
+ local k_lang="${key%%:*}"
165
+ [[ "$k_lang" == "*" || "$k_lang" == "$lang" ]] || continue
166
+ [[ "$k_lang" != "*" || "$include_global" == "true" ]] || continue
167
+ local entry="${LANG_TOOLS[$key]}"
168
+ _parse_lang_tool "$entry"
169
+ local category="${PARSED_LANG_TOOL[1]}"
170
+
171
+ # Filter by mode
172
+ case "$mode" in
173
+ quick)
174
+ case "$category" in
175
+ syntax|format|lint|lint+format|type-check|test) ;;
176
+ *) continue ;;
177
+ esac ;;
178
+ standard)
179
+ case "$category" in
180
+ syntax|format|lint|lint+format|type-check|test|security|deps|coverage|dead-code|complexity) ;;
181
+ *) continue ;;
182
+ esac ;;
183
+ deep) ;; # All categories
184
+ esac
185
+
186
+ results+=("$entry")
187
+ done
188
+ printf '%s\n' "${results[@]}"
189
+ }
190
+
191
+ _tool_command() {
192
+ local cmd="$1" file="$2"
193
+ if [[ "$cmd" == *'{}'* ]] && [[ -n "$file" ]]; then
194
+ local quoted_file
195
+ printf -v quoted_file '%q' "$file"
196
+ cmd="${cmd//\{\}/$quoted_file}"
197
+ fi
198
+ printf '%s\n' "$cmd"
199
+ }
200
+
201
+ _is_tool_available() {
202
+ local tool="$1"
203
+ case "$tool" in
204
+ python) command -v python3 &>/dev/null || command -v python &>/dev/null ;;
205
+ eslint|prettier|vitest|jest|markdownlint-cli2|tsc|biome)
206
+ command -v "$tool" &>/dev/null || {
207
+ command -v npx &>/dev/null && timeout 5 npx --no-install "$tool" --version &>/dev/null
208
+ } ;;
209
+ "npm audit") command -v npm &>/dev/null ;;
210
+ "go vet"|"go test") command -v go &>/dev/null ;;
211
+ cargo|"cargo test") command -v cargo &>/dev/null ;;
212
+ clippy) command -v cargo &>/dev/null && cargo clippy --help &>/dev/null ;;
213
+ rustfmt) command -v cargo &>/dev/null && cargo fmt --help &>/dev/null ;;
214
+ "docker compose") command -v docker &>/dev/null && docker compose version &>/dev/null ;;
215
+ pytest-cov) python -c 'import pytest_cov' &>/dev/null ;;
216
+ pip-audit) python -m pip_audit --help &>/dev/null || command -v pip-audit &>/dev/null ;;
217
+ *) command -v "$tool" &>/dev/null ;;
218
+ esac
219
+ }
220
+
221
+ _run_tool_check() {
222
+ local tool="$1" cmd="$2"
223
+ local timeout_val="${3:-30}"
224
+ if ! _is_tool_available "$tool"; then
225
+ printf '%s\n' "__TOOL_NOT_FOUND__"
226
+ return 2
227
+ fi
228
+ timeout "$timeout_val" bash -o pipefail -c "$cmd" 2>&1
229
+ }
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # shellcheck disable=SC1091
2
3
 
3
4
  import "@/utils/log"
4
5
  import "@/utils/colors"
@@ -9,11 +10,11 @@ _fix_storage() {
9
10
  }
10
11
 
11
12
  _fix_mkdir() {
13
+ local rc=0
12
14
  for dir in "$KARNEL_CONFIG" "$KARNEL_CACHE" "$KARNEL_DATA"; do
13
- mkdir -p "$dir" 2>/dev/null
14
- chmod 755 "$dir" 2>/dev/null
15
+ mkdir -p "$dir" && chmod 755 "$dir" 2>/dev/null || { rc=1; log_warn "Failed to create $dir"; }
15
16
  done
16
- return 0
17
+ return $rc
17
18
  }
18
19
 
19
20
  _fix_pkg_install() {
@@ -97,14 +98,18 @@ _fix_pg_start() {
97
98
  }
98
99
 
99
100
  _fix_pg_install() {
100
- source "$KARNEL_PATH/utils/env.sh" 2>/dev/null
101
- import "@/modules/db" 2>/dev/null
102
- if type install_db &>/dev/null; then
103
- install_db 2>/dev/null
104
- return $?
101
+ if ! command -v pg_ctl &>/dev/null; then
102
+ pkg install -y postgresql 2>/dev/null || return 1
105
103
  fi
106
- pkg install -y postgresql 2>/dev/null
107
- return $?
104
+ if ! command -v initdb &>/dev/null; then
105
+ return 1
106
+ fi
107
+ local pg_data="$PREFIX/var/lib/postgresql"
108
+ mkdir -p "$pg_data" 2>/dev/null
109
+ if [[ ! -f "$pg_data/PG_VERSION" ]]; then
110
+ initdb -D "$pg_data" 2>/dev/null || return 1
111
+ fi
112
+ return 0
108
113
  }
109
114
 
110
115
  _fix_symlinks() {
@@ -150,31 +155,24 @@ _fix_shell_syntax() {
150
155
  local config=""
151
156
  if [[ -f "$HOME/.zshrc" ]]; then
152
157
  config="$HOME/.zshrc"
158
+ if ! command -v zsh &>/dev/null; then
159
+ log_warn "zsh not installed — cannot validate .zshrc syntax"
160
+ return 1
161
+ fi
153
162
  elif [[ -f "$HOME/.bashrc" ]]; then
154
163
  config="$HOME/.bashrc"
164
+ else
165
+ return 1
155
166
  fi
156
- if [[ -n "$config" ]]; then
157
- cp "$config" "${config}.bak" 2>/dev/null
158
- local marker="# ===== Karnel Banner ====="
159
- local banner_block=""
160
- if grep -qF "$marker" "$config" 2>/dev/null; then
161
- local marker_line
162
- marker_line=$(grep -nF "$marker" "$config" | head -1 | cut -d: -f1)
163
- if [[ -n "$marker_line" ]]; then
164
- banner_block=$(sed -n "$((marker_line - 1)),\$p" "$config" 2>/dev/null)
165
- fi
166
- fi
167
- local tmpconfig
168
- tmpconfig=$(mktemp)
169
- sed '/^source.*\/dev\/null$/d; /^#.*syntax error/d' "$config" > "$tmpconfig" 2>/dev/null
170
- if [[ -n "$banner_block" ]]; then
171
- echo "" >> "$tmpconfig"
172
- echo "$banner_block" >> "$tmpconfig"
173
- fi
174
- cp "$tmpconfig" "$config" 2>/dev/null
175
- rm -f "$tmpconfig"
167
+ local bak="${config}.bak.$(date +%s)"
168
+ cp "$config" "$bak" 2>/dev/null || return 1
169
+ sed -i '/^# syntax error/d' "$config" 2>/dev/null
170
+ local validator="bash"
171
+ [[ "$config" == *.zshrc ]] && validator="zsh"
172
+ if "$validator" -n "$config" 2>/dev/null; then
176
173
  return 0
177
174
  fi
175
+ cp "$bak" "$config" 2>/dev/null
178
176
  return 1
179
177
  }
180
178
 
@@ -194,10 +192,11 @@ _fix_disk_cleanup() {
194
192
  }
195
193
 
196
194
  _fix_mkdir_single() {
197
- for dir in "$KARNEL_CONFIG" "$KARNEL_CACHE" "$KARNEL_DATA" "$HOME/.local/share/karnel-data"; do
198
- [[ -d "$dir" ]] || mkdir -p "$dir" 2>/dev/null
195
+ local rc=0
196
+ for dir in "$KARNEL_CONFIG" "$KARNEL_CACHE" "$KARNEL_DATA"; do
197
+ [[ -d "$dir" ]] || mkdir -p "$dir" 2>/dev/null || { rc=1; log_warn "Failed to create $dir"; }
199
198
  done
200
- return 0
199
+ return $rc
201
200
  }
202
201
 
203
202
  # ===== NEW FIX CALLBACKS =====
@@ -215,10 +214,12 @@ _fix_psutil() {
215
214
  }
216
215
 
217
216
  _fix_pip_check() {
218
- local broken
219
- broken=$(pip check 2>&1 | grep -oP '^\S+' | head -3)
220
- if [[ -n "$broken" ]]; then
221
- pip install --upgrade --force-reinstall $broken 2>/dev/null
217
+ local -a broken_pkgs=()
218
+ while IFS= read -r line; do
219
+ broken_pkgs+=("$line")
220
+ done < <(pip check 2>&1 | grep -oP '^\S+' | head -3)
221
+ if [[ ${#broken_pkgs[@]} -gt 0 ]]; then
222
+ pip install --upgrade --force-reinstall "${broken_pkgs[@]}" 2>/dev/null
222
223
  fi
223
224
  return 0
224
225
  }
@@ -230,11 +231,11 @@ _fix_npm_shebangs() {
230
231
  local shebang
231
232
  shebang=$(head -1 "$f" 2>/dev/null | tr -d '\0')
232
233
  if [[ "$shebang" == "#!/usr/bin/env node" ]]; then
233
- sed -i "1s|^.*$|#!$PREFIX/bin/node|" "$f"
234
- ((fixed++))
234
+ sed -i "1s|^.*$|#!$PREFIX/bin/node|" "$f" && ((fixed++))
235
235
  elif [[ "$shebang" == "#!/usr/bin/env bash" ]] || [[ "$shebang" == "#!/usr/bin/env sh" ]]; then
236
- sed -i "1s|^.*$|#!$PREFIX/bin/bash|" "$f"
237
- ((fixed++))
236
+ sed -i "1s|^.*$|#!$PREFIX/bin/bash|" "$f" && ((fixed++))
237
+ elif [[ "$shebang" == "#!/usr/bin/env python3" ]] || [[ "$shebang" == "#!/usr/bin/env python" ]]; then
238
+ sed -i "1s|^.*$|#!$PREFIX/bin/python3|" "$f" && ((fixed++))
238
239
  fi
239
240
  done
240
241
  return 0
@@ -256,7 +257,11 @@ _fix_pip_cache() {
256
257
  }
257
258
 
258
259
  _fix_pycache() {
259
- find "$PREFIX/lib/python3.*" -name "__pycache__" -exec rm -rf {} + 2>/dev/null
260
+ local python_dir
261
+ for python_dir in "$PREFIX"/lib/python3.*; do
262
+ [[ -d "$python_dir" ]] || continue
263
+ find "$python_dir" -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null
264
+ done
260
265
  return 0
261
266
  }
262
267
 
@@ -269,8 +274,16 @@ _fix_proot_ubuntu() {
269
274
  }
270
275
 
271
276
  _fix_dns() {
272
- echo 'nameserver 8.8.8.8' > "$PREFIX/etc/resolv.conf" 2>/dev/null
273
- return $?
277
+ if command -v nslookup &>/dev/null && nslookup github.com &>/dev/null; then
278
+ return 0
279
+ fi
280
+ local resolv_conf="$PREFIX/etc/resolv.conf"
281
+ if [[ -w "$resolv_conf" ]] || [[ -w "$PREFIX/etc" ]]; then
282
+ cp "$resolv_conf" "${resolv_conf}.bak" 2>/dev/null
283
+ echo 'nameserver 8.8.8.8' > "$resolv_conf" 2>/dev/null && return 0
284
+ echo 'nameserver 8.8.4.4' >> "$resolv_conf" 2>/dev/null || true
285
+ fi
286
+ return 1
274
287
  }
275
288
 
276
289
  _fix_mirror() {
@@ -287,12 +300,16 @@ _fix_locale() {
287
300
  config="$HOME/.bashrc"
288
301
  fi
289
302
  echo 'export LANG=en_US.UTF-8' >> "$config" 2>/dev/null
290
- return $?
291
303
  }
292
304
 
293
305
 
294
306
  _fix_zombies() {
295
- ps aux 2>/dev/null | awk '$8 ~ /^Z/ {print $2}' | xargs kill -9 2>/dev/null
307
+ local zombies
308
+ zombies=$(ps aux 2>/dev/null | awk '$8 ~ /^Z/ {print $2}')
309
+ if [[ -n "$zombies" ]]; then
310
+ log_warn "Zombie processes (PID: $zombies) cannot be killed — the parent process must reap them"
311
+ log_info "Run 'ps aux | grep Z' to see zombie parent PIDs"
312
+ fi
296
313
  return 0
297
314
  }
298
315