Files
claude-engineering-plugin/plugins/compound-engineering/skills/ce-polish-beta/scripts/read-launch-json.sh
2026-04-16 17:55:10 -05:00

88 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# read-launch-json.sh — read .claude/launch.json from the repo root and emit
# the selected configuration as JSON on stdout, or a sentinel on failure.
#
# Usage:
# read-launch-json.sh [config-name]
#
# Arguments:
# config-name (optional) — if multiple configurations exist and this arg
# matches a configuration's `name`, emit that one.
# If omitted and there are multiple configurations,
# emit a __MULTIPLE_CONFIGS__ sentinel followed by a
# JSON array of configuration names on the next line.
#
# Output contract:
# Success: single-line JSON object on stdout representing the chosen
# configuration. Shape mirrors VS Code's launch.json entry:
# {name, runtimeExecutable, runtimeArgs, port, cwd, env}.
# Sentinels (printed to stdout, one per line):
# __NO_LAUNCH_JSON__ - file not found
# __INVALID_LAUNCH_JSON__ - file exists but fails JSON parsing
# __MISSING_CONFIGURATIONS__ - valid JSON but no `configurations` array
# __MULTIPLE_CONFIGS__ - ambiguity, needs caller disambiguation.
# Followed by a JSON array of names on line 2.
# __CONFIG_NOT_FOUND__ - caller-provided name doesn't match any entry
#
# The script never exits non-zero for a missing or malformed file -- callers
# parse the sentinel and decide how to proceed. Exit code 1 is reserved for
# genuine operational failures (missing `jq`, git root not found).
set -u
REQUESTED_NAME="${1:-}"
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
if [ -z "$REPO_ROOT" ]; then
echo "ERROR: not in a git repository" >&2
exit 1
fi
if ! command -v jq >/dev/null 2>&1; then
echo "ERROR: jq is required but not installed" >&2
exit 1
fi
LAUNCH_PATH="$REPO_ROOT/.claude/launch.json"
if [ ! -f "$LAUNCH_PATH" ]; then
echo "__NO_LAUNCH_JSON__"
exit 0
fi
# Validate JSON. We parse with `jq empty` so malformed JSON is caught
# before any downstream query runs.
if ! jq empty "$LAUNCH_PATH" >/dev/null 2>&1; then
echo "__INVALID_LAUNCH_JSON__"
exit 0
fi
CONFIG_COUNT=$(jq '(.configurations // []) | length' "$LAUNCH_PATH")
if [ "$CONFIG_COUNT" = "0" ]; then
echo "__MISSING_CONFIGURATIONS__"
exit 0
fi
if [ "$CONFIG_COUNT" = "1" ]; then
jq -c '.configurations[0]' "$LAUNCH_PATH"
exit 0
fi
# Multiple configurations. If the caller named one, emit it. Otherwise, emit
# the sentinel + name list so the caller can prompt the user.
if [ -n "$REQUESTED_NAME" ]; then
MATCH=$(jq -c --arg name "$REQUESTED_NAME" '.configurations[] | select(.name == $name)' "$LAUNCH_PATH")
if [ -z "$MATCH" ]; then
echo "__CONFIG_NOT_FOUND__"
exit 0
fi
echo "$MATCH"
exit 0
fi
echo "__MULTIPLE_CONFIGS__"
jq -c '[.configurations[].name]' "$LAUNCH_PATH"
exit 0