karnel-termux 4.15.0 → 4.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  <p align="center">
10
10
  <a href="https://github.com/israelmarques1024-dotcom/karnel-termux">
11
- <img src="https://img.shields.io/badge/version-4.15.0-0078D4?style=for-the-badge" alt="Version">
11
+ <img src="https://img.shields.io/badge/version-4.15.2-0078D4?style=for-the-badge" alt="Version">
12
12
  </a>
13
13
  <a href="https://www.npmjs.com/package/karnel-termux">
14
14
  <img src="https://img.shields.io/npm/v/karnel-termux?style=for-the-badge&logo=npm&color=cb3837" alt="npm">
@@ -59,7 +59,7 @@ Created by **Israel Marques**.
59
59
  ### Via checksummed GitHub release (recommended)
60
60
 
61
61
  ```bash
62
- version=4.15.0
62
+ version=4.15.2
63
63
  tmpdir=$(mktemp -d) && trap 'rm -rf "$tmpdir"' EXIT
64
64
  base="https://github.com/israelmarques1024-dotcom/karnel-termux/releases/download/v$version"
65
65
  curl -fsSL "$base/karnel-termux-install.sh" -o "$tmpdir/karnel-termux-install.sh"
package/docs/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Documentation Changelog
2
2
 
3
+ ## 4.15.2 - 2026-08-16
4
+
5
+ - Implemented the previously missing `karnel brain add "text"` subcommand.
6
+ `karnel brain save` (interactive) told non-interactive users to use
7
+ `karnel brain add` when a terminal was unavailable, but the subcommand did
8
+ not exist and fell through to "Unknown subcommand". `add` now saves a memory
9
+ non-interactively with optional `--title`, `--category` and `--tags`.
10
+ - Fixed memory slug lookup in `karnel brain show/relate/edit/delete`. The help
11
+ documents `karnel brain show slug-name`, but stored memories use
12
+ `YYYY-MM-DD_<slug>.md` filenames and lookups required the exact, full,
13
+ date-prefixed basename. A shared `_brain_find_memory` helper now resolves the
14
+ bare slug (falls back to `*_<slug>.md`) so the documented short form works.
15
+ - Removed a duplicated `glow` rendering block in `karnel brain show`.
16
+ - `karnel brain search` (and related memory search in `ask`/`save` suggestions and
17
+ `delete` relation clean-up) now falls back to `grep -r` when `ripgrep` is not
18
+ installed, instead of failing with "ripgrep not found". Environments without
19
+ `rg` (fresh minimal containers, CI runners) can now search memories.
20
+
21
+ - Fixed the plugin registry pin: `PLUGIN_REGISTRY_COMMIT` now points to
22
+ `f19d3cd` (registry commit that pins reviewed plugin sources to commits/
23
+ tags instead of moving `main`), with the matching registry checksum
24
+ `ea82bf2f...`. Plugin updates previously failed with a "Checksum mismatch"
25
+ whenever a plugin repository advanced ahead of the stale registry snapshot.
26
+
3
27
  ## 4.15.0 - 2026-08-14
4
28
 
5
29
  - Replaced the unavailable GGA fork with the official Gentleman Guardian
@@ -1 +1 @@
1
- 0cb37fa9cbd9b82b371fdae9fd07c2041bfc4b19
1
+ c91732e5ece58c3a6b01d604a88b1cb1f3d64b0e
@@ -54,6 +54,66 @@ _brain_title() {
54
54
  fi
55
55
  }
56
56
 
57
+ _brain_find_memory() {
58
+ local slug="$1"
59
+ if [[ -z "$slug" ]]; then
60
+ return 1
61
+ fi
62
+ local f
63
+ f=$(find "$BRAIN_DIR" -name "${slug}.md" 2>/dev/null | head -1)
64
+ if [[ -z "$f" ]]; then
65
+ f=$(find "$BRAIN_DIR" -name "*_${slug}.md" 2>/dev/null | head -1)
66
+ fi
67
+ [[ -n "$f" ]] && echo "$f"
68
+ }
69
+
70
+ _brain_rg() {
71
+ local -a flags=()
72
+ local list=0
73
+ local pattern=""
74
+ while [[ $# -gt 0 ]]; do
75
+ case "$1" in
76
+ -i)
77
+ flags+=(-i)
78
+ shift
79
+ ;;
80
+ -l)
81
+ list=1
82
+ shift
83
+ ;;
84
+ --glob | --no-heading)
85
+ shift
86
+ ;;
87
+ -e)
88
+ pattern="$2"
89
+ shift 2
90
+ ;;
91
+ *)
92
+ pattern="$1"
93
+ shift
94
+ ;;
95
+ esac
96
+ done
97
+
98
+ if [[ -z "$pattern" ]]; then
99
+ return 1
100
+ fi
101
+
102
+ if command -v rg &>/dev/null; then
103
+ if ((list)); then
104
+ rg "${flags[@]}" -l --glob '*.md' "$pattern" "$BRAIN_DIR" 2>/dev/null
105
+ else
106
+ rg "${flags[@]}" -n --no-heading --glob '*.md' "$pattern" "$BRAIN_DIR" 2>/dev/null
107
+ fi
108
+ else
109
+ if ((list)); then
110
+ grep -r -E "${flags[@]}" -l --include='*.md' "$pattern" "$BRAIN_DIR" 2>/dev/null
111
+ else
112
+ grep -r -E -n "${flags[@]}" --include='*.md' "$pattern" "$BRAIN_DIR" 2>/dev/null
113
+ fi
114
+ fi
115
+ }
116
+
57
117
  _brain_slug_escape() {
58
118
  printf '%s\n' "$1" | sed 's/[\/&]/\\&/g; s/\n/\\n/g'
59
119
  }
@@ -199,6 +259,7 @@ brain_help() {
199
259
  echo
200
260
  printf " ${D_CYAN}%-12s${NC} %s\n" "init" "Initialize brain directory and GitHub repo"
201
261
  printf " ${D_CYAN}%-12s${NC} %s\n" "save" "Save a new memory interactively"
262
+ printf " ${D_CYAN}%-12s${NC} %s\n" "add" "Quick non-interactive save"
202
263
  printf " ${D_CYAN}%-12s${NC} %s\n" "search" "Search memories by keywords or tags"
203
264
  printf " ${D_CYAN}%-12s${NC} %s\n" "ls" "List memories by category"
204
265
  printf " ${D_CYAN}%-12s${NC} %s\n" "edit" "Edit a memory in your \$EDITOR"
@@ -214,6 +275,7 @@ brain_help() {
214
275
  echo
215
276
  printf " ${D_CYAN}karnel brain init${NC} # Create local brain\n"
216
277
  printf " ${D_CYAN}karnel brain save${NC} # Interactive save\n"
278
+ printf " ${D_CYAN}karnel brain add TEXT${NC} # Quick non-interactive save\n"
217
279
  printf " ${D_CYAN}karnel brain search react${NC} # Search all memories\n"
218
280
  printf " ${D_CYAN}karnel brain ls${NC} # List all categories\n"
219
281
  printf " ${D_CYAN}karnel brain ls react${NC} # List react category\n"
@@ -381,7 +443,7 @@ brain_save() {
381
443
  done
382
444
  $already || related_slugs+=("$match_slug")
383
445
  fi
384
- done < <(rg -l -i "tags:.*$tag" "$BRAIN_DIR" 2>/dev/null || true)
446
+ done < <(_brain_rg -i "tags:.*$tag" || true)
385
447
  done
386
448
  IFS=$' \t\n'
387
449
 
@@ -445,6 +507,86 @@ brain_save() {
445
507
  echo
446
508
  }
447
509
 
510
+ # ── Add (non-interactive) ───────────────────────────────────
511
+
512
+ brain_add() {
513
+ _brain_ensure || return 1
514
+
515
+ if [[ $# -lt 1 ]]; then
516
+ log_error "Usage: karnel brain add \"your text\" [--title T] [--category C] [--tags a,b]"
517
+ return 1
518
+ fi
519
+
520
+ local title="" category="" tags_input=""
521
+ local -a content_parts=()
522
+ while [[ $# -gt 0 ]]; do
523
+ case "$1" in
524
+ --title | -t)
525
+ title="$2"
526
+ shift 2
527
+ ;;
528
+ --category | -c)
529
+ category="$2"
530
+ shift 2
531
+ ;;
532
+ --tags)
533
+ tags_input="$2"
534
+ shift 2
535
+ ;;
536
+ --)
537
+ shift
538
+ content_parts+=("$*")
539
+ break
540
+ ;;
541
+ *)
542
+ content_parts+=("$1")
543
+ shift
544
+ ;;
545
+ esac
546
+ done
547
+
548
+ local text
549
+ text=$(echo "${content_parts[*]}" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
550
+ if [[ -z "$text" ]]; then
551
+ log_error "Memory text cannot be empty"
552
+ return 1
553
+ fi
554
+
555
+ if [[ -z "$title" ]]; then
556
+ title=$(echo "$text" | head -1 | cut -c1-60)
557
+ fi
558
+ if [[ -z "$title" ]]; then
559
+ title="memory-$(date +%Y%m%d-%H%M%S)"
560
+ fi
561
+
562
+ if [[ -z "$category" ]]; then
563
+ category="general"
564
+ fi
565
+ category=$(_brain_slug "$category")
566
+
567
+ local tags_formatted=""
568
+ if [[ -n "$tags_input" ]]; then
569
+ tags_formatted=$(echo "$tags_input" | sed 's/, */, /g' | sed 's/^, \|, $//g')
570
+ fi
571
+
572
+ local slug date_prefix
573
+ slug=$(_brain_slug "$title")
574
+ date_prefix=$(date +%Y-%m-%d)
575
+
576
+ mkdir -p "$BRAIN_DIR/$category"
577
+ local filepath="$BRAIN_DIR/$category/${date_prefix}_${slug}.md"
578
+
579
+ {
580
+ _brain_frontmatter "$title" "$tags_formatted" "$category" ""
581
+ echo
582
+ echo "$text"
583
+ } >"$filepath"
584
+
585
+ echo
586
+ log_success "Memory saved to ${D_CYAN}$category/${date_prefix}_${slug}.md${D_NC}"
587
+ echo
588
+ }
589
+
448
590
  # ── Search ──────────────────────────────────────────────────
449
591
 
450
592
  brain_search() {
@@ -463,15 +605,10 @@ brain_search() {
463
605
  separator
464
606
  echo
465
607
 
466
- if ! command -v rg &>/dev/null; then
467
- log_error "ripgrep not found — this shouldn't happen"
468
- return 1
469
- fi
470
-
471
608
  local -a results=()
472
609
  while IFS=':' read -r file line content; do
473
610
  results+=("$file|$line|$content")
474
- done < <(rg -n -i "$query" "$BRAIN_DIR" --glob '*.md' --no-heading 2>/dev/null || true)
611
+ done < <(_brain_rg -i "$query" || true)
475
612
 
476
613
  if [[ ${#results[@]} -eq 0 ]]; then
477
614
  log_warn "No results for: $query"
@@ -632,8 +769,8 @@ brain_relate() {
632
769
  file_b=$(_brain_pick_file "Second memory (# or name)")
633
770
  [[ -z "$file_b" ]] && return 0
634
771
  else
635
- file_a=$(find "$BRAIN_DIR" -name "${slug_a}.md" 2>/dev/null | head -1)
636
- file_b=$(find "$BRAIN_DIR" -name "${slug_b}.md" 2>/dev/null | head -1)
772
+ file_a=$(_brain_find_memory "$slug_a")
773
+ file_b=$(_brain_find_memory "$slug_b")
637
774
 
638
775
  if [[ -z "$file_a" ]]; then
639
776
  log_error "Memory not found: $slug_a"
@@ -687,7 +824,7 @@ brain_show() {
687
824
  local file=""
688
825
 
689
826
  if [[ -n "$slug" ]]; then
690
- file=$(find "$BRAIN_DIR" -name "${slug}.md" 2>/dev/null | head -1)
827
+ file=$(_brain_find_memory "$slug")
691
828
  if [[ -z "$file" ]]; then
692
829
  log_error "Memory not found: $slug"
693
830
  return 1
@@ -1077,7 +1214,7 @@ brain_edit() {
1077
1214
  local file=""
1078
1215
 
1079
1216
  if [[ -n "$slug" ]]; then
1080
- file=$(find "$BRAIN_DIR" -name "${slug}.md" 2>/dev/null | head -1)
1217
+ file=$(_brain_find_memory "$slug")
1081
1218
  if [[ -z "$file" ]]; then
1082
1219
  log_error "Memory not found: $slug"
1083
1220
  return 1
@@ -1132,7 +1269,7 @@ brain_delete() {
1132
1269
  local file=""
1133
1270
 
1134
1271
  if [[ -n "$slug" ]]; then
1135
- file=$(find "$BRAIN_DIR" -name "${slug}.md" 2>/dev/null | head -1)
1272
+ file=$(_brain_find_memory "$slug")
1136
1273
  if [[ -z "$file" ]]; then
1137
1274
  log_error "Memory not found: $slug"
1138
1275
  return 1
@@ -1163,7 +1300,7 @@ brain_delete() {
1163
1300
  file_slug=$(basename "$file" .md)
1164
1301
  while IFS= read -r rfile; do
1165
1302
  _brain_remove_related "$rfile" "$file_slug"
1166
- done < <(rg -l "$file_slug" "$BRAIN_DIR" --glob '*.md' 2>/dev/null || true)
1303
+ done < <(_brain_rg "$file_slug" || true)
1167
1304
 
1168
1305
  if [[ "$file" != "$BRAIN_DIR"/* ]]; then
1169
1306
  log_error "Refusing to delete file outside brain directory"
@@ -1404,7 +1541,7 @@ EOF
1404
1541
  if [[ -n "$f" ]]; then
1405
1542
  matching_files+=("$f")
1406
1543
  fi
1407
- done < <(rg -i -l "$clean_query" "$BRAIN_DIR" --glob '*.md' 2>/dev/null | head -n 5 || true)
1544
+ done < <(_brain_rg -i "$clean_query" | head -n 5 || true)
1408
1545
 
1409
1546
  if [[ ${#matching_files[@]} -eq 0 ]]; then
1410
1547
  local -a words=($clean_query)
@@ -1423,7 +1560,7 @@ EOF
1423
1560
  if [[ -n "$f" ]]; then
1424
1561
  matching_files+=("$f")
1425
1562
  fi
1426
- done < <(rg -i -l -e "$word_regex" "$BRAIN_DIR" --glob '*.md' 2>/dev/null | head -n 5 || true)
1563
+ done < <(_brain_rg -i -e "$word_regex" | head -n 5 || true)
1427
1564
  fi
1428
1565
  fi
1429
1566
 
@@ -1529,6 +1666,9 @@ brain_main() {
1529
1666
  save)
1530
1667
  brain_save
1531
1668
  ;;
1669
+ add)
1670
+ brain_add "$@"
1671
+ ;;
1532
1672
  search)
1533
1673
  brain_search "$@"
1534
1674
  ;;
@@ -1,8 +1,8 @@
1
1
  # shellcheck shell=bash
2
2
 
3
3
  PLUGINS_DIR="${KARNEL_DATA}/plugins"
4
- PLUGIN_REGISTRY_COMMIT="561780eb76b10ddac161fe5eeec6e5a4dd0db2f2"
5
- PLUGIN_REGISTRY_SHA256="a2fdad6519b5e6b979a7e6df21250bd348012df90c6cf79ccd946d1568edb40c"
4
+ PLUGIN_REGISTRY_COMMIT="f19d3cdd87c67f0a8fa052565ab23c74aea4b27b"
5
+ PLUGIN_REGISTRY_SHA256="ea82bf2f9182b5967c0ba9769882a92d8d1aa9ec430fbbbf0dcb21591907b620"
6
6
  PLUGIN_REGISTRY_URL="https://raw.githubusercontent.com/israelmarques1024-dotcom/karnel-plugins/${PLUGIN_REGISTRY_COMMIT}/registry.json"
7
7
  PLUGIN_DISPATCH_FOUND=0
8
8
  PLUGIN_SEMVER_RE='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*))*))?(\+([0-9A-Za-z-]+)(\.[0-9A-Za-z-]+)*)?$'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karnel-termux",
3
- "version": "4.15.0",
3
+ "version": "4.15.2",
4
4
  "description": "Modular Dev Environment for Termux — install languages, databases, AI agents, editors, and more with one command",
5
5
  "bin": {
6
6
  "karnel": "karnel/bin/karnel"