diff --git a/examples/codex/images/add_label.png b/examples/codex/images/add_label.png
new file mode 100644
index 0000000000..2c67b561eb
Binary files /dev/null and b/examples/codex/images/add_label.png differ
diff --git a/examples/codex/images/codex_action.png b/examples/codex/images/codex_action.png
new file mode 100644
index 0000000000..491de6651d
Binary files /dev/null and b/examples/codex/images/codex_action.png differ
diff --git a/examples/codex/images/jira_comment.png b/examples/codex/images/jira_comment.png
new file mode 100644
index 0000000000..2f010df408
Binary files /dev/null and b/examples/codex/images/jira_comment.png differ
diff --git a/examples/codex/images/jira_rule.png b/examples/codex/images/jira_rule.png
new file mode 100644
index 0000000000..a63dcae396
Binary files /dev/null and b/examples/codex/images/jira_rule.png differ
diff --git a/examples/codex/images/jira_status_change.png b/examples/codex/images/jira_status_change.png
new file mode 100644
index 0000000000..ac80c7f75b
Binary files /dev/null and b/examples/codex/images/jira_status_change.png differ
diff --git a/examples/codex/jira-github.ipynb b/examples/codex/jira-github.ipynb
new file mode 100644
index 0000000000..ce4e149572
--- /dev/null
+++ b/examples/codex/jira-github.ipynb
@@ -0,0 +1,314 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "raw"
+ }
+ },
+ "source": [
+ "# Automate Jira ↔ GitHub with `codex-cli`\n",
+ "\n",
+ "## What you'll build\n",
+ "\n",
+ "By the end of this walkthrough, you'll have an end-to-end automation that turns a **labelled Jira issue** into a\n",
+ "fully-fledged **GitHub pull request**, keeps the Jira ticket updated throughout the review process, and finally merges\n",
+ "the code once checks pass – all driven by the\n",
+ "[`codex-cli`](https://github.com/openai/openai-codex) agent working inside a GitHub Action.\n",
+ "\n",
+ "#
\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "raw"
+ }
+ },
+ "source": [
+ "The flow is:\n",
+ "1. Label a Jira issue \n",
+ "2. Jira Automation calls the GitHub Action \n",
+ "3. The action spins up `codex-cli` to implement the change \n",
+ "4. A PR is opened\n",
+ "5. Jira is transitioned & annotated – creating a neat, zero-click loop\n",
+ "\n",
+ "## Prerequisites\n",
+ "\n",
+ "* Jira: project admin rights + ability to create automation rules \n",
+ "* GitHub: write access, permission to add repository secrets, and a protected `main` branch \n",
+ "* API keys & secrets placed as repository secrets:\n",
+ " * `OPENAI_API_KEY` – your OpenAI key for `codex-cli` \n",
+ " * `JIRA_BASE_URL`, `JIRA_EMAIL`, `JIRA_API_TOKEN` – for REST calls from the action \n",
+ "* `codex-cli` installed locally (`pnpm add -g @openai/codex`) for ad-hoc testing \n",
+ "* A repository that already contains a `.github/workflows/` folder (any Node project is fine)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "raw"
+ }
+ },
+ "source": [
+ "## Create the Jira Automation Rule\n",
+ "\n",
+ "
\n",
+ "\n",
+ "* **Trigger – Issue updated**: fires whenever labels change \n",
+ "* **Condition – `labels` contains `autocodex`**: limits noise to explicitly opted-in issues \n",
+ "* **Action – Send web request**: POSTs the issue key/summary/description to your GitHub Action's `workflow_dispatch` endpoint\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "raw"
+ }
+ },
+ "source": [
+ "## Add the GitHub Action\n",
+ "\n",
+ "Create a workflow file in your `.github/workflows/` directory with the following YAML (Modify it as needed):\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```yaml\n",
+ "name: Codex Automated PR\n",
+ "on:\n",
+ " workflow_dispatch:\n",
+ " inputs:\n",
+ " issue_key:\n",
+ " description: 'JIRA issue key (e.g., PROJ-123)'\n",
+ " required: true\n",
+ " issue_summary:\n",
+ " description: 'Brief summary of the issue'\n",
+ " required: true\n",
+ " issue_description:\n",
+ " description: 'Detailed issue description'\n",
+ " required: true\n",
+ "\n",
+ "permissions:\n",
+ " contents: write # allow the action to push code & open the PR\n",
+ " pull-requests: write # allow the action to create and update PRs\n",
+ "\n",
+ "jobs:\n",
+ " codex_auto_pr:\n",
+ " runs-on: ubuntu-latest\n",
+ "\n",
+ " steps:\n",
+ " # 0 – Checkout repository\n",
+ " - uses: actions/checkout@v4\n",
+ " with:\n",
+ " fetch-depth: 0 # full history → lets Codex run tests / git blame if needed\n",
+ "\n",
+ " # 1 – Set up Node.js and Codex\n",
+ " - uses: actions/setup-node@v4\n",
+ " with:\n",
+ " node-version: 22\n",
+ " - run: pnpm add -g @openai/codex\n",
+ "\n",
+ " # 2 – Export / clean inputs (available via $GITHUB_ENV)\n",
+ " - id: vars\n",
+ " run: |\n",
+ " echo \"ISSUE_KEY=${{ github.event.inputs.issue_key }}\" >> $GITHUB_ENV\n",
+ " echo \"TITLE=${{ github.event.inputs.issue_summary }}\" >> $GITHUB_ENV\n",
+ " echo \"RAW_DESC=${{ github.event.inputs.issue_description }}\" >> $GITHUB_ENV\n",
+ " DESC_CLEANED=$(echo \"${{ github.event.inputs.issue_description }}\" | tr '\\n' ' ' | sed 's/\"/'\\''/g')\n",
+ " echo \"DESC=$DESC_CLEANED\" >> $GITHUB_ENV\n",
+ " echo \"BRANCH=codex/${{ github.event.inputs.issue_key }}\" >> $GITHUB_ENV\n",
+ "\n",
+ " # 3 – Transition Jira issue to \"In Progress\"\n",
+ " - name: Jira – Transition to In Progress\n",
+ " env:\n",
+ " ISSUE_KEY: ${{ env.ISSUE_KEY }}\n",
+ " JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}\n",
+ " JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}\n",
+ " JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}\n",
+ " run: |\n",
+ " curl -sS -X POST \\\n",
+ " --url \"$JIRA_BASE_URL/rest/api/3/issue/$ISSUE_KEY/transitions\" \\\n",
+ " --user \"$JIRA_EMAIL:$JIRA_API_TOKEN\" \\\n",
+ " --header 'Content-Type: application/json' \\\n",
+ " --data '{\"transition\":{\"id\":\"21\"}}'\n",
+ "\n",
+ " # 4 – Set Git author for CI commits\n",
+ " - run: |\n",
+ " git config user.email \"github-actions[bot]@users.noreply.github.com\"\n",
+ " git config user.name \"github-actions[bot]\"\n",
+ "\n",
+ " # 5 – Let Codex implement & commit (no push yet)\n",
+ " - name: Codex implement & commit\n",
+ " env:\n",
+ " OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\n",
+ " CODEX_QUIET_MODE: \"1\" # suppress chatty logs\n",
+ " run: |\n",
+ " set -e\n",
+ " codex --approval-mode full-auto --no-terminal --quiet \\\n",
+ " \"Implement JIRA ticket $ISSUE_KEY: $TITLE. $DESC\"\n",
+ "\n",
+ " git add -A\n",
+ " git commit -m \"feat($ISSUE_KEY): $TITLE\"\n",
+ "\n",
+ " # 6 – Open (and push) the PR in one go\n",
+ " - id: cpr\n",
+ " uses: peter-evans/create-pull-request@v6\n",
+ " with:\n",
+ " token: ${{ secrets.GITHUB_TOKEN }}\n",
+ " base: main\n",
+ " branch: ${{ env.BRANCH }}\n",
+ " title: \"${{ env.TITLE }} (${{ env.ISSUE_KEY }})\"\n",
+ " body: |\n",
+ " Auto-generated by Codex for JIRA **${{ env.ISSUE_KEY }}**.\n",
+ " ---\n",
+ " ${{ env.DESC }}\n",
+ "\n",
+ " # 7 – Transition Jira to \"In Review\" & drop the PR link\n",
+ " - name: Jira – Transition to In Review & Comment PR link\n",
+ " env:\n",
+ " ISSUE_KEY: ${{ env.ISSUE_KEY }}\n",
+ " JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}\n",
+ " JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}\n",
+ " JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}\n",
+ " PR_URL: ${{ steps.cpr.outputs.pull-request-url }}\n",
+ " run: |\n",
+ " # Status transition\n",
+ " curl -sS -X POST \\\n",
+ " --url \"$JIRA_BASE_URL/rest/api/3/issue/$ISSUE_KEY/transitions\" \\\n",
+ " --user \"$JIRA_EMAIL:$JIRA_API_TOKEN\" \\\n",
+ " --header 'Content-Type: application/json' \\\n",
+ " --data '{\"transition\":{\"id\":\"31\"}}'\n",
+ "\n",
+ " # Comment with PR link\n",
+ " curl -sS -X POST \\\n",
+ " --url \"$JIRA_BASE_URL/rest/api/3/issue/$ISSUE_KEY/comment\" \\\n",
+ " --user \"$JIRA_EMAIL:$JIRA_API_TOKEN\" \\\n",
+ " --header 'Content-Type: application/json' \\\n",
+ " --data \"{\\\"body\\\":{\\\"type\\\":\\\"doc\\\",\\\"version\\\":1,\\\"content\\\":[{\\\"type\\\":\\\"paragraph\\\",\\\"content\\\":[{\\\"type\\\":\\\"text\\\",\\\"text\\\":\\\"PR created: $PR_URL\\\"}]}]}}\"\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "raw"
+ }
+ },
+ "source": [
+ "## Key Steps in the Workflow\n",
+ "\n",
+ "1. **Codex Implementation & Commit** (Step 5)\n",
+ " - Uses OpenAI API to implement the JIRA ticket requirements\n",
+ " - Runs codex CLI in full-auto mode without terminal interaction\n",
+ " - Commits all changes with standardized commit message\n",
+ "\n",
+ "2. **Create Pull Request** (Step 6) \n",
+ " - Uses peter-evans/create-pull-request action\n",
+ " - Creates PR against main branch\n",
+ " - Sets PR title and description from JIRA ticket info\n",
+ " - Returns PR URL for later use\n",
+ "\n",
+ "3. **JIRA Updates** (Step 7)\n",
+ " - Transitions ticket to \"In Review\" status via JIRA API\n",
+ " - Posts comment with PR URL on the JIRA ticket\n",
+ " - Uses curl commands to interact with JIRA REST API\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "raw"
+ }
+ },
+ "source": [
+ "## Label an Issue\n",
+ "\n",
+ "Attach the special `autocodex` label to any bug/feature ticket:\n",
+ "\n",
+ "1. **During creation** – add it in the \"Labels\" field before hitting *Create* \n",
+ "2. **Existing issue** – hover the label area → click the pencil icon → type `autocodex`\n",
+ "\n",
+ "
\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "raw"
+ }
+ },
+ "source": [
+ "## End-to-end Flow in Action\n",
+ "\n",
+ "1. Jira label added → Automation triggers\n",
+ "2. `workflow_dispatch` fires; action spins up on GitHub\n",
+ "3. `codex-cli` edits the codebase & commits\n",
+ "4. PR is opened on the generated branch\n",
+ "5. Jira is moved to **In Review** and a comment with the PR URL is posted\n",
+ "6. Reviewers are notified per your normal branch protection settings\n",
+ "\n",
+ "
\n",
+ "
\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "raw"
+ }
+ },
+ "source": [
+ "## Review & Merge the PR\n",
+ "\n",
+ "* Confirm CI passes – tests, lint, build\n",
+ "* Approve & squash-merge\n",
+ "* The default branch protection will auto-close the Jira ticket once the PR merges if your *Smart Commits* integration is enabled\n",
+ "\n",
+ "## Conclusion\n",
+ "\n",
+ "This automation streamlines your development workflow by creating a seamless integration between Jira and GitHub:\n",
+ "\n",
+ "* **Zero-click implementation** - AI handles the code changes based on ticket descriptions\n",
+ "* **Automatic status tracking** - Tickets progress through your workflow without manual updates\n",
+ "* **Improved developer experience** - Focus on reviewing quality code instead of writing boilerplate\n",
+ "* **Reduced handoff friction** - The PR is ready for review as soon as the ticket is labeled\n",
+ "\n",
+ "The `codex-cli` tool is a powerful AI coding assistant that automates repetitive programming tasks. You can explore more about it at:\n",
+ "\n",
+ "* [OpenAI Codex-CLI GitHub Repository](https://github.com/openai/codex/)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": ".venv",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/registry.yaml b/registry.yaml
index fdc78fa2c9..c4fbdea338 100644
--- a/registry.yaml
+++ b/registry.yaml
@@ -3,6 +3,15 @@
# This file is used to generate cookbook.openai.com. It specifies which paths we
# should build pages for, and indicates metadata such as tags, creation date and
# authors for each page.
+- title: Automate Jira ↔ GitHub with Codex
+ path: examples/codex/jira-github.ipynb
+ date: 2025-06-21
+ authors:
+ - alwell-kevin
+ - narenoai
+ tags:
+ - codex
+ - automation
- title: Fine-Tuning Techniques - Choosing Between SFT, DPO, and RFT (With a Guide to DPO)
path: examples/Fine_tuning_direct_preference_optimization_guide.ipynb