Skip to content

How Do You Set Up an Automation Loop for AI Coding Workflows with Codex CLI?

Terminal automation workflow

I spent way too much time copying and pasting between ChatGPT and my code editor. Write some code, paste it to ChatGPT for review, get feedback, paste back to editor, repeat. For a small feature, this is fine. For a large project spanning multiple files? It becomes exhausting.

Then I stumbled across a Reddit thread where someone described their automation setup: ChatGPT for planning, Codex CLI for implementation, all running on a 2-minute loop with zero manual intervention. That sounded like magic. I had to try it.

The Problem: Manual Context Switching Kills Productivity

Large coding projects require constant back-and-forth:

  1. Planning - “What code should I write?”
  2. Implementing - Writing the actual code
  3. Reviewing - Checking if the code is good
  4. Fixing - Addressing bugs and issues
  5. Iterating - Improving the implementation

Each step requires explaining context to a different AI tool. Copy code, paste to ChatGPT, describe what you want, copy response, paste to editor. Do this 50 times and you’ll want to scream.

My First Attempt: A Simple Loop Script

I started with a basic shell script that would run Codex CLI every 2 minutes:

first-attempt.sh
#!/bin/bash
while true; do
codex "implement the feature from TODO.md"
sleep 120
done

This ran but it was useless. Codex had no memory of what it did before. Each iteration started fresh. I was automating a broken process.

The Breakthrough: State Persistence

The Reddit post mentioned shared markdown files for passing context between AI tools. That was the missing piece.

I created a state machine approach:

ai-automation-loop.sh
#!/bin/bash
# AI automation loop with state persistence
PROJECT_DIR="${1:-$(pwd)}"
LOG_FILE="$PROJECT_DIR/.ai-loop.log"
STATE_FILE="$PROJECT_DIR/.ai-state.json"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
run_iteration() {
local state=$(cat "$STATE_FILE" 2>/dev/null || echo '{"status": "planning"}')
case $(echo "$state" | jq -r '.status') in
"planning")
log "Running planning phase..."
claude "$(cat $PROJECT_DIR/.task-description.md)" > "$PROJECT_DIR/.plan.md"
echo '{"status": "implementing"}' > "$STATE_FILE"
;;
"implementing")
log "Running implementation phase..."
codex "$(cat $PROJECT_DIR/.plan.md)" >> "$PROJECT_DIR/.implementation.log"
echo '{"status": "reviewing"}' > "$STATE_FILE"
;;
"reviewing")
log "Running review phase..."
claude "Review this implementation: $(cat $PROJECT_DIR/.implementation.log)" > "$PROJECT_DIR/.review.md"
echo '{"status": "planning"}' > "$STATE_FILE"
;;
esac
}
main() {
log "Starting AI automation loop..."
while true; do
run_iteration
sleep 120
done
}
main "$@"

This script cycles through three phases: planning, implementing, and reviewing. Each phase outputs to a file that the next phase reads. The state is tracked in a JSON file.

But I hit another problem: what if one phase fails?

Adding Error Handling

I added proper error handling and prerequisites checking:

robust-ai-loop.sh
#!/bin/bash
set -e
PROJECT_DIR="${1:-$(pwd)}"
LOG_FILE="$PROJECT_DIR/.ai-loop.log"
STATE_FILE="$PROJECT_DIR/.ai-state.json"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
check_prerequisites() {
command -v codex >/dev/null 2>&1 || { log "ERROR: codex CLI not found"; exit 1; }
command -v claude >/dev/null 2>&1 || { log "WARNING: claude CLI not found, using fallback"; }
}
run_iteration() {
local state=$(cat "$STATE_FILE" 2>/dev/null || echo '{"status": "planning"}')
case $(echo "$state" | jq -r '.status') in
"planning")
log "Running planning phase..."
claude "$(cat $PROJECT_DIR/.task-description.md)" > "$PROJECT_DIR/.plan.md"
echo '{"status": "implementing"}' > "$STATE_FILE"
;;
"implementing")
log "Running implementation phase..."
codex "$(cat $PROJECT_DIR/.plan.md)" >> "$PROJECT_DIR/.implementation.log"
echo '{"status": "reviewing"}' > "$STATE_FILE"
;;
"reviewing")
log "Running review phase..."
claude "Review this implementation: $(cat $PROJECT_DIR/.implementation.log)" > "$PROJECT_DIR/.review.md"
echo '{"status": "planning"}' > "$STATE_FILE"
;;
esac
}
main() {
check_prerequisites
log "Starting AI automation loop..."
while true; do
run_iteration
sleep 120
done
}
main "$@"

Now the script would fail gracefully if tools were missing.

Using tmux for Parallel Processing

One insight from the Reddit thread: use multiple terminal tabs with different models. I set up tmux with three panes:

tmux setup commands
# Create new tmux session
tmux new-session -d -s ai-loop
# Split into three panes
tmux split-window -h -t ai-loop
tmux split-window -v -t ai-loop:0.1
# Pane 0: Planning with Claude
tmux send-keys -t ai-loop:0.0 'claude "Review code and suggest improvements"' Enter
# Pane 1: Implementation with Codex
tmux send-keys -t ai-loop:0.1 'codex "Implement the suggested changes"' Enter
# Pane 2: Testing
tmux send-keys -t ai-loop:0.2 'gemini-cli "Generate tests for implemented code"' Enter

This creates a parallel workflow where each AI tool handles a specialized task.

The Architecture

The final architecture looks like this:

[ChatGPT/Claude] --plan--> [Codex CLI] --implement--> [Output]
^ |
|_______________review feedback________________|

Each tool reads from and writes to shared files. The loop runs continuously on a timer.

What Actually Works

After running this for a week, here’s what I learned:

  1. 2 minutes is the minimum interval - Faster than that and tools don’t finish their tasks. I settled on 3 minutes.

  2. Context files are critical - Without .plan.md and .review.md, the tools have no memory. Each iteration is like talking to a fresh AI with no context.

  3. Multiple models > single model - Claude for planning (better reasoning), Codex for implementation (faster), different model for testing (fresh perspective).

  4. Monitor the log file - I check .ai-loop.log every few hours to make sure the loop is still running and not stuck.

  5. Start small - Test with a single feature before scaling to larger projects.

Common Mistakes I Made

No context persistence - My first attempt used no files. Each loop started fresh. Use files.

Too fast loop interval - I tried 30 seconds. The tools couldn’t keep up. Use at least 2 minutes.

Single AI tool - I initially used only Codex. Adding Claude for planning and a separate model for testing improved quality significantly.

No error handling - The script would crash silently. Adding set -e and logging made debugging possible.

Ignoring output - I set it and forgot it. The automation ran for hours without me checking. Now I review the output every few hours.

Advanced: Using agentify-sh for Direct Integration

For a more polished approach, I tried the agentify-sh/desktop project:

clone and run agentify-sh
# Clone the reference project
git clone https://github.com/agentify-sh/desktop.git
cd desktop
# Configure ChatGPT Pro integration
export OPENAI_API_KEY="your-key"
export CODEX_PROJECT_DIR="/path/to/project"
# Run the integrated loop
./start-loop.sh --interval 180 --models gpt-4,codex

This handles API calls directly instead of relying on CLI tools. It’s more reliable but requires API keys.

When This Actually Helps

This automation loop shines for:

  • Large refactoring projects - Multiple files, many changes, clear patterns
  • Repetitive tasks - Same type of change across many files
  • Documentation updates - Updating docs across a large codebase

It does not help for:

  • Creative features - Novel code requires more human oversight
  • Bug hunting - Bugs need careful investigation, not automation
  • Quick fixes - Setting up the loop takes longer than just fixing the bug

The Bottom Line

An AI coding automation loop reduces manual copy-paste cycles between tools. Start with a simple 2-minute loop using shared files for context. Add more tools as needed. Monitor the output regularly.

The setup takes 30 minutes. The time savings compound over the life of a project.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!


References:

Comments