spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / .github / actions / claude-code-action / action.yml
136 lines · 4.4 KBRaw
1name: "Claude Code Action"
2description: "Run Claude Code in GitHub Actions workflows"
3
4inputs:
5 github_token:
6 description: "GitHub token with repo and issues permissions"
7 required: true
8 anthropic_api_key:
9 description: "Anthropic API key"
10 required: true
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"
35
36runs:
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 }}