diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml index 9c4022b..051ea6d 100644 --- a/.github/workflows/deploy-website.yml +++ b/.github/workflows/deploy-website.yml @@ -8,6 +8,12 @@ on: paths: - "website/**" - "branding/**" + - "VERSION" + - "agents/**" + - "personas/**" + - "roles/**" + - "skills/**" + - "scripts/build-website.py" - ".github/workflows/deploy-website.yml" workflow_dispatch: @@ -38,7 +44,10 @@ jobs: python3 branding/decode_assets.py fi - # Static site root = website/ (no build step) + # Stitch pages + site.json from VERSION and catalog counts (no npm) + python3 scripts/build-website.py + + # Static site root = website/ (no JS framework) cp -a website/. _site/ # Canonical brand files from branding/ — only copy what exists @@ -71,8 +80,9 @@ jobs: # Avoid Jekyll processing on Pages touch _site/.nojekyll - # Drop internal docs from public site + # Drop internal docs and stitch fragments from public site rm -f _site/README.md + rm -rf _site/_src echo echo "=== _site layout ===" diff --git a/config/completions/bash/grokhunter.bash b/config/completions/bash/grokhunter.bash index d9dba8d..444d67c 100644 --- a/config/completions/bash/grokhunter.bash +++ b/config/completions/bash/grokhunter.bash @@ -7,7 +7,7 @@ _grokhunter_completions() { cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" - local cmds="status doctor binds proot-binds setup sync boot ensure models skills agents team coding-team scout benjamin lucas harper review fix desktop overlay ship docs modeler ci aider session host mcp plugin flow storage editor hook shell github secrets toolchain menu git-identity credits ai-smoke smoke install plan help version" + local cmds="status doctor binds proot-binds setup sync boot ensure models skills agents team coding-team scout benjamin lucas harper review fix desktop overlay ship docs modeler ci aider session host mcp plugin flow storage editor hook shell github secrets toolchain tui lab menu git-identity credits ai-smoke smoke install plan help version" local model_sub="install status force --force help" local skills_sub="install status help" local agents_sub="status list help" @@ -52,6 +52,12 @@ _grokhunter_completions() { ensure) COMPREPLY=( $(compgen -W "--force" -- "${cur}") ) ;; + tui|lab) + COMPREPLY=( $(compgen -W "help --help" -- "${cur}") ) + ;; + menu|kali-menu|desktop-menu) + COMPREPLY=( $(compgen -W "install remove help" -- "${cur}") ) + ;; ai-smoke|smoke|team|coding-team|scout|benjamin|lucas|harper|review|fix|desktop|plan) # free-form prompt ;; diff --git a/config/profile.d/grokhunter.sh b/config/profile.d/grokhunter.sh index a006d06..d5d3e8f 100644 --- a/config/profile.d/grokhunter.sh +++ b/config/profile.d/grokhunter.sh @@ -51,6 +51,7 @@ if [[ -n "${ZSH_VERSION:-}" ]]; then fpath=("${GROKHUNTER_HOME}/config/completions/zsh" ${fpath[@]}) fi (( ${+aliases[ghn]} )) || alias ghn='grok-nethunter' + (( ${+aliases[ghl]} )) || alias ghl='grokhunter tui' (( ${+aliases[ghd]} )) || alias ghd='grokhunter doctor' (( ${+aliases[ghs]} )) || alias ghs='grokhunter status' (( ${+aliases[ghsu]} )) || alias ghsu='grokhunter setup' @@ -74,6 +75,7 @@ if [[ -n "${BASH_VERSION:-}" ]]; then source "${GROKHUNTER_HOME}/config/completions/bash/grokhunter.bash" fi alias ghn='grok-nethunter' 2>/dev/null || true + alias ghl='grokhunter tui' 2>/dev/null || true alias ghd='grokhunter doctor' 2>/dev/null || true alias ghs='grokhunter status' 2>/dev/null || true alias ghsu='grokhunter setup' 2>/dev/null || true diff --git a/docs/SHELL.md b/docs/SHELL.md index 502eb30..989bb2f 100644 --- a/docs/SHELL.md +++ b/docs/SHELL.md @@ -57,6 +57,7 @@ Same installer. In `~/.bashrc`: | Alias | Expands to | |-------|------------| | `ghn` | `grok-nethunter` | +| `ghl` | `grokhunter tui` | | `ghd` | `grokhunter doctor` | | `ghs` | `grokhunter status` | | `ghsu` | `grokhunter setup` | diff --git a/lib/tui.sh b/lib/tui.sh new file mode 100644 index 0000000..b6e62c7 --- /dev/null +++ b/lib/tui.sh @@ -0,0 +1,425 @@ +#!/usr/bin/env bash +# GrokHunter lab TUI — thin menu over existing CLI. +# Not Grok Build. Bare `grokhunter` still launches grok-nethunter. +# Picker fallback: whiptail → dialog → fzf → numbered printf + read. + +# shellcheck disable=SC2034 + +_gh_tui_self() { + if [[ -n "${GH_TUI_SELF:-}" && -e "${GH_TUI_SELF}" ]]; then + printf '%s\n' "${GH_TUI_SELF}" + return 0 + fi + if [[ -n "${GROKHUNTER_HOME:-}" && -f "${GROKHUNTER_HOME}/bin/grokhunter" ]]; then + printf '%s\n' "${GROKHUNTER_HOME}/bin/grokhunter" + return 0 + fi + printf '%s\n' "grokhunter" +} + +_gh_tui_is_tty() { + [[ -t 0 && -t 1 ]] +} + +_gh_tui_usage() { + cat <<'EOF' +GrokHunter lab TUI + +Usage: + grokhunter tui Lab operations menu + grokhunter lab Alias for tui + grokhunter tui help This help + +This is the lab menu (status / doctor / setup / skills / …). +It is not Grok Build. Bare `grokhunter` still opens the Grok TUI. +`grokhunter menu` is the XFCE Applications submenu, not this screen. + +Needs a tty. Non-interactive: + grokhunter status + grokhunter doctor + grokhunter help + +Picker: whiptail → dialog → fzf → numbered prompt. +Never prints XAI_API_KEY or secrets.env contents. +EOF +} + +_gh_tui_picker_name() { + if command -v whiptail >/dev/null 2>&1; then + printf '%s\n' "whiptail" + return 0 + fi + if command -v dialog >/dev/null 2>&1; then + printf '%s\n' "dialog" + return 0 + fi + if command -v fzf >/dev/null 2>&1; then + printf '%s\n' "fzf" + return 0 + fi + printf '%s\n' "numbered" +} + +_gh_tui_main_items() { + cat <<'EOF' +1|status +2|doctor +3|setup +4|skills +5|models +6|binds +7|git-identity +8|XFCE menu +9|credits +a|agents +0|Grok TUI +q|quit +EOF +} + +_gh_tui_agent_items() { + cat <<'EOF' +t|team +s|scout +r|review +f|fix +d|desktop +b|back +q|quit +EOF +} + +_gh_tui_skills_items() { + cat <<'EOF' +s|status +i|install +b|back +EOF +} + +_gh_tui_models_items() { + cat <<'EOF' +s|status +i|install +b|back +EOF +} + +_gh_tui_binds_items() { + cat <<'EOF' +s|status +r|repair +b|back +EOF +} + +_gh_tui_ident_items() { + cat <<'EOF' +s|show +t|set +b|back +EOF +} + +_gh_tui_xfce_items() { + cat <<'EOF' +i|install +r|remove +b|back +EOF +} + +_gh_tui_pause() { + local _ans + if ! _gh_tui_is_tty; then + return 0 + fi + printf '\n[lab] Enter to continue · q quit: ' + if ! IFS= read -r _ans; then + return 2 + fi + case "${_ans}" in + q|Q|quit|QUIT) return 99 ;; + esac + return 0 +} + +_gh_tui_confirm() { + local prompt="${1:-Proceed?}" + local _ans + if ! _gh_tui_is_tty; then + return 1 + fi + printf '%s [y/N]: ' "${prompt}" + if ! IFS= read -r _ans; then + return 1 + fi + case "${_ans}" in + y|Y|yes|YES) return 0 ;; + esac + return 1 +} + +# Menu chrome goes to stderr. Selected key is printed on stdout. +# Returns 2 on EOF / cancel. +_gh_tui_pick() { + local title="$1" + local items_fn="$2" + local picker key label + local -a tags=() labels=() + picker="$(_gh_tui_picker_name)" + + local item_blob + item_blob="$("${items_fn}")" + while IFS='|' read -r key label; do + [[ -n "${key}" ]] || continue + tags+=("${key}") + labels+=("${label}") + done <<< "${item_blob}" + + case "${picker}" in + whiptail) + local -a args=() + local i + for i in "${!tags[@]}"; do + args+=("${tags[$i]}" "${labels[$i]}") + done + key="$(whiptail --title "GrokHunter lab" --menu "${title}" 20 60 12 "${args[@]}" 3>&1 1>&2 2>&3)" || return 2 + printf '%s\n' "${key}" + return 0 + ;; + dialog) + local -a args=() + local i + for i in "${!tags[@]}"; do + args+=("${tags[$i]}" "${labels[$i]}") + done + key="$(dialog --title "GrokHunter lab" --menu "${title}" 20 60 12 "${args[@]}" 3>&1 1>&2 2>&3)" || return 2 + printf '%s\n' "${key}" + return 0 + ;; + fzf) + local choice + choice="$("${items_fn}" | sed 's/|/ /' | fzf --prompt="lab> " --height=16 --reverse)" || return 2 + key="${choice%% *}" + key="${key%% *}" + printf '%s\n' "${key}" + return 0 + ;; + esac + + echo >&2 + echo "GrokHunter lab v${VERSION:-?} picker=${picker}" >&2 + echo "${title}" >&2 + echo >&2 + while IFS='|' read -r key label; do + [[ -n "${key}" ]] || continue + printf ' %s %s\n' "${key}" "${label}" >&2 + done <<< "${item_blob}" + echo >&2 + printf '> ' >&2 + if ! IFS= read -r key; then + return 2 + fi + key="${key#"${key%%[![:space:]]*}"}" + key="${key%"${key##*[![:space:]]}"}" + [[ -n "${key}" ]] || return 2 + printf '%s\n' "${key}" +} + +_gh_tui_run_cli() { + local self rc + self="$(_gh_tui_self)" + echo + set +e + bash "${self}" "$@" + rc=$? + set -e + echo + echo "[lab] exit ${rc}" + return 0 +} + +_gh_tui_open_grok() { + local self launcher + self="$(_gh_tui_self)" + echo + echo "[lab] opening Grok Build TUI…" + if declare -F _grok_launcher >/dev/null 2>&1; then + launcher="$(_grok_launcher)" + exec "${launcher}" + fi + exec bash "${self}" +} + +_gh_tui_open_grok_agent() { + local agent="$1" + local self + self="$(_gh_tui_self)" + echo + echo "[lab] launching agent ${agent}…" + exec bash "${self}" "${agent}" +} + +cmd_tui() { + local sub="${1:-}" + case "${sub}" in + help|-h|--help) + _gh_tui_usage + return 0 + ;; + esac + + if [[ "${NON_INTERACTIVE:-0}" == "1" || -n "${CI:-}" ]]; then + echo "grokhunter tui needs a tty (NON_INTERACTIVE/CI set)." >&2 + _gh_tui_usage >&2 + return 2 + fi + if ! _gh_tui_is_tty; then + echo "grokhunter tui needs a tty." >&2 + _gh_tui_usage >&2 + return 2 + fi + + trap 'echo; echo "[lab] interrupted"; exit 130' INT + + local key pause_rc + while true; do + key="$(_gh_tui_pick "Lab operations" _gh_tui_main_items)" || { + echo + echo "[lab] bye" + return 0 + } + case "${key}" in + q|Q|quit) + echo "[lab] bye" + return 0 + ;; + 1|status) + _gh_tui_run_cli status + ;; + 2|doctor) + _gh_tui_run_cli doctor + ;; + 3|setup) + if _gh_tui_confirm "Run grokhunter setup?"; then + _gh_tui_run_cli setup + else + echo "[lab] skipped setup" + fi + ;; + 4|skills) + key="$(_gh_tui_pick "skills" _gh_tui_skills_items)" || continue + case "${key}" in + i|I|install) + if _gh_tui_confirm "Install skills + agents + personas + roles?"; then + _gh_tui_run_cli skills install + else + echo "[lab] skipped skills install" + fi + ;; + q|Q|quit) echo "[lab] bye"; return 0 ;; + b|B|back) continue ;; + *) _gh_tui_run_cli skills status ;; + esac + ;; + 5|models) + key="$(_gh_tui_pick "models" _gh_tui_models_items)" || continue + case "${key}" in + i|I|install) + if _gh_tui_confirm "Install V9 / 4.6 model pickers?"; then + _gh_tui_run_cli models install + else + echo "[lab] skipped models install" + fi + ;; + q|Q|quit) echo "[lab] bye"; return 0 ;; + b|B|back) continue ;; + *) _gh_tui_run_cli models status ;; + esac + ;; + 6|binds) + key="$(_gh_tui_pick "binds" _gh_tui_binds_items)" || continue + case "${key}" in + r|R|repair) + if _gh_tui_confirm "Repair proot binds?"; then + _gh_tui_run_cli binds repair + else + echo "[lab] skipped binds repair" + fi + ;; + q|Q|quit) echo "[lab] bye"; return 0 ;; + b|B|back) continue ;; + *) _gh_tui_run_cli binds status ;; + esac + ;; + 7|git-identity|identity) + key="$(_gh_tui_pick "git-identity" _gh_tui_ident_items)" || continue + case "${key}" in + t|T|set) + if _gh_tui_confirm "Set git identity from gh / token / origin?"; then + _gh_tui_run_cli git-identity set + else + echo "[lab] skipped git-identity set" + fi + ;; + q|Q|quit) echo "[lab] bye"; return 0 ;; + b|B|back) continue ;; + *) _gh_tui_run_cli git-identity show ;; + esac + ;; + 8|menu|xfce) + key="$(_gh_tui_pick "XFCE menu (not this TUI)" _gh_tui_xfce_items)" || continue + case "${key}" in + i|I|install) + if _gh_tui_confirm "Install Applications → GrokHunter submenu?"; then + _gh_tui_run_cli menu install + else + echo "[lab] skipped menu install" + fi + ;; + r|R|remove) + if _gh_tui_confirm "Remove XFCE GrokHunter menu entries?"; then + _gh_tui_run_cli menu remove + else + echo "[lab] skipped menu remove" + fi + ;; + q|Q|quit) echo "[lab] bye"; return 0 ;; + *) continue ;; + esac + ;; + 9|credits) + _gh_tui_run_cli credits + ;; + a|A|agents) + key="$(_gh_tui_pick "agents (opens Grok TUI if no prompt)" _gh_tui_agent_items)" || continue + case "${key}" in + t|T|team) _gh_tui_open_grok_agent coding-team ;; + s|S|scout) _gh_tui_open_grok_agent scout ;; + r|R|review) _gh_tui_open_grok_agent review ;; + f|F|fix) _gh_tui_open_grok_agent fix ;; + d|D|desktop) _gh_tui_open_grok_agent desktop ;; + q|Q|quit) echo "[lab] bye"; return 0 ;; + *) continue ;; + esac + ;; + 0|grok|tui-grok) + _gh_tui_open_grok + ;; + *) + echo "[lab] unknown: ${key}" + ;; + esac + pause_rc=0 + _gh_tui_pause || pause_rc=$? + if [[ "${pause_rc}" -eq 99 ]]; then + echo "[lab] bye" + return 0 + fi + if [[ "${pause_rc}" -eq 2 ]]; then + echo "[lab] bye" + return 0 + fi + done +} diff --git a/scripts/build-website.py b/scripts/build-website.py new file mode 100644 index 0000000..11476bf --- /dev/null +++ b/scripts/build-website.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +"""Stitch GrokHunter static pages and write website/site.json. + +No npm. Safe to run on a phone (Python 3) or in GitHub Actions. +Fragments live in website/_src/. Generated HTML is committed so +`python3 -m http.server -d website` works without the stitch. +""" +from __future__ import annotations + +import json +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +WEB = ROOT / "website" +SRC = WEB / "_src" + +SKIP_AGENT_MD = {"README.md", "HANDOFF-TEMPLATES.md", "REFERENCES.md"} +PAGES = ( + { + "slug": "index", + "file": "index.html", + "body": "index.body.html", + "title": "GrokHunter {version} — AI coding lab on unrooted Android", + "description": ( + "Kali NetHunter Rootless × Grok Build 1.0.5 — AI coding lab for " + "unrooted Android. Grok 4.6, agents, personas, roles, Aider, XFCE desktop." + ), + }, + { + "slug": "install", + "file": "install.html", + "body": "install.body.html", + "title": "Install GrokHunter {version} — rootless overlay", + "description": "Install or refresh GrokHunter on unrooted Android. Overlay-only, XFCE, Grok Build.", + }, + { + "slug": "cli", + "file": "cli.html", + "body": "cli.body.html", + "title": "GrokHunter CLI — Grok TUI vs lab TUI", + "description": "grokhunter commands. Bare grokhunter opens Grok Build. grokhunter tui is the lab menu.", + }, + { + "slug": "desktop", + "file": "desktop.html", + "body": "desktop.body.html", + "title": "GrokHunter desktop — XFCE on Termux:X11", + "description": "nh-x11, grokhunter menu (XFCE submenu), binds, and phone-real X11 notes. Not the lab TUI.", + }, + { + "slug": "agents", + "file": "agents.html", + "body": "agents.body.html", + "title": "GrokHunter Coding Team — agents, personas, roles", + "description": "Coding Team loop and lab specialists for GrokHunter on unrooted Android.", + }, + { + "slug": "faq", + "file": "faq.html", + "body": "faq.body.html", + "title": "GrokHunter FAQ — rootless lab", + "description": "FAQ, architecture, and credits for the GrokHunter rootless coding lab.", + }, + { + "slug": "404", + "file": "404.html", + "body": "404.body.html", + "title": "GrokHunter — page not found", + "description": "That page is not on the GrokHunter site.", + }, +) + + +def count_catalog() -> dict[str, int]: + agents = sum( + 1 + for p in (ROOT / "agents").glob("*.md") + if p.name not in SKIP_AGENT_MD + ) + personas = sum(1 for _ in (ROOT / "personas").glob("*.toml")) + roles = sum(1 for _ in (ROOT / "roles").glob("*.toml")) + skills = sum(1 for p in (ROOT / "skills").iterdir() if p.is_dir()) + return { + "agents": agents, + "personas": personas, + "roles": roles, + "skills": skills, + } + + +def tokens(version: str, counts: dict[str, int]) -> dict[str, str]: + return { + "VERSION": version, + "MIN_GROK": "1.0.5", + "AGENTS": str(counts["agents"]), + "PERSONAS": str(counts["personas"]), + "ROLES": str(counts["roles"]), + "SKILLS": str(counts["skills"]), + } + + +def subst(text: str, table: dict[str, str]) -> str: + for key, val in table.items(): + text = text.replace("{{" + key + "}}", val) + return text + + +def stitch(page: dict, table: dict[str, str]) -> str: + head = (SRC / "head.html").read_text() + header = (SRC / "header.html").read_text() + body = (SRC / page["body"]).read_text() + footer = (SRC / "footer.html").read_text() + local = dict(table) + local["TITLE"] = page["title"].format(version=table["VERSION"]) + local["DESCRIPTION"] = page["description"] + local["PAGE"] = "" if page["file"] == "index.html" else page["file"] + local["SLUG"] = page["slug"] + html = head + header + body + footer + html = subst(html, local) + if "{{" in html: + leftover = [tok for tok in html.split("{{")[1:]] + raise SystemExit(f"unreplaced token in {page['file']}: {leftover[:3]}") + return html + + +def write_site_json(version: str, counts: dict[str, int]) -> None: + data = { + "version": version, + "min_grok": "1.0.5", + "overlay_cache": "2026.2.25", + "agents": counts["agents"], + "personas": counts["personas"], + "roles": counts["roles"], + "skills": counts["skills"], + "pages": [p["file"] for p in PAGES], + "tui": { + "bare": "Grok Build fullscreen TUI (grok-nethunter)", + "tui": "Lab operations menu (alias: lab)", + "menu": "Kali/XFCE Applications submenu", + }, + } + path = WEB / "site.json" + path.write_text(json.dumps(data, indent=2) + "\n") + print(f"wrote {path.relative_to(ROOT)}") + + +def main() -> int: + if not SRC.is_dir(): + print(f"missing {SRC}", file=sys.stderr) + return 1 + version = (ROOT / "VERSION").read_text().strip() + counts = count_catalog() + table = tokens(version, counts) + write_site_json(version, counts) + for page in PAGES: + out = WEB / page["file"] + out.write_text(stitch(page, table)) + print(f"wrote {out.relative_to(ROOT)}") + print( + f"catalog agents={counts['agents']} personas={counts['personas']} " + f"roles={counts['roles']} skills={counts['skills']}" + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/website/README.md b/website/README.md index 077f685..d858182 100644 --- a/website/README.md +++ b/website/README.md @@ -1,58 +1,41 @@ # GrokHunter website -Static product landing page for [GrokHunter](https://github.com/FineComputer14451/GrokHunter) **v1.0.10**. +Static product site for [GrokHunter](https://github.com/FineComputer14451/GrokHunter) **v1.0.10**. **Live:** https://finecomputer14451.github.io/GrokHunter/ -## Sections - -| Section | Content | -|---------|---------| -| Hero | Quick install + animated terminal (1.0.10 stack) | -| Stats | Version / Grok min / agents / personas / roles | -| Why | Comparison table | -| Features | 9 feature cards (Grok Build 1.0.5, Grok 4.6, agents, Aider, …) | -| Stack | skills · agents · personas · roles | -| Agents | Coding Team loop + roster table | -| Personas & roles | Full product lists | -| Install | One-liner, full, clone, overlay-only + flags | -| CLI | Full `grokhunter` command list | -| Upgrade | Paste-ready 1.0.10 upgrade path | -| Architecture | Overlay layers | -| FAQ | Rootless, auth, Aider 3.13, X11, scope | - -## Open locally +No npm. Pages are stitched from `website/_src/` by `scripts/build-website.py`. +Generated HTML is committed so a phone can open the files without running the stitch. + +## Pages + +| File | Content | +|------|---------| +| `index.html` | Hero, stats, why, features, links to the rest | +| `install.html` | Install + overlay-only + upgrade | +| `cli.html` | Command list (Grok TUI vs lab TUI vs XFCE `menu`) | +| `desktop.html` | XFCE / Termux:X11 / `nh-x11` / binds / XFCE submenu | +| `agents.html` | Stack, Coding Team, personas / roles | +| `faq.html` | Architecture, FAQ, credits | +| `404.html` | GitHub Pages fallback | +| `site.json` | Version + catalog counts + TUI wording | + +## Build ```bash +python3 scripts/build-website.py python3 -m http.server 8080 -d website -# then open http://localhost:8080 +# http://localhost:8080 ``` -Or open `index.html` directly in a browser. +`site.json` counts `agents/*.md` (minus README/HANDOFF/REFERENCES), `personas/*.toml`, `roles/*.toml`, and `skills/*/` directories. ## Deploy Workflow: [`.github/workflows/deploy-website.yml`](../.github/workflows/deploy-website.yml) -1. Pages source: **GitHub Actions** (already enabled for this repo) -2. Push `website/**` or `branding/**` to `main` **or** **Actions → Deploy website → Run workflow** +1. Pages source: **GitHub Actions** +2. Workflow runs `python3 scripts/build-website.py`, copies `website/` to `_site`, drops `_src/` and `README.md` 3. URL: https://finecomputer14451.github.io/GrokHunter/ -No Node/npm build — pure static HTML/CSS/JS. Brand tokens: `styles.css` (Grok cyan `#00E5C7` · Kali blue `#2777FF` · NetHunter red `#E31C3D` · geometric purple `#9B5DE5`). Assets: `website/assets/` (favicon, lockup, `og.jpg` 1200×630). X profile header: `branding/x-banner.jpg` (upload in X settings). - ---- - -## Geometric Branding Draft - -A new geometric low-poly wolf-fox mascot direction is under review: - -→ See [`branding/geometric-draft/`](../branding/geometric-draft/) - -- Cyan / Purple split -- Red eyes -- No crest -- Full favicon + lockup + hero/OG assets prepared - -Do not replace `website/assets/` until the draft is approved. -- Header mark is now the inline geometric SVG (cyan/purple split, red eyes). `website/assets/` raster favicon is unchanged until the draft is fully approved. -- Hero wash uses cyan left / purple right. `.chip-purple` and `.purple` are used in index.html. +Relative links only (`cli.html`, not `/GrokHunter/cli.html`) so project Pages and `file://` both work. diff --git a/website/_src/404.body.html b/website/_src/404.body.html new file mode 100644 index 0000000..9cb76ce --- /dev/null +++ b/website/_src/404.body.html @@ -0,0 +1,17 @@ +
+
+
+ +

Page not found

+

+ That URL is not part of the GrokHunter product site. +

+
+ Home + Install + Desktop + CLI +
+
+
+
diff --git a/website/_src/cli.body.html b/website/_src/cli.body.html new file mode 100644 index 0000000..79d3006 --- /dev/null +++ b/website/_src/cli.body.html @@ -0,0 +1,45 @@ +
+
+
+ +

grokhunter commands

+

+ Also: grok-nethunter fullscreen launcher · + grok native TUI · + grokhunter tui lab menu · + XFCE session: desktop.html + (nh-x11grokhunter desktop agent) · + aliases via profile (ghd, + ghp, ghsu, …) +

+
+
grokhunterGrok Build fullscreen TUI
+
grokhunter tuiLab operations menu (alias: lab)
+
grokhunter statusShort status line
+
grokhunter doctorFull health report
+
grokhunter bindsProot binds (status|repair|optimize)
+
grokhunter git-identityGitHub-attributable git user.name / email
+
grokhunter menuKali/XFCE Applications submenu — see desktop.html
+
grokhunter setupOne-shot: ensure + skills + doctor
+
grokhunter ensureGrok Build ≥ 1.0.5 + NetHunter profile
+
grokhunter skills installSkills, agents, personas, roles + wrappers
+
grokhunter teamLaunch Coding Team agent
+
grokhunter scout|review|fix|desktopSpecialist agent launchers
+
grokhunter overlay|ship|docsLab specialists (install / release / docs)
+
grokhunter modeler|ci|aiderModels/V9 agent, CI, Aider (`modeler` ≠ `models` CLI)
+
grokhunter session|host|mcptmux/resume, Termux vs Kali, MCP (`mcp` ≠ `grok mcp`)
+
grokhunter plugin|flow|storageplugins (`plugin` ≠ `grok plugin`), workflows, disk
+
grokhunter editor|hook|shellnvim/micro, Grok hooks, profile/completions
+
grokhunter github|secrets|toolchaingit-identity agent (≠ git-identity CLI), secrets.env, apt/compilers
+
grokhunter agents statusInstalled Coding Team agents
+
grokhunter models installV9 / 4.6 model pickers
+
grokhunter ai-smokeSpaceXAI API smoke test
+
grokhunter install [args]Installer (supports --overlay-only)
+
grokhunter plan "…"Built-in plan agent (1.0.5)
+
grokhunter -p "…"Headless one-shot
+
bash scripts/install_aider.shRepair Aider (uv + 3.12)
+
bash scripts/ci-unit.shLocal unit checks
+
+
+
+
diff --git a/website/_src/desktop.body.html b/website/_src/desktop.body.html new file mode 100644 index 0000000..f18266d --- /dev/null +++ b/website/_src/desktop.body.html @@ -0,0 +1,222 @@ +
+
+
+ +

XFCE on Termux:X11

+

+ Optional graphical session. Most pair work stays in the shell. + grokhunter menu installs the XFCE Applications submenu — it is not the lab TUI. +

+
+ Three different “menus” +
grokhunter           Grok Build fullscreen TUI
+grokhunter tui       lab operations menu (alias: lab)
+grokhunter menu      Applications → GrokHunter on XFCE
+nh-x11               start the desktop session
+
+
+
+ +
+
+ +

Install Termux:X11, then nh-x11

+

+ Need the Termux:X11 APK first. SharedUid + GitHub Termux is the smooth path. + F-Droid Termux uses the non-sharedUid APK. +

+
+
+ Launch desktop + +
+
nh-x11
+
+
+
bash install.sh --with-x11Helper + /tmp share for X sockets
+
nh-x11Default: legacy drawing on, compositor off
+
NH_X11_LEGACY=0 nh-x11GPU path if legacy drawing is too slow
+
NH_X11_SESSION=startlxde nh-x11Other DE already installed
+
grokhunter desktopCoding Team desktop agent — not the X session
+
+
+
+ +
+
+ +

X sockets have to be visible inside proot

+

+ grokhunter binds is the repair path when the display exists in Termux + but Kali says it cannot open it. +

+
+
+ Binds + +
+
grokhunter binds status
+grokhunter binds repair
+
+

+ Runtime triage playbook: skill x11-desktop. + Wrapper notes: bwrap-proot keeps GTK/glycin from aborting under proot. +

+
+
+ +
+
+ +

Applications → GrokHunter

+

+ Desktop entries for Grok Build, Coding Team, Scout, Aider, Doctor, Setup. + Log out/in of XFCE if the submenu does not appear immediately. +

+
+
+ Install submenu + +
+
grokhunter menu install
+# or: bash scripts/install_kali_menu.sh
+grokhunter menu remove
+
+
+
+ +
+
+ +

Phone-real wins, ranked

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PriorityActionEffect
1sharedUid APK (GitHub Termux)Stops Android throttling Termux when X11 is foreground
2Disable XFCE compositingBiggest smoothness gain on proot — nh-x11 tries this
3Light DE (XFCE / i3)Less CPU/RAM than GNOME/KDE
4Share /tmpRequired for X sockets — patched by --with-x11
5Avoid SD-card rootfsFaster apt, editors, builds
6Optional GPU (Turnip/Zink)Advanced, device-specific. GrokHunter does not auto-install drivers
+
+
+
+ +
+
+ +

When nh-x11 opens nothing

+
    +
  1. Confirm the Termux:X11 APK matches how Termux was installed (sharedUid only with GitHub Termux).
  2. +
  3. grokhunter binds status then grokhunter binds repair.
  4. +
  5. One DE only. Then: +
    +
    + Reset X11 + +
    +
    pkill -f termux.x11 || true
    +am force-stop com.termux.x11 || true
    +nh-x11
    +
    +
  6. +
  7. Leave legacy drawing on unless you are testing NH_X11_LEGACY=0.
  8. +
+

+ Longer notes: + docs/X11-PERFORMANCE.md + · skill x11-desktop · agent grokhunter desktop. +

+
+
+ +
+
+ +

Shell first, XFCE when the screen is large

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ShellXFCE + nh-x11
Battery / RAMLowHigh — keep one session
Pair programminggrokhunter / grokhunter tuiSame CLI inside a terminal window
Editorsnvim / microGUI editors if you accept the lag
ChromiumPatched --no-sandbox under proot. Lab only
+
+

+ Out of scope: Magisk, HID, firmware, rooted X11 tricks. + Rootless / proot only. +

+ +
+
+
diff --git a/website/_src/footer.html b/website/_src/footer.html new file mode 100644 index 0000000..fd21002 --- /dev/null +++ b/website/_src/footer.html @@ -0,0 +1,37 @@ + + + + + diff --git a/website/_src/head.html b/website/_src/head.html new file mode 100644 index 0000000..8411d66 --- /dev/null +++ b/website/_src/head.html @@ -0,0 +1,33 @@ + + + + + + {{TITLE}} + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/site.json b/website/site.json new file mode 100644 index 0000000..be37575 --- /dev/null +++ b/website/site.json @@ -0,0 +1,23 @@ +{ + "version": "1.0.10", + "min_grok": "1.0.5", + "overlay_cache": "2026.2.25", + "agents": 26, + "personas": 24, + "roles": 25, + "skills": 20, + "pages": [ + "index.html", + "install.html", + "cli.html", + "desktop.html", + "agents.html", + "faq.html", + "404.html" + ], + "tui": { + "bare": "Grok Build fullscreen TUI (grok-nethunter)", + "tui": "Lab operations menu (alias: lab)", + "menu": "Kali/XFCE Applications submenu" + } +}