karnel-termux 4.14.0 → 4.15.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.
- package/README.md +19 -7
- package/assets/fonts/font.ttf +0 -0
- package/docs/ARCHITECTURE.md +5 -0
- package/docs/CHANGELOG.md +23 -0
- package/docs/cli/README.md +97 -38
- package/install.sh +144 -63
- package/karnel/RELEASE_COMMIT +1 -0
- package/karnel/bin/karnel +49 -11
- package/karnel/cli/commands/backup.sh +165 -154
- package/karnel/cli/commands/env.sh +0 -3
- package/karnel/cli/commands/install.sh +8 -1
- package/karnel/cli/commands/list.sh +3 -0
- package/karnel/cli/commands/restore.sh +118 -77
- package/karnel/cli/commands/show.sh +8 -6
- package/karnel/cli/commands/start.sh +1 -0
- package/karnel/cli/commands/update.sh +2 -2
- package/karnel/cli/karnel.sh +27 -5
- package/karnel/modules/shell.sh +27 -10
- package/karnel/tools/ai/all.sh +28 -1
- package/karnel/tools/ai/ampcode/install.sh +63 -109
- package/karnel/tools/ai/cactus/README.md +9 -0
- package/karnel/tools/ai/cactus/install.sh +101 -4
- package/karnel/tools/ai/claude-code/install.sh +49 -22
- package/karnel/tools/ai/codebuff/install.sh +50 -118
- package/karnel/tools/ai/codegraph/install.sh +33 -23
- package/karnel/tools/ai/crush/install.sh +46 -10
- package/karnel/tools/ai/cursor-cli/install.sh +18 -28
- package/karnel/tools/ai/engram/install.sh +7 -4
- package/karnel/tools/ai/gentle-ai/install.sh +5 -25
- package/karnel/tools/ai/gentle-ai/termux-patches.go +0 -0
- package/karnel/tools/ai/gga/README.md +6 -6
- package/karnel/tools/ai/gga/install.sh +145 -101
- package/karnel/tools/ai/goose/install.sh +29 -8
- package/karnel/tools/ai/hermes-agent/install.sh +87 -49
- package/karnel/tools/ai/kimchi-code/install.sh +53 -90
- package/karnel/tools/ai/kiro/install.sh +102 -78
- package/karnel/tools/ai/mimocode/install.sh +45 -106
- package/karnel/tools/ai/odysseus/install.sh +28 -16
- package/karnel/tools/ai/opencode/install.sh +4 -0
- package/karnel/tools/ai/qoder/bin/qodercli +3 -2
- package/karnel/tools/ai/qoder/install.sh +108 -43
- package/karnel/tools/auto/all.sh +8 -7
- package/karnel/tools/auto/n8n/install.sh +1 -1
- package/karnel/tools/db/all.sh +8 -7
- package/karnel/tools/deploy/all.sh +8 -6
- package/karnel/tools/deploy/netlify/README.md +4 -0
- package/karnel/tools/deploy/supabase/install.sh +71 -33
- package/karnel/tools/dev/all.sh +13 -11
- package/karnel/tools/editor/all.sh +8 -7
- package/karnel/tools/editor/neovim/install.sh +1 -1
- package/karnel/tools/editor/nvchad/install.sh +86 -32
- package/karnel/tools/games/all.sh +8 -7
- package/karnel/tools/games/arcade/install.sh +2 -2
- package/karnel/tools/games/buzz/install.sh +2 -2
- package/karnel/tools/games/ctfgod/install.sh +2 -2
- package/karnel/tools/games/detective/install.sh +2 -2
- package/karnel/tools/games/pet-friends/install.sh +2 -2
- package/karnel/tools/games/tamagotchi/install.sh +2 -2
- package/karnel/tools/lang/all.sh +8 -7
- package/karnel/tools/network/all.sh +11 -13
- package/karnel/tools/network/dark/install.sh +1 -1
- package/karnel/tools/network/dedsec-network/install.sh +1 -1
- package/karnel/tools/npm/all.sh +8 -7
- package/karnel/tools/npm/live-server/install.sh +2 -1
- package/karnel/tools/npm/localtunnel/install.sh +2 -1
- package/karnel/tools/npm/markserv/install.sh +2 -1
- package/karnel/tools/npm/ncu/install.sh +2 -1
- package/karnel/tools/npm/nestjs/install.sh +2 -1
- package/karnel/tools/npm/ngrok/install.sh +2 -1
- package/karnel/tools/npm/prettier/install.sh +2 -1
- package/karnel/tools/npm/psqlformat/install.sh +2 -1
- package/karnel/tools/npm/turbopack/install.sh +20 -4
- package/karnel/tools/npm/typescript/install.sh +2 -1
- package/karnel/tools/npm/vercel/install.sh +2 -1
- package/karnel/tools/osint/all.sh +11 -13
- package/karnel/tools/plugins/install.sh +20 -27
- package/karnel/tools/security/aircrack-ng/install.sh +7 -2
- package/karnel/tools/security/all.sh +10 -4
- package/karnel/tools/security/amass/install.sh +22 -16
- package/karnel/tools/security/binwalk/install.sh +7 -2
- package/karnel/tools/security/burpsuite/install.sh +54 -26
- package/karnel/tools/security/dirb/install.sh +7 -2
- package/karnel/tools/security/dnsrecon/install.sh +7 -2
- package/karnel/tools/security/enum4linux/install.sh +7 -2
- package/karnel/tools/security/exiftool/install.sh +7 -2
- package/karnel/tools/security/ffuf/install.sh +18 -15
- package/karnel/tools/security/foremost/install.sh +7 -2
- package/karnel/tools/security/gobuster/install.sh +21 -17
- package/karnel/tools/security/hashcat/install.sh +7 -2
- package/karnel/tools/security/hydra/install.sh +7 -2
- package/karnel/tools/security/john/install.sh +7 -2
- package/karnel/tools/security/masscan/install.sh +6 -2
- package/karnel/tools/security/metasploit/install.sh +14 -8
- package/karnel/tools/security/netcat/install.sh +7 -2
- package/karnel/tools/security/nikto/install.sh +7 -2
- package/karnel/tools/security/nmap/install.sh +7 -2
- package/karnel/tools/security/smbclient/install.sh +7 -2
- package/karnel/tools/security/sqlmap/install.sh +7 -2
- package/karnel/tools/security/steghide/install.sh +7 -2
- package/karnel/tools/security/subfinder/install.sh +22 -16
- package/karnel/tools/security/tcpdump/install.sh +7 -2
- package/karnel/tools/security/theharvester/install.sh +7 -2
- package/karnel/tools/security/wafw00f/install.sh +42 -3
- package/karnel/tools/security/whatweb/install.sh +7 -2
- package/karnel/tools/security/whois/install.sh +7 -2
- package/karnel/tools/security/wpscan/install.sh +42 -3
- package/karnel/tools/security/zap/install.sh +44 -18
- package/karnel/tools/shell/all.sh +11 -10
- package/karnel/tools/shell/better-npm/install.sh +7 -4
- package/karnel/tools/shell/fzf-tab/install.sh +7 -4
- package/karnel/tools/shell/history-substring/install.sh +7 -4
- package/karnel/tools/shell/powerlevel10k/install.sh +7 -4
- package/karnel/tools/shell/you-should-use/install.sh +7 -4
- package/karnel/tools/shell/zsh-autopair/install.sh +7 -4
- package/karnel/tools/shell/zsh-autosuggestions/install.sh +7 -4
- package/karnel/tools/shell/zsh-completions/install.sh +7 -4
- package/karnel/tools/shell/zsh-defer/install.sh +7 -4
- package/karnel/tools/shell/zsh-syntax-highlighting/install.sh +7 -4
- package/karnel/tools/ui/all.sh +8 -7
- package/karnel/tools/utils/all.sh +13 -11
- package/karnel/tools/utils/applaunch/install.sh +2 -2
- package/karnel/tools/utils/fconv/install.sh +2 -2
- package/karnel/tools/utils/filecheck/install.sh +2 -2
- package/karnel/tools/utils/notes/install.sh +2 -2
- package/karnel/tools/utils/passman/install.sh +2 -2
- package/karnel/tools/utils/qrcode/install.sh +1 -1
- package/karnel/tools/utils/splash/install.sh +2 -2
- package/karnel/tools/utils/treex/install.sh +2 -2
- package/karnel/tools/utils/websites/install.sh +2 -2
- package/karnel/tools/voice/all.sh +1 -1
- package/karnel/utils/backup.sh +182 -0
- package/karnel/utils/bootstrap.sh +67 -3
- package/karnel/utils/downloaded-python.sh +50 -11
- package/karnel/utils/env.sh +27 -7
- package/karnel/utils/install.sh +272 -11
- package/karnel/utils/tools.sh +111 -6
- package/package.json +4 -3
- package/scripts/check-package.js +86 -9
- package/scripts/completion.bash +134 -13
- package/scripts/completion.zsh +138 -53
- package/scripts/npm-install.js +9 -3
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.
|
|
11
|
+
<img src="https://img.shields.io/badge/version-4.15.0-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">
|
|
@@ -56,10 +56,15 @@ Created by **Israel Marques**.
|
|
|
56
56
|
|
|
57
57
|
## Installation
|
|
58
58
|
|
|
59
|
-
### Via
|
|
59
|
+
### Via checksummed GitHub release (recommended)
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
|
|
62
|
+
version=4.15.0
|
|
63
|
+
tmpdir=$(mktemp -d) && trap 'rm -rf "$tmpdir"' EXIT
|
|
64
|
+
base="https://github.com/israelmarques1024-dotcom/karnel-termux/releases/download/v$version"
|
|
65
|
+
curl -fsSL "$base/karnel-termux-install.sh" -o "$tmpdir/karnel-termux-install.sh"
|
|
66
|
+
curl -fsSL "$base/karnel-termux-install.sh.sha256" -o "$tmpdir/karnel-termux-install.sh.sha256"
|
|
67
|
+
(cd "$tmpdir" && sha256sum -c karnel-termux-install.sh.sha256) && bash "$tmpdir/karnel-termux-install.sh" --ref "v$version"
|
|
63
68
|
```
|
|
64
69
|
|
|
65
70
|
### Via npm
|
|
@@ -80,6 +85,10 @@ After installation, run:
|
|
|
80
85
|
karnel
|
|
81
86
|
```
|
|
82
87
|
|
|
88
|
+
In a terminal, running `karnel` without a command opens a curated menu for
|
|
89
|
+
common workflows. The menu is not a complete inventory of CLI commands,
|
|
90
|
+
aliases, or options; use `karnel help` and the CLI reference for the full set.
|
|
91
|
+
|
|
83
92
|
---
|
|
84
93
|
|
|
85
94
|
## Usage
|
|
@@ -104,7 +113,7 @@ karnel
|
|
|
104
113
|
| `karnel start editor` | Start code-server (VS Code in browser) |
|
|
105
114
|
| `karnel pg` | PostgreSQL manager |
|
|
106
115
|
| `karnel init <template>` | Initialize projects with templates |
|
|
107
|
-
| `karnel deploy` |
|
|
116
|
+
| `karnel deploy` | Run Vercel, Railway, Netlify, or Supabase CLI commands |
|
|
108
117
|
| `karnel supabase` | Manage the Supabase CLI and remote-project helpers |
|
|
109
118
|
| `karnel robin` | Manage the Robin OSINT service |
|
|
110
119
|
| `karnel --version` | Show installed version |
|
|
@@ -363,7 +372,9 @@ karnel brain sync # Sync with private GitHub
|
|
|
363
372
|
|
|
364
373
|
## karnel voice
|
|
365
374
|
|
|
366
|
-
Capture audio from microphone, review in editor, copy
|
|
375
|
+
Capture audio from the microphone, optionally review it in an editor, copy it
|
|
376
|
+
to the clipboard, and dispatch an AI agent with the transcribed prompt. If an
|
|
377
|
+
editor is unavailable or no TTY is attached, Karnel uses the raw transcript.
|
|
367
378
|
|
|
368
379
|
```bash
|
|
369
380
|
karnel voice opencode # Record -> edit -> opencode run
|
|
@@ -415,7 +426,7 @@ Microphone -> termux-speech-to-text -> editor (edit) -> clipboard -> AI agent
|
|
|
415
426
|
|
|
416
427
|
- Termux:API: `pkg install termux-api`
|
|
417
428
|
- App Termux:API: https://karneltermux.vercel.app/termux/api
|
|
418
|
-
- Editor: `karnel install editor`
|
|
429
|
+
- Editor (optional): `karnel install editor`; otherwise use `--raw` or the automatic raw fallback
|
|
419
430
|
|
|
420
431
|
---
|
|
421
432
|
|
|
@@ -467,7 +478,8 @@ karnel env ls # List variables
|
|
|
467
478
|
|
|
468
479
|
## karnel deploy
|
|
469
480
|
|
|
470
|
-
|
|
481
|
+
Run an installed platform CLI through Karnel; arguments after the tool name are
|
|
482
|
+
forwarded unchanged:
|
|
471
483
|
|
|
472
484
|
```bash
|
|
473
485
|
karnel deploy vercel # Deploy to Vercel
|
|
Binary file
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -83,6 +83,11 @@ import "@/cli/commands/doctor/code"
|
|
|
83
83
|
|
|
84
84
|
The `@` symbol is replaced with `$KARNEL_PATH`. This avoids hardcoded paths.
|
|
85
85
|
|
|
86
|
+
`import()` is not an idempotent module loader: it calls `source` on every import
|
|
87
|
+
and does not track files already loaded. Top-level assignments and other side
|
|
88
|
+
effects therefore run again when the same file is imported more than once;
|
|
89
|
+
imported files must tolerate repeated evaluation where callers can repeat them.
|
|
90
|
+
|
|
86
91
|
### Critical Scope Implication
|
|
87
92
|
|
|
88
93
|
Because `import()` calls `source` from within a function, any `declare` statement
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Documentation Changelog
|
|
2
2
|
|
|
3
|
+
## 4.15.0 - 2026-08-14
|
|
4
|
+
|
|
5
|
+
- Replaced the unavailable GGA fork with the official Gentleman Guardian
|
|
6
|
+
Angel v2.10.1, pinned by commit, with Termux-safe staging, ownership
|
|
7
|
+
verification, rollback, and non-destructive uninstall.
|
|
8
|
+
- Made backup/restore transactional: staged configs, ancestor symlink
|
|
9
|
+
rejection, signal-safe rollback, concurrent backup isolation, validated
|
|
10
|
+
snapshot names, and explicit package/configuration phase separation.
|
|
11
|
+
- Hardened lifecycle ownership so pre-existing installs are never adopted,
|
|
12
|
+
arbitrary handler exit codes are treated as failures, and stale or empty
|
|
13
|
+
locks are recovered safely.
|
|
14
|
+
- Pinned release/npm/installer together: the npm package carries a validated
|
|
15
|
+
`RELEASE_COMMIT`, the release workflow is serialized per tag and refuses
|
|
16
|
+
divergent partial publications, and the installer activates only a verified,
|
|
17
|
+
clean checkout.
|
|
18
|
+
- Authenticated security and AI installers with fixed versions and official
|
|
19
|
+
SHA-256 checksums, safe archive extraction, staging, and rollback; unverifiable
|
|
20
|
+
upstream assets now fail closed instead of executing unauthenticated bytes.
|
|
21
|
+
- Fixed the npm postinstall to distinguish the npm bin symlink from a complete
|
|
22
|
+
managed installation, and removed the deprecated `curl | bash` guidance.
|
|
23
|
+
- Updated ShellCheck/syntax/test gates to 294 scripts and added regression
|
|
24
|
+
suites for backup, lifecycle, installer integrity, and AI installer hardening.
|
|
25
|
+
|
|
3
26
|
## 4.14.0 - 2026-08-14
|
|
4
27
|
|
|
5
28
|
- Added tested Cactus 2.0.1 support on ARM64 through Ubuntu Proot with an
|
package/docs/cli/README.md
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
karnel <command> [arguments]
|
|
5
5
|
```
|
|
6
6
|
|
|
7
|
-
With no command, Karnel opens
|
|
8
|
-
available and prints help in noninteractive contexts.
|
|
7
|
+
With no command, Karnel opens a curated interactive menu (TUI) when a terminal
|
|
8
|
+
is available and prints help in noninteractive contexts. The menu exposes common
|
|
9
|
+
workflows, not every command, alias, or option documented below.
|
|
9
10
|
|
|
10
11
|
---
|
|
11
12
|
|
|
@@ -442,8 +443,9 @@ karnel env ls
|
|
|
442
443
|
karnel voice [agent] [options]
|
|
443
444
|
```
|
|
444
445
|
|
|
445
|
-
Captures audio via `termux-speech-to-text`, opens the transcript in
|
|
446
|
-
copies to clipboard, and dispatches the AI agent.
|
|
446
|
+
Captures audio via `termux-speech-to-text`, optionally opens the transcript in
|
|
447
|
+
`$EDITOR`, copies it to the clipboard, and dispatches the AI agent. If no editor
|
|
448
|
+
is installed or no TTY is available, Karnel continues with the raw transcript.
|
|
447
449
|
|
|
448
450
|
### Agent targets
|
|
449
451
|
|
|
@@ -539,18 +541,21 @@ cd . && karnel init # Auto-detect
|
|
|
539
541
|
|
|
540
542
|
---
|
|
541
543
|
|
|
542
|
-
## deploy —
|
|
544
|
+
## deploy — Run deployment CLIs
|
|
543
545
|
|
|
544
546
|
```bash
|
|
545
547
|
karnel deploy <tool> [args...]
|
|
546
548
|
```
|
|
547
549
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
|
552
|
-
|
|
553
|
-
| `
|
|
550
|
+
`deploy` checks that the selected executable exists, then replaces Karnel with
|
|
551
|
+
that CLI and forwards all remaining arguments.
|
|
552
|
+
|
|
553
|
+
| Tool | Executable |
|
|
554
|
+
|------|------------|
|
|
555
|
+
| `vercel` | `vercel` |
|
|
556
|
+
| `railway` | `railway` |
|
|
557
|
+
| `netlify` | `netlify` |
|
|
558
|
+
| `supabase` | `supabase`; this is a generic CLI pass-through, not a deployment action by itself |
|
|
554
559
|
|
|
555
560
|
```bash
|
|
556
561
|
karnel deploy vercel
|
|
@@ -568,19 +573,19 @@ karnel deploy supabase
|
|
|
568
573
|
karnel supabase <subcommand> [options]
|
|
569
574
|
```
|
|
570
575
|
|
|
571
|
-
The top-level command manages Supabase CLI installation and
|
|
572
|
-
workflows. It does not start the local Supabase
|
|
573
|
-
Docker on a Linux host.
|
|
576
|
+
The top-level command manages the pinned Supabase CLI installation and provides
|
|
577
|
+
thin wrappers for linked-project workflows. It does not start the local Supabase
|
|
578
|
+
stack on Termux; `supabase start` requires Docker on a Linux host.
|
|
574
579
|
|
|
575
580
|
| Subcommand | Description |
|
|
576
581
|
|------------|-------------|
|
|
577
|
-
| `doctor` | Check CLI,
|
|
578
|
-
| `types` |
|
|
579
|
-
| `migrate` |
|
|
580
|
-
| `link` |
|
|
581
|
-
| `remote-start` / `remote` |
|
|
582
|
-
| `remote-status` / `status` |
|
|
583
|
-
| `install` / `uninstall` | Install or remove
|
|
582
|
+
| `doctor` | Check the CLI, `supabase/config.toml`, Docker expectations, and API reachability |
|
|
583
|
+
| `types` | Run `supabase gen types typescript --linked`; extra arguments are not forwarded |
|
|
584
|
+
| `migrate` | Forward arguments to `supabase db` |
|
|
585
|
+
| `link` | Forward arguments to `supabase link` |
|
|
586
|
+
| `remote-start` / `remote` | Print a guide for running the Docker-backed local stack on a Linux host |
|
|
587
|
+
| `remote-status` / `status` | Run `supabase status`, which reports the local stack rather than hosted-project health |
|
|
588
|
+
| `install` / `uninstall` | Install or remove Karnel's pinned Supabase CLI binary |
|
|
584
589
|
|
|
585
590
|
```bash
|
|
586
591
|
karnel supabase install
|
|
@@ -589,6 +594,43 @@ karnel supabase types
|
|
|
589
594
|
karnel supabase migrate push
|
|
590
595
|
```
|
|
591
596
|
|
|
597
|
+
The downloaded Linux binary may still fail on Android because of unsupported
|
|
598
|
+
system calls. The wrapper reports a `SIGSYS` failure and recommends PRoot or a
|
|
599
|
+
Linux host; installation alone does not guarantee native Android compatibility.
|
|
600
|
+
|
|
601
|
+
---
|
|
602
|
+
|
|
603
|
+
## plugin — Plugin manager
|
|
604
|
+
|
|
605
|
+
```bash
|
|
606
|
+
karnel plugin <subcommand> [options]
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
| Subcommand | Description |
|
|
610
|
+
|------------|-------------|
|
|
611
|
+
| `search [query]` | Search the pinned approved registry snapshot |
|
|
612
|
+
| `install <name>` | Install a plugin from that registry |
|
|
613
|
+
| `install <owner/repo> --unsafe` | Install an unreviewed repository after confirmation |
|
|
614
|
+
| `update <name>` | Atomically update an installed plugin |
|
|
615
|
+
| `remove` / `uninstall <name>` | Remove an installed plugin |
|
|
616
|
+
| `list` / `ls` | List installed plugins and their trust source |
|
|
617
|
+
| `create` / `scaffold <name>` | Create and activate a validated local plugin scaffold |
|
|
618
|
+
|
|
619
|
+
Search accepts `--command <name>`, `--compatible`, and `--capability <name>`.
|
|
620
|
+
Capabilities are `network`, `filesystem-read`, `filesystem-write`, `process`,
|
|
621
|
+
and `environment`. `--unsafe` applies only to `install` and `update`.
|
|
622
|
+
|
|
623
|
+
Plugins are Bash code, run with the current user's permissions, and are not
|
|
624
|
+
sandboxed. Registry review and manifest validation are not isolation boundaries.
|
|
625
|
+
|
|
626
|
+
```bash
|
|
627
|
+
karnel plugin search backup --compatible
|
|
628
|
+
karnel plugin install karnel-hello
|
|
629
|
+
karnel plugin install owner/repo --unsafe
|
|
630
|
+
karnel plugin update karnel-hello
|
|
631
|
+
karnel plugin remove karnel-hello
|
|
632
|
+
```
|
|
633
|
+
|
|
592
634
|
---
|
|
593
635
|
|
|
594
636
|
## pg — PostgreSQL manager
|
|
@@ -659,23 +701,29 @@ karnel backup restore [file]
|
|
|
659
701
|
```
|
|
660
702
|
|
|
661
703
|
Creates `$KARNEL_DATA/backups/termux-<timestamp>.tar.gz` with SHA256 checksum.
|
|
704
|
+
Concurrent runs reserve distinct names atomically instead of overwriting a
|
|
705
|
+
backup created in the same second.
|
|
662
706
|
|
|
663
707
|
### Included in backup
|
|
664
708
|
|
|
665
|
-
-
|
|
666
|
-
-
|
|
667
|
-
-
|
|
709
|
+
- Package selections embedded under `metadata/packages.list` (`dpkg --get-selections`)
|
|
710
|
+
- A catalog snapshot of tool installer directories, not a record of which tools are installed
|
|
711
|
+
- Selected shell configs (`.bashrc`, `.zshrc`, `.profile`, `.zshenv`, `.inputrc`)
|
|
668
712
|
- Termux configs (fonts, colors, properties)
|
|
669
|
-
- SSH keys
|
|
670
|
-
- `~/.config`
|
|
671
|
-
- APT
|
|
713
|
+
- SSH configuration, known hosts, authorized keys, and public keys; private keys are excluded
|
|
714
|
+
- Selected `~/.config` application directories; `github-copilot`, `nvm`, `coc`, `Code`, and `yarn` are excluded, as are symbolic links and all `.env`, credential, auth, and token files matched by the backup filter
|
|
715
|
+
- `$PREFIX/etc/apt/sources.list` only; files under `sources.list.d` and APT keys are not included
|
|
716
|
+
|
|
717
|
+
Backups are gzip-compressed, not encrypted. API environment variables and SSH
|
|
718
|
+
private keys are not exported, but copied application configuration can still
|
|
719
|
+
contain credentials. Protect local and cloud copies as sensitive plaintext data.
|
|
672
720
|
|
|
673
721
|
### Options
|
|
674
722
|
|
|
675
723
|
| Flag | Description |
|
|
676
724
|
|------|-------------|
|
|
677
|
-
| `--cloud` |
|
|
678
|
-
| `snapshot <name>` | Create a named snapshot |
|
|
725
|
+
| `--cloud` | Legacy plaintext upload; requires explicit `KARNEL_ALLOW_PLAINTEXT_CLOUD_BACKUP=1` acknowledgement |
|
|
726
|
+
| `snapshot <name>` | Create a timestamped named snapshot using the same contents and secret filter as a full backup; names accept 1-64 letters, numbers, dots, underscores, or hyphens |
|
|
679
727
|
| `list` / `ls` | List full backups and snapshots |
|
|
680
728
|
| `info` / `show [file]` | Show a backup's contents (latest if omitted) |
|
|
681
729
|
| `--cron` | Schedule a daily backup at 3:00 AM |
|
|
@@ -689,6 +737,11 @@ karnel backup snapshot before-update
|
|
|
689
737
|
karnel backup list
|
|
690
738
|
```
|
|
691
739
|
|
|
740
|
+
Cloud backup is disabled by default because the archive is not encrypted or
|
|
741
|
+
signed. The legacy opt-in uploads both archive and checksum, but they share the
|
|
742
|
+
same remote trust boundary. Package selections and the informational tool
|
|
743
|
+
catalog are embedded in the archive.
|
|
744
|
+
|
|
692
745
|
---
|
|
693
746
|
|
|
694
747
|
## restore — Full Termux restore
|
|
@@ -699,22 +752,28 @@ karnel restore [--cloud] [--list] [<file>]
|
|
|
699
752
|
|
|
700
753
|
### What it restores
|
|
701
754
|
|
|
702
|
-
-
|
|
755
|
+
- Selected shell configs to `~/`
|
|
703
756
|
- Termux configs
|
|
704
|
-
- SSH keys
|
|
705
|
-
-
|
|
706
|
-
-
|
|
707
|
-
-
|
|
708
|
-
- Karnel
|
|
709
|
-
|
|
710
|
-
|
|
757
|
+
- SSH configuration and public keys (legacy archives may also contain private keys)
|
|
758
|
+
- The selected `.config` directories present in the archive
|
|
759
|
+
- `$PREFIX/etc/apt/sources.list` when present
|
|
760
|
+
- Embedded package selections (via `dpkg --set-selections` + `apt-get dselect-upgrade`)
|
|
761
|
+
- The tool catalog is retained as metadata only; Karnel does not incorrectly reinstall every tool in the source catalog
|
|
762
|
+
|
|
763
|
+
Requires and verifies the SHA256 checksum before extraction. Restore rejects
|
|
764
|
+
archives containing traversal paths, links, devices, or other unsafe entries.
|
|
765
|
+
Configuration is first merged into staging so unrelated existing files remain
|
|
766
|
+
in place, then committed with local backups. A copy, move, or package-restore
|
|
767
|
+
failure rolls configuration back instead of reporting a partial success.
|
|
768
|
+
Package-manager operations themselves are not transactionally reversible by
|
|
769
|
+
Karnel if `apt-get` changes package state before returning an error.
|
|
711
770
|
|
|
712
771
|
### Options
|
|
713
772
|
|
|
714
773
|
| Argument | Description |
|
|
715
774
|
|----------|-------------|
|
|
716
775
|
| `<file>` | Path to a specific backup file |
|
|
717
|
-
| `--cloud` |
|
|
776
|
+
| `--cloud` | Legacy unauthenticated cloud restore; requires `KARNEL_ALLOW_UNAUTHENTICATED_CLOUD_RESTORE=1` |
|
|
718
777
|
| `--list`, `-l` | List available full backups and snapshots |
|
|
719
778
|
| `--help`, `-h` | Show help |
|
|
720
779
|
|
package/install.sh
CHANGED
|
@@ -14,12 +14,17 @@ readonly P_NC='\e[0m'
|
|
|
14
14
|
REPO="https://github.com/israelmarques1024-dotcom/karnel-termux"
|
|
15
15
|
BRANCH="main"
|
|
16
16
|
RELEASE_REF=""
|
|
17
|
+
INSTALL_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
18
|
+
RELEASE_COMMIT="${KARNEL_RELEASE_COMMIT:-}"
|
|
19
|
+
if [[ -z "$RELEASE_COMMIT" && -f "$INSTALL_SCRIPT_DIR/karnel/RELEASE_COMMIT" ]]; then
|
|
20
|
+
read -r RELEASE_COMMIT <"$INSTALL_SCRIPT_DIR/karnel/RELEASE_COMMIT" || RELEASE_COMMIT=""
|
|
21
|
+
fi
|
|
17
22
|
KARNEL_DATA="${XDG_DATA_HOME:-$HOME/.local/share}/karnel-data"
|
|
18
23
|
KARNEL_REPO="${XDG_DATA_HOME:-$HOME/.local/share}/karnel"
|
|
19
24
|
KARNEL_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/karnel"
|
|
20
25
|
KARNEL_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/karnel"
|
|
21
26
|
|
|
22
|
-
TOTAL_STEPS=
|
|
27
|
+
TOTAL_STEPS=4
|
|
23
28
|
CURRENT_STEP=0
|
|
24
29
|
|
|
25
30
|
_cols() {
|
|
@@ -66,26 +71,46 @@ log_info() {
|
|
|
66
71
|
echo -e " ${P_BORDER}→${P_NC} $1"
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
_INSTALL_STAGING_ROOT=""
|
|
75
|
+
_INSTALL_PREVIOUS_KARNEL_REPO=""
|
|
76
|
+
_INSTALL_REPO_ACTIVATED=false
|
|
77
|
+
_INSTALL_REPO_HAD_PREVIOUS=false
|
|
78
|
+
_INSTALL_KARNEL_SYMLINK_CHANGED=false
|
|
71
79
|
_INSTALL_PREVIOUS_KARNEL_SYMLINK=""
|
|
72
80
|
|
|
73
81
|
_cleanup_failed() {
|
|
74
82
|
echo -e "\n ${P_FAIL}✖${P_NC} Installation failed at step ${CURRENT_STEP}. Cleaning up..."
|
|
75
|
-
if $
|
|
76
|
-
rm -rf "$KARNEL_REPO"
|
|
77
|
-
fi
|
|
78
|
-
if $_INSTALL_CREATED_KARNEL_SYMLINK && [[ -L "$PREFIX/bin/karnel" ]]; then
|
|
83
|
+
if $_INSTALL_KARNEL_SYMLINK_CHANGED; then
|
|
79
84
|
if [[ -n "$_INSTALL_PREVIOUS_KARNEL_SYMLINK" ]]; then
|
|
80
|
-
|
|
85
|
+
local rollback_link_dir
|
|
86
|
+
rollback_link_dir=$(mktemp -d "$PREFIX/bin/.karnel-rollback.XXXXXX")
|
|
87
|
+
ln -s "$_INSTALL_PREVIOUS_KARNEL_SYMLINK" "$rollback_link_dir/karnel"
|
|
88
|
+
mv -Tf "$rollback_link_dir/karnel" "$PREFIX/bin/karnel"
|
|
89
|
+
rmdir "$rollback_link_dir"
|
|
81
90
|
else
|
|
82
91
|
rm -f "$PREFIX/bin/karnel"
|
|
83
92
|
fi
|
|
84
93
|
fi
|
|
94
|
+
if $_INSTALL_REPO_ACTIVATED; then
|
|
95
|
+
rm -rf "$KARNEL_REPO"
|
|
96
|
+
if $_INSTALL_REPO_HAD_PREVIOUS && [[ -d "$_INSTALL_PREVIOUS_KARNEL_REPO" ]]; then
|
|
97
|
+
mv "$_INSTALL_PREVIOUS_KARNEL_REPO" "$KARNEL_REPO"
|
|
98
|
+
fi
|
|
99
|
+
fi
|
|
100
|
+
[[ -z "$_INSTALL_STAGING_ROOT" ]] || rm -rf "$_INSTALL_STAGING_ROOT"
|
|
85
101
|
echo -e " ${P_DIM}Run install.sh again to retry${P_NC}"
|
|
86
102
|
exit 1
|
|
87
103
|
}
|
|
88
104
|
|
|
105
|
+
_finish_install() {
|
|
106
|
+
if $_INSTALL_REPO_HAD_PREVIOUS && [[ -d "$_INSTALL_PREVIOUS_KARNEL_REPO" ]]; then
|
|
107
|
+
rm -rf "$_INSTALL_PREVIOUS_KARNEL_REPO"
|
|
108
|
+
fi
|
|
109
|
+
[[ -z "$_INSTALL_STAGING_ROOT" ]] || rm -rf "$_INSTALL_STAGING_ROOT"
|
|
110
|
+
_INSTALL_REPO_ACTIVATED=false
|
|
111
|
+
_INSTALL_KARNEL_SYMLINK_CHANGED=false
|
|
112
|
+
}
|
|
113
|
+
|
|
89
114
|
separator() {
|
|
90
115
|
local cols=$(_cols)
|
|
91
116
|
local line=$(printf "%${cols}s")
|
|
@@ -178,7 +203,21 @@ install_dependencies() {
|
|
|
178
203
|
setup_directories() {
|
|
179
204
|
log_step 2 "Setting up directories"
|
|
180
205
|
|
|
181
|
-
|
|
206
|
+
umask 077
|
|
207
|
+
local directory
|
|
208
|
+
for directory in "$KARNEL_DATA" "$KARNEL_CACHE" "$KARNEL_CONFIG"; do
|
|
209
|
+
if [[ -L "$directory" ]]; then
|
|
210
|
+
log_fail "Refusing symlink directory: $directory"
|
|
211
|
+
return 1
|
|
212
|
+
fi
|
|
213
|
+
mkdir -p -m 700 "$directory" || return 1
|
|
214
|
+
chmod 700 "$directory" || return 1
|
|
215
|
+
done
|
|
216
|
+
if [[ -L "$KARNEL_REPO" ]]; then
|
|
217
|
+
log_fail "Refusing symlink directory: $KARNEL_REPO"
|
|
218
|
+
return 1
|
|
219
|
+
fi
|
|
220
|
+
mkdir -p -m 700 "$(dirname "$KARNEL_REPO")" || return 1
|
|
182
221
|
|
|
183
222
|
log_info "Repo $KARNEL_REPO"
|
|
184
223
|
log_info "Data $KARNEL_DATA"
|
|
@@ -190,11 +229,10 @@ setup_directories() {
|
|
|
190
229
|
clone_repo() {
|
|
191
230
|
log_step 3 "Cloning repository"
|
|
192
231
|
|
|
193
|
-
local script_dir
|
|
194
|
-
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
232
|
+
local script_dir="$INSTALL_SCRIPT_DIR"
|
|
195
233
|
local is_dev_install=0
|
|
196
234
|
|
|
197
|
-
if [[
|
|
235
|
+
if [[ "$script_dir" != "$KARNEL_REPO" ]] && git -C "$script_dir" rev-parse --is-inside-work-tree &>/dev/null; then
|
|
198
236
|
is_dev_install=1
|
|
199
237
|
fi
|
|
200
238
|
|
|
@@ -206,32 +244,38 @@ clone_repo() {
|
|
|
206
244
|
KARNEL_REPO="$script_dir"
|
|
207
245
|
log_info "Developer installation detected"
|
|
208
246
|
log_ok "Using local repository"
|
|
209
|
-
|
|
247
|
+
else
|
|
248
|
+
local existing_repo=0
|
|
249
|
+
if [[ -e "$KARNEL_REPO" ]]; then
|
|
250
|
+
if ! git -C "$KARNEL_REPO" rev-parse --is-inside-work-tree &>/dev/null; then
|
|
251
|
+
log_fail "Refusing to replace pre-existing non-repository: $KARNEL_REPO"
|
|
252
|
+
return 1
|
|
253
|
+
fi
|
|
254
|
+
existing_repo=1
|
|
255
|
+
fi
|
|
256
|
+
|
|
257
|
+
if [[ $existing_repo -eq 1 ]]; then
|
|
210
258
|
local origin_url
|
|
211
259
|
origin_url="$(git -C "$KARNEL_REPO" remote get-url origin 2>/dev/null)"
|
|
212
|
-
if [[ "$origin_url" != "$
|
|
260
|
+
if [[ "${origin_url%.git}" != "${REPO%.git}" ]]; then
|
|
213
261
|
log_fail "Existing Karnel repository has an unexpected origin"
|
|
214
262
|
return 1
|
|
215
263
|
fi
|
|
216
|
-
|
|
217
|
-
if
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
log_fail "Failed to update existing repository"
|
|
221
|
-
return 1
|
|
222
|
-
fi
|
|
223
|
-
else
|
|
224
|
-
if ! git -c core.hooksPath=/dev/null -C "$KARNEL_REPO" pull origin "$BRANCH" &>/dev/null; then
|
|
225
|
-
log_fail "Failed to update existing repository"
|
|
226
|
-
return 1
|
|
227
|
-
fi
|
|
264
|
+
local worktree_status
|
|
265
|
+
if ! worktree_status=$(git -C "$KARNEL_REPO" status --porcelain --untracked-files=all); then
|
|
266
|
+
log_fail "Failed to inspect existing Karnel repository"
|
|
267
|
+
return 1
|
|
228
268
|
fi
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
269
|
+
if [[ -n "$worktree_status" ]]; then
|
|
270
|
+
log_fail "Refusing to update a dirty Karnel repository"
|
|
271
|
+
return 1
|
|
272
|
+
fi
|
|
273
|
+
fi
|
|
274
|
+
|
|
275
|
+
_INSTALL_STAGING_ROOT=$(mktemp -d "$(dirname "$KARNEL_REPO")/.karnel-staging.XXXXXX")
|
|
276
|
+
local candidate_repo="$_INSTALL_STAGING_ROOT/repo"
|
|
233
277
|
progress_bar 0 10
|
|
234
|
-
git clone --depth=1
|
|
278
|
+
git clone --depth=1 --branch "$BRANCH" "$REPO" "$candidate_repo" &>/dev/null &
|
|
235
279
|
local pid=$!
|
|
236
280
|
local dots=0
|
|
237
281
|
while kill -0 "$pid" 2>/dev/null; do
|
|
@@ -239,11 +283,42 @@ clone_repo() {
|
|
|
239
283
|
printf "\r Cloning%s " "$(printf '%*s' "$dots" '' | tr ' ' '.')"
|
|
240
284
|
sleep 0.5
|
|
241
285
|
done
|
|
242
|
-
wait "$pid"
|
|
243
|
-
|
|
286
|
+
if ! wait "$pid"; then
|
|
287
|
+
log_fail "Failed to clone repository"
|
|
288
|
+
return 1
|
|
289
|
+
fi
|
|
290
|
+
if [[ -n "$RELEASE_REF" ]]; then
|
|
291
|
+
local candidate_commit
|
|
292
|
+
candidate_commit=$(git -C "$candidate_repo" rev-parse HEAD 2>/dev/null) || return 1
|
|
293
|
+
if [[ "$candidate_commit" != "$RELEASE_COMMIT" ]]; then
|
|
294
|
+
log_fail "Release commit mismatch for $RELEASE_REF"
|
|
295
|
+
log_info "Expected $RELEASE_COMMIT, got $candidate_commit"
|
|
296
|
+
return 1
|
|
297
|
+
fi
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
if [[ $existing_repo -eq 1 ]]; then
|
|
301
|
+
_INSTALL_PREVIOUS_KARNEL_REPO=$(mktemp -d "$(dirname "$KARNEL_REPO")/.karnel-previous.XXXXXX")
|
|
302
|
+
rmdir "$_INSTALL_PREVIOUS_KARNEL_REPO"
|
|
303
|
+
mv "$KARNEL_REPO" "$_INSTALL_PREVIOUS_KARNEL_REPO"
|
|
304
|
+
_INSTALL_REPO_HAD_PREVIOUS=true
|
|
305
|
+
fi
|
|
306
|
+
if ! mv "$candidate_repo" "$KARNEL_REPO"; then
|
|
307
|
+
if $_INSTALL_REPO_HAD_PREVIOUS; then
|
|
308
|
+
mv "$_INSTALL_PREVIOUS_KARNEL_REPO" "$KARNEL_REPO"
|
|
309
|
+
_INSTALL_REPO_HAD_PREVIOUS=false
|
|
310
|
+
fi
|
|
311
|
+
log_fail "Failed to activate repository"
|
|
312
|
+
return 1
|
|
313
|
+
fi
|
|
314
|
+
_INSTALL_REPO_ACTIVATED=true
|
|
244
315
|
progress_bar 10 10
|
|
245
316
|
echo
|
|
246
|
-
|
|
317
|
+
if [[ $existing_repo -eq 1 ]]; then
|
|
318
|
+
log_ok "Repository updated"
|
|
319
|
+
else
|
|
320
|
+
log_ok "Repository cloned"
|
|
321
|
+
fi
|
|
247
322
|
fi
|
|
248
323
|
|
|
249
324
|
export KARNEL_REPO
|
|
@@ -263,20 +338,21 @@ create_symlink() {
|
|
|
263
338
|
|
|
264
339
|
[[ -z "$PREFIX" ]] && { log_fail "PREFIX is not set. Are you running in Termux?"; return 1; }
|
|
265
340
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if [[ -e "$PREFIX/bin/karnel" && ! -L "$PREFIX/bin/karnel" ]]; then
|
|
341
|
+
if [[ ( -e "$PREFIX/bin/karnel" || -L "$PREFIX/bin/karnel" ) && ! -L "$PREFIX/bin/karnel" ]]; then
|
|
269
342
|
log_fail "Refusing to replace existing non-symlink: $PREFIX/bin/karnel"
|
|
270
343
|
return 1
|
|
271
344
|
fi
|
|
272
345
|
if [[ -L "$PREFIX/bin/karnel" ]]; then
|
|
273
346
|
_INSTALL_PREVIOUS_KARNEL_SYMLINK="$(readlink "$PREFIX/bin/karnel")"
|
|
274
347
|
fi
|
|
275
|
-
|
|
276
|
-
|
|
348
|
+
local link_staging
|
|
349
|
+
link_staging=$(mktemp -d "$PREFIX/bin/.karnel-link.XXXXXX")
|
|
350
|
+
ln -s "$KARNEL_REPO/karnel/bin/karnel" "$link_staging/karnel"
|
|
351
|
+
mv -Tf "$link_staging/karnel" "$PREFIX/bin/karnel"
|
|
352
|
+
rmdir "$link_staging"
|
|
353
|
+
_INSTALL_KARNEL_SYMLINK_CHANGED=true
|
|
277
354
|
|
|
278
355
|
if [[ -L "$PREFIX/bin/karnel" ]]; then
|
|
279
|
-
_INSTALL_CREATED_KARNEL_SYMLINK=true
|
|
280
356
|
log_ok "Symlink created: karnel → ${KARNEL_REPO}/karnel/bin/karnel"
|
|
281
357
|
else
|
|
282
358
|
log_fail "Failed to create symlink"
|
|
@@ -284,19 +360,6 @@ create_symlink() {
|
|
|
284
360
|
fi
|
|
285
361
|
}
|
|
286
362
|
|
|
287
|
-
save_config() {
|
|
288
|
-
log_step 5 "Saving configuration"
|
|
289
|
-
|
|
290
|
-
cat >"$KARNEL_CONFIG/config" <<EOF
|
|
291
|
-
karnel_repo='$KARNEL_REPO'
|
|
292
|
-
karnel_data='$KARNEL_DATA'
|
|
293
|
-
karnel_cache='$KARNEL_CACHE'
|
|
294
|
-
karnel_config='$KARNEL_CONFIG'
|
|
295
|
-
EOF
|
|
296
|
-
|
|
297
|
-
log_ok "Configuration saved"
|
|
298
|
-
}
|
|
299
|
-
|
|
300
363
|
show_final_message() {
|
|
301
364
|
echo
|
|
302
365
|
separator
|
|
@@ -322,15 +385,33 @@ show_final_message() {
|
|
|
322
385
|
}
|
|
323
386
|
|
|
324
387
|
main() {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
388
|
+
while [[ $# -gt 0 ]]; do
|
|
389
|
+
case "$1" in
|
|
390
|
+
--ref)
|
|
391
|
+
[[ $# -ge 2 && "$2" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] || {
|
|
392
|
+
echo -e "\n ${P_FAIL}✖${P_NC} Invalid or missing release ref" >&2
|
|
393
|
+
return 1
|
|
394
|
+
}
|
|
395
|
+
BRANCH="$2"
|
|
396
|
+
RELEASE_REF="$2"
|
|
397
|
+
shift 2
|
|
398
|
+
;;
|
|
399
|
+
--commit)
|
|
400
|
+
[[ $# -ge 2 && "$2" =~ ^[0-9a-f]{40}$ ]] || {
|
|
401
|
+
echo -e "\n ${P_FAIL}✖${P_NC} Invalid or missing release commit" >&2
|
|
402
|
+
return 1
|
|
403
|
+
}
|
|
404
|
+
RELEASE_COMMIT="$2"
|
|
405
|
+
shift 2
|
|
406
|
+
;;
|
|
407
|
+
*)
|
|
408
|
+
echo -e "\n ${P_FAIL}✖${P_NC} Usage: install.sh [--ref vX.Y.Z --commit SHA]" >&2
|
|
409
|
+
return 1
|
|
410
|
+
;;
|
|
411
|
+
esac
|
|
412
|
+
done
|
|
413
|
+
if [[ -n "$RELEASE_REF" && ! "$RELEASE_COMMIT" =~ ^[0-9a-f]{40}$ ]]; then
|
|
414
|
+
echo -e "\n ${P_FAIL}✖${P_NC} Release installation requires an immutable commit SHA" >&2
|
|
334
415
|
return 1
|
|
335
416
|
fi
|
|
336
417
|
|
|
@@ -346,7 +427,7 @@ main() {
|
|
|
346
427
|
setup_directories
|
|
347
428
|
clone_repo
|
|
348
429
|
create_symlink
|
|
349
|
-
|
|
430
|
+
_finish_install
|
|
350
431
|
show_final_message
|
|
351
432
|
}
|
|
352
433
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0cb37fa9cbd9b82b371fdae9fd07c2041bfc4b19
|