Turn a vague “do X in this repo” task into an iterative, GPT-reviewed Junie workflow with clear acceptance criteria.
This script:
- creates a fresh working directory and Git branch for your task,
- asks GPT to define concrete acceptance criteria,
- runs Junie against the repo,
- has GPT review the changes and decide if the task is done,
- and, if not, asks GPT to spell out the remaining steps for the next Junie run.
Given:
- a natural-language task description, and
- a Git repository URL,
the script will:
-
Create a task folder + branch
- Slugifies your task (e.g.
"Add login form"→add-login-form). - Creates a folder named after that slug inside a base directory.
- Clones the repo into that folder.
- Creates and checks out a new Git branch with the same slug.
- Slugifies your task (e.g.
-
Generate
confirmation.md(acceptance criteria)- Calls GPT with your task.
- GPT returns a Markdown checklist of specific, objectively verifiable goals.
- The checklist is written to
confirmation.mdin the repo.
-
Run an iterative Junie + GPT review loop
For up to
Niterations (default: 5):- Iteration 1: Junie is run with your original natural-language task.
- Later iterations: Junie is asked to
“Implement all remaining work described insteps_to_complete_the_task.mdso that all goals inconfirmation.mdare fully satisfied.”
Each iteration:
-
Runs Junie in the repo and saves a log:
junie_output_iter_<n>.txt
-
Captures the current Git diff:
git diffoutput as a big text blob.
-
Sends to GPT:
- the original task text,
- the current
confirmation.mdchecklist, - the latest Junie log,
- the current Git diff.
-
GPT replies (as JSON) with:
{ "done": true | false, "reason": "short explanation", "steps_md": "Markdown for steps_to_complete_the_task.md or empty if done" } -
The script either:
- Stops successfully if
done: true, or - Writes
steps_to_complete_the_task.mdusingsteps_mdand runs another iteration, or - Stops with a failure message if GPT says it’s not done but doesn’t provide steps.
- Stops successfully if
-
Stop conditions
The script exits when:
- GPT says the task is done ✅, or
- GPT says it’s not done but gives no steps (to avoid looping forever), or
- It hits the max iteration count, and tells you to inspect the repo and Markdown files.
Inside the task’s working directory:
-
confirmation.md
GPT-generated acceptance criteria checklist. -
steps_to_complete_the_task.md(optional, created after first “not done” review)
GPT-generated, concrete remaining work for Junie. -
junie_output_iter_<n>.txt
Combined log of Junie command, return code, stdout, and stderr for each iteration.
Plus the Git branch created specifically for this task.
By default, JunieOrchestrator operates in Strict Mode. This means it will strictly adhere to your task description and will NOT add unrequested requirements like:
- Unit tests
- CI/CD pipelines
- Documentation
- Refactoring
- Static analysis / Linting
If you simply ask for "a basic data class", you will get just the data class.
If you want a robust, production-ready implementation with all the bells and whistles, you must explicitly ask for them in your task description.
Example of a Strict/Simple Task:
"Create a simple Python data class for 'Fart' with fields for sound and smell." Result: A single file with the class. No tests, no extra fluff.
Example of a Complex Task:
"Create a production-ready Python data class for 'Fart'. Include input validation for smell intensity, comprehensive unit tests using pytest, Sphinx-style docstrings, and a GitHub Actions workflow to run the tests." Result: The class with validation, a test file, docstrings, and a
.github/workflows/test.ymlfile.
By default, JunieOrchestrator creates all task folders inside a dedicated junie-tasks/ directory in your current location. This keeps your workspace organized and makes it easy to ignore all orchestration work in git.
Benefits:
- All task folders are automatically ignored by git (via
.gitignore) - Your repository root stays clean
- Easy to manage multiple tasks
- No risk of accidentally committing task folders
Example structure:
your-project/
├── junie-tasks/ # Created automatically
│ ├── add-login-form/ # Task 1
│ ├── fix-bug-123/ # Task 2
│ └── refactor-api/ # Task 3
└── .gitignore # Ignores junie-tasks/
Custom location:
You can specify a different base directory with the --base-dir option:
junie-orchestrator "your task" --repo <url> --base-dir ./my-custom-folderBefore installing JunieOrchestrator, ensure you have:
- Python >= 3.7
- Git installed and on
$PATH - Junie CLI installed and on
$PATH - OpenAI API key (you'll need to set this as an environment variable)
-
Clone or navigate to the project directory:
cd /path/to/JunieOrchestrator -
Install in editable mode:
pip install -e .The
-eflag installs the package in "editable" mode, which means changes to the code are immediately reflected without reinstalling. This is perfect for development. -
Set your OpenAI API key:
export OPENAI_API_KEY="your-api-key-here"
Add this to your
~/.bashrc,~/.zshrc, or equivalent to make it permanent. -
Verify installation:
junieOrchestrator --help
You should see the help message with all available options.
Once installed, you can use the junieOrchestrator command from anywhere:
junieOrchestrator "Add unit tests for authentication" -r "https://github.com/user/repo.git"junieOrchestrator "Refactor database layer" \
-r "https://github.com/user/repo.git" \
-b "./my_tasks" \
-n 10 \
-m "gpt-4"task(optional, positional): Natural-language task description for Junie (not needed with--continue)-c, --continue [FOLDER_NAME]: Continue a previously interrupted job. If FOLDER_NAME is omitted, auto-detects from current directory or prompts for selection-r, --repo: Git repository URL (if omitted, you'll be prompted). Not needed with--continue-b, --base-dir: Base directory where the task folder will be created (default: current directory)-n, --max-iterations: Maximum number of Junie iterations before giving up (default: 5). Ignored with--continue-m, --model: GPT model name for confirmation/review (default: gpt-4.1-mini). Ignored with--continue
# Minimal - will prompt for repo URL
junieOrchestrator "Fix bug in payment processing"
# With custom base directory
junieOrchestrator "Add login form" -r "git@github.com:user/repo.git" -b "./tasks"
# With more iterations and specific model
junieOrchestrator "Implement caching layer" \
-r "https://github.com/user/repo.git" \
-n 10 \
-m "gpt-4"If you need to interrupt a job for any reason (Ctrl+C, system shutdown, etc.), you can resume it later using the --continue flag. There are three convenient ways to use it:
How it works:
- After each iteration, the orchestrator saves its state to
.junie_state.jsonin the working directory - This state includes the original task, repo URL, model, max iterations, and current iteration number
- When you use
--continue, it loads this state and resumes from the next iteration - All previous work (confirmation.md, steps_to_complete_the_task.md, junie_output files) is preserved
Three ways to continue:
-
Auto-detect from current directory (simplest):
# Navigate to the job folder cd add-login-form # Just run with --continue (no folder name needed!) junieOrchestrator --continue
-
Select from a list (when you have multiple jobs):
# Run --continue without a folder name in the base directory junieOrchestrator --continue # You'll see a list of available jobs to choose from: # Available jobs: # 1. add-login-form (iteration 2/5) # 2. fix-bug-123 (iteration 1/5) # Select a job (1-2):
-
Specify folder name explicitly (classic way):
# Resume the job by specifying the folder name junieOrchestrator --continue add-login-form # With custom base directory (if you used -b when starting) junieOrchestrator --continue add-login-form -b "./tasks"
Notes:
- The folder name is derived from the slugified task description (e.g., "Add login form" → "add-login-form")
- The
--continueflag ignores-r,-n, and-moptions (uses saved values from state) - You cannot specify both a task and
--continueat the same time
To uninstall the library:
pip uninstall junie-orchestrator- Python >= 3.7
gitinstalled and on$PATH- Junie CLI installed and on
$PATH - OpenAI Python client (installed automatically with the package):
pip install openai>=1.0.0