Skip to content

Instantly share code, notes, and snippets.

@shikhirsingh
Created February 26, 2026 21:12
Show Gist options
  • Select an option

  • Save shikhirsingh/50a222f67e215ad34f5fc6faf73f592e to your computer and use it in GitHub Desktop.

Select an option

Save shikhirsingh/50a222f67e215ad34f5fc6faf73f592e to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# find-environment.sh (v6)
# Purpose: Gather system info so an LLM can recommend correct install commands.
# Works on macOS + Linux. Outputs key=value lines grouped by sections.
set -euo pipefail
section(){ echo; echo "===== $1 ====="; }
kv(){ printf "%s = %s\n" "$1" "${2:-}"; }
have(){ command -v "$1" >/dev/null 2>&1; }
one_line(){ tr '\n' ';' | sed 's/;*$//' ; }
ver_line() {
local c="$1" out=""
if ! have "$c"; then kv "TOOL.${c}.installed" "no"; return; fi
out="$("$c" --version 2>/dev/null | head -n 1 || true)"
[[ -z "$out" ]] && out="$("$c" -V 2>/dev/null | head -n 1 || true)"
[[ -z "$out" ]] && out="$("$c" -v 2>/dev/null | head -n 1 || true)"
[[ -z "$out" ]] && out="(version flag not recognized)"
kv "TOOL.${c}.path" "$(command -v "$c")"
kv "TOOL.${c}.version" "$out"
}
public_ip_best_effort() {
local ip=""
for url in \
"https://api.ipify.org" \
"https://ifconfig.me/ip" \
"https://checkip.amazonaws.com" \
"https://icanhazip.com"
do
if have curl; then
ip="$(curl -fsS --max-time 5 "$url" 2>/dev/null | tr -d ' \n\r\t' || true)"
elif have wget; then
ip="$(wget -qO- --timeout=5 "$url" 2>/dev/null | tr -d ' \n\r\t' || true)"
else
ip=""
fi
if [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ || "$ip" =~ : ]]; then
echo "$ip"; return 0
fi
done
echo "unavailable"
}
# ---------------------------
# TOP MESSAGE + LEGEND
# ---------------------------
echo "LLM_README = This output is a machine environment report grouped by '===== SECTION ====='. Each following line is 'key = value'. Use OS/HW to pick compatible installers and binaries; use VIRTUALIZATION to know if this is a VM/container (affects networking/services/drivers); use NETWORK+FW for connectivity/firewall; use OPEN_PORTS+WEBSERVER to avoid port conflicts; use NODE_ECOSYSTEM to handle Node version managers/proxies/registries."
echo "LLM_LEGEND.VIRTUALIZATION = Interpreting VIRT.* keys: (1) VIRT.detect from systemd-detect-virt (if present) may return values like 'none' (bare metal), 'kvm', 'vmware', 'oracle' (VirtualBox), 'microsoft' (Hyper-V), 'qemu', 'lxc', 'docker', 'podman', etc. (2) VIRT.detect.container is specifically about containers; VIRT.detect.vm is specifically about virtual machines. (3) VIRT.wsl=yes means Linux is running under Windows Subsystem for Linux; kernel/module installs behave differently. (4) VIRT.cgroup_container_hint=yes means process 1 appears to be inside a container (Docker/LXC/Kubernetes), which often restricts systemctl/service management and changes network interfaces. (5) VIRT.cpu_hypervisor_flag=present indicates the CPU reports being virtualized, but does NOT prove container vs VM by itself. Implications: containers/WSL often cannot run systemd normally, may have NAT networking, and cannot install kernel drivers; VMs may allow drivers but can have bridged/NAT network differences."
echo "LLM_LEGEND.FIREWALL = Interpreting FW.* keys: UFW/firewalld/nftables/iptables may be active even if one tool is missing. If firewall is active, incoming ports may be blocked; installations that expose services (Postgres 5432, Redis 6379, web 80/443) may need allow rules. On macOS, socketfilterfw global state indicates built-in firewall."
echo "LLM_LEGEND.OPEN_PORTS = OPEN_PORTS.tcp_listen enumerates listening sockets. If process/PID is shown (ss/lsof), that identifies what owns a port (nginx, node, docker-proxy). If no PID appears, permissions may be limited; try running the script with sudo or interpret as incomplete."
echo "LLM_LEGEND.NODE = Node installs frequently break due to: version managers (nvm/fnm/volta/asdf) selecting a different node than expected; registries/proxies/certs (npm config registry/proxy/cafile/strict-ssl); and missing native build toolchain (Xcode CLT on macOS, build-essential/python3 on Linux). Use NODE.mgr.* + NPM.* + NODE_NATIVE_BUILD_PREREQS."
# ---------------------------
# SYSTEM
# ---------------------------
section "SYSTEM"
kv "REPORT.name" "find-environment"
kv "REPORT.version" "6"
kv "DATE_UTC" "$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || true)"
kv "HOSTNAME" "$(hostname 2>/dev/null || true)"
kv "USER" "${USER:-}"
kv "SHELL" "${SHELL:-}"
kv "PWD" "$(pwd 2>/dev/null || true)"
kv "UMASK" "$(umask 2>/dev/null || true)"
kv "UPTIME" "$(uptime 2>/dev/null || true)"
os_name="$(uname -s 2>/dev/null || true)"
kv "OS.uname" "$os_name"
kv "OS.kernel" "$(uname -r 2>/dev/null || true)"
kv "HW.arch" "$(uname -m 2>/dev/null || true)"
if [[ "$os_name" == "Darwin" ]]; then
kv "OS.family" "macOS"
kv "OS.version" "$(sw_vers -productVersion 2>/dev/null || true)"
kv "OS.build" "$(sw_vers -buildVersion 2>/dev/null || true)"
kv "OS.product_name" "$(sw_vers -productName 2>/dev/null || true)"
else
kv "OS.family" "Linux"
if [[ -f /etc/os-release ]]; then
# shellcheck disable=SC1091
. /etc/os-release
kv "OS.pretty_name" "${PRETTY_NAME:-}"
kv "OS.distro_id" "${ID:-}"
kv "OS.distro_version" "${VERSION_ID:-}"
kv "OS.distro_like" "${ID_LIKE:-}"
fi
kv "OS.libc" "$( (have ldd && ldd --version 2>/dev/null | head -n1) || echo "unknown" )"
fi
kv "LLM_CONTEXT.SYSTEM" "Interpretation: OS.family + HW.arch decide packaging and binary compatibility (e.g., arm64 vs x86_64)."
# ---------------------------
# INIT SYSTEM
# ---------------------------
section "INIT_SYSTEM"
if have systemctl; then
kv "INIT.system" "systemd"
elif have launchctl; then
kv "INIT.system" "launchd"
else
kv "INIT.system" "unknown"
fi
kv "LLM_CONTEXT.INIT_SYSTEM" "Interpretation: databases and daemons are managed by systemd on many Linux systems, and by launchd on macOS. Containers often lack a full init system."
# ---------------------------
# HARDWARE
# ---------------------------
section "HARDWARE"
if [[ "$os_name" == "Darwin" ]]; then
kv "CPU.brand" "$(sysctl -n machdep.cpu.brand_string 2>/dev/null || true)"
kv "CPU.physical_cores" "$(sysctl -n hw.physicalcpu 2>/dev/null || true)"
kv "CPU.logical_cores" "$(sysctl -n hw.logicalcpu 2>/dev/null || true)"
kv "HW.model" "$(sysctl -n hw.model 2>/dev/null || true)"
mem_bytes="$(sysctl -n hw.memsize 2>/dev/null || true)"
if [[ -n "${mem_bytes:-}" ]]; then
kv "RAM.bytes" "$mem_bytes"
kv "RAM.gib" "$(awk -v b="$mem_bytes" 'BEGIN{printf "%.2f", b/1024/1024/1024}')"
fi
kv "RAM.swapusage" "$(sysctl -n vm.swapusage 2>/dev/null || true)"
else
kv "CPU.model" "$(awk -F: '/model name/ {print $2; exit}' /proc/cpuinfo 2>/dev/null | sed 's/^ //')"
kv "CPU.logical_cores" "$(getconf _NPROCESSORS_ONLN 2>/dev/null || true)"
[[ -r /proc/meminfo ]] && kv "RAM.meminfo_MemTotal_kB" "$(awk '/MemTotal/ {print $2}' /proc/meminfo 2>/dev/null || true)"
have free && kv "RAM.free_human" "$(free -h 2>/dev/null | one_line)"
have lscpu && kv "CPU.lscpu_selected" "$(lscpu 2>/dev/null | awk -F: '
/Architecture|Model name|Vendor ID|CPU\(s\)|Thread\(s\) per core|Core\(s\) per socket|Socket\(s\)|Virtualization/{
gsub(/^[ \t]+/,"",$2); printf "%s=%s; ", $1, $2
}' | sed 's/; $//')"
fi
kv "LLM_CONTEXT.HARDWARE" "Interpretation: RAM/cores constrain Docker + DBs; very low RAM may require lightweight DB configs or container limits."
# ---------------------------
# STORAGE
# ---------------------------
section "STORAGE"
kv "DISK.df_root" "$(df -h / 2>/dev/null | tail -n 1 || true)"
if [[ "$os_name" == "Darwin" ]]; then
have diskutil && kv "DISK.diskutil_root" "$(diskutil info / 2>/dev/null | awk -F: '
/File System Personality|Volume Name|Device Identifier|Disk Size|APFS Container Reference/{
gsub(/^[ \t]+/,"",$2); printf "%s=%s; ", $1, $2
}' | sed 's/; $//')"
else
have lsblk && kv "DISK.lsblk" "$(lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE -r 2>/dev/null | one_line)"
fi
kv "LLM_CONTEXT.STORAGE" "Interpretation: Docker images + DB data dirs + build caches can quickly consume disk; low free space commonly breaks installs."
# ---------------------------
# GPU
# ---------------------------
section "GPU"
if [[ "$os_name" == "Darwin" ]]; then
kv "GPU.summary" "$(system_profiler SPDisplaysDataType 2>/dev/null | awk '
/Chipset Model:/ {gsub(/^[ \t]+Chipset Model: /,""); printf "Chipset=%s; ", $0}
/VRAM/ {gsub(/^[ \t]+/,""); printf "%s; ", $0}
/Metal:/ {gsub(/^[ \t]+/,""); printf "%s; ", $0}
' | sed 's/; $//')"
else
if have nvidia-smi; then
kv "GPU.nvidia" "$(nvidia-smi --query-gpu=name,driver_version,memory.total,memory.free,compute_mode --format=csv,noheader 2>/dev/null | one_line)"
kv "GPU.nvidia.cuda_version_hint" "$(nvidia-smi 2>/dev/null | grep -oE 'CUDA Version: [0-9.]+' | head -n1 | sed 's/CUDA Version: //' || true)"
fi
have nvcc && kv "GPU.cuda_toolkit" "$(nvcc --version 2>/dev/null | one_line)"
if have rocm-smi; then
kv "GPU.rocm" "$(rocm-smi 2>/dev/null | head -30 | one_line)"
fi
if have lspci; then
kv "GPU.pci" "$(lspci 2>/dev/null | grep -Ei 'vga|3d|display' | one_line)"
elif [[ -d /sys/class/drm ]]; then
kv "GPU.sysfs_drm" "$(ls -1 /sys/class/drm 2>/dev/null | tr '\n' ',' | sed 's/,$//')"
fi
fi
kv "LLM_CONTEXT.GPU" "Interpretation: NVIDIA+driver suggests CUDA possible; AMD+rocm-smi suggests ROCm; otherwise assume CPU-only unless you explicitly install GPU stack."
# ---------------------------
# VIRTUALIZATION
# ---------------------------
section "VIRTUALIZATION"
if have systemd-detect-virt; then
kv "VIRT.detect" "$(systemd-detect-virt 2>/dev/null || true)"
kv "VIRT.detect.container" "$(systemd-detect-virt --container 2>/dev/null || true)"
kv "VIRT.detect.vm" "$(systemd-detect-virt --vm 2>/dev/null || true)"
else
kv "VIRT.detect" "unknown (systemd-detect-virt not installed)"
fi
if [[ -r /proc/version ]] && grep -qi microsoft /proc/version 2>/dev/null; then
kv "VIRT.wsl" "yes"
else
kv "VIRT.wsl" "no"
fi
if [[ -r /proc/1/cgroup ]] && grep -Eqi 'docker|kubepods|containerd|lxc' /proc/1/cgroup 2>/dev/null; then
kv "VIRT.cgroup_container_hint" "yes"
kv "VIRT.cgroup_sample" "$(head -n 5 /proc/1/cgroup 2>/dev/null | one_line)"
else
kv "VIRT.cgroup_container_hint" "no"
fi
if [[ "$os_name" == "Darwin" ]]; then
hv="$(sysctl -n kern.hv_vmm_present 2>/dev/null || true)"
[[ -n "${hv:-}" ]] && kv "VIRT.kern_hv_vmm_present" "$hv"
else
if [[ -r /proc/cpuinfo ]] && grep -q "^flags" /proc/cpuinfo 2>/dev/null; then
grep -q " hypervisor " /proc/cpuinfo 2>/dev/null && kv "VIRT.cpu_hypervisor_flag" "present" || kv "VIRT.cpu_hypervisor_flag" "not_present_or_unknown"
fi
fi
kv "LLM_CONTEXT.VIRTUALIZATION" "Interpretation: If VIRT.detect is 'docker/lxc/podman' OR VIRT.cgroup_container_hint=yes, treat as a container: system services may not be manageable and host networking differs. If VIRT.detect is 'kvm/vmware/oracle/microsoft/qemu', treat as a VM: you likely can run systemd and install packages normally, but IPs may be NATed. If VIRT.wsl=yes, treat as WSL: kernel drivers/systemd behaviors differ."
kv "LLM_CONTEXT.VIRTUALIZATION.IMPLICATIONS" "Common impacts: (a) Installing GPU drivers/kernel modules often fails inside containers/WSL. (b) Opening inbound ports may require host/VM NAT config. (c) systemctl may not exist or may not work inside containers."
# ---------------------------
# NETWORK + FIREWALL
# ---------------------------
section "NETWORK"
if have curl; then
kv "NET.internet_https" "$(curl -fsS --max-time 5 https://example.com >/dev/null 2>&1 && echo "CONNECTED" || echo "OFFLINE/RESTRICTED")"
else
kv "NET.internet_https" "unknown (curl missing)"
fi
kv "NET.public_ip" "$(public_ip_best_effort)"
if [[ "$os_name" == "Darwin" ]]; then
kv "NET.local_ip.en0" "$(ipconfig getifaddr en0 2>/dev/null || true)"
kv "NET.local_ip.en1" "$(ipconfig getifaddr en1 2>/dev/null || true)"
have ifconfig && kv "NET.ifconfig_summary" "$(ifconfig 2>/dev/null | awk '
/^[a-z0-9]/ {iface=$1; gsub(":", "", iface)}
/inet / && $2!="127.0.0.1" {print iface" inet="$2}
/ether / {print iface" mac="$2}
' | one_line)"
kv "NET.default_route" "$(route -n get default 2>/dev/null | awk -F: '/gateway|interface/{gsub(/^[ \t]+/, "", $2); printf "%s=%s; ", $1, $2}' | sed 's/; $//')"
kv "NET.dns_resolvers" "$(scutil --dns 2>/dev/null | awk '/nameserver\[[0-9]+\]/{print $3}' | paste -sd, - || true)"
else
if have ip; then
kv "NET.interfaces" "$(ip -o link show 2>/dev/null | awk -F': ' '{print $2}' | paste -sd, - || true)"
kv "NET.ipv4_addrs" "$(ip -o -4 addr show 2>/dev/null | awk '{print $2"="$4}' | paste -sd';' - || true)"
kv "NET.default_route" "$(ip route show default 2>/dev/null | head -n 1 || true)"
else
kv "NET.ipv4_addrs" "$(hostname -I 2>/dev/null | tr ' ' ',' | sed 's/,$//' || true)"
fi
if have resolvectl; then
kv "NET.dns_resolvers" "$(resolvectl dns 2>/dev/null | one_line)"
elif [[ -f /etc/resolv.conf ]]; then
kv "NET.dns_resolvers" "$(awk '/^nameserver/{print $2}' /etc/resolv.conf 2>/dev/null | paste -sd, - || true)"
fi
fi
if [[ "$os_name" == "Darwin" ]]; then
if [[ -f /usr/libexec/ApplicationFirewall/socketfilterfw ]]; then
kv "FW.macos.global_state" "$(/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2>/dev/null || echo "unknown")"
kv "FW.macos.stealth_mode" "$(/usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode 2>/dev/null || echo "unknown")"
else
kv "FW.macos" "unknown (socketfilterfw missing)"
fi
else
if have ufw; then
kv "FW.ufw.status" "$( (sudo -n ufw status 2>/dev/null || ufw status 2>/dev/null) | head -n 8 | one_line)"
else
kv "FW.ufw.installed" "no"
fi
if have firewall-cmd; then
kv "FW.firewalld.state" "$(firewall-cmd --state 2>/dev/null || echo "unknown")"
else
kv "FW.firewalld.installed" "no"
fi
if have nft; then
kv "FW.nftables.ruleset_present" "$( (sudo -n nft list ruleset 2>/dev/null || nft list ruleset 2>/dev/null) | head -n 1 >/dev/null && echo "yes" || echo "no_or_perm")"
else
kv "FW.nftables.installed" "no"
fi
if have iptables; then
kv "FW.iptables.rule_count_lines" "$( (sudo -n iptables -S 2>/dev/null || iptables -S 2>/dev/null) | wc -l | tr -d ' ' || echo "unknown")"
else
kv "FW.iptables.installed" "no"
fi
fi
kv "LLM_CONTEXT.NETWORK" "Interpretation: NET.public_ip is best-effort external IP (useful for allowlists/remote access). Local IPs may differ due to NAT/VPN/containers. If FW indicates active firewall, inbound ports may need allow rules."
# ---------------------------
# OPEN PORTS
# ---------------------------
section "OPEN_PORTS"
if have ss; then
kv "OPEN_PORTS.method" "ss"
kv "OPEN_PORTS.tcp_listen" "$(ss -tulpen 2>/dev/null | awk 'NR==1{next} $1 ~ /^tcp/ && $5 ~ /:/ {print $1" "$5" pid="$7}' | one_line)"
elif have lsof; then
kv "OPEN_PORTS.method" "lsof"
kv "OPEN_PORTS.tcp_listen" "$(lsof -nP -iTCP -sTCP:LISTEN 2>/dev/null | awk 'NR==1{next}{print $1" "$9" pid="$2" user="$3}' | one_line)"
elif have netstat; then
kv "OPEN_PORTS.method" "netstat"
kv "OPEN_PORTS.tcp_listen" "$(netstat -tlnp 2>/dev/null | awk 'NR<=2{next}{print $4" pid/prog="$7}' | one_line)"
else
kv "OPEN_PORTS.method" "none"
kv "OPEN_PORTS.tcp_listen" "unknown_no_ss_lsof_netstat"
fi
kv "LLM_CONTEXT.OPEN_PORTS" "Interpretation: These are *listening* ports on this machine. If installing a service that needs a port already LISTENING, either stop the existing service or reconfigure the new service to another port."
# ---------------------------
# WEBSERVER CHECK
# ---------------------------
section "WEBSERVER_CHECK"
if have ps; then
kv "WEBSERVER.process_hits" "$(ps aux 2>/dev/null | grep -Ei 'nginx|apache2|httpd|caddy|traefik|lighttpd|openresty' | grep -v grep | head -n 20 | one_line || true)"
fi
if have systemctl; then
kv "WEBSERVER.systemd_active" "$(systemctl list-units --type=service --state=running 2>/dev/null | grep -Ei 'nginx|apache2|httpd|caddy|traefik|lighttpd' | one_line || true)"
elif have launchctl; then
kv "WEBSERVER.launchd_matches" "$(launchctl list 2>/dev/null | grep -Ei 'nginx|apache|httpd|caddy|traefik|lighttpd' | one_line || true)"
fi
probe_ports=(80 443 3000 3001 8080 8081 8000 8888)
if have curl; then
for p in "${probe_ports[@]}"; do
r1="$(curl -sS -I --max-time 2 "http://127.0.0.1:$p" 2>/dev/null | head -n 1 || true)"
r2="$(curl -sS -I -k --max-time 2 "https://127.0.0.1:$p" 2>/dev/null | head -n 1 || true)"
[[ -n "$r1" ]] && kv "WEBSERVER.http_head.${p}" "$r1"
[[ -n "$r2" ]] && kv "WEBSERVER.https_head.${p}" "$r2"
done
else
kv "WEBSERVER.http_probe" "skipped_curl_missing"
fi
kv "LLM_CONTEXT.WEBSERVER_CHECK" "Interpretation: If you see responses on 80/443/8080/etc, a web app or reverse proxy is already running and may conflict with new installs."
# ---------------------------
# SECURITY / LIMITS
# ---------------------------
section "SECURITY_CONTEXT"
kv "SUDO.present" "$(have sudo && echo yes || echo no)"
if have sudo; then
kv "SUDO.noninteractive" "$(sudo -n true 2>/dev/null && echo YES || echo NO_or_PASSWORD_REQUIRED)"
fi
if [[ "$os_name" != "Darwin" ]]; then
kv "SEC.selinux" "$( (have getenforce && getenforce 2>/dev/null) || echo "unknown/not_present")"
kv "SEC.apparmor" "$( (have aa-status && aa-status 2>/dev/null | head -n 1) || (test -d /sys/kernel/security/apparmor && echo "present" || echo "not_present") )"
fi
kv "LLM_CONTEXT.SECURITY_CONTEXT" "Interpretation: If sudo is restricted, installations may need user-space paths (HOME) rather than system paths; SELinux/AppArmor can block services from binding ports or reading/writing certain paths."
section "LIMITS"
kv "ULIMIT.nofile" "$(ulimit -n 2>/dev/null || true)"
kv "ULIMIT.nproc" "$(ulimit -u 2>/dev/null || true)"
kv "ULIMIT.stack_kb" "$(ulimit -s 2>/dev/null || true)"
kv "LLM_CONTEXT.LIMITS" "Interpretation: Very low ulimits can cause DB/server crashes or build failures."
# ---------------------------
# TOOLS CORE
# ---------------------------
section "TOOLS_CORE"
for t in curl wget git openssl ssh make gcc g++ clang cmake pkg-config jq rsync tar unzip \
python python3 pip pip3 conda virtualenv \
node npm npx pnpm yarn corepack bun deno \
docker docker-compose podman kubectl helm terraform \
sqlite3 psql mysql mariadb mongod mongosh redis-server redis-cli \
ss netstat lsof ip ifconfig; do
ver_line "$t"
done
kv "LLM_CONTEXT.TOOLS_CORE" "Interpretation: Missing core tooling is often the real reason installs fail; prefer installing missing prerequisites first."
# ---------------------------
# CONTAINERS (Docker detail)
# ---------------------------
section "CONTAINERS"
if have docker; then
kv "DOCKER.version" "$(docker --version 2>/dev/null || true)"
kv "DOCKER.daemon_access" "$(docker info >/dev/null 2>&1 && echo "OK" || echo "NO_or_DAEMON_DOWN")"
if docker info >/dev/null 2>&1; then
kv "DOCKER.info.selected" "$(docker info 2>/dev/null | awk -F: '
/Server Version|Docker Root Dir|Storage Driver|Cgroup Driver|Operating System|Architecture|CPUs|Total Memory/{
gsub(/^[ \t]+/,"",$2); printf "%s=%s; ", $1, $2
}' | sed 's/; $//')"
fi
kv "DOCKER.context" "$(docker context show 2>/dev/null || true)"
kv "DOCKER.compose_v2" "$(docker compose version 2>/dev/null | head -n1 || echo "unavailable")"
fi
kv "LLM_CONTEXT.CONTAINERS" "Interpretation: If DOCKER.daemon_access is not OK, container-based installs will fail until the daemon is running and permissions are fixed."
# ---------------------------
# SERVICES HINTS
# ---------------------------
section "SERVICES_HINTS"
if have systemctl; then
kv "SERVICES.running.matches" "$(systemctl list-units --type=service --state=running 2>/dev/null | grep -iE 'docker|containerd|mysql|postgres|mongo|redis|nginx|apache|ollama' | head -n 30 | one_line || true)"
elif have launchctl; then
kv "SERVICES.launchctl.matches" "$(launchctl list 2>/dev/null | grep -iE 'docker|mysql|postgres|mongo|redis|ollama' | head -n 30 | one_line || true)"
else
kv "SERVICES.manager" "unknown"
fi
kv "LLM_CONTEXT.SERVICES_HINTS" "Interpretation: Existing running services can explain port conflicts and suggest pre-installed components."
# ---------------------------
# NODE ECOSYSTEM
# ---------------------------
section "NODE_ECOSYSTEM"
if have node; then
kv "NODE.process.version" "$(node -p 'process.version' 2>/dev/null || true)"
kv "NODE.process.platform" "$(node -p 'process.platform' 2>/dev/null || true)"
kv "NODE.process.arch" "$(node -p 'process.arch' 2>/dev/null || true)"
kv "NODE.process.versions" "$(node -p 'JSON.stringify(process.versions)' 2>/dev/null || true)"
fi
for m in nvm fnm volta asdf mise; do
if have "$m"; then
kv "NODE.mgr.${m}.path" "$(command -v "$m")"
kv "NODE.mgr.${m}.version" "$("$m" --version 2>/dev/null | head -n1 || true)"
else
kv "NODE.mgr.${m}.installed" "no"
fi
done
kv "NODE.nvm.NVM_DIR" "${NVM_DIR:-}"
[[ -z "${NVM_DIR:-}" && -d "$HOME/.nvm" ]] && kv "NODE.nvm.dir_detected" "$HOME/.nvm"
if have npm; then
kv "NPM.version" "$(npm --version 2>/dev/null || true)"
kv "NPM.prefix" "$(npm prefix -g 2>/dev/null || true)"
kv "NPM.global_root" "$(npm root -g 2>/dev/null || true)"
kv "NPM.cache" "$(npm config get cache 2>/dev/null || true)"
kv "NPM.registry" "$(npm config get registry 2>/dev/null || true)"
kv "NPM.proxy" "$(npm config get proxy 2>/dev/null || true)"
kv "NPM.https_proxy" "$(npm config get https-proxy 2>/dev/null || true)"
kv "NPM.strict_ssl" "$(npm config get strict-ssl 2>/dev/null || true)"
kv "NPM.cafile" "$(npm config get cafile 2>/dev/null || true)"
kv "NPM.userconfig" "$(npm config get userconfig 2>/dev/null || true)"
kv "NPM.globalconfig" "$(npm config get globalconfig 2>/dev/null || true)"
fi
if have pnpm; then
kv "PNPM.version" "$(pnpm --version 2>/dev/null || true)"
kv "PNPM.store_path" "$(pnpm store path 2>/dev/null || true)"
fi
if have yarn; then
kv "YARN.version" "$(yarn --version 2>/dev/null || true)"
kv "YARN.registry" "$(yarn config get registry 2>/dev/null || true)"
fi
if have corepack; then
kv "COREPACK.version" "$(corepack --version 2>/dev/null || true)"
kv "COREPACK.status_hint" "$(corepack -v >/dev/null 2>&1 && echo "present" || echo "present_but_restricted")"
fi
kv "LLM_CONTEXT.NODE_ECOSYSTEM" "Interpretation: NODE.mgr.* indicates Node version management that can override system node. NPM.* fields reveal registry/proxy/cert settings that commonly break installs in corporate networks."
section "NODE_NATIVE_BUILD_PREREQS"
if [[ "$os_name" == "Darwin" ]]; then
kv "XCODE.select_path" "$(xcode-select -p 2>/dev/null || echo "missing")"
kv "CLANG.version" "$(have clang && clang --version 2>/dev/null | head -n1 || echo "missing")"
else
kv "PYTHON3.version" "$(have python3 && python3 --version 2>/dev/null || echo "missing")"
kv "MAKE.version" "$(have make && make --version 2>/dev/null | head -n1 || echo "missing")"
kv "GCC.version" "$(have gcc && gcc --version 2>/dev/null | head -n1 || echo "missing")"
fi
kv "LLM_CONTEXT.NODE_NATIVE_BUILD_PREREQS" "Interpretation: Missing build tools cause node-gyp failures when installing native modules."
# ---------------------------
# ENV VARS
# ---------------------------
section "ENV_VARS"
kv "ENV.PATH" "${PATH:-}"
kv "ENV.HOME" "${HOME:-}"
kv "ENV.LANG" "${LANG:-}"
kv "ENV.TERM" "${TERM:-}"
kv "ENV.HTTP_PROXY" "${HTTP_PROXY:-}"
kv "ENV.HTTPS_PROXY" "${HTTPS_PROXY:-}"
kv "ENV.NO_PROXY" "${NO_PROXY:-}"
kv "ENV.NPM_CONFIG_REGISTRY" "${NPM_CONFIG_REGISTRY:-}"
kv "ENV.NODE_OPTIONS" "${NODE_OPTIONS:-}"
kv "ENV.DOCKER_HOST" "${DOCKER_HOST:-}"
kv "ENV.JAVA_HOME" "${JAVA_HOME:-}"
kv "ENV.GOPATH" "${GOPATH:-}"
kv "ENV.CUDA_HOME" "${CUDA_HOME:-}"
kv "ENV.LD_LIBRARY_PATH" "${LD_LIBRARY_PATH:-}"
kv "ENV.VIRTUAL_ENV" "${VIRTUAL_ENV:-}"
kv "ENV.CONDA_DEFAULT_ENV" "${CONDA_DEFAULT_ENV:-}"
kv "LLM_CONTEXT.ENV_VARS" "Interpretation: These env vars can silently alter installs and runtime; proxies/registries are especially important."
echo
echo "===== END find-environment ====="
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment