From skillry-runtime-and-local-app
Use when you need to diagnose startup, process, port, dependency, environment, and runtime health failures.
How this skill is triggered — by the user, by Claude, or both
Slash command
/skillry-runtime-and-local-app:08-runtime-diagnosticsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Provide a systematic, non-destructive procedure for diagnosing why a local or dev-environment application fails to start, crashes immediately, or behaves incorrectly at runtime. It covers port conflicts, missing or wrong environment variables, runtime/dependency version mismatches, wrong working directory, broken native modules, and process-level resource limits — the failure classes behind mos...
Provide a systematic, non-destructive procedure for diagnosing why a local or dev-environment application fails to start, crashes immediately, or behaves incorrectly at runtime. It covers port conflicts, missing or wrong environment variables, runtime/dependency version mismatches, wrong working directory, broken native modules, and process-level resource limits — the failure classes behind most "it works on my machine" reports. The output is, per step, the command run, the finding, the action taken, and the verification that the issue is resolved.
npm run dev / python manage.py runserver / go run . exits non-zero and the cause is not obvious.EADDRINUSE on a specific port.npm run dev 2>&1 | tee /tmp/startup.log.EADDRINUSE: find the holder with lsof -i :PORT (macOS/Linux) or netstat -ano | findstr :PORT (Windows), confirm the PID belongs to a stale dev server (ps -p PID -o pid,command), then kill it and confirm the port frees.node --version against .nvmrc / engines.node; python --version against .python-version / pyproject.toml; go version against the go directive in go.mod. Switch with nvm/pyenv before continuing on a mismatch..env.example for required keys, then confirm each is set and non-empty without printing values. Validate plausibility (a DATABASE_URL that starts with postgres://).node_modules present and in sync with the lockfile (npm ci). Python: the venv is active (which python points inside it) and pip check is clean. Go: go mod verify.uploads/, tmp/, logs/, or certs/ to exist with correct permissions at startup. Confirm with ls -la.psql "$DATABASE_URL" -c '\conninfo', redis-cli -u "$REDIS_URL" ping) and HTTP deps (curl -s -o /dev/null -w '%{http_code}\n' "$API/health"). Report the actual response, not "it worked."ps aux | grep -E 'node|python|ruby|java' — look for two instances on the same port, or a process that should be dead.df -h (a full disk causes opaque write failures), free -m / vm_stat (memory), and ulimit -n (macOS defaults to 256 file descriptors, which connection-heavy Node apps exhaust).dmesg for OOM-killer evidence.process.cwd() / os.getcwd() and verify the .env actually read is the one you edited.lsof -i :PORT; no stale process holds the port..nvmrc / .python-version / go.mod..env.example.npm ci / pip check / go mod verify).lsof, not taken from the startup log line.# 1. Capture the full startup error
npm run dev 2>&1 | tee /tmp/startup.log | head -50
# 2. Port conflict: find, identify, free
lsof -i :3000 # macOS/Linux (Windows: netstat -ano | findstr :3000)
ps -p "$(lsof -ti :3000)" -o pid,command # confirm it is a stale dev server
kill "$(lsof -ti :3000)" && lsof -i :3000 || echo "port 3000 free"
# 3. Runtime version vs project requirement
node --version; cat .nvmrc 2>/dev/null
python --version; cat .python-version 2>/dev/null
go version; grep '^go ' go.mod 2>/dev/null
# 4. Env shape WITHOUT printing values
for k in $(grep -oE '^[A-Z0-9_]+' .env.example 2>/dev/null); do
[ -n "${!k:-}" ] && echo "$k set" || echo "$k MISSING"
done
# 5. Dependency integrity
npm ci --dry-run 2>&1 | tail -5 # Node lockfile in sync?
pip check # Python broken requirements
go mod verify # Go module checksums
# 7. External connectivity
psql "$DATABASE_URL" -c '\conninfo' 2>&1 | head -1
redis-cli -u "$REDIS_URL" ping 2>/dev/null
curl -s -o /dev/null -w 'http=%{http_code} t=%{time_total}s\n' "$API_BASE/health"
# 9. Resource limits
df -h . ; ulimit -n ; (free -m 2>/dev/null || vm_stat | head -5)
# Decode the exit signal of a process that died immediately
"$@"; echo "exit=$?" # 137=OOM/SIGKILL, 139=SIGSEGV, 143=SIGTERM, 130=Ctrl-C
dmesg 2>/dev/null | rg -i "killed process|out of memory" | tail -5 # Linux OOM-killer evidence
# Attach to a crashing Node process to see the real stack
node --stack-trace-limit=50 --unhandled-rejections=strict dist/server.js 2>&1 | head -40
# Confirm which config file the app actually loaded (wrong-CWD trap)
node -e 'console.log(process.cwd())' # where it thinks it is
rg -n "dotenv|load_dotenv|godotenv" src/ | head # how/where env is loaded
# Container parity: rebuild native modules for the runtime that will actually run them
npm rebuild bcrypt sharp 2>&1 | tail -5
# Watch a backgrounded service settle (replaces a blind sleep)
until curl -fsS http://localhost:3000/health >/dev/null 2>&1; do sleep 0.5; done; echo "ready"
# Trace a "cannot find module" / version-mismatch to the exact package
npm ls <pkg> 2>&1 | rg "<pkg>|deduped|invalid" # resolved version + conflicts
node -e 'console.log(require.resolve("<pkg>"))' # which copy is actually loaded
pip show <pkg> | rg "Version|Location" # Python: installed version + path
# File-descriptor leak: count open FDs for the process over time
PID=$(lsof -ti :3000); ls /proc/$PID/fd 2>/dev/null | wc -l # Linux
lsof -p "$PID" | wc -l # macOS
# Verify the runtime inside a container matches the host expectation
docker run --rm -v "$PWD":/app -w /app node:20 node --version
docker run --rm -v "$PWD":/app -w /app node:20 npm ci && echo "installs clean in target image"
| Symptom | Likely cause | First command |
|---|---|---|
EADDRINUSE | stale dev server on the port | lsof -i :PORT |
| exits with code 137 | OOM kill | dmesg | rg -i 'out of memory' |
| exits with code 139 | native module segfault | npm rebuild <native-pkg> |
| "cannot find module X" | install out of sync with lockfile | npm ci |
| connects nowhere, no error | wrong working directory / .env not loaded | node -e 'console.log(process.cwd())' |
ECONNREFUSED to DB | DB down or wrong DATABASE_URL | psql "$DATABASE_URL" -c '\conninfo' |
| routes 500 silently | unhandled async rejection | run with --unhandled-rejections=strict |
| works once then hangs | file-descriptor exhaustion | ulimit -n then raise it |
__dirname / os.getcwd(); launching from the wrong directory silently loads empty or wrong config. Confirm the launch directory..env not loaded. dotenv reads from the current directory but the .env sits in a parent, or dotenv.config() runs after the code that reads process.env. Load config before first use.package.json changed but install did not re-run, so node_modules holds the wrong version. Re-run npm ci.bcrypt/sharp/canvas compiled on macOS fail inside a Linux container. Rebuild in the target environment with npm rebuild.unhandledRejection handler and inspect logs.kill -9 a process you have not positively tied to this project — you may take down something unrelated.head -1 and missing the real cause three lines down. Capture the full stderr, then read it.ulimit -n when the real bug is a connection leak that never closes sockets — the limit just delays the crash.rm -rf node_modules as a reflex. Sometimes right, but it hides the actual mismatch and wastes minutes; check npm ci --dry-run first to see what is really out of sync.lsof.For each diagnostic step report: the command run and its exact output (secrets redacted), the finding (e.g. "port 3000 held by PID 8421 — stale nodemon from a prior session"), the action taken (kill 8421), and the verification (app now responds on localhost:3000). End with a one-sentence root-cause summary.
npm install / pip install with elevated privileges or outside the project's virtual environment.Done means the startup failure is traced to a named root cause with command-level evidence, the resolving action is applied and verified (the app starts or the dependency responds), and any remaining unresolved factor is flagged with the next safe step — all without exposing secrets or killing unidentified processes.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub fluxonlab/skillry --plugin skillry-runtime-and-local-app