mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-02 11:32:42 +00:00
- 16 cross-shell utilities converted to sh/bash chezmoi executables: ai c2p cp-appid extract_agents fab gdc gh-sonr-org-migrate ghg-clone ghn gho git-summary launch_omp_livediff_overlay lc-elir mdcp mdp pj (ghg-clone not named ghg: unrelated cargo binary owns that name) - cwd/history helpers stay per-shell: yy c cd clip-last + ghg/ghn/gho cd-wrappers in bash/functions/ and zsh/functions/, loaded by rc files - fish keeps only shell-state functions; converted ones now hit PATH - cp-appid ignore gating moved to .local/bin path - dot_agents/skills: 82 skills materialized from dotstate storage so dot_claude skill symlinks resolve on fresh bootstrap; dotstate profile/symlinks.json released .agents/skills .bashrc .zshrc
91 lines
2.9 KiB
Bash
Executable File
91 lines
2.9 KiB
Bash
Executable File
#!/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
|