@@ -71,14 +71,46 @@ PR_DESCRIPTION=$(jq -r '.body // "No description provided."' /tmp/pr_meta.json)
7171PR_DIFF=$( cat /tmp/pr_diff.txt)
7272FILE_LIST=$( jq -r ' .files[].path' /tmp/pr_meta.json)
7373
74- # Read the prompt template and substitute placeholders
75- PROMPT=$( cat " /skills/$SKILL_NAME /prompt.md" )
76- PROMPT=" ${PROMPT// \{\{ PR_NUMBER\}\} / $PR_NUMBER } "
77- PROMPT=" ${PROMPT// \{\{ PR_TITLE\}\} / $PR_TITLE } "
78- PROMPT=" ${PROMPT// \{\{ PR_AUTHOR\}\} / $PR_AUTHOR } "
79- PROMPT=" ${PROMPT// \{\{ PR_DESCRIPTION\}\} / $PR_DESCRIPTION } "
80- PROMPT=" ${PROMPT// \{\{ FILE_LIST\}\} / $FILE_LIST } "
81- PROMPT=" ${PROMPT// \{\{ PR_DIFF\}\} / $PR_DIFF } "
74+ # Build the prompt file from template + PR context.
75+ # Write to a file instead of holding in a shell variable to avoid
76+ # "Argument list too long" on large PRs (ARG_MAX ~2MB).
77+ PROMPT_FILE=/tmp/prompt.md
78+ {
79+ cat " /skills/$SKILL_NAME /prompt.md"
80+ } > " $PROMPT_FILE "
81+
82+ # Substitute placeholders using sed (handles large diffs without hitting ARG_MAX).
83+ # Small fields first (safe as shell vars), then large fields via temp files.
84+ sed -i " s|{{PR_NUMBER}}|$PR_NUMBER |g" " $PROMPT_FILE "
85+ sed -i " s|{{PR_TITLE}}|$PR_TITLE |g" " $PROMPT_FILE "
86+ sed -i " s|{{PR_AUTHOR}}|$PR_AUTHOR |g" " $PROMPT_FILE "
87+
88+ # Large fields: use sed with file-read to avoid shell expansion limits.
89+ # PR_DESCRIPTION, FILE_LIST, and PR_DIFF are written to temp files
90+ # and inserted via sed's r command with a marker-delete approach.
91+ echo " $PR_DESCRIPTION " > /tmp/pr_description.txt
92+ echo " $FILE_LIST " > /tmp/pr_filelist.txt
93+
94+ # For each large placeholder: replace the line containing it with the file contents.
95+ # Using awk because sed r-command can't replace inline — it only appends.
96+ for placeholder_pair in \
97+ " {{PR_DESCRIPTION}}:/tmp/pr_description.txt" \
98+ " {{FILE_LIST}}:/tmp/pr_filelist.txt" \
99+ " {{PR_DIFF}}:/tmp/pr_diff.txt" ; do
100+ marker=" ${placeholder_pair%%:* } "
101+ file=" ${placeholder_pair##*: } "
102+ if grep -qF " $marker " " $PROMPT_FILE " && [ -f " $file " ]; then
103+ awk -v marker=" $marker " -v file=" $file " '
104+ index($0, marker) {
105+ while ((getline line < file) > 0) print line
106+ close(file)
107+ next
108+ }
109+ { print }
110+ ' " $PROMPT_FILE " > /tmp/prompt_tmp.md
111+ mv /tmp/prompt_tmp.md " $PROMPT_FILE "
112+ fi
113+ done
82114
83115# ---------------------------------------------------------------------------
84116# Multi-turn conversation via per-turn invocations
@@ -102,7 +134,9 @@ mkfifo "$FIFO"
102134exec 3<> " $FIFO "
103135
104136# First turn: initial skill prompt (one-shot, creates the conversation)
105- claude -p " $PROMPT " \
137+ # The full prompt is written to a file to avoid ARG_MAX on large PRs.
138+ # We pass a short bootstrap prompt that tells Claude to read the file.
139+ claude -p " Read the file /tmp/prompt.md and follow its instructions exactly. It contains a skill prompt with PR context. Start immediately." \
106140 --output-format stream-json \
107141 --verbose \
108142 --dangerously-skip-permissions \
0 commit comments