#!/usr/bin/env bash set -euo pipefail SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TEMPLATE="$SKILL_DIR/../assets/templates/instructions.md" usage() { cat < Scaffold an apm instructions file from the bundled template. Arguments: name Kebab-case stem. Becomes .instructions.md and, after install, the deployed rule's filename. root Existing path at or below the target package. The script walks up for the nearest apm.yml with a top-level type: field (instructions, skill, hybrid or prompts); an apm.yml without type: is a marketplace-only manifest and is skipped. Creates /.apm/instructions/.instructions.md Exit codes: 0 File created, or already existed (no-op) 1 Invalid arguments, missing root, no package found, or template not found USAGE } if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then usage exit 0 fi if [[ $# -lt 2 ]]; then echo "Error: name and root are required." >&2 echo "" >&2 usage >&2 exit 1 fi NAME="$1" ROOT="${2/#\~/$HOME}" if ! grep -qE '^[a-z0-9]+(-[a-z0-9]+)*$' <<< "$NAME"; then echo "Error: name must use lowercase letters, numbers, and hyphens only." >&2 echo " No leading, trailing, or consecutive hyphens." >&2 echo " Received: '$NAME'" >&2 exit 1 fi if [[ ! -f "$TEMPLATE" ]]; then echo "Error: template not found at '$TEMPLATE'." >&2 echo " Run this script from its original location inside the instructions-author skill." >&2 exit 1 fi if [[ ! -d "$ROOT" ]]; then echo "Error: root directory '$ROOT' does not exist." >&2 exit 1 fi ROOT="$(cd "$ROOT" && pwd)" # Same marker as agent-author's new-agent.sh: a top-level type: naming one of # the four package types, with matching quotes if quoted. is_apm_package_manifest() { local apm_yml="$1" line while IFS= read -r line || [[ -n "$line" ]]; do if [[ "$line" =~ ^type:[[:space:]]*(instructions|skill|hybrid|prompts)([[:space:]]|$) ]]; then return 0 fi if [[ "$line" =~ ^type:[[:space:]]*([\"\'])(instructions|skill|hybrid|prompts)([\"\'])([[:space:]]|$) ]] \ && [[ "${BASH_REMATCH[1]}" == "${BASH_REMATCH[3]}" ]]; then return 0 fi done < "$apm_yml" return 1 } PACKAGE_ROOT="" current="$ROOT" while true; do if [[ -f "$current/apm.yml" ]] && is_apm_package_manifest "$current/apm.yml"; then PACKAGE_ROOT="$current" break fi if [[ -e "$current/.git" ]]; then break fi parent="$(dirname "$current")" [[ "$parent" == "$current" ]] && break current="$parent" done if [[ -z "$PACKAGE_ROOT" ]]; then echo "Error: no apm package found at or above '$ROOT'." >&2 echo " Instructions only deploy from a package's .apm/instructions/. Run" >&2 echo " /apm-workflow configure (apm plugin init) there first, then retry." >&2 exit 1 fi DEST_DIR="$PACKAGE_ROOT/.apm/instructions" DEST="$DEST_DIR/$NAME.instructions.md" if [[ -f "$DEST" ]]; then echo "Skipping '$DEST' — already exists." >&2 exit 0 fi mkdir -p "$DEST_DIR" cp "$TEMPLATE" "$DEST" echo "Created: $DEST" >&2 echo "" >&2 echo "Next steps:" >&2 echo " 1. Fill in $DEST — replace every FILL IN: placeholder and delete the comments." >&2 echo " 2. Check '$NAME' does not collide with a hand-authored rule: install overwrites" >&2 echo " /rules/$NAME.* on most targets without warning." >&2 echo " 3. Verify with a real compile, not --validate: apm compile --dry-run --target " >&2