11name : " Claude Code Action"
2- description : " Custom Claude Code runner for PraisonAI "
2+ description : " Run Claude Code in GitHub Actions workflows "
33
44inputs :
5- anthropic_api_key :
5+ github_token :
6+ description : " GitHub token with repo and issues permissions"
67 required : true
8+ anthropic_api_key :
79 description : " Anthropic API key"
8- github_token :
910 required : true
10- description : " GitHub token for repo access"
11+ prompt :
12+ description : " The prompt to send to Claude Code"
13+ required : false
14+ default : " "
15+ prompt_file :
16+ description : " Path to a file containing the prompt to send to Claude Code"
17+ required : false
18+ default : " "
19+ allowed_tools :
20+ description : " Comma-separated list of allowed tools for Claude Code to use"
21+ required : false
22+ default : " "
23+ output_file :
24+ description : " File to save Claude Code output to (optional)"
25+ required : false
26+ default : " "
27+ timeout_minutes :
28+ description : " Timeout in minutes for Claude Code execution"
29+ required : false
30+ default : " 10"
31+ install_github_mcp :
32+ description : " Whether to install the GitHub MCP server"
33+ required : false
34+ default : " false"
1135
1236runs :
13- using : " docker"
14- image : " docker://ghcr.io/mervinpraison/praisonai-claudecode:latest"
15- env :
16- ANTHROPIC_API_KEY : ${{ inputs.anthropic_api_key }}
17- GITHUB_TOKEN : ${{ inputs.github_token }}
18- args :
19- - " --anthropic-api-key=${{ inputs.anthropic_api_key }}"
20- - " --github-token=${{ inputs.github_token }}"
37+ using : " composite"
38+ steps :
39+ - name : Install Claude Code
40+ shell : bash
41+ run : npm install -g @anthropic-ai/claude-code
42+
43+ - name : Install GitHub MCP Server
44+ if : inputs.install_github_mcp == 'true'
45+ shell : bash
46+ run : |
47+ claude mcp add-json github '{
48+ "command": "docker",
49+ "args": [
50+ "run",
51+ "-i",
52+ "--rm",
53+ "-e",
54+ "GITHUB_PERSONAL_ACCESS_TOKEN",
55+ "ghcr.io/github/github-mcp-server:sha-ff3036d"
56+ ],
57+ "env": {
58+ "GITHUB_PERSONAL_ACCESS_TOKEN": "${{ inputs.GITHUB_TOKEN }}"
59+ }
60+ }'
61+
62+ - name : Prepare Prompt File
63+ shell : bash
64+ id : prepare_prompt
65+ run : |
66+ # Check if either prompt or prompt_file is provided
67+ if [ -z "${{ inputs.prompt }}" ] && [ -z "${{ inputs.prompt_file }}" ]; then
68+ echo "::error::Neither 'prompt' nor 'prompt_file' was provided. At least one is required."
69+ exit 1
70+ fi
71+
72+ # Determine which prompt source to use
73+ if [ ! -z "${{ inputs.prompt_file }}" ]; then
74+ # Check if the prompt file exists
75+ if [ ! -f "${{ inputs.prompt_file }}" ]; then
76+ echo "::error::Prompt file '${{ inputs.prompt_file }}' does not exist."
77+ exit 1
78+ fi
79+
80+ # Use the provided prompt file
81+ PROMPT_PATH="${{ inputs.prompt_file }}"
82+ else
83+ mkdir -p /tmp/claude-action
84+ PROMPT_PATH="/tmp/claude-action/prompt.txt"
85+ echo "${{ inputs.prompt }}" > "$PROMPT_PATH"
86+ fi
87+
88+ # Verify the prompt file is not empty
89+ if [ ! -s "$PROMPT_PATH" ]; then
90+ echo "::error::Prompt is empty. Please provide a non-empty prompt."
91+ exit 1
92+ fi
93+
94+ # Save the prompt path for the next step
95+ echo "PROMPT_PATH=$PROMPT_PATH" >> $GITHUB_ENV
96+
97+ - name : Run Claude Code
98+ shell : bash
99+ id : run_claude
100+ run : |
101+ ALLOWED_TOOLS_ARG=""
102+ if [ ! -z "${{ inputs.allowed_tools }}" ]; then
103+ ALLOWED_TOOLS_ARG="--allowedTools ${{ inputs.allowed_tools }}"
104+ fi
105+
106+ # Set a timeout to ensure the command doesn't run indefinitely
107+ timeout_seconds=$((${{ inputs.timeout_minutes }} * 60))
108+
109+ if [ -z "${{ inputs.output_file }}" ]; then
110+ # Run Claude Code and output to console
111+ timeout $timeout_seconds claude \
112+ -p \
113+ --verbose \
114+ --output-format stream-json \
115+ "$(cat ${{ env.PROMPT_PATH }})" \
116+ ${{ inputs.allowed_tools != '' && format('--allowedTools "{0}"', inputs.allowed_tools) || '' }}
117+ else
118+ # Run Claude Code and tee output to console and file
119+ timeout $timeout_seconds claude \
120+ -p \
121+ --verbose \
122+ --output-format stream-json \
123+ "$(cat ${{ env.PROMPT_PATH }})" \
124+ ${{ inputs.allowed_tools != '' && format('--allowedTools "{0}"', inputs.allowed_tools) || '' }} | tee output.txt
125+
126+ # Process output.txt into JSON in a separate step
127+ jq -s '.' output.txt > output.json
128+
129+ # Extract the result from the last item in the array (system message)
130+ jq -r '.[-1].result' output.json > "${{ inputs.output_file }}"
131+
132+ echo "Complete output saved to output.json, final response saved to ${{ inputs.output_file }}"
133+ fi
134+ env :
135+ ANTHROPIC_API_KEY : ${{ inputs.anthropic_api_key }}
136+ GITHUB_TOKEN : ${{ inputs.github_token }}
0 commit comments