Skip to content

Commit 6945abc

Browse files
2 parents 00e76c8 + bd0c5a6 commit 6945abc

File tree

5 files changed

+105
-19
lines changed

5 files changed

+105
-19
lines changed

Dockerfile.claude-automation

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ RUN apk add --no-cache \
1212
# Install Claude Code globally
1313
RUN npm install -g @anthropic-ai/claude-code
1414

15+
# Install Codex CLI globally
16+
# Based on the GitHub repo, Codex is available as a npm package
17+
RUN npm install -g codex
18+
1519
# Create workspace directory
1620
WORKDIR /workspace
1721

README.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
# Claude Code Automation MVP
22

3-
An MVP application that automates coding tasks using Claude Code in sandboxed environments. Users can submit text prompts describing what they want to develop for a configured GitHub repository, and Claude Code will analyze the codebase, make the necessary changes, and create commits that can be turned into pull requests.
3+
An MVP application that automates coding tasks using Claude Code or Codex CLI in sandboxed environments. Users can submit text prompts describing what they want to develop for a configured GitHub repository, and the selected AI model will analyze the codebase, make the necessary changes, and create commits that can be turned into pull requests.
44

55
## Features
66

7-
- 🤖 **Claude Code Integration**: Leverages Claude Code for intelligent code generation and modification
8-
- 🐳 **Sandboxed Execution**: Runs Claude Code in isolated Docker containers for security
7+
- 🤖 **Multiple AI Models**: Choose between Claude Code and Codex CLI for code generation
8+
- 🐳 **Sandboxed Execution**: Runs AI models in isolated Docker containers for security
99
- 🔄 **Git Integration**: Automatically clones repositories, makes commits, and creates pull requests
1010
- 🌐 **Web Interface**: Clean, modern UI for submitting prompts and reviewing changes
1111
- 📊 **Real-time Status**: Live updates on task progress and completion
1212
- 🔍 **Git Diff Viewer**: Review all changes before creating pull requests
13+
- 🎯 **Model Comparison**: Easily compare outputs from different AI models
1314

1415
## Architecture
1516

1617
- **Frontend**: Next.js with TypeScript and TailwindCSS
1718
- **Backend**: Python Flask API with Docker orchestration
18-
- **Automation**: Claude Code running in isolated Alpine Linux containers
19+
- **AI Models**:
20+
- Claude Code (Anthropic) - Advanced coding model
21+
- Codex CLI (OpenAI) - Lightweight coding agent
1922
- **Git Operations**: GitHub API integration for repository management
2023

2124
## Prerequisites
@@ -50,10 +53,11 @@ An MVP application that automates coding tasks using Claude Code in sandboxed en
5053

5154
1. **Setup GitHub Token**: Click "Setup GitHub Token" in the frontend and enter your token
5255
2. **Configure Repository**: Enter the GitHub repository URL and branch
53-
3. **Enter Prompt**: Describe what you want Claude Code to develop
54-
4. **Start Task**: Click "Code" to begin the automation process
55-
5. **Review Changes**: View the git diff when the task completes
56-
6. **Create PR**: If satisfied with changes, click "Create PR"
56+
3. **Select AI Model**: Choose between Claude Code or Codex CLI
57+
4. **Enter Prompt**: Describe what you want the AI to develop
58+
5. **Start Task**: Click "Code" to begin the automation process
59+
6. **Review Changes**: View the git diff when the task completes
60+
7. **Create PR**: If satisfied with changes, click "Create PR"
5761

5862
## Example Prompts
5963

@@ -74,8 +78,8 @@ FLASK_DEBUG=True
7478

7579
## API Endpoints
7680

77-
- `POST /start-task` - Start a new Claude Code automation task
78-
- `GET /task-status/<task_id>` - Get task status and progress
81+
- `POST /start-task` - Start a new automation task (supports `model` parameter: "claude" or "codex")
82+
- `GET /task-status/<task_id>` - Get task status and progress (includes model used)
7983
- `GET /git-diff/<task_id>` - Retrieve git diff for completed tasks
8084
- `POST /create-pr/<task_id>` - Create a pull request from completed task
8185

async-code-web/app/page.tsx

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com
99
import { Badge } from "@/components/ui/badge";
1010
import { Label } from "@/components/ui/label";
1111
import { Separator } from "@/components/ui/separator";
12+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
1213

1314

1415
interface Task {
@@ -17,6 +18,7 @@ interface Task {
1718
prompt: string;
1819
repo_url: string;
1920
branch: string;
21+
model?: string;
2022
commit_hash?: string;
2123
error?: string;
2224
created_at: number;
@@ -70,6 +72,7 @@ export default function Home() {
7072
const [repoUrl, setRepoUrl] = useState("https://github.com/ObservedObserver/streamlit-react");
7173
const [branch, setBranch] = useState("main");
7274
const [githubToken, setGithubToken] = useState("");
75+
const [model, setModel] = useState("claude");
7376
const [currentTask, setCurrentTask] = useState<Task | null>(null);
7477
const [gitDiff, setGitDiff] = useState("");
7578
const [isLoading, setIsLoading] = useState(false);
@@ -150,7 +153,8 @@ export default function Home() {
150153
prompt: prompt.trim(),
151154
repo_url: repoUrl,
152155
branch: branch,
153-
github_token: githubToken
156+
github_token: githubToken,
157+
model: model
154158
})
155159
});
156160

@@ -163,6 +167,7 @@ export default function Home() {
163167
prompt: prompt.trim(),
164168
repo_url: repoUrl,
165169
branch: branch,
170+
model: model,
166171
created_at: Date.now()
167172
});
168173
setGitDiff("");
@@ -229,14 +234,15 @@ export default function Home() {
229234
if (!currentTask || currentTask.status !== "completed") return;
230235

231236
try {
237+
const modelName = currentTask.model === 'codex' ? 'Codex' : 'Claude Code';
232238
const response = await fetch(`${API_BASE}/create-pr/${currentTask.id}`, {
233239
method: 'POST',
234240
headers: {
235241
'Content-Type': 'application/json',
236242
},
237243
body: JSON.stringify({
238-
title: `Claude Code: ${currentTask.prompt.substring(0, 50)}...`,
239-
body: `Automated changes generated by Claude Code.\n\nPrompt: ${currentTask.prompt}`
244+
title: `${modelName}: ${currentTask.prompt.substring(0, 50)}...`,
245+
body: `Automated changes generated by ${modelName}.\n\nPrompt: ${currentTask.prompt}`
240246
})
241247
});
242248

@@ -300,8 +306,8 @@ export default function Home() {
300306
<Code2 className="w-4 h-4 text-white" />
301307
</div>
302308
<div>
303-
<h1 className="text-xl font-semibold text-slate-900">Claude Code</h1>
304-
<p className="text-sm text-slate-500">AI-Powered Code Automation</p>
309+
<h1 className="text-xl font-semibold text-slate-900">AI Code Automation</h1>
310+
<p className="text-sm text-slate-500">Claude Code & Codex CLI Integration</p>
305311
</div>
306312
</div>
307313
<Button
@@ -324,7 +330,7 @@ export default function Home() {
324330
What are we coding next?
325331
</h2>
326332
<p className="text-slate-600">
327-
Describe what you want to build and Claude will analyze your repository and make the necessary changes
333+
Describe what you want to build and your selected AI model will analyze your repository and make the necessary changes
328334
</p>
329335
</div>
330336

@@ -433,6 +439,30 @@ export default function Home() {
433439
/>
434440
</div>
435441
</div>
442+
443+
{/* Model Selection */}
444+
<div className="space-y-2">
445+
<Label htmlFor="model" className="flex items-center gap-2">
446+
<Code2 className="w-3 h-3" />
447+
AI Model
448+
</Label>
449+
<Select value={model} onValueChange={setModel}>
450+
<SelectTrigger id="model">
451+
<SelectValue placeholder="Select an AI model" />
452+
</SelectTrigger>
453+
<SelectContent>
454+
<SelectItem value="claude">
455+
Claude Code - Anthropic's advanced coding model
456+
</SelectItem>
457+
<SelectItem value="codex">
458+
Codex CLI - OpenAI's lightweight coding agent
459+
</SelectItem>
460+
</SelectContent>
461+
</Select>
462+
<p className="text-sm text-slate-600">
463+
Choose between Claude Code or Codex CLI for your automation needs
464+
</p>
465+
</div>
436466
</div>
437467

438468
<div className="flex justify-end">
@@ -461,7 +491,7 @@ export default function Home() {
461491
{getStatusIcon(currentTask.status)}
462492
{currentTask.status}
463493
</Badge>
464-
Task Status
494+
Task Status {currentTask.model && `(${currentTask.model.toUpperCase()})`}
465495
</CardTitle>
466496
<CardDescription>
467497
{new Date(currentTask.created_at).toLocaleString()}{currentTask.repo_url}
@@ -618,7 +648,7 @@ export default function Home() {
618648
Ready to Start Coding
619649
</h3>
620650
<p className="text-slate-600 max-w-md mx-auto">
621-
Enter a detailed prompt describing what you want to build. Claude will analyze your repository
651+
Enter a detailed prompt describing what you want to build. Your selected AI model will analyze your repository
622652
and implement the necessary changes automatically.
623653
</p>
624654
</CardContent>

server/main.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,15 @@ def start_task():
9494
repo_url = data.get('repo_url')
9595
branch = data.get('branch', 'main')
9696
github_token = data.get('github_token')
97+
model = data.get('model', 'claude') # Default to claude for backward compatibility
9798

9899
if not all([prompt, repo_url, github_token]):
99100
return jsonify({'error': 'prompt, repo_url, and github_token are required'}), 400
100101

102+
# Validate model selection
103+
if model not in ['claude', 'codex']:
104+
return jsonify({'error': 'model must be either "claude" or "codex"'}), 400
105+
101106
# Generate unique task ID
102107
task_id = str(uuid.uuid4())
103108

@@ -109,6 +114,7 @@ def start_task():
109114
'repo_url': repo_url,
110115
'branch': branch,
111116
'github_token': github_token,
117+
'model': model,
112118
'container_id': None,
113119
'commit_hash': None,
114120
'git_diff': None,
@@ -152,6 +158,7 @@ def get_task_status(task_id):
152158
'prompt': task['prompt'],
153159
'repo_url': task['repo_url'],
154160
'branch': task['branch'],
161+
'model': task.get('model', 'claude'), # Include model in response
155162
'commit_hash': task.get('commit_hash'),
156163
'changed_files': task.get('changed_files', []),
157164
'error': task.get('error'),
@@ -550,6 +557,7 @@ def run_claude_code_task(task_id):
550557

551558
logger.info(f"🚀 Starting Claude Code task {task_id}")
552559
logger.info(f"📋 Task details: prompt='{task['prompt'][:50]}...', repo={task['repo_url']}, branch={task['branch']}")
560+
logger.info(f"Starting {task.get('model', 'claude').upper()} task {task_id}")
553561

554562
# Escape special characters in prompt for shell safety
555563
escaped_prompt = task['prompt'].replace('"', '\\"').replace('$', '\\$').replace('`', '\\`')
@@ -566,6 +574,9 @@ def run_claude_code_task(task_id):
566574
'ANTHROPIC_NONINTERACTIVE': '1' # Custom flag for Anthropic tools
567575
}
568576

577+
# Determine which CLI to use
578+
model_cli = task.get('model', 'claude')
579+
569580
# Create the command to run in container
570581
container_command = f'''
571582
set -e
@@ -701,7 +712,7 @@ def run_claude_code_task(task_id):
701712
702713
# Commit changes locally
703714
git add .
704-
git commit -m "Claude Code: {escaped_prompt[:100]}"
715+
git commit -m "{model_cli.capitalize()}: {escaped_prompt[:100]}"
705716
706717
# Get commit info
707718
COMMIT_HASH=$(git rev-parse HEAD)

test-model-selection.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/bash
2+
3+
echo "Testing Model Selection API..."
4+
5+
# Test Claude model
6+
echo "Testing Claude Code model..."
7+
curl -X POST http://localhost:5000/start-task \
8+
-H "Content-Type: application/json" \
9+
-d '{
10+
"prompt": "Add a test comment to README",
11+
"repo_url": "https://github.com/test/repo",
12+
"branch": "main",
13+
"github_token": "test_token",
14+
"model": "claude"
15+
}'
16+
17+
echo -e "\n\nTesting Codex CLI model..."
18+
curl -X POST http://localhost:5000/start-task \
19+
-H "Content-Type: application/json" \
20+
-d '{
21+
"prompt": "Add a test comment to README",
22+
"repo_url": "https://github.com/test/repo",
23+
"branch": "main",
24+
"github_token": "test_token",
25+
"model": "codex"
26+
}'
27+
28+
echo -e "\n\nTesting invalid model..."
29+
curl -X POST http://localhost:5000/start-task \
30+
-H "Content-Type: application/json" \
31+
-d '{
32+
"prompt": "Add a test comment to README",
33+
"repo_url": "https://github.com/test/repo",
34+
"branch": "main",
35+
"github_token": "test_token",
36+
"model": "invalid_model"
37+
}'

0 commit comments

Comments
 (0)