omni-catalyst 1.0.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 (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1137 -0
  3. package/core/bin/core +85 -0
  4. package/core/bin/omni +21 -0
  5. package/core/cli/commands/--version.sh +8 -0
  6. package/core/cli/commands/brain.sh +1549 -0
  7. package/core/cli/commands/doctor.sh +834 -0
  8. package/core/cli/commands/env.sh +226 -0
  9. package/core/cli/commands/init.sh +1266 -0
  10. package/core/cli/commands/install.sh +759 -0
  11. package/core/cli/commands/list.sh +397 -0
  12. package/core/cli/commands/open.sh +71 -0
  13. package/core/cli/commands/pg.sh +761 -0
  14. package/core/cli/commands/reinstall.sh +694 -0
  15. package/core/cli/commands/show.sh +90 -0
  16. package/core/cli/commands/uninstall.sh +700 -0
  17. package/core/cli/commands/update.sh +754 -0
  18. package/core/cli/commands/voice.sh +170 -0
  19. package/core/cli/core.sh +82 -0
  20. package/core/cli/omni.sh +634 -0
  21. package/core/modules/ai.sh +152 -0
  22. package/core/modules/auto.sh +90 -0
  23. package/core/modules/db.sh +94 -0
  24. package/core/modules/deploy.sh +50 -0
  25. package/core/modules/dev.sh +126 -0
  26. package/core/modules/editor.sh +101 -0
  27. package/core/modules/lang.sh +100 -0
  28. package/core/modules/npm.sh +122 -0
  29. package/core/modules/shell.sh +312 -0
  30. package/core/modules/ui.sh +115 -0
  31. package/core/tools/ai/all.sh +63 -0
  32. package/core/tools/ai/antigravity-cli/README.md +45 -0
  33. package/core/tools/ai/antigravity-cli/bin/agy +28 -0
  34. package/core/tools/ai/antigravity-cli/helper/agy_helper.c +39 -0
  35. package/core/tools/ai/antigravity-cli/install.sh +469 -0
  36. package/core/tools/ai/claude-code/README.md +45 -0
  37. package/core/tools/ai/claude-code/bin/claude +29 -0
  38. package/core/tools/ai/claude-code/helper/claude_helper.c +42 -0
  39. package/core/tools/ai/claude-code/install.sh +278 -0
  40. package/core/tools/ai/codegraph/README.md +43 -0
  41. package/core/tools/ai/codegraph/bin/codegraph +3 -0
  42. package/core/tools/ai/codegraph/install.sh +149 -0
  43. package/core/tools/ai/codex/README.md +44 -0
  44. package/core/tools/ai/codex/install.sh +104 -0
  45. package/core/tools/ai/command-code/README.md +62 -0
  46. package/core/tools/ai/command-code/install.sh +136 -0
  47. package/core/tools/ai/engram/README.md +44 -0
  48. package/core/tools/ai/engram/install.sh +127 -0
  49. package/core/tools/ai/freebuff/README.md +52 -0
  50. package/core/tools/ai/freebuff/bin/freebuff +28 -0
  51. package/core/tools/ai/freebuff/helper/freebuff_helper.c +47 -0
  52. package/core/tools/ai/freebuff/install.sh +301 -0
  53. package/core/tools/ai/gemini-cli/README.md +46 -0
  54. package/core/tools/ai/gemini-cli/install.sh +111 -0
  55. package/core/tools/ai/gentle-ai/README.md +42 -0
  56. package/core/tools/ai/gentle-ai/install.sh +253 -0
  57. package/core/tools/ai/gentle-ai/termux-patches.go +256 -0
  58. package/core/tools/ai/gga/README.md +49 -0
  59. package/core/tools/ai/gga/install.sh +134 -0
  60. package/core/tools/ai/hermes-agent/README.md +50 -0
  61. package/core/tools/ai/hermes-agent/install.sh +80 -0
  62. package/core/tools/ai/heygen/README.md +24 -0
  63. package/core/tools/ai/heygen/install.sh +126 -0
  64. package/core/tools/ai/kilocode-cli/README.md +45 -0
  65. package/core/tools/ai/kilocode-cli/bin/kilocode +21 -0
  66. package/core/tools/ai/kilocode-cli/helper/kilocode_helper.c +47 -0
  67. package/core/tools/ai/kilocode-cli/install.sh +179 -0
  68. package/core/tools/ai/kimchi-code/README.md +8 -0
  69. package/core/tools/ai/kimchi-code/install.sh +120 -0
  70. package/core/tools/ai/kimi-code/README.md +45 -0
  71. package/core/tools/ai/kimi-code/install.sh +111 -0
  72. package/core/tools/ai/kiro-cli/README.md +23 -0
  73. package/core/tools/ai/kiro-cli/install.sh +127 -0
  74. package/core/tools/ai/mimocode/README.md +43 -0
  75. package/core/tools/ai/mimocode/bin/mimo +28 -0
  76. package/core/tools/ai/mimocode/helper/mimocode_helper.c +47 -0
  77. package/core/tools/ai/mimocode/install.sh +287 -0
  78. package/core/tools/ai/minimax-cli/README.md +45 -0
  79. package/core/tools/ai/minimax-cli/install.sh +111 -0
  80. package/core/tools/ai/mistral-vibe/README.md +46 -0
  81. package/core/tools/ai/mistral-vibe/install.sh +119 -0
  82. package/core/tools/ai/odysseus/README.md +35 -0
  83. package/core/tools/ai/odysseus/install.sh +163 -0
  84. package/core/tools/ai/ollama/README.md +44 -0
  85. package/core/tools/ai/ollama/install.sh +78 -0
  86. package/core/tools/ai/openclaude/README.md +46 -0
  87. package/core/tools/ai/openclaude/install.sh +110 -0
  88. package/core/tools/ai/openclaw/README.md +47 -0
  89. package/core/tools/ai/openclaw/install.sh +112 -0
  90. package/core/tools/ai/opencode/README.md +51 -0
  91. package/core/tools/ai/opencode/bin/opencode +28 -0
  92. package/core/tools/ai/opencode/helper/opencode_helper.c +57 -0
  93. package/core/tools/ai/opencode/install.sh +290 -0
  94. package/core/tools/ai/pi/README.md +46 -0
  95. package/core/tools/ai/pi/install.sh +104 -0
  96. package/core/tools/ai/qwen-code/README.md +45 -0
  97. package/core/tools/ai/qwen-code/install.sh +111 -0
  98. package/core/tools/ai/seedance/README.md +22 -0
  99. package/core/tools/ai/seedance/install.sh +134 -0
  100. package/core/tools/ai/veo3/README.md +36 -0
  101. package/core/tools/ai/veo3/install.sh +151 -0
  102. package/core/tools/auto/all.sh +57 -0
  103. package/core/tools/auto/n8n/README.md +47 -0
  104. package/core/tools/auto/n8n/install.sh +102 -0
  105. package/core/tools/db/all.sh +60 -0
  106. package/core/tools/db/mariadb/README.md +43 -0
  107. package/core/tools/db/mariadb/install.sh +65 -0
  108. package/core/tools/db/mongodb/README.md +42 -0
  109. package/core/tools/db/mongodb/install.sh +73 -0
  110. package/core/tools/db/postgresql/README.md +45 -0
  111. package/core/tools/db/postgresql/install.sh +65 -0
  112. package/core/tools/db/sqlite/README.md +44 -0
  113. package/core/tools/db/sqlite/install.sh +65 -0
  114. package/core/tools/deploy/all.sh +39 -0
  115. package/core/tools/deploy/netlify/install.sh +41 -0
  116. package/core/tools/deploy/railway/install.sh +47 -0
  117. package/core/tools/deploy/vercel/install.sh +43 -0
  118. package/core/tools/dev/all.sh +75 -0
  119. package/core/tools/dev/bat/README.md +44 -0
  120. package/core/tools/dev/bat/install.sh +82 -0
  121. package/core/tools/dev/bc/README.md +44 -0
  122. package/core/tools/dev/bc/install.sh +82 -0
  123. package/core/tools/dev/cloudflared/README.md +43 -0
  124. package/core/tools/dev/cloudflared/install.sh +82 -0
  125. package/core/tools/dev/curl/README.md +43 -0
  126. package/core/tools/dev/curl/install.sh +82 -0
  127. package/core/tools/dev/fzf/README.md +44 -0
  128. package/core/tools/dev/fzf/install.sh +82 -0
  129. package/core/tools/dev/gh/README.md +43 -0
  130. package/core/tools/dev/gh/install.sh +82 -0
  131. package/core/tools/dev/html2text/README.md +44 -0
  132. package/core/tools/dev/html2text/install.sh +82 -0
  133. package/core/tools/dev/imagemagick/README.md +44 -0
  134. package/core/tools/dev/imagemagick/install.sh +82 -0
  135. package/core/tools/dev/jq/README.md +44 -0
  136. package/core/tools/dev/jq/install.sh +82 -0
  137. package/core/tools/dev/lsd/README.md +44 -0
  138. package/core/tools/dev/lsd/install.sh +82 -0
  139. package/core/tools/dev/make/README.md +44 -0
  140. package/core/tools/dev/make/install.sh +82 -0
  141. package/core/tools/dev/ncurses/README.md +42 -0
  142. package/core/tools/dev/ncurses/install.sh +82 -0
  143. package/core/tools/dev/proot/README.md +43 -0
  144. package/core/tools/dev/proot/install.sh +82 -0
  145. package/core/tools/dev/shfmt/README.md +44 -0
  146. package/core/tools/dev/shfmt/install.sh +82 -0
  147. package/core/tools/dev/tmate/README.md +44 -0
  148. package/core/tools/dev/tmate/install.sh +82 -0
  149. package/core/tools/dev/translate/README.md +44 -0
  150. package/core/tools/dev/translate/install.sh +82 -0
  151. package/core/tools/dev/tree/README.md +44 -0
  152. package/core/tools/dev/tree/install.sh +82 -0
  153. package/core/tools/dev/udocker/README.md +44 -0
  154. package/core/tools/dev/udocker/install.sh +82 -0
  155. package/core/tools/dev/wget/README.md +44 -0
  156. package/core/tools/dev/wget/install.sh +82 -0
  157. package/core/tools/editor/all.sh +58 -0
  158. package/core/tools/editor/neovim/README.md +43 -0
  159. package/core/tools/editor/neovim/install.sh +66 -0
  160. package/core/tools/editor/nvchad/README.md +45 -0
  161. package/core/tools/editor/nvchad/install.sh +110 -0
  162. package/core/tools/lang/all.sh +63 -0
  163. package/core/tools/lang/clang/README.md +43 -0
  164. package/core/tools/lang/clang/install.sh +79 -0
  165. package/core/tools/lang/golang/README.md +43 -0
  166. package/core/tools/lang/golang/install.sh +79 -0
  167. package/core/tools/lang/nodejs/README.md +43 -0
  168. package/core/tools/lang/nodejs/install.sh +79 -0
  169. package/core/tools/lang/perl/README.md +43 -0
  170. package/core/tools/lang/perl/install.sh +79 -0
  171. package/core/tools/lang/php/README.md +43 -0
  172. package/core/tools/lang/php/install.sh +79 -0
  173. package/core/tools/lang/python/README.md +43 -0
  174. package/core/tools/lang/python/install.sh +79 -0
  175. package/core/tools/lang/rust/README.md +43 -0
  176. package/core/tools/lang/rust/install.sh +79 -0
  177. package/core/tools/npm/all.sh +67 -0
  178. package/core/tools/npm/live-server/README.md +43 -0
  179. package/core/tools/npm/live-server/install.sh +95 -0
  180. package/core/tools/npm/localtunnel/README.md +43 -0
  181. package/core/tools/npm/localtunnel/install.sh +111 -0
  182. package/core/tools/npm/markserv/README.md +43 -0
  183. package/core/tools/npm/markserv/install.sh +94 -0
  184. package/core/tools/npm/ncu/README.md +43 -0
  185. package/core/tools/npm/ncu/install.sh +94 -0
  186. package/core/tools/npm/nestjs/README.md +43 -0
  187. package/core/tools/npm/nestjs/install.sh +94 -0
  188. package/core/tools/npm/ngrok/README.md +44 -0
  189. package/core/tools/npm/ngrok/install.sh +94 -0
  190. package/core/tools/npm/prettier/README.md +43 -0
  191. package/core/tools/npm/prettier/install.sh +94 -0
  192. package/core/tools/npm/psqlformat/README.md +43 -0
  193. package/core/tools/npm/psqlformat/install.sh +94 -0
  194. package/core/tools/npm/turbopack/README.md +8 -0
  195. package/core/tools/npm/turbopack/install.sh +41 -0
  196. package/core/tools/npm/typescript/README.md +43 -0
  197. package/core/tools/npm/typescript/install.sh +94 -0
  198. package/core/tools/npm/vercel/README.md +43 -0
  199. package/core/tools/npm/vercel/install.sh +94 -0
  200. package/core/tools/shell/all.sh +67 -0
  201. package/core/tools/shell/better-npm/README.md +43 -0
  202. package/core/tools/shell/better-npm/install.sh +85 -0
  203. package/core/tools/shell/fzf-tab/README.md +44 -0
  204. package/core/tools/shell/fzf-tab/install.sh +85 -0
  205. package/core/tools/shell/history-substring/README.md +43 -0
  206. package/core/tools/shell/history-substring/install.sh +85 -0
  207. package/core/tools/shell/powerlevel10k/README.md +43 -0
  208. package/core/tools/shell/powerlevel10k/install.sh +85 -0
  209. package/core/tools/shell/you-should-use/README.md +43 -0
  210. package/core/tools/shell/you-should-use/install.sh +85 -0
  211. package/core/tools/shell/zsh-autopair/README.md +44 -0
  212. package/core/tools/shell/zsh-autopair/install.sh +85 -0
  213. package/core/tools/shell/zsh-autosuggestions/README.md +43 -0
  214. package/core/tools/shell/zsh-autosuggestions/install.sh +85 -0
  215. package/core/tools/shell/zsh-completions/README.md +43 -0
  216. package/core/tools/shell/zsh-completions/install.sh +85 -0
  217. package/core/tools/shell/zsh-defer/README.md +43 -0
  218. package/core/tools/shell/zsh-defer/install.sh +85 -0
  219. package/core/tools/shell/zsh-syntax-highlighting/README.md +43 -0
  220. package/core/tools/shell/zsh-syntax-highlighting/install.sh +72 -0
  221. package/core/tools/ui/all.sh +61 -0
  222. package/core/tools/ui/banner/README.md +42 -0
  223. package/core/tools/ui/banner/install.sh +151 -0
  224. package/core/tools/ui/cursor/README.md +42 -0
  225. package/core/tools/ui/cursor/install.sh +58 -0
  226. package/core/tools/ui/extra-keys/README.md +43 -0
  227. package/core/tools/ui/extra-keys/install.sh +62 -0
  228. package/core/tools/ui/font/README.md +43 -0
  229. package/core/tools/ui/font/install.sh +63 -0
  230. package/core/utils/banner.sh +519 -0
  231. package/core/utils/bootstrap.sh +25 -0
  232. package/core/utils/colors.sh +31 -0
  233. package/core/utils/dialogrc +30 -0
  234. package/core/utils/env.sh +53 -0
  235. package/core/utils/log.sh +598 -0
  236. package/install.sh +272 -0
  237. package/package.json +43 -0
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env bash
2
+
3
+ import "@/utils/log"
4
+ import "@/utils/colors"
5
+
6
+ : "${OMNI_CACHE:=$HOME/.cache/omni}"
7
+ : "${OMNI_PATH:=$HOME/omni/core}"
8
+ : "${PREFIX:=$PREFIX}"
9
+
10
+ LOG_FILE="$OMNI_CACHE/install_ai.log"
11
+ GENTLE_AI_DATA_DIR="${GENTLE_AI_DATA_DIR:-$HOME/.local/share/omni-data/gentle-ai}"
12
+
13
+ _gentle_ai_dependencies() {
14
+ loading "Installing dependencies" _gentle_ai_dependencies_impl
15
+ }
16
+
17
+ _gentle_ai_dependencies_impl() {
18
+ declare -A DEPS=(
19
+ ["golang"]="go"
20
+ ["git"]="git"
21
+ ["curl"]="curl"
22
+ )
23
+
24
+ local pkg_name bin_name
25
+ for pkg_name in "${!DEPS[@]}"; do
26
+ bin_name="${DEPS[$pkg_name]}"
27
+ if ! command -v "$bin_name" &>/dev/null; then
28
+ if ! pkg install "$pkg_name" -y &>>"$LOG_FILE"; then
29
+ log_error "Failed to install $pkg_name"
30
+ return 1
31
+ fi
32
+ fi
33
+ done
34
+
35
+ return 0
36
+ }
37
+
38
+ _gentle_ai_ensure_go() {
39
+ loading "Checking Go version" _gentle_ai_ensure_go_impl
40
+ }
41
+
42
+ _gentle_ai_ensure_go_impl() {
43
+ if ! command -v go &>/dev/null; then
44
+ log_error "Go is required but not installed"
45
+ return 1
46
+ fi
47
+
48
+ local go_installed
49
+ go_installed=$(go version | sed 's/.*go\([0-9.]*\).*/\1/')
50
+
51
+ local go_required
52
+ if [ -f "$GENTLE_AI_DATA_DIR/go.mod" ]; then
53
+ go_required=$(sed -n 's/^go \([0-9.]*\)/\1/p' "$GENTLE_AI_DATA_DIR/go.mod" | head -1)
54
+ fi
55
+
56
+ if [ -z "$go_required" ]; then
57
+ go_required="1.25.0"
58
+ fi
59
+
60
+ if ! _version_ge "$go_installed" "$go_required"; then
61
+ log_error "Go $go_required+ required (detected $go_installed). Run: pkg upgrade golang"
62
+ return 1
63
+ fi
64
+
65
+ return 0
66
+ }
67
+
68
+ _version_ge() {
69
+ local v1="$1" v2="$2"
70
+ local highest
71
+ highest=$(printf '%s\n%s\n' "$v1" "$v2" | sort -V | tail -1)
72
+ [ "$highest" = "$v1" ]
73
+ }
74
+
75
+ _clone_or_update_repo() {
76
+ loading "Cloning or updating gentle-ai repo" _clone_or_update_repo_impl
77
+ }
78
+
79
+ _clone_or_update_repo_impl() {
80
+ local repo_url="https://github.com/Gentleman-Programming/gentle-ai.git"
81
+
82
+ if [ -d "$GENTLE_AI_DATA_DIR/.git" ]; then
83
+ git -C "$GENTLE_AI_DATA_DIR" remote set-url origin "$repo_url" &>>"$LOG_FILE"
84
+ git -C "$GENTLE_AI_DATA_DIR" stash --include-untracked &>>"$LOG_FILE" || true
85
+ if ! git -C "$GENTLE_AI_DATA_DIR" fetch origin &>>"$LOG_FILE"; then
86
+ log_error "Failed to fetch from remote"
87
+ return 1
88
+ fi
89
+ if ! git -C "$GENTLE_AI_DATA_DIR" reset --hard origin/main &>>"$LOG_FILE"; then
90
+ log_error "Failed to reset to origin/main"
91
+ return 1
92
+ fi
93
+ else
94
+ if [ -d "$GENTLE_AI_DATA_DIR" ]; then
95
+ rm -rf "$GENTLE_AI_DATA_DIR"
96
+ fi
97
+ if ! git clone "$repo_url" "$GENTLE_AI_DATA_DIR" &>>"$LOG_FILE"; then
98
+ log_error "Failed to clone gentle-ai repo"
99
+ return 1
100
+ fi
101
+ fi
102
+
103
+ return 0
104
+ }
105
+
106
+ _build_and_apply_patches() {
107
+ loading "Applying Termux patches" _build_and_apply_patches_impl
108
+ }
109
+
110
+ _build_and_apply_patches_impl() {
111
+ local patcher_src="$OMNI_PATH/tools/ai/gentle-ai/termux-patches.go"
112
+ local patcher_bin="$OMNI_CACHE/termux-patcher"
113
+
114
+ mkdir -p "$OMNI_CACHE"
115
+
116
+ if [ ! -f "$patcher_bin" ] || [ "$patcher_src" -nt "$patcher_bin" ]; then
117
+ if ! go build -o "$patcher_bin" "$patcher_src" &>>"$LOG_FILE"; then
118
+ log_error "Failed to compile patcher"
119
+ return 1
120
+ fi
121
+ fi
122
+
123
+ pushd "$GENTLE_AI_DATA_DIR" &>/dev/null || return 1
124
+
125
+ local patch_out patch_rc
126
+ patch_out=$("$patcher_bin" "$GENTLE_AI_DATA_DIR" 2>&1)
127
+ patch_rc=$?
128
+
129
+ echo "$patch_out" >>"$LOG_FILE"
130
+
131
+ if [ $patch_rc -ne 0 ]; then
132
+ popd &>/dev/null || true
133
+ echo ""
134
+ log_error "Termux patches failed. Output:"
135
+ echo "$patch_out"
136
+ return 1
137
+ fi
138
+
139
+ popd &>/dev/null || true
140
+ return 0
141
+ }
142
+
143
+ _compile() {
144
+ loading "Compiling gentle-ai" _compile_impl
145
+ }
146
+
147
+ _compile_impl() {
148
+ if ! command -v gcc &>/dev/null && ! command -v clang &>/dev/null; then
149
+ export CGO_ENABLED=0
150
+ fi
151
+
152
+ local build_dir="$GENTLE_AI_DATA_DIR/cmd/gentle-ai"
153
+ if [ ! -d "$build_dir" ]; then
154
+ log_error "Entry point not found at cmd/gentle-ai"
155
+ return 1
156
+ fi
157
+
158
+ pushd "$GENTLE_AI_DATA_DIR" &>/dev/null || return 1
159
+
160
+ if ! go mod download &>>"$LOG_FILE"; then
161
+ popd &>/dev/null || true
162
+ log_error "Failed to download Go dependencies"
163
+ return 1
164
+ fi
165
+
166
+ if ! go build -trimpath -ldflags="-s -w" -o gentle-ai ./cmd/gentle-ai/ &>>"$LOG_FILE"; then
167
+ popd &>/dev/null || true
168
+ log_error "Failed to compile gentle-ai"
169
+ return 1
170
+ fi
171
+
172
+ popd &>/dev/null || true
173
+
174
+ if [ ! -f "$GENTLE_AI_DATA_DIR/gentle-ai" ]; then
175
+ log_error "Compilation succeeded but binary not found"
176
+ return 1
177
+ fi
178
+
179
+ return 0
180
+ }
181
+
182
+ _install_binary() {
183
+ loading "Installing binary" _install_binary_impl
184
+ }
185
+
186
+ _install_binary_impl() {
187
+ if ! cp "$GENTLE_AI_DATA_DIR/gentle-ai" "$PREFIX/bin/gentle-ai" &>>"$LOG_FILE"; then
188
+ log_error "Failed to install binary to $PREFIX/bin/gentle-ai"
189
+ return 1
190
+ fi
191
+
192
+ chmod +x "$PREFIX/bin/gentle-ai"
193
+ return 0
194
+ }
195
+
196
+ install_gentle_ai() {
197
+ if command -v gentle-ai &>/dev/null; then
198
+ log_info "gentle-ai is already installed"
199
+ return 2
200
+ fi
201
+
202
+ log_info "Installing gentle-ai..."
203
+ mkdir -p "$(dirname "$LOG_FILE")" "$OMNI_CACHE"
204
+
205
+ _gentle_ai_dependencies || return 1
206
+ _clone_or_update_repo || return 1
207
+ _gentle_ai_ensure_go || return 1
208
+ _build_and_apply_patches || return 1
209
+ _compile || return 1
210
+ _install_binary || return 1
211
+
212
+ log_success "gentle-ai installed"
213
+ return 0
214
+ }
215
+
216
+ uninstall_gentle_ai() {
217
+ if ! command -v gentle-ai &>/dev/null; then
218
+ log_info "gentle-ai is not installed"
219
+ return 2
220
+ fi
221
+ log_info "Uninstalling gentle-ai..."
222
+ mkdir -p "$(dirname "$LOG_FILE")"
223
+
224
+ rm -f "$PREFIX/bin/gentle-ai"
225
+ rm -rf "$GENTLE_AI_DATA_DIR"
226
+
227
+ if [ ! -f "$PREFIX/bin/gentle-ai" ] && [ ! -d "$GENTLE_AI_DATA_DIR" ]; then
228
+ log_success "gentle-ai uninstalled"
229
+ return 0
230
+ else
231
+ log_error "Failed to uninstall gentle-ai"
232
+ return 1
233
+ fi
234
+ }
235
+
236
+ update_gentle_ai() {
237
+ log_info "Updating gentle-ai..."
238
+ mkdir -p "$(dirname "$LOG_FILE")"
239
+
240
+ _clone_or_update_repo || return 1
241
+ _gentle_ai_ensure_go || return 1
242
+ _build_and_apply_patches || return 1
243
+ _compile || return 1
244
+ _install_binary || return 1
245
+
246
+ log_success "gentle-ai updated"
247
+ return 0
248
+ }
249
+
250
+ reinstall_gentle_ai() {
251
+ uninstall_gentle_ai
252
+ install_gentle_ai
253
+ }
@@ -0,0 +1,256 @@
1
+ // termux-patches applies the necessary source-code changes to compile and run
2
+ // gentle-ai on Android/Termux.
3
+ //
4
+ // Unlike a sed-based approach, this program uses exact Go source patterns so
5
+ // that upstream changes that break the patch are DETECTED (non-zero exit)
6
+ // rather than silently skipped.
7
+ //
8
+ // Usage:
9
+ //
10
+ // go run termux-patches.go [source-directory]
11
+ //
12
+ // Default source-directory is "." (current directory).
13
+ // The program modifies files in-place.
14
+ package main
15
+
16
+ import (
17
+ "fmt"
18
+ "os"
19
+ "path/filepath"
20
+ "strings"
21
+ )
22
+
23
+ func main() {
24
+ srcDir := "."
25
+ if len(os.Args) > 1 {
26
+ srcDir = os.Args[1]
27
+ }
28
+
29
+ type patchDef struct {
30
+ path string
31
+ patchFn func(string) (string, error)
32
+ }
33
+
34
+ patches := []patchDef{
35
+ {filepath.Join(srcDir, "internal/system/detect.go"), patchDetectGo},
36
+ {filepath.Join(srcDir, "internal/system/guard.go"), patchGuardGo},
37
+ {filepath.Join(srcDir, "internal/update/upgrade/download.go"), patchDownloadGo},
38
+ {filepath.Join(srcDir, "internal/tui/model.go"), patchModelGo},
39
+ {filepath.Join(srcDir, "internal/components/engram/download.go"), patchEngramDownloadGo},
40
+ }
41
+
42
+ anyFailed := false
43
+ for _, p := range patches {
44
+ content, err := os.ReadFile(p.path)
45
+ if err != nil {
46
+ fmt.Fprintf(os.Stderr, "ERROR reading %s: %v\n", p.path, err)
47
+ anyFailed = true
48
+ continue
49
+ }
50
+ result, err := p.patchFn(string(content))
51
+ if err != nil {
52
+ fmt.Fprintf(os.Stderr, "ERROR patching %s: %v\n", p.path, err)
53
+ anyFailed = true
54
+ continue
55
+ }
56
+ if result != string(content) {
57
+ if err := os.WriteFile(p.path, []byte(result), 0o644); err != nil {
58
+ fmt.Fprintf(os.Stderr, "ERROR writing %s: %v\n", p.path, err)
59
+ anyFailed = true
60
+ continue
61
+ }
62
+ fmt.Printf("PATCHED %s\n", p.path)
63
+ } else {
64
+ fmt.Printf("ALREADY PATCHED %s\n", p.path)
65
+ }
66
+ }
67
+
68
+ if anyFailed {
69
+ os.Exit(1)
70
+ }
71
+ }
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // helpers
75
+ // ---------------------------------------------------------------------------
76
+
77
+ func tab(n int) string {
78
+ return strings.Repeat("\t", n)
79
+ }
80
+
81
+ // assertReplace replaces old with new in src once.
82
+ // If old is not found, it checks whether new is already present (idempotent).
83
+ // If neither is found, it returns an error with a descriptive message.
84
+ func assertReplace(src, old, new, desc string) (string, error) {
85
+ if strings.Contains(src, old) {
86
+ return strings.Replace(src, old, new, 1), nil
87
+ }
88
+ if strings.Contains(src, new) {
89
+ return src, nil
90
+ }
91
+ return src, fmt.Errorf("%s: pattern not found in source", desc)
92
+ }
93
+
94
+ // ---------------------------------------------------------------------------
95
+ // 1. internal/system/detect.go
96
+ // ---------------------------------------------------------------------------
97
+
98
+ func patchDetectGo(src string) (string, error) {
99
+ var err error
100
+
101
+ // 1a. IsSupportedOS: add android to the list.
102
+ old1 := tab(1) + `return goos == "darwin" || goos == "linux" || goos == "windows"` + "\n}"
103
+ new1 := tab(1) + `return goos == "darwin" || goos == "linux" || goos == "windows" || goos == "android"` + "\n}"
104
+ src, err = assertReplace(src, old1, new1, "IsSupportedOS return")
105
+ if err != nil {
106
+ return src, err
107
+ }
108
+
109
+ // 1b. resolvePlatformProfile: add case "android" before default.
110
+ old2 := "" +
111
+ tab(1) + `case "windows":` + "\n" +
112
+ tab(2) + `profile.PackageManager = "winget"` + "\n" +
113
+ tab(2) + `profile.Supported = true` + "\n" +
114
+ tab(2) + `return profile` + "\n" +
115
+ tab(1) + `default:`
116
+ new2 := "" +
117
+ tab(1) + `case "windows":` + "\n" +
118
+ tab(2) + `profile.PackageManager = "winget"` + "\n" +
119
+ tab(2) + `profile.Supported = true` + "\n" +
120
+ tab(2) + `return profile` + "\n" +
121
+ tab(1) + `case "android":` + "\n" +
122
+ tab(2) + `profile.PackageManager = "pkg"` + "\n" +
123
+ tab(2) + `profile.Supported = true` + "\n" +
124
+ tab(2) + `distro := detectLinuxDistro(linuxOSRelease)` + "\n" +
125
+ tab(2) + `if distro != LinuxDistroUnknown {` + "\n" +
126
+ tab(3) + `profile.LinuxDistro = distro` + "\n" +
127
+ tab(2) + `}` + "\n" +
128
+ tab(2) + `return profile` + "\n" +
129
+ tab(1) + `default:`
130
+ src, err = assertReplace(src, old2, new2, "resolvePlatformProfile android case")
131
+ if err != nil {
132
+ return src, err
133
+ }
134
+
135
+ // 1c. osReleaseContent: read $PREFIX/etc/os-release on android.
136
+ old3 := "" +
137
+ `func osReleaseContent(goos string) (string, error) {` + "\n" +
138
+ tab(1) + `if goos != "linux" {` + "\n" +
139
+ tab(2) + `return "", nil` + "\n" +
140
+ tab(1) + `}`
141
+ new3 := "" +
142
+ `func osReleaseContent(goos string) (string, error) {` + "\n" +
143
+ tab(1) + `if goos == "android" {` + "\n" +
144
+ tab(2) + `prefix := os.Getenv("PREFIX")` + "\n" +
145
+ tab(2) + `if prefix != "" {` + "\n" +
146
+ tab(3) + `if data, err := os.ReadFile(prefix + "/etc/os-release"); err == nil {` + "\n" +
147
+ tab(4) + `return string(data), nil` + "\n" +
148
+ tab(3) + `}` + "\n" +
149
+ tab(2) + `}` + "\n" +
150
+ tab(2) + `return "", nil` + "\n" +
151
+ tab(1) + `}` + "\n" +
152
+ tab(1) + `if goos != "linux" {` + "\n" +
153
+ tab(2) + `return "", nil` + "\n" +
154
+ tab(1) + `}`
155
+ src, err = assertReplace(src, old3, new3, "osReleaseContent android PREFIX")
156
+ if err != nil {
157
+ return src, err
158
+ }
159
+
160
+ return src, nil
161
+ }
162
+
163
+ // ---------------------------------------------------------------------------
164
+ // 2. internal/system/guard.go
165
+ // ---------------------------------------------------------------------------
166
+
167
+ func patchGuardGo(src string) (string, error) {
168
+ // EnsureSupportedOS error message: mention Android.
169
+ old1 := `return fmt.Errorf("%w: only macOS, Linux, and Windows are supported (detected %s)", ErrUnsupportedOS, goos)`
170
+ new1 := `return fmt.Errorf("%w: only macOS, Linux, Windows, and Android are supported (detected %s)", ErrUnsupportedOS, goos)`
171
+ return assertReplace(src, old1, new1, "EnsureSupportedOS error message Android")
172
+ }
173
+
174
+ // ---------------------------------------------------------------------------
175
+ // 3. internal/update/upgrade/download.go
176
+ // ---------------------------------------------------------------------------
177
+
178
+ func patchDownloadGo(src string) (string, error) {
179
+ // On Android/Termux, download linux binaries (no android releases on
180
+ // GitHub). profile is passed by value so the modification is local.
181
+ old1 := `func Download(ctx context.Context, r update.UpdateResult, profile system.PlatformProfile) error {` + "\n" +
182
+ tab(1) + `if profile.OS == "windows" {`
183
+ new1 := `func Download(ctx context.Context, r update.UpdateResult, profile system.PlatformProfile) error {` + "\n" +
184
+ tab(1) + `if profile.OS == "android" {` + "\n" +
185
+ tab(2) + `profile.OS = "linux"` + "\n" +
186
+ tab(1) + `}` + "\n" +
187
+ "\n" +
188
+ tab(1) + `if profile.OS == "windows" {`
189
+ return assertReplace(src, old1, new1, "Download android->linux redirect")
190
+ }
191
+
192
+ // ---------------------------------------------------------------------------
193
+ // 4. internal/tui/model.go
194
+ // ---------------------------------------------------------------------------
195
+
196
+ func patchModelGo(src string) (string, error) {
197
+ // openBrowserCmd: use termux-open-url on android.
198
+ old1 := "" +
199
+ tab(2) + `case "windows":` + "\n" +
200
+ tab(3) + `cmd = execCommandFn("rundll32", "url.dll,FileProtocolHandler", url)` + "\n" +
201
+ tab(2) + `default:` + "\n" +
202
+ tab(3) + `cmd = execCommandFn("xdg-open", url)`
203
+ new1 := "" +
204
+ tab(2) + `case "windows":` + "\n" +
205
+ tab(3) + `cmd = execCommandFn("rundll32", "url.dll,FileProtocolHandler", url)` + "\n" +
206
+ tab(2) + `case "android":` + "\n" +
207
+ tab(3) + `cmd = execCommandFn("termux-open-url", url)` + "\n" +
208
+ tab(2) + `default:` + "\n" +
209
+ tab(3) + `cmd = execCommandFn("xdg-open", url)`
210
+ return assertReplace(src, old1, new1, "openBrowserCmd android case")
211
+ }
212
+
213
+ // ---------------------------------------------------------------------------
214
+ // 5. internal/components/engram/download.go
215
+ // ---------------------------------------------------------------------------
216
+
217
+ func patchEngramDownloadGo(src string) (string, error) {
218
+ var err error
219
+
220
+ // 5a. DownloadLatestBinary: redirect android -> linux for asset URLs.
221
+ old1 := "" +
222
+ tab(1) + `goos := profile.OS` + "\n" +
223
+ tab(1) + `goarch := normalizeArch(runtime.GOARCH)`
224
+ new1 := "" +
225
+ tab(1) + `goos := profile.OS` + "\n" +
226
+ tab(1) + `if goos == "android" {` + "\n" +
227
+ tab(2) + `goos = "linux"` + "\n" +
228
+ tab(1) + `}` + "\n" +
229
+ tab(1) + `goarch := normalizeArch(runtime.GOARCH)`
230
+ src, err = assertReplace(src, old1, new1, "engram DownloadLatestBinary android->linux")
231
+ if err != nil {
232
+ return src, err
233
+ }
234
+
235
+ // 5b. engramInstallDir: use $PREFIX/bin on Termux.
236
+ old2 := "" +
237
+ `func engramInstallDir(goos string) string {` + "\n" +
238
+ tab(1) + `if goos == "windows" {`
239
+ new2 := "" +
240
+ `func engramInstallDir(goos string) string {` + "\n" +
241
+ tab(1) + `if goos == "android" {` + "\n" +
242
+ tab(2) + `prefix := os.Getenv("PREFIX")` + "\n" +
243
+ tab(2) + `if prefix != "" {` + "\n" +
244
+ tab(3) + `return filepath.Join(prefix, "bin")` + "\n" +
245
+ tab(2) + `}` + "\n" +
246
+ tab(2) + `return "/data/data/com.termux/files/usr/bin"` + "\n" +
247
+ tab(1) + `}` + "\n" +
248
+ "\n" +
249
+ tab(1) + `if goos == "windows" {`
250
+ src, err = assertReplace(src, old2, new2, "engramInstallDir android PREFIX")
251
+ if err != nil {
252
+ return src, err
253
+ }
254
+
255
+ return src, nil
256
+ }
@@ -0,0 +1,49 @@
1
+ # Gentleman Guardian Angel
2
+
3
+ Provider-agnostic AI code review on every commit
4
+
5
+ **Package:** gga
6
+ **Author:** Gentleman-Programming
7
+ **Repository:** https://github.com/israel676767/omni
8
+ **Official:** https://github.com/Gentleman-Programming/gentleman-guardian-angel
9
+ **Termux fork:** https://github.com/israel676767/gga-termux
10
+ **Type:** AI code review CLI (Pure Bash)
11
+ **License:** MIT
12
+
13
+ ## Description
14
+
15
+ GGA (Gentleman Guardian Angel) is a provider-agnostic AI code review tool that runs on every commit. It validates staged files against your `AGENTS.md` rules using any LLM provider (Claude, Gemini, Codex, OpenCode, Ollama, LM Studio, GitHub Models). Pure Bash, zero dependencies, works as a standard pre-commit git hook.
16
+
17
+ The Termux fork adapts the installer/uninstaller for Android environments (Termux detects `$PREFIX` and installs to `$PREFIX/bin` and `$PREFIX/share/gga/lib`).
18
+
19
+ ## Dependencies
20
+
21
+ - git, curl
22
+ - bash 5.0+
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ core install ai --gga
28
+ ```
29
+
30
+ ## Uninstall
31
+
32
+ ```bash
33
+ core uninstall ai --gga
34
+ ```
35
+
36
+ ## Update
37
+
38
+ ```bash
39
+ core update ai --gga
40
+ ```
41
+
42
+ ## Notes
43
+
44
+ - Source cloned to `$OMNI_DATA/gga-termux/` (`~/.local/share/omni-data/gga-termux/`)
45
+ - Binary installed to `$PREFIX/bin/gga`
46
+ - Libraries installed to `$PREFIX/share/gga/lib/`
47
+ - Clones the Termux-compatible fork and runs its bundled `install.sh` / `uninstall.sh`
48
+ - Repository is updated via `git pull` on `core update ai --gga`
49
+ - Requires the gga repo to be present at runtime only during install/update (can be safely removed afterward)
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env bash
2
+
3
+ import "@/utils/log"
4
+ import "@/utils/colors"
5
+
6
+ LOG_FILE="$OMNI_CACHE/install_ai.log"
7
+ GGA_DATA_DIR="$OMNI_DATA/gga-termux"
8
+
9
+ _gga_dependencies() {
10
+ loading "Installing dependencies" _gga_dependencies_impl
11
+ }
12
+
13
+ _gga_dependencies_impl() {
14
+ declare -A DEPS=(
15
+ ["git"]="git"
16
+ ["curl"]="curl"
17
+ )
18
+
19
+ local pkg_name bin_name
20
+ for pkg_name in "${!DEPS[@]}"; do
21
+ bin_name="${DEPS[$pkg_name]}"
22
+ if ! command -v "$bin_name" &>/dev/null; then
23
+ if ! pkg install "$pkg_name" -y &>>"$LOG_FILE"; then
24
+ log_error "Failed to install $pkg_name"
25
+ return 1
26
+ fi
27
+ fi
28
+ done
29
+
30
+ return 0
31
+ }
32
+
33
+ _gga_clone_or_update_repo() {
34
+ loading "Cloning or updating gga-termux repo" _gga_clone_or_update_repo_impl
35
+ }
36
+
37
+ _gga_clone_or_update_repo_impl() {
38
+ local repo_url="https://github.com/israel676767/gga-termux.git"
39
+
40
+ if [ -d "$GGA_DATA_DIR/.git" ]; then
41
+ if ! git -C "$GGA_DATA_DIR" pull --ff-only &>>"$LOG_FILE"; then
42
+ log_error "Failed to update gga-termux repo"
43
+ return 1
44
+ fi
45
+ else
46
+ mkdir -p "$(dirname "$GGA_DATA_DIR")"
47
+ if ! git clone "$repo_url" "$GGA_DATA_DIR" &>>"$LOG_FILE"; then
48
+ log_error "Failed to clone gga-termux repo"
49
+ return 1
50
+ fi
51
+ fi
52
+
53
+ return 0
54
+ }
55
+
56
+ _gga_run_installer() {
57
+ loading "Running gga-termux installer" _gga_run_installer_impl
58
+ }
59
+
60
+ _gga_run_installer_impl() {
61
+ if [ ! -d "$GGA_DATA_DIR" ] || [ ! -f "$GGA_DATA_DIR/install.sh" ]; then
62
+ log_error "gga-termux repo not found at $GGA_DATA_DIR"
63
+ return 1
64
+ fi
65
+
66
+ if ! (cd "$GGA_DATA_DIR" && bash ./install.sh < /dev/null) &>>"$LOG_FILE"; then
67
+ log_error "gga-termux install.sh failed (see $LOG_FILE)"
68
+ return 1
69
+ fi
70
+
71
+ return 0
72
+ }
73
+
74
+ install_gga() {
75
+ if command -v gga &>/dev/null; then
76
+ log_info "GGA is already installed"
77
+ return 2
78
+ fi
79
+
80
+ log_info "Installing GGA..."
81
+
82
+ mkdir -p "$(dirname "$LOG_FILE")"
83
+
84
+ _gga_dependencies || return 1
85
+ _gga_clone_or_update_repo || return 1
86
+ _gga_run_installer || return 1
87
+
88
+ log_success "GGA installed"
89
+ return 0
90
+ }
91
+
92
+ uninstall_gga() {
93
+ if ! command -v gga &>/dev/null; then
94
+ log_info "GGA is not installed"
95
+ return 2
96
+ fi
97
+ log_info "Uninstalling GGA..."
98
+ mkdir -p "$(dirname "$LOG_FILE")"
99
+
100
+ if [ -d "$GGA_DATA_DIR" ] && [ -f "$GGA_DATA_DIR/uninstall.sh" ]; then
101
+ log_info "Running gga-termux uninstaller..."
102
+ if ! (cd "$GGA_DATA_DIR" && printf "n\n" | bash ./uninstall.sh) &>>"$LOG_FILE"; then
103
+ log_warn "gga-termux uninstall.sh failed, falling back to manual cleanup"
104
+ fi
105
+ fi
106
+
107
+ rm -f "$PREFIX/bin/gga"
108
+ rm -rf "$PREFIX/share/gga"
109
+ rm -rf "$GGA_DATA_DIR"
110
+
111
+ if [ ! -f "$PREFIX/bin/gga" ] && [ ! -d "$GGA_DATA_DIR" ]; then
112
+ log_success "GGA uninstalled"
113
+ return 0
114
+ else
115
+ log_error "Failed to uninstall GGA"
116
+ return 1
117
+ fi
118
+ }
119
+
120
+ update_gga() {
121
+ log_info "Updating GGA..."
122
+ mkdir -p "$(dirname "$LOG_FILE")"
123
+
124
+ _gga_clone_or_update_repo || return 1
125
+ _gga_run_installer || return 1
126
+
127
+ log_success "GGA updated"
128
+ return 0
129
+ }
130
+
131
+ reinstall_gga() {
132
+ uninstall_gga
133
+ install_gga
134
+ }