#!/usr/bin/env bash # fzf package.json script runner with auto-detected package manager. # ── Locate nearest package.json (walk up) ────────────────────────── dir=$PWD pkg="" while :; do if [ -f "$dir/package.json" ]; then pkg="$dir/package.json" break fi [ "$dir" = / ] && break dir=$(dirname "$dir") done if [ -z "$pkg" ]; then echo "pj: no package.json found in this tree" >&2 exit 1 fi root=$(dirname "$pkg") # ── Detect package manager ───────────────────────────────────────── # Priority: packageManager field (corepack) → lockfiles (walking up # past $root to catch monorepo-root locks) → npm fallback pm=$(jq -r '.packageManager // empty' "$pkg") pm=${pm%%@*} if [ -z "$pm" ]; then d=$root while [ -z "$pm" ]; do if [ -f "$d/bun.lockb" ] || [ -f "$d/bun.lock" ]; then pm=bun elif [ -f "$d/pnpm-lock.yaml" ]; then pm=pnpm elif [ -f "$d/yarn.lock" ]; then pm=yarn elif [ -f "$d/package-lock.json" ]; then pm=npm fi [ "$d" = / ] && break d=$(dirname "$d") done [ -n "$pm" ] || pm=npm fi # ── Pick a script ────────────────────────────────────────────────── script=$(jq -r '.scripts // {} | keys[]' "$pkg" | fzf \ --prompt="$pm run ❯ " \ --header="$root" \ --height=40% --layout=reverse --border \ --preview="jq -r --arg s {} '.scripts[\$s]' \"$pkg\"" \ --preview-window=up:2:wrap) [ -n "$script" ] || exit 0 # ── Run (npm needs `--` to forward extra args) ──────────────────── extra=("$@") if [ "$pm" = npm ] && [ $# -gt 0 ]; then extra=(-- "$@") fi # Wrap long-running server scripts in openlogs (live log tail for agents). # Matches dev/start/serve and namespaced variants like dev:web, start:api. wrapper="" if [[ $script =~ ^(dev|start|serve|watch)(:.*)?$ ]]; then # Resolve the binary: PATH → mise resolution → mise installs glob ol=$(command -v openlogs || true) if [ -z "$ol" ] && command -v mise >/dev/null 2>&1; then ol=$(mise which openlogs 2>/dev/null || true) fi if [ -z "$ol" ]; then for cand in "$HOME"/.local/share/mise/installs/node/*/bin/openlogs; do [ -x "$cand" ] && { ol=$cand; break; } done fi if [ -n "$ol" ] && [ -x "$ol" ]; then wrapper=$ol else echo "pj: openlogs not found, running unwrapped" >&2 fi fi if [ -n "$wrapper" ]; then echo "→ $wrapper $pm run $script $*" >&2 exec "$wrapper" "$pm" run "$script" "${extra[@]}" else echo "→ $pm run $script $*" >&2 exec "$pm" run "$script" "${extra[@]}" fi