Skill Tracer
Skills › Compound Engineering › ce-polish › resolve-package-manager.sh

resolve-package-manager.sh

95 lines · skills/ce-polish/scripts/resolve-package-manager.sh at 3449230

1#!/usr/bin/env bash
2#
3# resolve-package-manager.sh — detect which JS package manager a project uses
4# by inspecting lockfiles, and emit the binary name plus canonical command tail.
5#
6# Usage:
7# resolve-package-manager.sh [path]
8#
9# Arguments:
10# path (optional) — directory to inspect. When omitted, defaults to the
11# repo root via `git rev-parse --show-toplevel`.
13# Output contract (two lines on stdout):
14# Line 1: package-manager binary token (`npm` | `pnpm` | `yarn` | `bun`)
15# Line 2: canonical argv tail for running a dev script
16# - npm: "run dev" (npm requires the `run` verb)
17# - pnpm: "dev" (pnpm allows bare script names)
18# - yarn: "dev" (yarn allows bare script names)
19# - bun: "run dev" (bun requires the `run` verb)
21# Lockfile priority order (first match wins):
22# 1. pnpm-lock.yaml -> pnpm
23# 2. yarn.lock -> yarn
24# 3. bun.lock -> bun (text format, preferred — newer canonical)
25# 4. bun.lockb -> bun (binary format, legacy)
26# 5. package-lock.json -> npm
27# When both bun.lock and bun.lockb are present, bun.lock (text) is checked
28# first and wins because it is the newer canonical format.
30# Sentinel (stdout, exit 0):
31# __NO_PACKAGE_JSON__ — the target directory has no package.json
33# Errors (stderr, exit 1):
34# ERROR: <message> — path does not exist, is not a directory, or
35# no positional arg and not inside a git repo
37set -u
39TARGET_PATH="${1:-}"
41# Resolve target directory: positional arg or git repo root.
42if [ -n "$TARGET_PATH" ]; then
43 if [ ! -d "$TARGET_PATH" ]; then
44 echo "ERROR: path does not exist or is not a directory: $TARGET_PATH" >&2
45 exit 1
46 fi
47else
48 TARGET_PATH=$(git rev-parse --show-toplevel 2>/dev/null)
49 if [ -z "$TARGET_PATH" ]; then
50 echo "ERROR: not in a git repository and no path argument provided" >&2
51 exit 1
52 fi
53fi
55# Sentinel: no package.json means this is not a JS/TS project.
56if [ ! -f "$TARGET_PATH/package.json" ]; then
57 echo "__NO_PACKAGE_JSON__"
58 exit 0
59fi
61# Check lockfiles in priority order.
62if [ -f "$TARGET_PATH/pnpm-lock.yaml" ]; then
63 echo "pnpm"
64 echo "dev"
65 exit 0
66fi
68if [ -f "$TARGET_PATH/yarn.lock" ]; then
69 echo "yarn"
70 echo "dev"
71 exit 0
72fi
74if [ -f "$TARGET_PATH/bun.lock" ]; then
75 echo "bun"
76 echo "run dev"
77 exit 0
78fi
80if [ -f "$TARGET_PATH/bun.lockb" ]; then
81 echo "bun"
82 echo "run dev"
83 exit 0
84fi
86if [ -f "$TARGET_PATH/package-lock.json" ]; then
87 echo "npm"
88 echo "run dev"
89 exit 0
90fi
92# Fallback: package.json present but no recognized lockfile.
93echo "npm"
94echo "run dev"
95exit 0