Showing preview only (1,113K chars total). Download the full file or copy to clipboard to get everything.
Repository: frankbria/ralph-claude-code
Branch: main
Commit: f70254390018
Files: 91
Total size: 1.0 MB
Directory structure:
gitextract_5qewtfdp/
├── .claude/
│ └── memories/
│ └── project_memory.json
├── .gitattributes
├── .github/
│ ├── aw/
│ │ └── actions-lock.json
│ └── workflows/
│ ├── claude-code-review.yml
│ ├── claude.yml
│ ├── opencode-review.yml
│ ├── test.yml
│ ├── triage-incoming-issues.lock.yml
│ └── triage-incoming-issues.md
├── .gitignore
├── CLAUDE.md
├── CONTRIBUTING.md
├── IMPLEMENTATION_PLAN.md
├── IMPLEMENTATION_STATUS.md
├── LICENSE
├── README.md
├── SPECIFICATION_WORKSHOP.md
├── TESTING.md
├── create_files.sh
├── docs/
│ ├── archive/
│ │ └── 2025-10-milestones/
│ │ ├── EXPERT_PANEL_REVIEW.md
│ │ ├── PHASE1_COMPLETION.md
│ │ ├── PHASE2_COMPLETION.md
│ │ ├── README.md
│ │ ├── STATUS.md
│ │ ├── TEST_IMPLEMENTATION_SUMMARY.md
│ │ └── USE_CASES.md
│ ├── code-review/
│ │ ├── 2026-01-08-cli-parsing-tests-review.md
│ │ └── 2026-01-08-phase-1.1-modern-cli-review.md
│ ├── generated/
│ │ └── .gitkeep
│ └── user-guide/
│ ├── 01-quick-start.md
│ ├── 02-understanding-ralph-files.md
│ ├── 03-writing-requirements.md
│ └── README.md
├── examples/
│ ├── rest-api/
│ │ ├── .ralph/
│ │ │ ├── PROMPT.md
│ │ │ ├── fix_plan.md
│ │ │ └── specs/
│ │ │ └── api.md
│ │ └── README.md
│ └── simple-cli-tool/
│ ├── .ralph/
│ │ ├── PROMPT.md
│ │ └── fix_plan.md
│ └── README.md
├── install.sh
├── lib/
│ ├── circuit_breaker.sh
│ ├── date_utils.sh
│ ├── enable_core.sh
│ ├── file_protection.sh
│ ├── response_analyzer.sh
│ ├── task_sources.sh
│ ├── timeout_utils.sh
│ └── wizard_utils.sh
├── logs/
│ └── .gitkeep
├── migrate_to_ralph_folder.sh
├── package.json
├── ralph_enable.sh
├── ralph_enable_ci.sh
├── ralph_import.sh
├── ralph_loop.sh
├── ralph_monitor.sh
├── sample-prd.md
├── setup.sh
├── specs/
│ └── stdlib/
│ └── .gitkeep
├── src/
│ └── .gitkeep
├── templates/
│ ├── .gitignore
│ ├── AGENT.md
│ ├── PROMPT.md
│ ├── fix_plan.md
│ ├── ralphrc.template
│ └── specs/
│ └── .gitkeep
├── tests/
│ ├── helpers/
│ │ ├── fixtures.bash
│ │ ├── mocks.bash
│ │ └── test_helper.bash
│ ├── integration/
│ │ ├── test_edge_cases.bats
│ │ ├── test_installation.bats
│ │ ├── test_loop_execution.bats
│ │ ├── test_prd_import.bats
│ │ └── test_project_setup.bats
│ ├── test_error_detection.sh
│ ├── test_stuck_loop_detection.sh
│ └── unit/
│ ├── test_circuit_breaker_recovery.bats
│ ├── test_cli_modern.bats
│ ├── test_cli_parsing.bats
│ ├── test_enable_core.bats
│ ├── test_exit_detection.bats
│ ├── test_file_protection.bats
│ ├── test_integrity_check.bats
│ ├── test_json_parsing.bats
│ ├── test_ralph_enable.bats
│ ├── test_rate_limiting.bats
│ ├── test_session_continuity.bats
│ ├── test_task_sources.bats
│ └── test_wizard_utils.bats
└── uninstall.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .claude/memories/project_memory.json
================================================
{
"memories": [],
"manual_memories": [],
"realtime_memories": [
{
"type": "message",
"content": "Can we approve and merge PRs 202 and 208?",
"added_at": "2026-03-15T22:06:45.260456",
"source": "realtime_capture"
}
],
"created_at": "2026-03-15T22:06:45.260428",
"updated_at": "2026-03-15T22:06:45.260458"
}
================================================
FILE: .gitattributes
================================================
.github/workflows/*.lock.yml linguist-generated=true merge=ours
================================================
FILE: .github/aw/actions-lock.json
================================================
{
"entries": {
"actions/github-script@v8": {
"repo": "actions/github-script",
"version": "v8",
"sha": "ed597411d8f924073f98dfc5c65a23a2325f34cd"
},
"github/gh-aw/actions/setup@v0.46.5": {
"repo": "github/gh-aw/actions/setup",
"version": "v0.46.5",
"sha": "5a79466d65414632d47c7869b27170ade5b9404e"
}
}
}
================================================
FILE: .github/workflows/claude-code-review.yml
================================================
name: Claude Code Review
on:
# Using pull_request_target to run with base repo permissions (access to secrets)
# This allows the workflow to run for fork PRs after maintainer approval
# Security: This workflow only READS PR code for review, it does NOT execute it
pull_request_target:
types: [opened, synchronize]
# Skip review for documentation and config-only changes
paths-ignore:
- "**/*.md"
- ".github/**"
- ".gitignore"
- "pyproject.toml"
# Cancel in-progress runs for the same PR to avoid duplicate reviews
concurrency:
group: claude-code-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
claude-review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # Needed to post review comments
issues: read
id-token: write
steps:
- name: Calculate total changes
id: calc
run: |
additions=${{ github.event.pull_request.additions }}
deletions=${{ github.event.pull_request.deletions }}
total=$((additions + deletions))
echo "total=$total" >> $GITHUB_OUTPUT
- name: Checkout PR code for review
# Only review substantial changes (5+ files OR 20+ lines changed)
if: |
github.event.pull_request.changed_files >= 5 ||
steps.calc.outputs.total >= 20
uses: actions/checkout@v4
with:
# Checkout the PR head commit (pull_request_target defaults to base branch)
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 1
- name: Run Claude Code Review
# Only review substantial changes (5+ files OR 20+ lines changed)
if: |
github.event.pull_request.changed_files >= 5 ||
steps.calc.outputs.total >= 20
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Explicit github_token needed for pull_request_target (OIDC doesn't work)
github_token: ${{ secrets.GITHUB_TOKEN }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage
NOTE: review the other comments on the pull request - including yours.
If you are reviewing changes or enhancements beyond the first creation of the pull request,
make sure your comments are consistent with your previous reviews, or are
referring to them in a consistent way.
IMPORTANT FORMATTING NOTE: The use of the number symbol, '#', has a specific meaning in GitHub. It creates a link to an existing GitHub
Issue or PR. If you plan to make that link, feel free to use # as a symbole in text. However, if you're simply referring to a numbered item
in your own text, do not use the # symbol because it will link to an issue or PR which isn't related. Just write 'Number' or "No.".
There's no need to repeat information unless it is critical and not
being reflected in comments or code. Be aware of your prior reviews and that the new file information
may reflect changes because of previous reviews.
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
================================================
FILE: .github/workflows/claude.yml
================================================
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
# Cancel in-progress runs for the same issue/PR to avoid duplicate responses
concurrency:
group: claude-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: true
jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'
# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)'
================================================
FILE: .github/workflows/opencode-review.yml
================================================
name: OpenCode PR Review
on:
# Using pull_request (not pull_request_target) because the OpenCode action
# doesn't support pull_request_target. This means it only works for PRs from
# branches in this repo (not forks). Fork PRs are reviewed by claude-code-review.yml instead.
pull_request:
types: [opened, synchronize]
# Skip review for documentation and config-only changes
# Exclude this workflow file to prevent self-triggering loops
paths-ignore:
- "**/*.md"
- ".github/workflows/opencode-review.yml"
- ".gitignore"
- "pyproject.toml"
# Cancel in-progress runs for the same PR to avoid duplicate reviews
concurrency:
group: opencode-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
opencode-review:
runs-on: ubuntu-latest
timeout-minutes: 10 # Prevent hanging - kill after 10 min
permissions:
id-token: write
contents: read
pull-requests: write
issues: write
steps:
- name: Calculate total changes
id: calc
run: |
additions=${{ github.event.pull_request.additions }}
deletions=${{ github.event.pull_request.deletions }}
total=$((additions + deletions))
echo "total=$total" >> $GITHUB_OUTPUT
- name: Checkout repository
# Only review substantial changes (5+ files OR 20+ lines changed)
if: |
github.event.pull_request.changed_files >= 5 ||
steps.calc.outputs.total >= 20
uses: actions/checkout@v6
with:
fetch-depth: 1
persist-credentials: false
- name: Clear git credentials to avoid duplicate auth
if: |
github.event.pull_request.changed_files >= 5 ||
steps.calc.outputs.total >= 20
run: |
# Clear all GitHub-related git config to prevent auth conflicts
git config --global --unset-all http.https://github.com/.extraheader || true
git config --local --unset-all http.https://github.com/.extraheader || true
git config --global --unset-all credential.helper || true
git config --local --unset-all credential.helper || true
git config --global --unset-all credential."https://github.com".helper || true
git config --local --unset-all credential."https://github.com".helper || true
# Remove any credential URLs
git config --global --unset-all credential.url || true
git config --local --unset-all credential.url || true
# Clear any includeIf configs that might add credentials
# Note: git config doesn't support wildcards, so we iterate over matching keys
# Use case-insensitive grep to catch both "includeIf" and "includeif"
for key in $(git config --global --list --name-only 2>/dev/null | grep -i "^includeif\." || true); do
git config --global --unset "$key" || true
done
for key in $(git config --local --list --name-only 2>/dev/null | grep -i "^includeif\." || true); do
git config --local --unset "$key" || true
done
- name: Run OpenCode PR Review
# Only review substantial changes (5+ files OR 20+ lines changed)
if: |
github.event.pull_request.changed_files >= 5 ||
steps.calc.outputs.total >= 20
uses: anomalyco/opencode/github@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ZHIPU_API_KEY: ${{ secrets.ZHIPU_API_KEY }}
# Pass PR context as environment variables for the review
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
REPO_NAME: ${{ github.repository }}
with:
model: zai-coding-plan/glm-4.7
use_github_token: true
prompt: |
You are reviewing PR #${{ github.event.pull_request.number }} in repository ${{ github.repository }}.
PR TITLE: ${{ github.event.pull_request.title }}
Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage
IMPORTANT NOTES:
- Review the other comments on the pull request - including any prior reviews.
- If you are reviewing changes beyond the first creation of the pull request,
make sure your comments are consistent with previous reviews.
- There's no need to repeat information unless it is critical and not
being reflected in comments or code.
- Be aware of prior reviews and that new file information may reflect
changes because of previous reviews.
Use the repository's CLAUDE.md for guidance on style and conventions.
Be constructive and helpful in your feedback.
IMPORTANT: Post exactly ONE comment using `gh pr comment`, then STOP.
Do not attempt additional actions after posting your review.
================================================
FILE: .github/workflows/test.yml
================================================
name: Test Suite
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
# Coverage threshold - configurable, not hardcoded
# Set to 0 to disable threshold enforcement
#
# NOTE: kcov cannot trace subprocess executions due to LD_PRELOAD limitations.
# When bats runs tests, it spawns new bash processes that kcov cannot instrument.
# This is a known limitation (see: https://github.com/bats-core/bats-core/issues/15)
# Coverage is kept as informational-only; test pass rate is the quality gate.
COVERAGE_THRESHOLD: 0
KCOV_VERSION: "42"
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: |
npm install
sudo apt-get update
sudo apt-get install -y jq
- name: Run unit tests
run: npm run test:unit
- name: Run integration tests
run: npm run test:integration || true
- name: Run E2E tests
run: npm run test:e2e || true
- name: Generate test report
run: |
echo "## Test Results" >> $GITHUB_STEP_SUMMARY
echo "✅ Unit tests passed" >> $GITHUB_STEP_SUMMARY
coverage:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: |
npm install
sudo apt-get update
sudo apt-get install -y jq
- name: Build and install kcov from source
run: |
# Install kcov build dependencies
sudo apt-get install -y \
cmake \
g++ \
binutils-dev \
libcurl4-openssl-dev \
libdw-dev \
libiberty-dev \
zlib1g-dev \
libssl-dev
# Clone and build kcov
git clone --depth 1 --branch v${KCOV_VERSION} https://github.com/SimonKagstrom/kcov.git /tmp/kcov-src
cd /tmp/kcov-src
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
make -j$(nproc)
sudo make install
# Verify installation
/usr/local/bin/kcov --version
- name: Verify kcov installation
run: |
which kcov
kcov --version
- name: Run tests with coverage
run: |
mkdir -p coverage
# Use full path to bats since kcov subprocess doesn't inherit npm PATH
BATS_CMD="$(pwd)/node_modules/.bin/bats"
# Run CLI parsing tests under kcov
kcov --include-path="$(pwd)/ralph_loop.sh,$(pwd)/lib" \
--exclude-pattern=tests/,node_modules/ \
coverage/cli-parsing \
bash -c "$BATS_CMD tests/unit/test_cli_parsing.bats" || true
# Run all unit tests under kcov for comprehensive coverage
kcov --include-path="$(pwd)/ralph_loop.sh,$(pwd)/lib" \
--exclude-pattern=tests/,node_modules/ \
coverage/all-unit \
bash -c "$BATS_CMD tests/unit/" || true
- name: Parse coverage results
id: coverage
run: |
# Extract coverage percentage from kcov JSON output
COVERAGE_FILE="coverage/all-unit/kcov-merged/coverage.json"
if [[ -f "$COVERAGE_FILE" ]]; then
COVERAGE_PCT=$(jq -r '.percent_covered // "0"' "$COVERAGE_FILE" | cut -d'.' -f1)
echo "coverage_percent=$COVERAGE_PCT" >> $GITHUB_OUTPUT
echo "Coverage: ${COVERAGE_PCT}%"
else
# Fallback: try to find any coverage.json
COVERAGE_FILE=$(find coverage -name "coverage.json" -type f 2>/dev/null | head -1)
if [[ -n "$COVERAGE_FILE" && -f "$COVERAGE_FILE" ]]; then
COVERAGE_PCT=$(jq -r '.percent_covered // "0"' "$COVERAGE_FILE" | cut -d'.' -f1)
echo "coverage_percent=$COVERAGE_PCT" >> $GITHUB_OUTPUT
echo "Coverage (from $COVERAGE_FILE): ${COVERAGE_PCT}%"
else
echo "coverage_percent=0" >> $GITHUB_OUTPUT
echo "Warning: Could not find coverage results"
# List what we do have for debugging
find coverage -type f -name "*.json" 2>/dev/null || echo "No JSON files found"
ls -laR coverage/ 2>/dev/null || echo "Coverage directory empty or not found"
fi
fi
- name: Check coverage threshold
run: |
COVERAGE=${{ steps.coverage.outputs.coverage_percent }}
THRESHOLD=${{ env.COVERAGE_THRESHOLD }}
echo "## Coverage Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Coverage | ${COVERAGE}% |" >> $GITHUB_STEP_SUMMARY
echo "| Threshold | ${THRESHOLD}% |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [[ "$THRESHOLD" -eq 0 ]]; then
echo "✅ Coverage threshold enforcement disabled" >> $GITHUB_STEP_SUMMARY
echo "Coverage threshold enforcement disabled (COVERAGE_THRESHOLD=0)"
exit 0
fi
if [[ -z "$COVERAGE" || "$COVERAGE" == "0" ]]; then
echo "⚠️ Coverage measurement failed - skipping threshold check" >> $GITHUB_STEP_SUMMARY
echo "Coverage measurement failed - skipping threshold check"
exit 0
fi
if [[ "$COVERAGE" -lt "$THRESHOLD" ]]; then
echo "❌ Coverage ${COVERAGE}% is below threshold ${THRESHOLD}%" >> $GITHUB_STEP_SUMMARY
echo "::error::Coverage ${COVERAGE}% is below threshold ${THRESHOLD}%"
exit 1
else
echo "✅ Coverage ${COVERAGE}% meets threshold ${THRESHOLD}%" >> $GITHUB_STEP_SUMMARY
echo "Coverage ${COVERAGE}% meets threshold ${THRESHOLD}%"
fi
- name: Upload coverage artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: coverage/
retention-days: 7
- name: Upload coverage to Codecov (optional)
uses: codecov/codecov-action@v4
if: always()
continue-on-error: true
with:
directory: coverage/all-unit
fail_ci_if_error: false
verbose: true
================================================
FILE: .github/workflows/triage-incoming-issues.lock.yml
================================================
#
# ___ _ _
# / _ \ | | (_)
# | |_| | __ _ ___ _ __ | |_ _ ___
# | _ |/ _` |/ _ \ '_ \| __| |/ __|
# | | | | (_| | __/ | | | |_| | (__
# \_| |_/\__, |\___|_| |_|\__|_|\___|
# __/ |
# _ _ |___/
# | | | | / _| |
# | | | | ___ _ __ _ __| |_| | _____ ____
# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___|
# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
#
# This file was automatically generated by gh-aw (v0.46.5). DO NOT EDIT.
#
# To update this file, edit the corresponding .md file and run:
# gh aw compile
# Not all edits will cause changes to this file.
#
# For more information: https://github.github.com/gh-aw/introduction/overview/
#
#
# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"68257b0ae35205e70608bbfa4e344cdd25ea710254fdb5addb4e8d9b53311a0e","compiler_version":"v0.46.5"}
name: "Issue Triage Assistant"
"on":
issues:
types:
- opened
# roles: all # Roles processed as role check in pre-activation job
workflow_dispatch:
permissions: {}
concurrency:
group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number }}"
run-name: "Issue Triage Assistant"
jobs:
activation:
runs-on: ubuntu-slim
permissions:
contents: read
outputs:
body: ${{ steps.sanitized.outputs.body }}
comment_id: ""
comment_repo: ""
text: ${{ steps.sanitized.outputs.text }}
title: ${{ steps.sanitized.outputs.title }}
steps:
- name: Setup Scripts
uses: github/gh-aw/actions/setup@5a79466d65414632d47c7869b27170ade5b9404e # v0.46.5
with:
destination: /opt/gh-aw/actions
- name: Validate context variables
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/validate_context_variables.cjs');
await main();
- name: Checkout .github and .agents folders
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
.github
.agents
fetch-depth: 1
persist-credentials: false
- name: Check workflow file timestamps
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_WORKFLOW_FILE: "triage-incoming-issues.lock.yml"
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/check_workflow_timestamp_api.cjs');
await main();
- name: Compute current body text
id: sanitized
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/compute_text.cjs');
await main();
- name: Create prompt with built-in context
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
run: |
bash /opt/gh-aw/actions/create_prompt_first.sh
cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT"
<system>
GH_AW_PROMPT_EOF
cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT"
cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT"
cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT"
cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT"
<safe-outputs>
<description>GitHub API Access Instructions</description>
<important>
The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations.
</important>
<instructions>
To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls.
Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body).
**IMPORTANT - temporary_id format rules:**
- If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed)
- If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i
- Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive)
- Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
- INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore)
- VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678
- To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate
Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i.
Discover available tools from the safeoutputs MCP server.
**Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped.
**Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed.
</instructions>
</safe-outputs>
<github-context>
The following GitHub context information is available for this workflow:
{{#if __GH_AW_GITHUB_ACTOR__ }}
- **actor**: __GH_AW_GITHUB_ACTOR__
{{/if}}
{{#if __GH_AW_GITHUB_REPOSITORY__ }}
- **repository**: __GH_AW_GITHUB_REPOSITORY__
{{/if}}
{{#if __GH_AW_GITHUB_WORKSPACE__ }}
- **workspace**: __GH_AW_GITHUB_WORKSPACE__
{{/if}}
{{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }}
- **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__
{{/if}}
{{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }}
- **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__
{{/if}}
{{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }}
- **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__
{{/if}}
{{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }}
- **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__
{{/if}}
{{#if __GH_AW_GITHUB_RUN_ID__ }}
- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
{{/if}}
</github-context>
GH_AW_PROMPT_EOF
cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT"
</system>
GH_AW_PROMPT_EOF
cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT"
{{#runtime-import .github/workflows/triage-incoming-issues.md}}
GH_AW_PROMPT_EOF
- name: Interpolate variables and render templates
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs');
await main();
- name: Substitute placeholders
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }}
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: ${{ needs.pre_activation.outputs.matched_command }}
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs');
// Call the substitution function
return await substitutePlaceholders({
file: process.env.GH_AW_PROMPT,
substitutions: {
GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID,
GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER,
GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER,
GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER,
GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY,
GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID,
GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE,
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED,
GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND
}
});
- name: Validate prompt placeholders
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh
- name: Print prompt
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
run: bash /opt/gh-aw/actions/print_prompt_summary.sh
- name: Upload prompt artifact
if: success()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: prompt
path: /tmp/gh-aw/aw-prompts/prompt.txt
retention-days: 1
agent:
needs: activation
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
GH_AW_ASSETS_ALLOWED_EXTS: ""
GH_AW_ASSETS_BRANCH: ""
GH_AW_ASSETS_MAX_SIZE_KB: 0
GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl
GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json
GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json
GH_AW_WORKFLOW_ID_SANITIZED: triageincomingissues
outputs:
checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
has_patch: ${{ steps.collect_output.outputs.has_patch }}
model: ${{ steps.generate_aw_info.outputs.model }}
output: ${{ steps.collect_output.outputs.output }}
output_types: ${{ steps.collect_output.outputs.output_types }}
secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }}
steps:
- name: Setup Scripts
uses: github/gh-aw/actions/setup@5a79466d65414632d47c7869b27170ade5b9404e # v0.46.5
with:
destination: /opt/gh-aw/actions
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Create gh-aw temp directory
run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
- name: Configure Git credentials
env:
REPO_NAME: ${{ github.repository }}
SERVER_URL: ${{ github.server_url }}
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
# Re-authenticate git with GitHub token
SERVER_URL_STRIPPED="${SERVER_URL#https://}"
git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
echo "Git configured with standard GitHub Actions identity"
- name: Checkout PR branch
id: checkout-pr
if: |
github.event.pull_request
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
with:
github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs');
await main();
- name: Generate agentic run info
id: generate_aw_info
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const fs = require('fs');
const awInfo = {
engine_id: "copilot",
engine_name: "GitHub Copilot CLI",
model: process.env.GH_AW_MODEL_AGENT_COPILOT || "",
version: "",
agent_version: "0.0.411",
cli_version: "v0.46.5",
workflow_name: "Issue Triage Assistant",
experimental: false,
supports_tools_allowlist: true,
run_id: context.runId,
run_number: context.runNumber,
run_attempt: process.env.GITHUB_RUN_ATTEMPT,
repository: context.repo.owner + '/' + context.repo.repo,
ref: context.ref,
sha: context.sha,
actor: context.actor,
event_name: context.eventName,
staged: false,
allowed_domains: ["defaults"],
firewall_enabled: true,
awf_version: "v0.20.1",
awmg_version: "v0.1.4",
steps: {
firewall: "squid"
},
created_at: new Date().toISOString()
};
// Write to /tmp/gh-aw directory to avoid inclusion in PR
const tmpPath = '/tmp/gh-aw/aw_info.json';
fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2));
console.log('Generated aw_info.json at:', tmpPath);
console.log(JSON.stringify(awInfo, null, 2));
// Set model as output for reuse in other steps/jobs
core.setOutput('model', awInfo.model);
- name: Validate COPILOT_GITHUB_TOKEN secret
id: validate-secret
run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
- name: Install GitHub Copilot CLI
run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.411
- name: Install awf binary
run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.20.1
- name: Determine automatic lockdown mode for GitHub MCP Server
id: determine-automatic-lockdown
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
with:
script: |
const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs');
await determineAutomaticLockdown(github, context, core);
- name: Download container images
run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.20.1 ghcr.io/github/gh-aw-firewall/api-proxy:0.20.1 ghcr.io/github/gh-aw-firewall/squid:0.20.1 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.30.3 node:lts-alpine
- name: Write Safe Outputs Config
run: |
mkdir -p /opt/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF'
{"add_comment":{"max":10},"add_labels":{"allowed":["bug","enhancement","needs-info","documentation"],"max":3},"assign_to_user":{"allowed":["frankbria"],"max":1},"close_issue":{"max":1,"target":"triggering"},"missing_data":{},"missing_tool":{},"noop":{"max":1}}
GH_AW_SAFE_OUTPUTS_CONFIG_EOF
cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_EOF'
[
{
"description": "Close a GitHub issue with a closing comment. You can and should always add a comment when closing an issue to explain the action or provide context. This tool is ONLY for closing issues - use update_issue if you need to change the title, body, labels, or other metadata without closing. Use close_issue when work is complete, the issue is no longer relevant, or it's a duplicate. The closing comment should explain the resolution or reason for closing. If the issue is already closed, a comment will still be posted. CONSTRAINTS: Maximum 1 issue(s) can be closed. Target: triggering.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"body": {
"description": "Closing comment explaining why the issue is being closed and summarizing any resolution, workaround, or conclusion.",
"type": "string"
},
"issue_number": {
"description": "Issue number to close. This is the numeric ID from the GitHub URL (e.g., 901 in github.com/owner/repo/issues/901). If omitted, closes the issue that triggered this workflow (requires an issue event trigger).",
"type": [
"number",
"string"
]
}
},
"required": [
"body"
],
"type": "object"
},
"name": "close_issue"
},
{
"description": "Add a comment to an existing GitHub issue, pull request, or discussion. Use this to provide feedback, answer questions, or add information to an existing conversation. For creating new items, use create_issue, create_discussion, or create_pull_request instead. IMPORTANT: Comments are subject to validation constraints enforced by the MCP server - maximum 65536 characters for the complete comment (including footer which is added automatically), 10 mentions (@username), and 50 links. Exceeding these limits will result in an immediate error with specific guidance. NOTE: By default, this tool requires discussions:write permission. If your GitHub App lacks Discussions permission, set 'discussions: false' in the workflow's safe-outputs.add-comment configuration to exclude this permission. CONSTRAINTS: Maximum 10 comment(s) can be added.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"body": {
"description": "The comment text in Markdown format. This is the 'body' field - do not use 'comment_body' or other variations. Provide helpful, relevant information that adds value to the conversation. CONSTRAINTS: The complete comment (your body text + automatically added footer) must not exceed 65536 characters total. Maximum 10 mentions (@username), maximum 50 links (http/https URLs). A footer (~200-500 characters) is automatically appended with workflow attribution, so leave adequate space. If these limits are exceeded, the tool call will fail with a detailed error message indicating which constraint was violated.",
"type": "string"
},
"item_number": {
"description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). If omitted, the tool will attempt to resolve the target from the current workflow context (triggering issue, PR, or discussion).",
"type": "number"
}
},
"required": [
"body"
],
"type": "object"
},
"name": "add_comment"
},
{
"description": "Add labels to an existing GitHub issue or pull request for categorization and filtering. Labels must already exist in the repository. For creating new issues with labels, use create_issue with the labels property instead. CONSTRAINTS: Only these labels are allowed: [bug enhancement needs-info documentation].",
"inputSchema": {
"additionalProperties": false,
"properties": {
"item_number": {
"description": "Issue or PR number to add labels to. This is the numeric ID from the GitHub URL (e.g., 456 in github.com/owner/repo/issues/456). If omitted, adds labels to the item that triggered this workflow.",
"type": "number"
},
"labels": {
"description": "Label names to add (e.g., ['bug', 'priority-high']). Labels must exist in the repository.",
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
},
"name": "add_labels"
},
{
"description": "Assign one or more GitHub users to an issue. Use this to delegate work to specific team members. Users must have access to the repository.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"assignee": {
"description": "Single GitHub username to assign. Use 'assignees' array for multiple users.",
"type": "string"
},
"assignees": {
"description": "GitHub usernames to assign to the issue (e.g., ['octocat', 'mona']). Users must have access to the repository.",
"items": {
"type": "string"
},
"type": "array"
},
"issue_number": {
"description": "Issue number to assign users to. This is the numeric ID from the GitHub URL (e.g., 543 in github.com/owner/repo/issues/543). If omitted, assigns to the issue that triggered this workflow.",
"type": [
"number",
"string"
]
}
},
"required": [
"issue_number"
],
"type": "object"
},
"name": "assign_to_user"
},
{
"description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"alternatives": {
"description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).",
"type": "string"
},
"reason": {
"description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).",
"type": "string"
},
"tool": {
"description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
"name": "missing_tool"
},
{
"description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"message": {
"description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').",
"type": "string"
}
},
"required": [
"message"
],
"type": "object"
},
"name": "noop"
},
{
"description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.",
"inputSchema": {
"additionalProperties": false,
"properties": {
"alternatives": {
"description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).",
"type": "string"
},
"context": {
"description": "Additional context about the missing data or where it should come from (max 256 characters).",
"type": "string"
},
"data_type": {
"description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.",
"type": "string"
},
"reason": {
"description": "Explanation of why this data is needed to complete the task (max 256 characters).",
"type": "string"
}
},
"required": [],
"type": "object"
},
"name": "missing_data"
}
]
GH_AW_SAFE_OUTPUTS_TOOLS_EOF
cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF'
{
"add_comment": {
"defaultMax": 1,
"fields": {
"body": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 65000
},
"item_number": {
"issueOrPRNumber": true
}
}
},
"add_labels": {
"defaultMax": 5,
"fields": {
"item_number": {
"issueOrPRNumber": true
},
"labels": {
"required": true,
"type": "array",
"itemType": "string",
"itemSanitize": true,
"itemMaxLength": 128
}
}
},
"assign_to_user": {
"defaultMax": 1,
"fields": {
"assignee": {
"type": "string",
"sanitize": true,
"maxLength": 39
},
"assignees": {
"type": "[]string",
"sanitize": true,
"maxLength": 39
},
"issue_number": {
"issueOrPRNumber": true
}
}
},
"close_issue": {
"defaultMax": 1,
"fields": {
"body": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 65000
},
"issue_number": {
"optionalPositiveInteger": true
}
}
},
"missing_tool": {
"defaultMax": 20,
"fields": {
"alternatives": {
"type": "string",
"sanitize": true,
"maxLength": 512
},
"reason": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 256
},
"tool": {
"type": "string",
"sanitize": true,
"maxLength": 128
}
}
},
"noop": {
"defaultMax": 1,
"fields": {
"message": {
"required": true,
"type": "string",
"sanitize": true,
"maxLength": 65000
}
}
}
}
GH_AW_SAFE_OUTPUTS_VALIDATION_EOF
- name: Generate Safe Outputs MCP Server Config
id: safe-outputs-config
run: |
# Generate a secure random API key (360 bits of entropy, 40+ chars)
# Mask immediately to prevent timing vulnerabilities
API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
echo "::add-mask::${API_KEY}"
PORT=3001
# Set outputs for next steps
{
echo "safe_outputs_api_key=${API_KEY}"
echo "safe_outputs_port=${PORT}"
} >> "$GITHUB_OUTPUT"
echo "Safe Outputs MCP server will run on port ${PORT}"
- name: Start Safe Outputs MCP HTTP Server
id: safe-outputs-start
env:
DEBUG: '*'
GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }}
GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }}
GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json
GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json
GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
run: |
# Environment variables are set above to prevent template injection
export DEBUG
export GH_AW_SAFE_OUTPUTS_PORT
export GH_AW_SAFE_OUTPUTS_API_KEY
export GH_AW_SAFE_OUTPUTS_TOOLS_PATH
export GH_AW_SAFE_OUTPUTS_CONFIG_PATH
export GH_AW_MCP_LOG_DIR
bash /opt/gh-aw/actions/start_safe_outputs_server.sh
- name: Start MCP Gateway
id: start-mcp-gateway
env:
GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }}
GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }}
GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }}
GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
run: |
set -eo pipefail
mkdir -p /tmp/gh-aw/mcp-config
# Export gateway environment variables for MCP config and gateway script
export MCP_GATEWAY_PORT="80"
export MCP_GATEWAY_DOMAIN="host.docker.internal"
MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
echo "::add-mask::${MCP_GATEWAY_API_KEY}"
export MCP_GATEWAY_API_KEY
export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads"
mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}"
export DEBUG="*"
export GH_AW_ENGINE="copilot"
export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_LOCKDOWN -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.1.4'
mkdir -p /home/runner/.copilot
cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh
{
"mcpServers": {
"github": {
"type": "stdio",
"container": "ghcr.io/github/github-mcp-server:v0.30.3",
"env": {
"GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN",
"GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}",
"GITHUB_READ_ONLY": "1",
"GITHUB_TOOLSETS": "context,repos,issues,pull_requests"
}
},
"safeoutputs": {
"type": "http",
"url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT",
"headers": {
"Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}"
}
}
},
"gateway": {
"port": $MCP_GATEWAY_PORT,
"domain": "${MCP_GATEWAY_DOMAIN}",
"apiKey": "${MCP_GATEWAY_API_KEY}",
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
GH_AW_MCP_CONFIG_EOF
- name: Generate workflow overview
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs');
await generateWorkflowOverview(core);
- name: Download prompt artifact
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with:
name: prompt
path: /tmp/gh-aw/aw-prompts
- name: Clean git credentials
run: bash /opt/gh-aw/actions/clean_git_credentials.sh
- name: Execute GitHub Copilot CLI
id: agentic_execution
# Copilot CLI tool arguments (sorted):
timeout-minutes: 20
run: |
set -o pipefail
sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.20.1 --skip-pull --enable-api-proxy \
-- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"}' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
env:
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
GH_AW_MODEL_AGENT_COPILOT: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
GITHUB_HEAD_REF: ${{ github.head_ref }}
GITHUB_REF_NAME: ${{ github.ref_name }}
GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }}
GITHUB_WORKSPACE: ${{ github.workspace }}
XDG_CONFIG_HOME: /home/runner
- name: Configure Git credentials
env:
REPO_NAME: ${{ github.repository }}
SERVER_URL: ${{ github.server_url }}
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
# Re-authenticate git with GitHub token
SERVER_URL_STRIPPED="${SERVER_URL#https://}"
git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
echo "Git configured with standard GitHub Actions identity"
- name: Copy Copilot session state files to logs
if: always()
continue-on-error: true
run: |
# Copy Copilot session state files to logs folder for artifact collection
# This ensures they are in /tmp/gh-aw/ where secret redaction can scan them
SESSION_STATE_DIR="$HOME/.copilot/session-state"
LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs"
if [ -d "$SESSION_STATE_DIR" ]; then
echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR"
mkdir -p "$LOGS_DIR"
cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true
echo "Session state files copied successfully"
else
echo "No session-state directory found at $SESSION_STATE_DIR"
fi
- name: Stop MCP Gateway
if: always()
continue-on-error: true
env:
MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }}
GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }}
run: |
bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID"
- name: Redact secrets in logs
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/redact_secrets.cjs');
await main();
env:
GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN'
SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Safe Outputs
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: safe-output
path: ${{ env.GH_AW_SAFE_OUTPUTS }}
if-no-files-found: warn
- name: Ingest agent output
id: collect_output
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com"
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_API_URL: ${{ github.api_url }}
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/collect_ndjson_output.cjs');
await main();
- name: Upload sanitized agent output
if: always() && env.GH_AW_AGENT_OUTPUT
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: agent-output
path: ${{ env.GH_AW_AGENT_OUTPUT }}
if-no-files-found: warn
- name: Upload engine output files
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: agent_outputs
path: |
/tmp/gh-aw/sandbox/agent/logs/
/tmp/gh-aw/redacted-urls.log
if-no-files-found: ignore
- name: Parse agent logs for step summary
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs');
await main();
- name: Parse MCP Gateway logs for step summary
if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs');
await main();
- name: Print firewall logs
if: always()
continue-on-error: true
env:
AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs
run: |
# Fix permissions on firewall logs so they can be uploaded as artifacts
# AWF runs with sudo, creating files owned by root
sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true
# Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step)
if command -v awf &> /dev/null; then
awf logs summary | tee -a "$GITHUB_STEP_SUMMARY"
else
echo 'AWF binary not installed, skipping firewall log summary'
fi
- name: Upload agent artifacts
if: always()
continue-on-error: true
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: agent-artifacts
path: |
/tmp/gh-aw/aw-prompts/prompt.txt
/tmp/gh-aw/aw_info.json
/tmp/gh-aw/mcp-logs/
/tmp/gh-aw/sandbox/firewall/logs/
/tmp/gh-aw/agent-stdio.log
/tmp/gh-aw/agent/
if-no-files-found: ignore
conclusion:
needs:
- activation
- agent
- detection
- safe_outputs
if: (always()) && (needs.agent.result != 'skipped')
runs-on: ubuntu-slim
permissions:
contents: read
discussions: write
issues: write
pull-requests: write
outputs:
noop_message: ${{ steps.noop.outputs.noop_message }}
tools_reported: ${{ steps.missing_tool.outputs.tools_reported }}
total_count: ${{ steps.missing_tool.outputs.total_count }}
steps:
- name: Setup Scripts
uses: github/gh-aw/actions/setup@5a79466d65414632d47c7869b27170ade5b9404e # v0.46.5
with:
destination: /opt/gh-aw/actions
- name: Download agent output artifact
continue-on-error: true
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with:
name: agent-output
path: /tmp/gh-aw/safeoutputs/
- name: Setup agent output environment variable
run: |
mkdir -p /tmp/gh-aw/safeoutputs/
find "/tmp/gh-aw/safeoutputs/" -type f -print
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV"
- name: Process No-Op Messages
id: noop
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_NOOP_MAX: 1
GH_AW_WORKFLOW_NAME: "Issue Triage Assistant"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/noop.cjs');
await main();
- name: Record Missing Tool
id: missing_tool
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "Issue Triage Assistant"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/missing_tool.cjs');
await main();
- name: Handle Agent Failure
id: handle_agent_failure
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "Issue Triage Assistant"
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
GH_AW_WORKFLOW_ID: "triage-incoming-issues"
GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }}
GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
GH_AW_GROUP_REPORTS: "false"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs');
await main();
- name: Handle No-Op Message
id: handle_noop_message
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "Issue Triage Assistant"
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }}
GH_AW_NOOP_REPORT_AS_ISSUE: "true"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs');
await main();
detection:
needs: agent
if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true'
runs-on: ubuntu-latest
permissions: {}
timeout-minutes: 10
outputs:
success: ${{ steps.parse_results.outputs.success }}
steps:
- name: Setup Scripts
uses: github/gh-aw/actions/setup@5a79466d65414632d47c7869b27170ade5b9404e # v0.46.5
with:
destination: /opt/gh-aw/actions
- name: Download agent artifacts
continue-on-error: true
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with:
name: agent-artifacts
path: /tmp/gh-aw/threat-detection/
- name: Download agent output artifact
continue-on-error: true
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with:
name: agent-output
path: /tmp/gh-aw/threat-detection/
- name: Print agent output types
env:
AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }}
run: |
echo "Agent output-types: $AGENT_OUTPUT_TYPES"
- name: Setup threat detection
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
WORKFLOW_NAME: "Issue Triage Assistant"
WORKFLOW_DESCRIPTION: "No description provided"
HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/setup_threat_detection.cjs');
await main();
- name: Ensure threat-detection directory and log
run: |
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- name: Validate COPILOT_GITHUB_TOKEN secret
id: validate-secret
run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
- name: Install GitHub Copilot CLI
run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.411
- name: Execute GitHub Copilot CLI
id: agentic_execution
# Copilot CLI tool arguments (sorted):
# --allow-tool shell(cat)
# --allow-tool shell(grep)
# --allow-tool shell(head)
# --allow-tool shell(jq)
# --allow-tool shell(ls)
# --allow-tool shell(tail)
# --allow-tool shell(wc)
timeout-minutes: 20
run: |
set -o pipefail
COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"
mkdir -p /tmp/
mkdir -p /tmp/gh-aw/
mkdir -p /tmp/gh-aw/agent/
mkdir -p /tmp/gh-aw/sandbox/agent/logs/
copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION"${GH_AW_MODEL_DETECTION_COPILOT:+ --model "$GH_AW_MODEL_DETECTION_COPILOT"} 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log
env:
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
GH_AW_MODEL_DETECTION_COPILOT: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }}
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GITHUB_HEAD_REF: ${{ github.head_ref }}
GITHUB_REF_NAME: ${{ github.ref_name }}
GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }}
GITHUB_WORKSPACE: ${{ github.workspace }}
XDG_CONFIG_HOME: /home/runner
- name: Parse threat detection results
id: parse_results
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/parse_threat_detection_results.cjs');
await main();
- name: Upload threat detection log
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: threat-detection.log
path: /tmp/gh-aw/threat-detection/detection.log
if-no-files-found: ignore
safe_outputs:
needs:
- agent
- detection
if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true')
runs-on: ubuntu-slim
permissions:
contents: read
discussions: write
issues: write
pull-requests: write
timeout-minutes: 15
env:
GH_AW_ENGINE_ID: "copilot"
GH_AW_WORKFLOW_ID: "triage-incoming-issues"
GH_AW_WORKFLOW_NAME: "Issue Triage Assistant"
outputs:
assign_to_user_assigned: ${{ steps.process_safe_outputs.outputs.assigned }}
create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }}
create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }}
process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }}
steps:
- name: Setup Scripts
uses: github/gh-aw/actions/setup@5a79466d65414632d47c7869b27170ade5b9404e # v0.46.5
with:
destination: /opt/gh-aw/actions
- name: Download agent output artifact
continue-on-error: true
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
with:
name: agent-output
path: /tmp/gh-aw/safeoutputs/
- name: Setup agent output environment variable
run: |
mkdir -p /tmp/gh-aw/safeoutputs/
find "/tmp/gh-aw/safeoutputs/" -type f -print
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV"
- name: Process Safe Outputs
id: process_safe_outputs
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":10},\"add_labels\":{\"allowed\":[\"bug\",\"enhancement\",\"needs-info\",\"documentation\"]},\"assign_to_user\":{\"allowed\":[\"frankbria\"],\"max\":1},\"close_issue\":{\"max\":1,\"target\":\"triggering\"},\"missing_data\":{},\"missing_tool\":{}}"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs');
setupGlobals(core, github, context, exec, io);
const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs');
await main();
- name: Upload safe output items manifest
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: safe-output-items
path: /tmp/safe-output-items.jsonl
if-no-files-found: warn
================================================
FILE: .github/workflows/triage-incoming-issues.md
================================================
---
on:
issues:
types: [opened]
workflow_dispatch:
roles: all
permissions:
contents: read
actions: read
safe-outputs:
add-labels:
allowed: [bug, enhancement, needs-info, documentation]
add-comment:
max: 10
assign-to-user:
allowed: [frankbria]
close-issue:
target: "triggering"
---
# Issue Triage Assistant
## Trigger Modes
**Issue event trigger**: When triggered by a new issue being opened, triage only that issue.
**Manual dispatch trigger**: When triggered via workflow_dispatch, fetch ALL open issues that have no labels yet (unlabeled), and triage each one. Skip issues that already have labels assigned.
## Triage Instructions
For each issue, analyze the title and description to determine its category:
1. **Bug reports**: If the issue is a true bug not already identified elsewhere, apply the label "bug" and assign it to "@frankbria".
2. **Duplicates**: If the issue is already addressed in another open issue, comment explaining which issue it duplicates and close it.
3. **Feature requests**: If the issue is a feature request or enhancement proposal, apply the label "enhancement".
4. **Support / unclear**: If the issue is a support question or too vague to categorize, comment with guidance and suggest an appropriate next step for the user.
For each issue triaged, add a comment explaining the categorization and any recommended next steps.
================================================
FILE: .gitignore
================================================
# Ralph generated files (inside .ralph/ subfolder)
.ralph/.call_count
.ralph/.last_reset
.ralph/.exit_signals
.ralph/status.json
.ralph/.ralph_session
.ralph/.ralph_session_history
.ralph/.claude_session_id
.ralph/.response_analysis
.ralph/.circuit_breaker_state
.ralph/.circuit_breaker_history
.ralph/.json_parse_result
.ralph/.last_output_length
# Ralph logs and generated docs
.ralph/logs/*
!.ralph/logs/.gitkeep
.ralph/docs/generated/*
!.ralph/docs/generated/.gitkeep
# General logs
*.log
# OS files
.DS_Store
Thumbs.db
# Temporary files
*.tmp
.temp/
# Node modules (if using Node.js projects)
node_modules/
# Python cache (if using Python projects)
__pycache__/
*.pyc
# Rust build (if using Rust projects)
target/
# IDE files
.vscode/
.idea/
*.swp
*.swo
# Claude Code local settings
.claude/settings.local.json
# Ralph backup directories (created by migration)
.ralph_backup_*
================================================
FILE: CLAUDE.md
================================================
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Overview
This is the Ralph for Claude Code repository - an autonomous AI development loop system that enables continuous development cycles with intelligent exit detection and rate limiting.
See [README.md](README.md) for version info, changelog, and user documentation.
## Core Architecture
The system consists of four main bash scripts and a modular library system:
### Main Scripts
1. **ralph_loop.sh** - The main autonomous loop that executes Claude Code repeatedly
2. **ralph_monitor.sh** - Live monitoring dashboard for tracking loop status
3. **setup.sh** - Project initialization script for new Ralph projects
4. **create_files.sh** - Bootstrap script that creates the entire Ralph system
5. **ralph_import.sh** - PRD/specification import tool that converts documents to Ralph format
- Uses modern Claude Code CLI with `--output-format json` for structured responses
- Implements `detect_response_format()` and `parse_conversion_response()` for JSON parsing
- Backward compatible with older CLI versions (automatic text fallback)
6. **ralph_enable.sh** - Interactive wizard for enabling Ralph in existing projects
- Multi-step wizard with environment detection, task source selection, configuration
- Imports tasks from beads, GitHub Issues, or PRD documents
- Generates `.ralphrc` project configuration file
7. **ralph_enable_ci.sh** - Non-interactive version for CI/automation
- Same functionality as interactive version with CLI flags
- JSON output mode for machine parsing
- Exit codes: 0 (success), 1 (error), 2 (already enabled)
### Library Components (lib/)
The system uses a modular architecture with reusable components in the `lib/` directory:
1. **lib/circuit_breaker.sh** - Circuit breaker pattern implementation
- Prevents runaway loops by detecting stagnation
- Three states: CLOSED (normal), HALF_OPEN (monitoring), OPEN (halted)
- Configurable thresholds for no-progress and error detection
- Automatic state transitions and recovery
2. **lib/response_analyzer.sh** - Intelligent response analysis
- Analyzes Claude Code output for completion signals
- **JSON output format detection and parsing** (with text fallback)
- Supports both flat JSON format and Claude CLI format (`result`, `sessionId`, `metadata`)
- Extracts structured fields: status, exit_signal, work_type, files_modified, asking_questions, question_count
- **Question detection**: `detect_questions()` with `QUESTION_PATTERNS` array — detects when Claude asks questions instead of acting autonomously (Issue #190)
- **Session management**: `store_session_id()`, `get_last_session_id()`, `should_resume_session()`
- Automatic session persistence to `.ralph/.claude_session_id` file with 24-hour expiration
- Session lifecycle: `get_session_id()`, `reset_session()`, `log_session_transition()`, `init_session_tracking()`
- Session history tracked in `.ralph/.ralph_session_history` (last 50 transitions)
- Session auto-reset on: circuit breaker open, manual interrupt, project completion
- Detects test-only loops, stuck error patterns, and question-only loops
- Two-stage error filtering to eliminate false positives
- Multi-line error matching for accurate stuck loop detection
- Confidence scoring for exit decisions
3. **lib/date_utils.sh** - Cross-platform date utilities
- ISO timestamp generation for logging
- Epoch time calculations for rate limiting
- ISO-to-epoch conversion for cooldown timer comparisons (`parse_iso_to_epoch()`)
4. **lib/timeout_utils.sh** - Cross-platform timeout command utilities
- Detects and uses appropriate timeout command for the platform
- Linux: Uses standard `timeout` from GNU coreutils
- macOS: Uses `gtimeout` from Homebrew coreutils
- `portable_timeout()` function for seamless cross-platform execution
- Automatic detection with caching for performance
5. **lib/enable_core.sh** - Shared logic for ralph enable commands
- Idempotency checks: `check_existing_ralph()`, `is_ralph_enabled()`
- Safe file operations: `safe_create_file()`, `safe_create_dir()`
- Project detection: `detect_project_context()`, `detect_git_info()`, `detect_task_sources()`
- Template generation: `generate_prompt_md()`, `generate_agent_md()`, `generate_fix_plan_md()`, `generate_ralphrc()`
6. **lib/wizard_utils.sh** - Interactive prompt utilities for enable wizard
- User prompts: `confirm()`, `prompt_text()`, `prompt_number()`
- Selection utilities: `select_option()`, `select_multiple()`, `select_with_default()`
- Output formatting: `print_header()`, `print_bullet()`, `print_success/warning/error/info()`
- POSIX-compatible: Uses `tr '[:upper:]' '[:lower:]'` instead of `${,,}` for bash 3.x support (Issue #187)
7. **lib/task_sources.sh** - Task import from external sources
- Beads integration: `check_beads_available()`, `fetch_beads_tasks()`, `get_beads_count()`
- GitHub integration: `check_github_available()`, `fetch_github_tasks()`, `get_github_issue_count()`
- PRD extraction: `extract_prd_tasks()`, supports checkbox and numbered list formats
- Task normalization: `normalize_tasks()`, `prioritize_tasks()`, `import_tasks_from_sources()`
8. **lib/file_protection.sh** - File integrity validation for Ralph projects (Issue #149)
- `RALPH_REQUIRED_PATHS` array: critical files needed for the loop to function
- `validate_ralph_integrity()`: checks all required paths exist, sets `RALPH_MISSING_FILES`
- `get_integrity_report()`: human-readable report with missing files and recovery instructions
- Lightweight validation that runs every loop iteration
## Key Commands
### Installation
```bash
# Install Ralph globally (run once)
./install.sh
# Uninstall Ralph
./install.sh uninstall
```
### Setting Up a New Project
```bash
# Create a new Ralph-managed project (run from anywhere)
ralph-setup my-project-name
cd my-project-name
```
### Migrating Existing Projects
```bash
# Migrate from flat structure to .ralph/ subfolder (v0.10.0+)
cd existing-project
ralph-migrate
```
### Enabling Ralph in Existing Projects
```bash
# Interactive wizard (recommended for humans)
cd existing-project
ralph-enable
# With specific task source
ralph-enable --from beads
ralph-enable --from github --label "sprint-1"
ralph-enable --from prd ./docs/requirements.md
# Force overwrite existing .ralph/
ralph-enable --force
# Non-interactive for CI/scripts
ralph-enable-ci # Sensible defaults
ralph-enable-ci --from github # With task source
ralph-enable-ci --project-type typescript # Override detection
ralph-enable-ci --json # Machine-readable output
```
### Running the Ralph Loop
```bash
# Start with integrated tmux monitoring (recommended)
ralph --monitor
# Start without monitoring
ralph
# With custom parameters and monitoring
ralph --monitor --calls 50 --prompt my_custom_prompt.md
# Check current status
ralph --status
# Circuit breaker management
ralph --reset-circuit
ralph --circuit-status
ralph --auto-reset-circuit # Auto-reset OPEN state on startup
# Session management
ralph --reset-session # Reset session state manually
```
### Monitoring
```bash
# Integrated tmux monitoring (recommended)
ralph --monitor
# Manual monitoring in separate terminal
ralph-monitor
# tmux session management
tmux list-sessions
tmux attach -t <session-name>
```
### Running Tests
```bash
# Run all tests
npm test
# Run specific test suites
npm run test:unit
npm run test:integration
# Run individual test files
bats tests/unit/test_cli_parsing.bats
bats tests/unit/test_json_parsing.bats
bats tests/unit/test_cli_modern.bats
bats tests/unit/test_enable_core.bats
bats tests/unit/test_task_sources.bats
bats tests/unit/test_ralph_enable.bats
bats tests/unit/test_circuit_breaker_recovery.bats
bats tests/unit/test_file_protection.bats
bats tests/unit/test_integrity_check.bats
```
## Ralph Loop Configuration
The loop is controlled by several key files and environment variables within the `.ralph/` subfolder:
- **.ralph/PROMPT.md** - Main prompt file that drives each loop iteration
- **.ralph/fix_plan.md** - Prioritized task list that Ralph follows
- **.ralph/AGENT.md** - Build and run instructions maintained by Ralph
- **.ralph/status.json** - Real-time status tracking (JSON format)
- **.ralph/logs/** - Execution logs for each loop iteration
### Rate Limiting
- Default: 100 API calls per hour (configurable via `--calls` flag)
- Automatic hourly reset with countdown display
- Call tracking persists across script restarts
### Modern CLI Configuration (Phase 1.1)
Ralph uses modern Claude Code CLI flags for structured communication:
**Configuration Variables:**
```bash
CLAUDE_CODE_CMD="claude" # Claude Code CLI command (configurable via .ralphrc, Issue #97)
CLAUDE_OUTPUT_FORMAT="json" # Output format: json (default) or text
CLAUDE_ALLOWED_TOOLS="Write,Read,Edit,Bash(git add *),Bash(git commit *),...,Bash(npm *),Bash(pytest)" # Allowed tool permissions (see File Protection)
CLAUDE_USE_CONTINUE=true # Enable session continuity
CLAUDE_MIN_VERSION="2.0.76" # Minimum Claude CLI version
CLAUDE_AUTO_UPDATE=true # Auto-update Claude CLI at startup (set false for air-gapped environments)
```
**Auto-Update Configuration:**
- `CLAUDE_AUTO_UPDATE` controls whether Ralph checks npm registry and attempts `npm update -g` at startup
- **Local workstation / home server**: Keep `true` (default) — CLI updates include bug fixes and new features that improve Ralph's effectiveness. The 200-500ms startup overhead is negligible for loops that run hours
- **Docker container**: Set `false` in `.ralphrc` — container is ephemeral and version is pinned at image build time. The npm registry query and potential update are pure overhead
- **Air-gapped environment**: Set `false` — npm registry is unreachable, the check will timeout and log a warning
- Update failure is non-blocking: Ralph logs a warning and continues the loop normally
**Claude Code CLI Command (Issue #97):**
- `CLAUDE_CODE_CMD` defaults to `"claude"` (global install)
- Configurable via `.ralphrc` for alternative installations (e.g., `"npx @anthropic-ai/claude-code"`)
- Auto-detected during `ralph-enable` and `ralph-setup` (prefers `claude` if available, falls back to npx)
- Validated at startup with `validate_claude_command()` — displays clear error with installation instructions if not found
- After validation, `check_claude_version()` verifies minimum version compatibility and `check_claude_updates()` queries npm registry for latest version with auto-update attempt (Issue #190)
- Both functions use `compare_semver()` for proper major→minor→patch sequential comparison (safe for any patch number, unlike integer arithmetic)
- Environment variable `CLAUDE_CODE_CMD` takes precedence over `.ralphrc`
**CLI Options:**
- `--output-format json|text` - Set Claude output format (default: json). Note: `--live` mode requires JSON and will auto-switch from text to json.
- `--allowed-tools "Write,Read,Bash(git *)"` - Restrict allowed tools
- `--no-continue` - Disable session continuity, start fresh each loop
**Loop Context:**
Each loop iteration injects context via `build_loop_context()`:
- Current loop number
- Remaining tasks from fix_plan.md
- Circuit breaker state (if not CLOSED)
- Previous loop work summary
- Corrective guidance if previous loop detected questions (Issue #190)
**Session Continuity:**
- Sessions are preserved in `.ralph/.claude_session_id`
- Use `--continue` flag to maintain context across loops
- Disable with `--no-continue` for isolated iterations
### Intelligent Exit Detection
The loop uses a dual-condition check to prevent premature exits during productive iterations:
**Exit requires BOTH conditions:**
1. `recent_completion_indicators >= 2` (heuristic-based detection from natural language patterns)
2. Claude's explicit `EXIT_SIGNAL: true` in the RALPH_STATUS block
The `EXIT_SIGNAL` value is read from `.ralph/.response_analysis` (at `.analysis.exit_signal`) which is populated by `response_analyzer.sh` from Claude's RALPH_STATUS output block.
**Other exit conditions (checked before completion indicators):**
- Multiple consecutive "done" signals from Claude Code (`done_signals >= 2`)
- Too many test-only loops indicating feature completeness (`test_loops >= 3`)
- All items in .ralph/fix_plan.md marked as completed
**Example behavior when EXIT_SIGNAL is false:**
```
Loop 5: Claude outputs "Phase complete, moving to next feature"
→ completion_indicators: 3 (high confidence from patterns)
→ EXIT_SIGNAL: false (Claude explicitly says more work needed)
→ Result: CONTINUE (respects Claude's explicit intent)
Loop 8: Claude outputs "All tasks complete, project ready"
→ completion_indicators: 4
→ EXIT_SIGNAL: true (Claude confirms project is done)
→ Result: EXIT with "project_complete"
```
**Rationale:** Natural language patterns like "done" or "complete" can trigger false positives during productive work (e.g., "feature done, moving to tests"). By requiring Claude's explicit EXIT_SIGNAL confirmation, Ralph avoids exiting mid-iteration when Claude is still working.
## CI/CD Pipeline
Ralph uses GitHub Actions for continuous integration:
### Workflows (`.github/workflows/`)
1. **test.yml** - Main test suite
- Runs on push to `main`/`develop` and PRs to `main`
- Executes unit, integration, and E2E tests
- Coverage reporting with kcov (informational only)
- Uploads coverage artifacts
2. **claude.yml** - Claude Code GitHub Actions integration
- Automated code review capabilities
3. **claude-code-review.yml** - PR code review workflow
- Automated review on pull requests
### Coverage Note
Bash code coverage measurement with kcov has fundamental limitations when tracing subprocess executions. The `COVERAGE_THRESHOLD` is set to 0 (disabled) because kcov cannot instrument subprocesses spawned by bats. **Test pass rate (100%) is the quality gate.** See [bats-core#15](https://github.com/bats-core/bats-core/issues/15) for details.
## Project Structure for Ralph-Managed Projects
Each project created with `./setup.sh` follows this structure with a `.ralph/` subfolder:
```
project-name/
├── .ralph/ # Ralph configuration and state (hidden folder)
│ ├── PROMPT.md # Main development instructions
│ ├── fix_plan.md # Prioritized TODO list
│ ├── AGENT.md # Build/run instructions
│ ├── specs/ # Project specifications
│ ├── examples/ # Usage examples
│ ├── logs/ # Loop execution logs
│ └── docs/generated/ # Auto-generated documentation
└── src/ # Source code (at project root)
```
> **Migration**: Existing projects can be migrated with `ralph-migrate`.
## Template System
Templates in `templates/` provide starting points for new projects:
- **PROMPT.md** - Instructions for Ralph's autonomous behavior
- **fix_plan.md** - Initial task structure
- **AGENT.md** - Build system template
## File Naming Conventions
- Ralph control files (`fix_plan.md`, `AGENT.md`, `PROMPT.md`) reside in the `.ralph/` directory
- Hidden files within `.ralph/` (e.g., `.ralph/.call_count`, `.ralph/.exit_signals`) track loop state
- `.ralph/logs/` contains timestamped execution logs
- `.ralph/docs/generated/` for Ralph-created documentation
- `docs/code-review/` for code review reports (at project root)
## Global Installation
Ralph installs to:
- **Commands**: `~/.local/bin/` (ralph, ralph-monitor, ralph-setup, ralph-import, ralph-migrate, ralph-enable, ralph-enable-ci)
- **Templates**: `~/.ralph/templates/`
- **Scripts**: `~/.ralph/` (ralph_loop.sh, ralph_monitor.sh, setup.sh, ralph_import.sh, migrate_to_ralph_folder.sh, ralph_enable.sh, ralph_enable_ci.sh)
- **Libraries**: `~/.ralph/lib/` (circuit_breaker.sh, response_analyzer.sh, date_utils.sh, timeout_utils.sh, enable_core.sh, wizard_utils.sh, task_sources.sh, file_protection.sh)
After installation, the following global commands are available:
- `ralph` - Start the autonomous development loop
- `ralph-monitor` - Launch the monitoring dashboard
- `ralph-setup` - Create a new Ralph-managed project
- `ralph-import` - Import PRD/specification documents to Ralph format
- `ralph-migrate` - Migrate existing projects from flat structure to `.ralph/` subfolder
- `ralph-enable` - Interactive wizard to enable Ralph in existing projects
- `ralph-enable-ci` - Non-interactive version for CI/automation
## Integration Points
Ralph integrates with:
- **Claude Code CLI**: Uses `npx @anthropic/claude-code` as the execution engine
- **tmux**: Terminal multiplexer for integrated monitoring sessions
- **Git**: Expects projects to be git repositories
- **jq**: For JSON processing of status and exit signals
- **GitHub Actions**: CI/CD pipeline for automated testing
- **Standard Unix tools**: bash, grep, date, etc.
## Exit Conditions and Thresholds
Ralph uses multiple mechanisms to detect when to exit:
### Exit Detection Thresholds
- `MAX_CONSECUTIVE_TEST_LOOPS=3` - Exit if too many test-only iterations
- `MAX_CONSECUTIVE_DONE_SIGNALS=2` - Exit on repeated completion signals
- `TEST_PERCENTAGE_THRESHOLD=30%` - Flag if testing dominates recent loops
- Completion detection via .ralph/fix_plan.md checklist items
### Startup State Reset (Issue #194)
Every new `ralph` invocation unconditionally resets `.exit_signals` and removes `.response_analysis` **before** the main loop begins. This prevents stale completion signals from a prior run (crash, SIGKILL, API-limit exit) from triggering `should_exit_gracefully()` on the first iteration before any Claude execution occurs. The API-limit "user chose exit" path also calls `reset_session()` to clean up state.
### Completion Indicators with EXIT_SIGNAL Gate
The `completion_indicators` exit condition requires dual verification:
| completion_indicators | EXIT_SIGNAL | .response_analysis | Result |
|-----------------------|-------------|-------------------|--------|
| >= 2 | `true` | exists | **Exit** ("project_complete") |
| >= 2 | `false` | exists | **Continue** (Claude still working) |
| >= 2 | N/A | missing | **Continue** (defaults to false) |
| >= 2 | N/A | malformed | **Continue** (defaults to false) |
| < 2 | `true` | exists | **Continue** (threshold not met) |
**Implementation** (`ralph_loop.sh:312-327`):
```bash
local claude_exit_signal="false"
if [[ -f "$RALPH_DIR/.response_analysis" ]]; then
claude_exit_signal=$(jq -r '.analysis.exit_signal // false' "$RALPH_DIR/.response_analysis" 2>/dev/null || echo "false")
fi
if [[ $recent_completion_indicators -ge 2 ]] && [[ "$claude_exit_signal" == "true" ]]; then
echo "project_complete"
return 0
fi
```
**Conflict Resolution:** When `STATUS: COMPLETE` but `EXIT_SIGNAL: false` in RALPH_STATUS, the explicit EXIT_SIGNAL takes precedence. This allows Claude to mark a phase complete while indicating more phases remain.
### Timeout Handling (Issues #175, #198)
When Claude Code exceeds `CLAUDE_TIMEOUT_MINUTES`, `portable_timeout` terminates the process with exit code **124**. The loop handles this differently depending on the execution mode:
**Live mode** (`--live`/`--monitor`): The streaming pipeline captures per-command exit codes via `PIPESTATUS`. Timeout events are logged as a WARN:
```text
[timestamp] [WARN] Claude Code execution timed out after 15 minutes
```
**Background mode** (default): The Claude process runs in a background subshell (`&`). The exit code is captured via `wait $claude_pid`.
**Productive Timeout Detection (Issue #198):**
In both modes, when exit code 124 is detected, the timeout handler checks git for actual work done during the execution (comparing HEAD to `.loop_start_sha`). This prevents treating productive timeouts as failures:
| Timeout + Git State | Result |
|---|---|
| Files changed (committed/staged/unstaged) | **Productive timeout**: runs full analysis pipeline (`save_claude_session`, `analyze_response`, `update_exit_signals`, `record_loop_result`), writes `timed_out_productive` status, returns 0 |
| No files changed | **Idle timeout**: returns 1 (generic error) |
**Session ID Fallback:** When the stream is truncated (missing `"type":"result"` message), session ID is extracted from the `"type":"system"` message, which is always written first and survives truncation.
### API Limit Detection (Issues #183, #100)
The API limit detection uses a four-layer approach to avoid false positives. In stream-json mode, output files contain echoed file content from tool results (`"type":"user"` lines). If project files mention "5-hour limit", naive grep patterns match those echoed strings, incorrectly triggering the API limit recovery flow.
**Layer 1 — Timeout guard:**
Exit code 124 (timeout) is checked first. Productive timeouts (files changed) return 0; idle timeouts return 1 (generic error). Neither returns code 2 (API limit).
**Layer 2 — Structural JSON detection (primary):**
Parses `rate_limit_event` JSON in the output for `"status":"rejected"`. This is the definitive signal from the Claude CLI.
**Layer 3 — Filtered text fallback:**
Only searches `tail -30` of the output file, filtering out `"type":"user"`, `"tool_result"`, and `"tool_use_id"` lines before matching text patterns for standard 5-hour limit messages.
**Layer 4 — Extra Usage quota (Issue #100):**
Detects Claude Code "Extra Usage" mode exhaustion (`"You're out of extra usage · resets 9pm"`). Uses the same noise filtering as Layer 3.
**Unattended mode:** When the API limit prompt times out (no user response within 30s), Ralph auto-waits instead of exiting, supporting unattended operation.
### Circuit Breaker Thresholds
- `CB_NO_PROGRESS_THRESHOLD=3` - Open circuit after 3 loops with no file changes
- `CB_SAME_ERROR_THRESHOLD=5` - Open circuit after 5 loops with repeated errors
- `CB_OUTPUT_DECLINE_THRESHOLD=70%` - Open circuit if output declines by >70%
- `CB_PERMISSION_DENIAL_THRESHOLD=2` - Open circuit after 2 loops with permission denials (Issue #101)
- **Question loop suppression** (Issue #190): When `asking_questions=true`, the `consecutive_no_progress` counter is held steady (not incremented). This prevents the circuit breaker from opening prematurely when Claude asks questions in headless mode. A corrective message is injected via `build_loop_context()` in the next loop iteration.
### Circuit Breaker Auto-Recovery (Issue #160)
The OPEN state is no longer terminal. Two recovery mechanisms are available:
**Cooldown Timer (default):** After `CB_COOLDOWN_MINUTES` (default: 30) in OPEN state, the circuit transitions to HALF_OPEN on next `init_circuit_breaker()` call. The existing HALF_OPEN logic handles recovery (progress → CLOSED) or re-trip (no progress → OPEN).
**Auto-Reset:** When `CB_AUTO_RESET=true`, the circuit resets directly to CLOSED on startup, bypassing the cooldown. Use for fully unattended operation.
**Configuration:**
```bash
CB_COOLDOWN_MINUTES=30 # Minutes before OPEN → HALF_OPEN (0 = immediate)
CB_AUTO_RESET=false # true = bypass cooldown, reset to CLOSED on startup
```
**CLI flag:** `ralph --auto-reset-circuit` sets `CB_AUTO_RESET=true` for a single run.
**State file:** The `opened_at` field tracks when the circuit entered OPEN state. Old state files without this field fall back to `last_change` for backward compatibility.
### Permission Denial Detection (Issue #101)
When Claude Code is denied permission to execute commands (e.g., `npm install`), Ralph detects this from the `permission_denials` array in the JSON output and halts the loop immediately:
1. **Detection**: The `parse_json_response()` function extracts `permission_denials` from Claude Code output
2. **Fields tracked**:
- `has_permission_denials` (boolean)
- `permission_denial_count` (integer)
- `denied_commands` (array of command strings)
3. **Exit behavior**: When `has_permission_denials=true`, Ralph exits with reason "permission_denied"
4. **User guidance**: Ralph displays instructions to update `ALLOWED_TOOLS` in `.ralphrc`
**Example `.ralphrc` tool patterns:**
```bash
# Broad patterns (recommended for development)
ALLOWED_TOOLS="Write,Read,Edit,Bash(git *),Bash(npm *),Bash(pytest)"
# Specific patterns (more restrictive)
ALLOWED_TOOLS="Write,Read,Edit,Bash(git commit),Bash(npm install)"
```
### API Error Detection via `is_error` Field (Issues #134, #199)
The Claude CLI can exit with code 0 but set `is_error: true` in the JSON output for API-level failures (400 concurrency errors, 401 OAuth token expiry). Ralph detects this before persisting any session state:
1. **Detection**: In `execute_claude_code()`, after exit code 0, `jq` reads `.is_error` from the output JSON
2. **Session protection**: If `is_error` is true, the session is NOT persisted (prevents infinite retry with bad session ID)
3. **Session reset**: The session is explicitly reset so the next loop starts fresh
4. **Specific handling**: "tool use concurrency" errors get a targeted reset reason for logging clarity
5. **Defense in depth**: `save_claude_session()` independently checks `is_error` as a guard, preventing bad sessions even if call order changes in refactors
### Error Detection
Ralph uses advanced error detection with two-stage filtering to eliminate false positives:
**Stage 1: JSON Field Filtering**
- Filters out JSON field patterns like `"is_error": false` that contain the word "error" but aren't actual errors
- Pattern: `grep -v '"[^"]*error[^"]*":'`
**Stage 2: Actual Error Detection**
- Detects real error messages in specific contexts:
- Error prefixes: `Error:`, `ERROR:`, `error:`
- Context-specific errors: `]: error`, `Link: error`
- Error occurrences: `Error occurred`, `failed with error`
- Exceptions: `Exception`, `Fatal`, `FATAL`
- Pattern: `grep -cE '(^Error:|^ERROR:|^error:|\]: error|Link: error|Error occurred|failed with error|[Ee]xception|Fatal|FATAL)'`
**Multi-line Error Matching**
- Detects stuck loops by verifying ALL error lines appear in ALL recent history files
- Uses literal fixed-string matching (`grep -qF`) to avoid regex edge cases
- Prevents false negatives when multiple distinct errors occur simultaneously
### File Protection (Issue #149)
Ralph uses a multi-layered strategy to prevent Claude from accidentally deleting its own configuration files:
**Layer 1: ALLOWED_TOOLS Restriction**
- The default `CLAUDE_ALLOWED_TOOLS` uses granular `Bash(git add *)`, `Bash(git commit *)` etc. instead of `Bash(git *)`, preventing `git clean`, `git rm`, and other destructive git commands
- Users can override in `.ralphrc` but the defaults are safe
**Layer 2: PROMPT.md Warning**
- The PROMPT.md template includes a "Protected Files (DO NOT MODIFY)" section listing `.ralph/` and `.ralphrc`
- This instructs Claude to never delete, move, rename, or overwrite these files
**Layer 3: Pre-Loop Integrity Check**
- `validate_ralph_integrity()` from `lib/file_protection.sh` runs at startup and before every loop iteration
- Checks for required paths: `.ralph/`, `.ralph/PROMPT.md`, `.ralph/fix_plan.md`, `.ralph/AGENT.md`, `.ralphrc`
- On failure: logs error, displays recovery report, resets session, and halts the loop
- Recovery: `ralph-enable --force` restores missing files
**Required vs Optional Files:**
| Required (validation fails) | Optional (no validation) |
|---|---|
| `.ralph/` directory | `.ralph/logs/` |
| `.ralph/PROMPT.md` | `.ralph/status.json` |
| `.ralph/fix_plan.md` | `.ralph/.call_count` |
| `.ralph/AGENT.md` | `.ralph/.exit_signals` |
| `.ralphrc` | `.ralph/.circuit_breaker_state` |
## Test Suite
### Test Files (584 tests total)
| File | Tests | Description |
|------|-------|-------------|
| `test_circuit_breaker_recovery.bats` | 22 | Cooldown timer, auto-reset, parse_iso_to_epoch, CLI flag (Issue #160) + current_loop init/display fix (#194) |
| `test_cli_parsing.bats` | 35 | CLI argument parsing for all flags + monitor parameter forwarding |
| `test_cli_modern.bats` | 111 | Modern CLI commands (Phase 1.1) + build_claude_command fix + live mode text format fix (#164) + errexit pipeline guard (#175) + ALLOWED_TOOLS tightening (#149) + API limit false positive detection (#183) + Claude CLI command validation (#97) + stale call counter fix (#196) + is_error detection (#134, #199) + set-e removal (#208) + question detection + version check + semver comparison + stderr separation (#190) + productive timeout detection + session ID fallback + stale analysis cleanup (#198) + Extra Usage quota detection (#100) |
| `test_json_parsing.bats` | 52 | JSON output format parsing + Claude CLI format + session management + array format + question detection (#190) |
| `test_session_continuity.bats` | 26 | Session lifecycle management + expiration + circuit breaker integration + issue #91 fix |
| `test_exit_detection.bats` | 54 | Exit signal detection + EXIT_SIGNAL-based completion indicators + progress detection + question detection integration (#190) + stale exit signal prevention (#194) |
| `test_rate_limiting.bats` | 11 | Rate limiting behavior |
| `test_loop_execution.bats` | 20 | Integration tests |
| `test_edge_cases.bats` | 25 | Edge case handling |
| `test_installation.bats` | 15 | Global installation/uninstall workflows + dotfile template copying (#174) |
| `test_project_setup.bats` | 50 | Project setup (setup.sh) validation + .ralphrc permissions + .gitignore (#174) |
| `test_prd_import.bats` | 33 | PRD import (ralph_import.sh) workflows + modern CLI tests |
| `test_enable_core.bats` | 38 | Enable core library (idempotency, project detection, template generation, .gitignore #174) |
| `test_task_sources.bats` | 23 | Task sources (beads, GitHub, PRD extraction, normalization) |
| `test_ralph_enable.bats` | 24 | Ralph enable integration tests (wizard, CI version, JSON output, .ralphrc validation #149) |
| `test_wizard_utils.bats` | 20 | Wizard utility functions (stdout/stderr separation, prompt functions) |
| `test_file_protection.bats` | 15 | File integrity validation (RALPH_REQUIRED_PATHS, validate_ralph_integrity, get_integrity_report) (Issue #149) |
| `test_integrity_check.bats` | 10 | Pre-loop integrity check in ralph_loop.sh (startup + in-loop validation) (Issue #149) |
### Running Tests
```bash
# All tests
npm test
# Unit tests only
npm run test:unit
# Specific test file
bats tests/unit/test_cli_parsing.bats
```
## Feature Development Quality Standards
**CRITICAL**: All new features MUST meet the following mandatory requirements before being considered complete.
### Testing Requirements
- **Test Pass Rate**: 100% - all tests must pass, no exceptions
- **Test Types Required**:
- Unit tests for bash script functions (if applicable)
- Integration tests for Ralph loop behavior
- End-to-end tests for full development cycles
- **Test Quality**: Tests must validate behavior, not just achieve coverage metrics
- **Test Documentation**: Complex test scenarios must include comments explaining the test strategy
> **Note on Coverage**: The 85% coverage threshold is aspirational for bash scripts. Due to kcov subprocess limitations, test pass rate is the enforced quality gate.
### E2E Testing Philosophy (v2 UI)
When Ralph introduces a web-based UI (v2), end-to-end testing is the primary quality gate for all frontend work:
- **Framework**: Playwright for all browser automation and E2E tests
- **Real services only**: E2E tests run against real backends — no mocked APIs or stubbed services
- **User journey coverage**: Every user-facing workflow must have at least one E2E test covering the happy path
- **Visual regression**: Use Playwright screenshot comparisons for layout-critical components
- **Accessibility**: Include automated a11y checks (e.g., `@axe-core/playwright`) in E2E runs
- **CI integration**: E2E tests must pass in the GitHub Actions pipeline before merge
### Git Workflow Requirements
Before moving to the next feature, ALL changes must be:
1. **Committed with Clear Messages**:
```bash
git add .
git commit -m "feat(module): descriptive message following conventional commits"
```
- Use conventional commit format: `feat:`, `fix:`, `docs:`, `test:`, `refactor:`, etc.
- Include scope when applicable: `feat(loop):`, `fix(monitor):`, `test(setup):`
- Write descriptive messages that explain WHAT changed and WHY
2. **Pushed to Remote Repository**:
```bash
git push origin <branch-name>
```
- Never leave completed features uncommitted
- Push regularly to maintain backup and enable collaboration
- Ensure CI/CD pipelines pass before considering feature complete
3. **Branch Hygiene**:
- Work on feature branches, never directly on `main`
- Branch naming convention: `feature/<feature-name>`, `fix/<issue-name>`, `docs/<doc-update>`
- Create pull requests for all significant changes
4. **Ralph Integration**:
- Update .ralph/fix_plan.md with new tasks before starting work
- Mark items complete in .ralph/fix_plan.md upon completion
- Update .ralph/PROMPT.md if Ralph's behavior needs modification
- Test Ralph loop with new features before completion
### Documentation Requirements
**ALL implementation documentation MUST remain synchronized with the codebase**:
1. **Script Documentation**:
- Bash: Comments for all functions and complex logic
- Update inline comments when implementation changes
- Remove outdated comments immediately
2. **Implementation Documentation**:
- Update relevant sections in this CLAUDE.md file
- Keep template files in `templates/` current
- Update configuration examples when defaults change
- Document breaking changes prominently
3. **README Updates**:
- Keep feature lists current
- Update setup instructions when commands change
- Maintain accurate command examples
- Update version compatibility information
4. **Template Maintenance**:
- Update template files when new patterns are introduced
- Keep PROMPT.md template current with best practices
- Update AGENT.md template with new build patterns
- Document new Ralph configuration options
5. **CLAUDE.md Maintenance**:
- Add new commands to "Key Commands" section
- Update "Exit Conditions and Thresholds" when logic changes
- Keep installation instructions accurate and tested
- Document new Ralph loop behaviors or quality gates
### Feature Completion Checklist
Before marking ANY feature as complete, verify:
- [ ] All tests pass (if applicable)
- [ ] Script functionality manually tested
- [ ] All changes committed with conventional commit messages
- [ ] All commits pushed to remote repository
- [ ] CI/CD pipeline passes
- [ ] .ralph/fix_plan.md task marked as complete
- [ ] Implementation documentation updated
- [ ] Inline code comments updated or added
- [ ] CLAUDE.md updated (if new patterns introduced)
- [ ] Template files updated (if applicable)
- [ ] Breaking changes documented
- [ ] Ralph loop tested with new features
- [ ] Installation process verified (if applicable)
### Rationale
These standards ensure:
- **Quality**: Thorough testing prevents regressions in Ralph's autonomous behavior
- **Traceability**: Git commits and fix_plan.md provide clear history of changes
- **Maintainability**: Current documentation reduces onboarding time and prevents knowledge loss
- **Collaboration**: Pushed changes enable team visibility and code review
- **Reliability**: Consistent quality gates maintain Ralph loop stability
- **Automation**: Ralph integration ensures continuous development practices
**Enforcement**: AI agents should automatically apply these standards to all feature development tasks without requiring explicit instruction for each task.
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Ralph for Claude Code
Thank you for your interest in contributing to Ralph! This guide will help you get started and ensure your contributions follow our established patterns and quality standards.
**Every contribution matters** - from fixing typos to implementing major features. We appreciate your help in making Ralph better!
## Table of Contents
1. [Getting Started](#getting-started)
2. [Development Workflow](#development-workflow)
3. [Code Style Guidelines](#code-style-guidelines)
4. [Testing Requirements](#testing-requirements)
5. [Pull Request Process](#pull-request-process)
6. [Code Review Guidelines](#code-review-guidelines)
7. [Quality Standards](#quality-standards)
8. [Community Guidelines](#community-guidelines)
---
## Getting Started
### Prerequisites
Before contributing, ensure you have the following installed:
- **Bash 4.0+** - For script execution
- **jq** - JSON processing (required)
- **git** - Version control (required)
- **tmux** - Terminal multiplexer (recommended)
- **Node.js 18+** - For running tests via npm
### Clone the Repository
```bash
# Fork the repository on GitHub first, then clone your fork
git clone https://github.com/YOUR_USERNAME/ralph-claude-code.git
cd ralph-claude-code
```
### Install Dependencies
```bash
# Install BATS testing framework and dependencies
npm install
# Verify BATS is available
./node_modules/.bin/bats --version
# Optional: Install Ralph globally for testing
./install.sh
```
### Verify Your Setup
```bash
# Run the test suite to ensure everything works
npm test
# You should see output like:
# ✓ 276 tests passed (100% pass rate)
```
### Project Structure
```
ralph-claude-code/
├── ralph_loop.sh # Main loop script
├── ralph_monitor.sh # Live monitoring dashboard
├── setup.sh # Project initialization
├── ralph_import.sh # PRD import tool
├── install.sh # Global installation script
├── lib/ # Modular library components
│ ├── circuit_breaker.sh
│ ├── response_analyzer.sh
│ └── date_utils.sh
├── templates/ # Project templates
├── tests/ # Test suite
│ ├── unit/ # Unit tests
│ ├── integration/ # Integration tests
│ ├── e2e/ # End-to-end tests
│ └── helpers/ # Test utilities
└── docs/ # Documentation
```
---
## Development Workflow
### Branch Naming Conventions
Always create a feature branch - never work directly on `main`:
| Branch Type | Format | Example |
|-------------|--------|---------|
| New features | `feature/<feature-name>` | `feature/log-rotation` |
| Bug fixes | `fix/<issue-name>` | `fix/rate-limit-reset` |
| Documentation | `docs/<doc-update>` | `docs/api-reference` |
| Tests | `test/<test-area>` | `test/circuit-breaker` |
| Refactoring | `refactor/<area>` | `refactor/response-analyzer` |
```bash
# Create a new feature branch
git checkout -b feature/my-awesome-feature
```
### Commit Message Format
We use [Conventional Commits](https://www.conventionalcommits.org/) for clear, structured commit history:
```
<type>(<scope>): <description>
[optional body]
[optional footer]
```
**Types:**
| Type | Description | Example |
|------|-------------|---------|
| `feat` | New feature | `feat(loop): add dry-run mode` |
| `fix` | Bug fix | `fix(monitor): correct refresh rate` |
| `docs` | Documentation only | `docs(readme): update installation steps` |
| `test` | Adding/updating tests | `test(setup): add template validation tests` |
| `refactor` | Code change (no features/fixes) | `refactor(analyzer): simplify error detection` |
| `chore` | Maintenance tasks | `chore(deps): update bats-assert` |
**Examples from Recent Commits:**
```bash
# Feature addition
feat(import): add JSON output format support
# Bug fix with scope
fix(loop): replace non-existent --prompt-file with -p flag
# Documentation update
docs(status): update IMPLEMENTATION_STATUS.md with phased structure
# Test addition
test(cli): add 27 comprehensive CLI parsing tests
```
**Writing Good Commit Messages:**
- Use imperative mood ("add" not "added")
- Explain WHAT changed and WHY (not HOW)
- Keep the subject line under 72 characters
- Reference issues when applicable (`fixes #123`)
### Workflow Diagram
```
┌─────────────────────────────────────────────────────────────────────┐
│ Contribution Workflow │
└─────────────────────────────────────────────────────────────────────┘
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 1. Fork │────>│ 2. Clone │────>│ 3. Branch│────>│ 4. Code │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│
v
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 8. Merge │<────│ 7. PR │<────│ 6. Push │<────│ 5. Test │
└──────────┘ │ Approved │ └──────────┘ │ (100%) │
└──────────┘ └──────────┘
^
│
┌──────────┐
│ CI/CD │
│ Passes │
└──────────┘
```
---
## Code Style Guidelines
### Bash Best Practices
Ralph follows consistent bash conventions across all scripts:
**File Structure:**
```bash
#!/bin/bash
# Script description
# Purpose and usage notes
# Source dependencies
source "$(dirname "${BASH_SOURCE[0]}")/lib/date_utils.sh"
# Configuration constants (UPPER_CASE)
MAX_CALLS_PER_HOUR=100
CB_NO_PROGRESS_THRESHOLD=3
STATUS_FILE="status.json"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Helper functions (snake_case)
helper_function() {
local param1=$1
local param2=$2
# Implementation
}
# Main logic
main() {
# Entry point
}
# Export functions for reuse
export -f helper_function
# Execute main if run directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
```
**Naming Conventions:**
| Element | Convention | Example |
|---------|------------|---------|
| Functions | snake_case | `get_circuit_state()` |
| Local variables | snake_case | `local loop_count=0` |
| Constants | UPPER_SNAKE_CASE | `MAX_CALLS_PER_HOUR` |
| File names | snake_case.sh | `circuit_breaker.sh` |
| Control files | snake_case.md | `fix_plan.md`, `AGENT.md` |
**Function Documentation:**
```bash
# Get current circuit breaker state
# Returns the state as a string: CLOSED, HALF_OPEN, or OPEN
# Falls back to CLOSED if state file doesn't exist
get_circuit_state() {
if [[ ! -f "$CB_STATE_FILE" ]]; then
echo "$CB_STATE_CLOSED"
return
fi
jq -r '.state' "$CB_STATE_FILE" 2>/dev/null || echo "$CB_STATE_CLOSED"
}
```
**Error Handling:**
```bash
# Always validate inputs
if [[ -z "$1" ]]; then
echo -e "${RED}Error: Missing required argument${NC}" >&2
exit 1
fi
# Use proper exit codes
# 0 = success, 1 = general error, 2 = invalid usage
```
**Cross-Platform Compatibility:**
```bash
# Use portable date commands
if command -v gdate &> /dev/null; then
DATE_CMD="gdate" # macOS with coreutils
else
DATE_CMD="date" # Linux
fi
```
**JSON State Management:**
```bash
# Always validate JSON before parsing
if ! jq '.' "$STATE_FILE" > /dev/null 2>&1; then
echo "Error: Invalid JSON in state file"
return 1
fi
# Use jq for safe parsing
local state=$(jq -r '.state' "$STATE_FILE" 2>/dev/null || echo "CLOSED")
```
---
## Testing Requirements
### Mandatory Testing Standards
**All new features must include tests. This is non-negotiable.**
| Requirement | Standard | Enforcement |
|-------------|----------|-------------|
| Test Pass Rate | 100% | **Mandatory** - CI blocks merge |
| Test Coverage | 85% | Aspirational - informational only |
> **Note on Coverage:** Bash code coverage with kcov cannot trace subprocess executions. Test pass rate is the enforced quality gate, not coverage percentage.
### Test Organization
```
tests/
├── unit/ # Fast, isolated tests
│ ├── test_cli_parsing.bats # CLI argument tests
│ ├── test_json_parsing.bats # JSON output parsing
│ ├── test_exit_detection.bats
│ ├── test_rate_limiting.bats
│ ├── test_session_continuity.bats
│ └── test_cli_modern.bats
├── integration/ # Multi-component tests
│ ├── test_loop_execution.bats
│ ├── test_edge_cases.bats
│ ├── test_installation.bats
│ ├── test_project_setup.bats
│ └── test_prd_import.bats
├── e2e/ # End-to-end workflows
└── helpers/
└── test_helper.bash # Shared test utilities
```
### Running Tests
| Command | Purpose | When to Use |
|---------|---------|-------------|
| `npm test` | Run all tests | Before committing, before PR |
| `npm run test:unit` | Unit tests only | During development |
| `npm run test:integration` | Integration tests only | Testing interactions |
| `bats tests/unit/test_file.bats` | Single test file | Debugging specific tests |
### Writing Tests
**Test Structure:**
```bash
#!/usr/bin/env bats
# Unit Tests for Feature X
load '../helpers/test_helper'
# Setup runs before each test
setup() {
source "$(dirname "$BATS_TEST_FILENAME")/../helpers/test_helper.bash"
# Create isolated test environment
export TEST_TEMP_DIR="$(mktemp -d /tmp/ralph-test.XXXXXX)"
cd "$TEST_TEMP_DIR"
# Initialize test state
echo "0" > ".call_count"
}
# Teardown runs after each test
teardown() {
cd /
rm -rf "$TEST_TEMP_DIR"
}
# Test: Descriptive name explaining what's being tested
@test "can_make_call returns success when under limit" {
echo "50" > ".call_count"
export MAX_CALLS_PER_HOUR=100
run can_make_call
assert_success
}
# Test: Failure case
@test "can_make_call returns failure when at limit" {
echo "100" > ".call_count"
export MAX_CALLS_PER_HOUR=100
run can_make_call
assert_failure
}
```
**Test Best Practices:**
1. **Test both success and failure cases**
2. **Use descriptive test names** that explain the scenario
3. **Isolate tests** - each test should be independent
4. **Mock external dependencies** (Claude CLI, tmux, etc.)
5. **Test edge cases** (empty files, invalid input, boundary values)
6. **Add comments** for complex test scenarios
**Available Test Helpers:**
```bash
# From tests/helpers/test_helper.bash
assert_success # Check command succeeded (exit 0)
assert_failure # Check command failed (exit != 0)
assert_equal # Compare two values
assert_output # Check command output
assert_file_exists # Verify file exists
assert_dir_exists # Verify directory exists
strip_colors # Remove ANSI color codes
create_mock_prompt # Create test PROMPT.md
create_mock_fix_plan # Create test fix_plan.md
create_mock_status # Create test status.json
```
---
## Pull Request Process
### Before Creating a PR
Run through this checklist:
- [ ] All tests pass locally (`npm test`)
- [ ] New code includes appropriate tests
- [ ] Commits follow conventional format
- [ ] Documentation updated if needed
- [ ] No debug code or console.log statements
- [ ] No secrets or credentials committed
### Creating the PR
1. **Push your branch:**
```bash
git push origin feature/my-feature
```
2. **Open a Pull Request** on GitHub with:
**PR Title:** Follow conventional commit format
```
feat(loop): add dry-run mode for testing
```
**PR Description Template:**
```markdown
## Summary
Brief description of what this PR does (1-3 bullet points).
- Adds dry-run mode to preview loop execution
- Includes new CLI flag `--dry-run`
- Logs actions without making actual changes
## Test Plan
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing completed
## Related Issues
Fixes #123
Related to #456
## Screenshots (if applicable)
[Add screenshots for UI/output changes]
## Breaking Changes
[List any breaking changes, or "None"]
```
### After PR Creation
1. **Wait for CI/CD** - GitHub Actions will run all tests
2. **Address review feedback** - Make requested changes promptly
3. **Keep PR updated** - Rebase if main branch has changed
---
## Code Review Guidelines
### For Contributors
**Responding to Feedback:**
- Thank reviewers for their time
- Ask questions if requirements are unclear
- Make requested changes promptly
- Update PR description as changes evolve
- Don't take feedback personally - it's about the code
**If You Disagree:**
- Explain your reasoning clearly
- Provide context for your decisions
- Be open to alternative approaches
- Defer to maintainer judgment when in doubt
### For Reviewers
**What to Check:**
| Area | Questions to Ask |
|------|------------------|
| **Correctness** | Does the code do what it claims? |
| **Tests** | Are tests comprehensive? Do they pass? |
| **Style** | Does it follow bash conventions? |
| **Documentation** | Are comments and docs updated? |
| **Breaking Changes** | Will this affect existing users? |
| **Performance** | Any obvious performance issues? |
**Review Best Practices:**
1. **Be constructive** - Focus on improvements, not criticism
2. **Be specific** - Point to exact lines when possible
3. **Explain why** - Help contributors learn
4. **Acknowledge good work** - Note well-written code
5. **Approve when ready** - Don't hold PRs hostage
---
## Quality Standards
### Quality Gates
All PRs must pass these automated checks:
| Gate | Requirement | Enforcement |
|------|-------------|-------------|
| Unit Tests | 100% pass | **Blocks merge** |
| Integration Tests | 100% pass | **Blocks merge** |
| Coverage | 85% | Informational only |
| Conventional Commits | Required | Manual review |
| Documentation | Updated | Manual review |
### Documentation Standards
**When to Update Documentation:**
- Adding new CLI flags → Update README.md, CLAUDE.md
- Adding new features → Update README.md "Features" section
- Changing behavior → Update relevant docs
- Adding new patterns → Update CLAUDE.md
**Keep in Sync:**
1. **CLAUDE.md** - Technical specifications, quality standards
2. **README.md** - User-facing documentation, installation
3. **Templates** - Keep template files current
4. **Inline comments** - Update when code changes
### Feature Completion Checklist
Before marking any feature complete:
- [ ] All tests pass (100% pass rate)
- [ ] Script functionality manually tested
- [ ] Commits follow conventional format
- [ ] All commits pushed to remote
- [ ] CI/CD pipeline passes
- [ ] CLAUDE.md updated (if new patterns)
- [ ] README.md updated (if user-facing)
- [ ] Breaking changes documented
- [ ] Installation verified (if applicable)
---
## Community Guidelines
### Priority Contribution Areas
**High Priority - Help Needed!**
1. **Test Implementation** - Expand test coverage
- See [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) for specifications
2. **Feature Development**
- Log rotation functionality
- Dry-run mode
- Config file support (.ralphrc)
- Metrics tracking
- Desktop notifications
- Backup/rollback system
3. **Documentation**
- Usage tutorials and examples
- Troubleshooting guides
- Video walkthroughs
4. **Real-World Testing**
- Use Ralph on your projects
- Report bugs and edge cases
- Share your experience
### Communication
**Before Major Changes:**
- Open an issue for discussion
- Check existing issues for planned work
- Join discussions on pull requests
**Getting Help:**
- Review documentation first (README.md, CLAUDE.md)
- Check [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) for roadmap
- Open issues for questions
- Reference related issues in discussions
### Code of Conduct
- Be respectful and professional
- Welcome newcomers and help them succeed
- Focus on constructive feedback
- Assume good intentions
- Celebrate diverse perspectives
### Recognition
- All contributors acknowledged in release notes
- Significant contributions noted in README
- Active contributors may become maintainers
---
## Additional Resources
- [README.md](README.md) - Project overview and quick start
- [CLAUDE.md](CLAUDE.md) - Technical specifications
- [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) - Development roadmap
- [IMPLEMENTATION_STATUS.md](IMPLEMENTATION_STATUS.md) - Progress tracking
- [GitHub Issues](https://github.com/frankbria/ralph-claude-code/issues) - Bug reports and feature requests
---
**Thank you for contributing to Ralph!** Your efforts help make autonomous AI development more accessible to everyone.
================================================
FILE: IMPLEMENTATION_PLAN.md
================================================
# Ralph for Claude Code - Implementation Plan
**Version**: v0.9.8 | **Tests**: 276 passing (100% pass rate) | **CI/CD**: GitHub Actions
---
## Current Phase
### Phase 1: CLI Modernization (In Progress)
Phase 1 focuses on modernizing Ralph's CLI integration with Claude Code, including JSON output parsing, session management, and documentation.
**Status**: Core features complete (1.1-1.4), remaining items are documentation and bug fixes.
| Issue | Title | Priority | Status |
|-------|-------|----------|--------|
| #51 | Phase 1.5: Implement session expiration for .claude_session_id | P2 | Open |
| #24 | Phase 1.9: Create TESTING.md documentation | P3 | Open |
| #25 | Phase 1.10: Create CONTRIBUTING.md guide | P3 | Open |
| #26 | Phase 1.11: Update README with testing instructions | P3 | Open |
| #27 | Phase 1.12: Add badges to README | P3 | Open |
**Completed Phase 1 Issues**: #28 (CLI commands), #29 (JSON parsing), #30 (session management), #31 (ralph-import), #48 (security), #50 (input validation)
---
## Planned Development
### Phase 2: Agent SDK Integration (P2)
Migrate from CLI-only execution to a hybrid CLI/SDK architecture using Claude's Agent SDK.
| Issue | Title | Priority | Status |
|-------|-------|----------|--------|
| #32 | Phase 2.1: Create Agent SDK proof of concept | P2 | Open |
| #33 | Phase 2.2: Define custom tools for Agent SDK | P2 | Open |
| #34 | Phase 2.3: Implement hybrid CLI/SDK architecture | P2 | Open |
| #35 | Phase 2.4: Document SDK migration strategy | P2 | Open |
---
### Phase 3: Configuration & Infrastructure (P2-P3)
Add configuration file support, infrastructure features, and advanced functionality.
| Issue | Title | Priority | Status |
|-------|-------|----------|--------|
| #36 | Phase 3.1: Add JSON configuration file support | P2 | Open |
| #37 | Phase 3.2: Update installation for SDK support | P2 | Open |
| #18 | Phase 3.4: Implement log rotation feature | P2 | Open |
| #19 | Phase 3.5: Implement dry-run mode feature | P2 | Open |
| #20 | Phase 3.6: Implement config file support (.ralphrc) | P2 | Open |
| #38 | Phase 3.3: Create CLI and SDK documentation | P3 | Open |
| #21 | Phase 3.7: Implement metrics and analytics | P3 | Open |
| #22 | Phase 3.8: Implement notification system | P3 | Open |
| #23 | Phase 3.9: Implement backup and rollback system | P3 | Open |
---
### Phase 4: Validation Testing (P2-P3)
Comprehensive testing for all new features and integration scenarios.
| Issue | Title | Priority | Status |
|-------|-------|----------|--------|
| #14 | Phase 4.4: Implement tmux integration tests | P2 | Open |
| #15 | Phase 4.5: Implement monitor dashboard tests | P2 | Open |
| #16 | Phase 4.6: Implement status update tests | P2 | Open |
| #39 | Phase 4.1: Implement CLI enhancement tests | P3 | Open |
| #40 | Phase 4.2: Implement SDK integration tests | P3 | Open |
| #41 | Phase 4.3: Implement backward compatibility tests | P3 | Open |
| #17 | Phase 4.7: Implement E2E full loop tests | P3 | Open |
---
### Phase 5: GitHub Issue Integration (P4)
Enable Ralph to import development plans directly from GitHub issues.
| Issue | Title | Priority | Status |
|-------|-------|----------|--------|
| #69 | Phase 5.1: Allow plan import from GitHub Issue | P4 | Open |
| #70 | Phase 5.2: Assess issue completeness and generate implementation plan | P4 | Open |
| #71 | Phase 5.3: Filter and select GitHub issues by metadata | P4 | Open |
| #72 | Phase 5.4: Batch processing and issue queue management | P4 | Open |
| #73 | Phase 5.5: Issue lifecycle management and completion workflows | P4 | Open |
**Summary**: Import single issues (#69), generate plans for incomplete issues (#70), filter by labels/assignees (#71), process multiple issues (#72), and manage issue lifecycle (#73).
---
### Phase 6: Sandbox Execution Environments (P4)
Run Ralph in isolated sandbox environments for security and reproducibility.
| Issue | Title | Priority | Status |
|-------|-------|----------|--------|
| #49 | Phase 6.0: Sandbox execution environments (umbrella) | P4 | Open |
| #74 | Phase 6.1: Local Docker Sandbox Execution | P4 | Open |
| #75 | Phase 6.2: E2B Cloud Sandbox Integration | P4 | Open |
| #76 | Phase 6.3: Sandbox File Synchronization | P4 | Open |
| #77 | Phase 6.4: Sandbox Security and Resource Policies | P4 | Open |
| #78 | Phase 6.5: Generic Sandbox Interface and Plugin Architecture | P4 | Open |
| #79 | Phase 6.6: Daytona Sandbox Integration | P4 | Open |
| #80 | Phase 6.7: Cloudflare Sandbox Integration | P4 | Open |
**First-class providers**: Docker (local), E2B, Daytona, Cloudflare
**Plugin-based** (via Phase 6.5): Gitpod, Codespaces, Modal, Replit, etc.
---
## Priority Legend
| Priority | Description | Target |
|----------|-------------|--------|
| **P0** | Critical - Foundation/Blocking | Immediate |
| **P1** | High - Core features | Near-term |
| **P2** | Medium - Important enhancements | Mid-term |
| **P3** | Low - Nice to have | When available |
| **P4** | Enhancements - New functionality | Future |
---
## Implementation Order
**Recommended sequence**:
1. **Phase 1 Completion** (P2-P3): Finish documentation and bug fixes
2. **Phase 3 Core** (P2): Log rotation, dry-run, config file support
3. **Phase 4 Testing** (P2): tmux, monitor, status tests
4. **Phase 2 SDK** (P2): Agent SDK integration (can run parallel with Phase 3)
5. **Phase 3 Advanced** (P3): Metrics, notifications, backup
6. **Phase 4 Validation** (P3): CLI, SDK, backward compatibility tests
7. **Phase 5 GitHub** (P4): GitHub issue integration
8. **Phase 6 Sandbox** (P4): Sandbox execution environments
---
## Test Coverage
**Current**: 276 tests across 11 test files (100% pass rate)
| Category | Tests | Files |
|----------|-------|-------|
| CLI Parsing | 27 | test_cli_parsing.bats |
| CLI Modern | 29 | test_cli_modern.bats |
| JSON Parsing | 36 | test_json_parsing.bats |
| Session Continuity | 26 | test_session_continuity.bats |
| Exit Detection | 20 | test_exit_detection.bats |
| Rate Limiting | 15 | test_rate_limiting.bats |
| Loop Execution | 20 | test_loop_execution.bats |
| Edge Cases | 20 | test_edge_cases.bats |
| Installation | 14 | test_installation.bats |
| Project Setup | 36 | test_project_setup.bats |
| PRD Import | 33 | test_prd_import.bats |
---
## Completed Development
<details>
<summary>Click to expand completed work</summary>
### Phase 1: CLI Modernization (Completed Issues)
| Issue | Title | Status |
|-------|-------|--------|
| #28 | Phase 1.1: Update CLI commands with modern options | Closed |
| #29 | Phase 1.2: Enhance response parsing for JSON output | Closed |
| #30 | Phase 1.3: Add session management for continuity | Closed |
| #31 | Phase 1.4: Update ralph-import with CLI enhancements | Closed |
| #48 | MAJOR-01: Enhance shell escaping to prevent command injection | Closed |
| #50 | MAJOR-02: Add input validation for --allowed-tools flag | Closed |
### Testing Issues (Completed)
| Issue | Title | Status |
|-------|-------|--------|
| #10 | Implement CLI parsing tests | Closed |
| #11 | Implement installation tests | Closed |
| #12 | Implement project setup tests | Closed |
| #13 | Implement PRD import tests | Closed |
### Bug Fixes (Completed)
| Issue | Title | Status |
|-------|-------|--------|
| #1 | Cannot find file ~/.ralph/lib/response_analyzer.sh | Closed |
| #2 | is_error: false triggers "error" circuit breaker incorrectly | Closed |
| #5 | Bug: date: illegal option -- d on macOS | Closed |
| #7 | Review codebase for updated Anthropic CLI | Closed |
| #42 | Windows: Git Bash windows spawn when running Ralph loop | Closed |
| #55 | --prompt-file flag does not exist in Claude Code CLI | Closed |
### Other Completed
| Issue | Title | Status |
|-------|-------|--------|
| #56 | Project featured in Awesome Claude Code! | Closed |
| #63 | Fix IMPLEMENTATION_PLAN | Closed |
</details>
---
## Version History
| Version | Key Changes |
|---------|-------------|
| v0.9.8 | Modern CLI for PRD import with JSON output |
| v0.9.7 | Session lifecycle management with auto-reset |
| v0.9.6 | JSON output and session management |
| v0.9.5 | PRD import tests (22 tests) |
| v0.9.4 | Project setup tests (36 tests) |
| v0.9.3 | Installation tests (14 tests) |
| v0.9.2 | Prompt file fix (-p flag) |
| v0.9.1 | Modern CLI commands (Phase 1.1) |
| v0.9.0 | Circuit breaker enhancements |
---
**Last Updated**: 2026-01-10
**Status**: Phase 1 in progress, Phases 2-6 planned
================================================
FILE: IMPLEMENTATION_STATUS.md
================================================
# Implementation Status Summary
**Last Updated**: 2026-01-10
**Version**: v0.9.8
**Overall Status**: Phase 1 in progress (core complete, documentation remaining)
---
## Current State
### Test Coverage
| Metric | Current | Target |
|--------|---------|--------|
| **Total Tests** | 276 | 300+ |
| **Pass Rate** | 100% | 100% |
| **Unit Tests** | 154 | 160+ |
| **Integration Tests** | 122 | 140+ |
| **E2E Tests** | 0 | 10+ |
### Test Files (11 files, 276 tests)
| File | Tests | Status |
|------|-------|--------|
| test_cli_parsing.bats | 27 | ✅ Complete |
| test_cli_modern.bats | 29 | ✅ Complete |
| test_json_parsing.bats | 36 | ✅ Complete |
| test_session_continuity.bats | 26 | ✅ Complete |
| test_exit_detection.bats | 20 | ✅ Complete |
| test_rate_limiting.bats | 15 | ✅ Complete |
| test_loop_execution.bats | 20 | ✅ Complete |
| test_edge_cases.bats | 20 | ✅ Complete |
| test_installation.bats | 14 | ✅ Complete |
| test_project_setup.bats | 36 | ✅ Complete |
| test_prd_import.bats | 33 | ✅ Complete |
### Code Quality
- **CI/CD**: ✅ GitHub Actions operational
- **Response Analyzer**: ✅ lib/response_analyzer.sh (JSON parsing, session management)
- **Circuit Breaker**: ✅ lib/circuit_breaker.sh (three-state pattern)
- **Date Utilities**: ✅ lib/date_utils.sh (cross-platform)
- **Test Helpers**: ✅ Complete infrastructure
---
## Phase Status
### Phase 1: CLI Modernization (80% Complete)
**Completed**:
- [x] #28 - Update CLI commands with modern options
- [x] #29 - Enhance response parsing for JSON output
- [x] #30 - Add session management for continuity
- [x] #31 - Update ralph-import with CLI enhancements
- [x] #48 - Shell escaping security fix
- [x] #50 - Input validation for --allowed-tools
- [x] #10 - CLI parsing tests (27 tests)
- [x] #11 - Installation tests (14 tests)
- [x] #12 - Project setup tests (36 tests)
- [x] #13 - PRD import tests (33 tests)
- [x] #25 - Create CONTRIBUTING.md guide (P3)
- [x] #24 - Create TESTING.md documentation (P3)
- [x] #26 - Update README with testing instructions (P3)
- [x] #27 - Add badges to README (P3)
**Remaining**:
- [ ] #51 - Session expiration for .claude_session_id (P2)
### Phase 2: Agent SDK Integration (0% Complete)
- [ ] #32 - Create Agent SDK proof of concept (P2)
- [ ] #33 - Define custom tools for Agent SDK (P2)
- [ ] #34 - Implement hybrid CLI/SDK architecture (P2)
- [ ] #35 - Document SDK migration strategy (P2)
### Phase 3: Configuration & Infrastructure (0% Complete)
- [ ] #36 - Add JSON configuration file support (P2)
- [ ] #37 - Update installation for SDK support (P2)
- [ ] #18 - Implement log rotation feature (P2)
- [ ] #19 - Implement dry-run mode feature (P2)
- [ ] #20 - Implement config file support (.ralphrc) (P2)
- [ ] #38 - Create CLI and SDK documentation (P3)
- [ ] #21 - Implement metrics and analytics (P3)
- [ ] #22 - Implement notification system (P3)
- [ ] #23 - Implement backup and rollback system (P3)
### Phase 4: Validation Testing (0% Complete)
- [ ] #14 - Implement tmux integration tests (P2)
- [ ] #15 - Implement monitor dashboard tests (P2)
- [ ] #16 - Implement status update tests (P2)
- [ ] #39 - Implement CLI enhancement tests (P3)
- [ ] #40 - Implement SDK integration tests (P3)
- [ ] #41 - Implement backward compatibility tests (P3)
- [ ] #17 - Implement E2E full loop tests (P3)
### Phase 5: GitHub Issue Integration (0% Complete)
- [ ] #69 - Allow plan import from GitHub Issue (P4)
- [ ] #70 - Assess issue completeness and generate implementation plan (P4)
- [ ] #71 - Filter and select GitHub issues by metadata (P4)
- [ ] #72 - Batch processing and issue queue management (P4)
- [ ] #73 - Issue lifecycle management and completion workflows (P4)
### Phase 6: Sandbox Execution Environments (0% Complete)
- [ ] #49 - Sandbox execution environments (umbrella) (P4)
- [ ] #74 - Local Docker Sandbox Execution (P4)
- [ ] #75 - E2B Cloud Sandbox Integration (P4)
- [ ] #76 - Sandbox File Synchronization (P4)
- [ ] #77 - Sandbox Security and Resource Policies (P4)
- [ ] #78 - Generic Sandbox Interface and Plugin Architecture (P4)
- [ ] #79 - Daytona Sandbox Integration (P4)
- [ ] #80 - Cloudflare Sandbox Integration (P4)
---
## Recent Completions
### v0.9.8 (2026-01-10)
- Modern CLI for PRD import with JSON output
- 11 new tests for modern CLI features
- Test count: 265 → 276
### v0.9.7
- Session lifecycle management with auto-reset triggers
- 26 new tests for session continuity
- Test count: 239 → 265
### v0.9.6
- JSON output and session management
- 16 new tests for Claude CLI format
- Test count: 223 → 239
### v0.9.5
- PRD import tests (22 tests)
- Test count: 201 → 223
### v0.9.4
- Project setup tests (36 tests)
- Test count: 165 → 201
### v0.9.3
- Installation tests (14 tests)
- Test count: 151 → 165
### v0.9.2
- Prompt file fix (-p flag)
- 6 new tests for build_claude_command
- Test count: 145 → 151
### v0.9.1
- Modern CLI commands (Phase 1.1)
- 70 new tests (JSON, CLI modern, CLI parsing)
- CI/CD pipeline operational
### v0.9.0
- Circuit breaker enhancements
- Two-stage error filtering
- Multi-line error matching
---
## Closed Issues
<details>
<summary>Click to expand (20 closed issues)</summary>
| Issue | Title |
|-------|-------|
| #1 | Cannot find file ~/.ralph/lib/response_analyzer.sh |
| #2 | is_error: false triggers "error" circuit breaker incorrectly |
| #5 | Bug: date: illegal option -- d on macOS |
| #7 | Review codebase for updated Anthropic CLI |
| #10 | Implement CLI parsing tests |
| #11 | Implement installation tests |
| #12 | Implement project setup tests |
| #13 | Implement PRD import tests |
| #28 | Phase 1.1: Update CLI commands with modern options |
| #29 | Phase 1.2: Enhance response parsing for JSON output |
| #30 | Phase 1.3: Add session management for continuity |
| #31 | Phase 1.4: Update ralph-import with CLI enhancements |
| #42 | Windows: Git Bash windows spawn when running Ralph loop |
| #48 | MAJOR-01: Enhance shell escaping to prevent command injection |
| #50 | MAJOR-02: Add input validation for --allowed-tools flag |
| #55 | --prompt-file flag does not exist in Claude Code CLI |
| #56 | Project featured in Awesome Claude Code! |
| #63 | Fix IMPLEMENTATION_PLAN |
</details>
---
## Open Issues by Priority
### P2 (Medium - Important)
| Issue | Phase | Title |
|-------|-------|-------|
| #51 | 1.5 | Session expiration for .claude_session_id |
| #32 | 2.1 | Create Agent SDK proof of concept |
| #33 | 2.2 | Define custom tools for Agent SDK |
| #34 | 2.3 | Implement hybrid CLI/SDK architecture |
| #35 | 2.4 | Document SDK migration strategy |
| #36 | 3.1 | Add JSON configuration file support |
| #37 | 3.2 | Update installation for SDK support |
| #18 | 3.4 | Implement log rotation feature |
| #19 | 3.5 | Implement dry-run mode feature |
| #20 | 3.6 | Implement config file support (.ralphrc) |
| #14 | 4.4 | Implement tmux integration tests |
| #15 | 4.5 | Implement monitor dashboard tests |
| #16 | 4.6 | Implement status update tests |
### P3 (Low - Nice to have)
| Issue | Phase | Title |
|-------|-------|-------|
| #24 | 1.9 | Create TESTING.md documentation |
| #25 | 1.10 | Create CONTRIBUTING.md guide |
| #26 | 1.11 | Update README with testing instructions |
| #27 | 1.12 | Add badges to README |
| #38 | 3.3 | Create CLI and SDK documentation |
| #21 | 3.7 | Implement metrics and analytics |
| #22 | 3.8 | Implement notification system |
| #23 | 3.9 | Implement backup and rollback system |
| #39 | 4.1 | Implement CLI enhancement tests |
| #40 | 4.2 | Implement SDK integration tests |
| #41 | 4.3 | Implement backward compatibility tests |
| #17 | 4.7 | Implement E2E full loop tests |
### P4 (Enhancements - New functionality)
| Issue | Phase | Title |
|-------|-------|-------|
| #69 | 5.1 | Allow plan import from GitHub Issue |
| #70 | 5.2 | Assess issue completeness and generate plan |
| #71 | 5.3 | Filter and select GitHub issues by metadata |
| #72 | 5.4 | Batch processing and issue queue management |
| #73 | 5.5 | Issue lifecycle management |
| #49 | 6.0 | Sandbox execution environments (umbrella) |
| #74 | 6.1 | Local Docker Sandbox Execution |
| #75 | 6.2 | E2B Cloud Sandbox Integration |
| #76 | 6.3 | Sandbox File Synchronization |
| #77 | 6.4 | Sandbox Security and Resource Policies |
| #78 | 6.5 | Generic Sandbox Interface |
| #79 | 6.6 | Daytona Sandbox Integration |
| #80 | 6.7 | Cloudflare Sandbox Integration |
---
## Summary Statistics
| Category | Count |
|----------|-------|
| Total Open Issues | 36 |
| P2 Issues | 13 |
| P3 Issues | 12 |
| P4 Issues | 13 |
| Closed Issues | 20 |
| Total Tests | 276 |
| Test Pass Rate | 100% |
---
**Status**: ✅ Solid foundation with comprehensive test coverage
**Next Steps**: Complete Phase 1 documentation, then Phase 3 core features (log rotation, dry-run, config)
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2025 Frank Bria
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Ralph for Claude Code
[](https://github.com/frankbria/ralph-claude-code/actions/workflows/test.yml)
[](LICENSE)


[](https://github.com/frankbria/ralph-claude-code/issues)
[](https://github.com/hesreallyhim/awesome-claude-code)
[](https://x.com/FrankBria18044)
> **Autonomous AI development loop with intelligent exit detection and rate limiting**
Ralph is an implementation of the Geoffrey Huntley's technique for Claude Code that enables continuous autonomous development cycles he named after [Ralph Wiggum](https://ghuntley.com/ralph/). It enables continuous autonomous development cycles where Claude Code iteratively improves your project until completion, with built-in safeguards to prevent infinite loops and API overuse.
**Install once, use everywhere** - Ralph becomes a global command available in any directory.
## Project Status
**Version**: v0.11.5 - Active Development
**Core Features**: Working and tested
**Test Coverage**: 566 tests, 100% pass rate
### What's Working Now
- Autonomous development loops with intelligent exit detection
- **Dual-condition exit gate**: Requires BOTH completion indicators AND explicit EXIT_SIGNAL
- Rate limiting with hourly reset (100 calls/hour, configurable)
- Circuit breaker with advanced error detection (prevents runaway loops)
- Response analyzer with semantic understanding and two-stage error filtering
- **JSON output format support with automatic fallback to text parsing**
- **Session continuity with `--resume` flag for context preservation (no session hijacking)**
- **Session expiration with configurable timeout (default: 24 hours)**
- **Modern CLI flags: `--output-format`, `--allowed-tools`, `--no-continue`**
- **Interactive project enablement with `ralph-enable` wizard**
- **`.ralphrc` configuration file for project settings**
- **Live streaming output with `--live` flag for real-time Claude Code visibility**
- Multi-line error matching for accurate stuck loop detection
- 5-hour API limit handling with user prompts
- tmux integration for live monitoring
- PRD import functionality
- **CI/CD pipeline with GitHub Actions**
- **Dedicated uninstall script for clean removal**
### Recent Improvements
**v0.11.5 - Community Bug Fixes** (latest)
- Fixed API limit false positive: Timeout (exit code 124) no longer misidentified as API 5-hour limit (#183)
- Three-layer API limit detection: timeout guard → structural JSON (`rate_limit_event`) → filtered text fallback
- Unattended mode: API limit prompt now auto-waits on timeout instead of exiting
- Fixed bash 3.x compatibility: `${,,}` lowercase substitution replaced with POSIX `tr` (#187)
- Added 8 new tests for API limit detection (548 → 566 tests)
**v0.11.4 - Bug Fixes & Compatibility**
- Fixed progress detection: Git commits within a loop now count as progress (#141)
- Fixed checkbox regex: Date entries `[2026-01-29]` no longer counted as checkboxes (#144)
- Fixed session hijacking: Use `--resume <session_id>` instead of `--continue` (#151)
- Fixed EXIT_SIGNAL override: `STATUS: COMPLETE` with `EXIT_SIGNAL: false` now continues working (#146)
- Fixed ralph-import hanging indefinitely (added `--print` flag for non-interactive mode)
- Fixed ralph-import absolute path handling
- Fixed cross-platform date commands for macOS with Homebrew coreutils
- Added configurable circuit breaker thresholds via environment variables (#99)
- Added tmux support for non-zero `base-index` configurations
- Added 13 new regression tests for progress detection and checkbox regex
**v0.11.3 - Live Streaming & Beads Fix**
- Added live streaming output mode with `--live` flag for real-time Claude Code visibility (#125)
- Fixed beads task import using correct `bd list` arguments (#150)
- Applied CodeRabbit review fixes: camelCase variables, status-respecting fallback, jq guards
- Added 12 new tests for live streaming and beads import improvements
**v0.11.2 - Setup Permissions Fix**
- Fixed issue #136: `ralph-setup` now creates `.ralphrc` with consistent tool permissions
- Updated default `ALLOWED_TOOLS` to include `Edit`, `Bash(npm *)`, and `Bash(pytest)`
- Both `ralph-setup` and `ralph-enable` now create identical `.ralphrc` configurations
- Monitor now forwards all CLI parameters to inner ralph loop (#126)
- Added 16 new tests for permissions and parameter forwarding
**v0.11.1 - Completion Indicators Fix**
- Fixed premature exit after exactly 5 loops in JSON output mode
- `completion_indicators` now only accumulates when `EXIT_SIGNAL: true`
- Aligns with documented dual-condition exit gate behavior
**v0.11.0 - Ralph Enable Wizard**
- Added `ralph-enable` interactive wizard for enabling Ralph in existing projects
- 5-phase wizard: Environment Detection → Task Source Selection → Configuration → File Generation → Verification
- Auto-detects project type (TypeScript, Python, Rust, Go) and framework (Next.js, FastAPI, Django)
- Imports tasks from beads, GitHub Issues, or PRD documents
- Added `ralph-enable-ci` non-interactive version for CI/automation
- New library components: `enable_core.sh`, `wizard_utils.sh`, `task_sources.sh`
**v0.10.1 - Bug Fixes & Monitor Path Corrections**
- Fixed `ralph_monitor.sh` hardcoded paths for v0.10.0 compatibility
- Fixed EXIT_SIGNAL parsing in JSON format
- Added safety circuit breaker (force exit after 5 consecutive completion indicators)
- Fixed checkbox parsing for indented markdown
**v0.10.0 - .ralph/ Subfolder Structure (BREAKING CHANGE)**
- **Breaking**: Moved all Ralph-specific files to `.ralph/` subfolder
- Project root stays clean: only `src/`, `README.md`, and user files remain
- Added `ralph-migrate` command for upgrading existing projects
<details>
<summary>Earlier versions (v0.9.x)</summary>
**v0.9.9 - EXIT_SIGNAL Gate & Uninstall Script**
- Fixed premature exit bug: completion indicators now require Claude's explicit `EXIT_SIGNAL: true`
- Added dedicated `uninstall.sh` script for clean Ralph removal
**v0.9.8 - Modern CLI for PRD Import**
- Modernized `ralph_import.sh` to use Claude Code CLI JSON output format
- Enhanced error handling with structured JSON error messages
**v0.9.7 - Session Lifecycle Management**
- Complete session lifecycle management with automatic reset triggers
- Added `--reset-session` CLI flag for manual session reset
**v0.9.6 - JSON Output & Session Management**
- Extended `parse_json_response()` to support Claude Code CLI JSON format
- Added session management functions
**v0.9.5 - v0.9.0** - PRD import tests, project setup tests, installation tests, prompt file fix, modern CLI commands, circuit breaker enhancements
</details>
### In Progress
- Expanding test coverage
- Log rotation functionality
- Dry-run mode
- Metrics and analytics tracking
- Desktop notifications
- Git backup and rollback system
- [Automated badge updates](#138)
**Timeline to v1.0**: ~4 weeks | [Full roadmap](IMPLEMENTATION_PLAN.md) | **Contributions welcome!**
## Features
- **Autonomous Development Loop** - Continuously executes Claude Code with your project requirements
- **Intelligent Exit Detection** - Dual-condition check requiring BOTH completion indicators AND explicit EXIT_SIGNAL
- **Session Continuity** - Preserves context across loop iterations with automatic session management
- **Session Expiration** - Configurable timeout (default: 24 hours) with automatic session reset
- **Rate Limiting** - Built-in API call management with hourly limits and countdown timers
- **5-Hour API Limit Handling** - Three-layer detection (timeout guard, JSON parsing, filtered text) with auto-wait for unattended mode
- **Live Monitoring** - Real-time dashboard showing loop status, progress, and logs
- **Task Management** - Structured approach with prioritized task lists and progress tracking
- **Project Templates** - Quick setup for new projects with best-practice structure
- **Interactive Project Setup** - `ralph-enable` wizard for existing projects with task import
- **Configuration Files** - `.ralphrc` for project-specific settings and tool permissions
- **Comprehensive Logging** - Detailed execution logs with timestamps and status tracking
- **Configurable Timeouts** - Set execution timeout for Claude Code operations (1-120 minutes)
- **Verbose Progress Mode** - Optional detailed progress updates during execution
- **Response Analyzer** - AI-powered analysis of Claude Code responses with semantic understanding
- **Circuit Breaker** - Advanced error detection with two-stage filtering, multi-line error matching, and automatic recovery
- **CI/CD Integration** - GitHub Actions workflow with automated testing
- **Clean Uninstall** - Dedicated uninstall script for complete removal
- **Live Streaming Output** - Real-time visibility into Claude Code execution with `--live` flag
## Quick Start
Ralph has two phases: **one-time installation** and **per-project setup**.
```
INSTALL ONCE USE MANY TIMES
+-----------------+ +----------------------+
| ./install.sh | -> | ralph-setup project1 |
| | | ralph-enable |
| Adds global | | ralph-import prd.md |
| commands | | ... |
+-----------------+ +----------------------+
```
### Phase 1: Install Ralph (One Time Only)
Install Ralph globally on your system:
```bash
git clone https://github.com/frankbria/ralph-claude-code.git
cd ralph-claude-code
./install.sh
```
This adds `ralph`, `ralph-monitor`, `ralph-setup`, `ralph-import`, `ralph-migrate`, `ralph-enable`, and `ralph-enable-ci` commands to your PATH.
> **Note**: You only need to do this once per system. After installation, you can delete the cloned repository if desired.
### Phase 2: Initialize Projects (Per Project)
#### Option A: Enable Ralph in Existing Project (Recommended)
```bash
cd my-existing-project
# Interactive wizard - auto-detects project type and imports tasks
ralph-enable
# Or with specific task source
ralph-enable --from beads
ralph-enable --from github --label "sprint-1"
ralph-enable --from prd ./docs/requirements.md
# Start autonomous development
ralph --monitor
```
#### Option B: Import Existing PRD/Specifications
```bash
# Convert existing PRD/specs to Ralph format
ralph-import my-requirements.md my-project
cd my-project
# Review and adjust the generated files:
# - .ralph/PROMPT.md (Ralph instructions)
# - .ralph/fix_plan.md (task priorities)
# - .ralph/specs/requirements.md (technical specs)
# Start autonomous development
ralph --monitor
```
#### Option C: Create New Project from Scratch
```bash
# Create blank Ralph project
ralph-setup my-awesome-project
cd my-awesome-project
# Configure your project requirements manually
# Edit .ralph/PROMPT.md with your project goals
# Edit .ralph/specs/ with detailed specifications
# Edit .ralph/fix_plan.md with initial priorities
# Start autonomous development
ralph --monitor
```
### Ongoing Usage (After Setup)
Once Ralph is installed and your project is initialized:
```bash
# Navigate to any Ralph project and run:
ralph --monitor # Integrated tmux monitoring (recommended)
# Or use separate terminals:
ralph # Terminal 1: Ralph loop
ralph-monitor # Terminal 2: Live monitor dashboard
```
### Uninstalling Ralph
To completely remove Ralph from your system:
```bash
# Run the uninstall script
./uninstall.sh
# Or if you deleted the repo, download and run:
curl -sL https://raw.githubusercontent.com/frankbria/ralph-claude-code/main/uninstall.sh | bash
```
## Understanding Ralph Files
After running `ralph-enable` or `ralph-import`, you'll have a `.ralph/` directory with several files. Here's what each file does and whether you need to edit it:
| File | Auto-Generated? | You Should... |
|------|-----------------|---------------|
| `.ralph/PROMPT.md` | Yes (smart defaults) | **Review & customize** project goals and principles |
| `.ralph/fix_plan.md` | Yes (can import tasks) | **Add/modify** specific implementation tasks |
| `.ralph/AGENT.md` | Yes (detects build commands) | Rarely edit (auto-maintained by Ralph) |
| `.ralph/specs/` | Empty directory | Add files when PROMPT.md isn't detailed enough |
| `.ralph/specs/stdlib/` | Empty directory | Add reusable patterns and conventions |
| `.ralphrc` | Yes (project-aware) | Rarely edit (sensible defaults) |
### Key File Relationships
```
PROMPT.md (high-level goals)
↓
specs/ (detailed requirements when needed)
↓
fix_plan.md (specific tasks Ralph executes)
↓
AGENT.md (build/test commands - auto-maintained)
```
### When to Use specs/
- **Simple projects**: PROMPT.md + fix_plan.md is usually enough
- **Complex features**: Add specs/feature-name.md for detailed requirements
- **Team conventions**: Add specs/stdlib/convention-name.md for reusable patterns
See the [User Guide](docs/user-guide/) for detailed explanations and the [examples/](examples/) directory for realistic project configurations.
## How It Works
Ralph operates on a simple but powerful cycle:
1. **Read Instructions** - Loads `PROMPT.md` with your project requirements
2. **Execute Claude Code** - Runs Claude Code with current context and priorities
3. **Track Progress** - Updates task lists and logs execution results
4. **Evaluate Completion** - Checks for exit conditions and project completion signals
5. **Repeat** - Continues until project is complete or limits are reached
### Intelligent Exit Detection
Ralph uses a **dual-condition check** to prevent premature exits during productive iterations:
**Exit requires BOTH conditions:**
1. `completion_indicators >= 2` (heuristic detection from natural language patterns)
2. Claude's explicit `EXIT_SIGNAL: true` in the RALPH_STATUS block
**Example behavior:**
```
Loop 5: Claude outputs "Phase complete, moving to next feature"
→ completion_indicators: 3 (high confidence from patterns)
→ EXIT_SIGNAL: false (Claude says more work needed)
→ Result: CONTINUE (respects Claude's explicit intent)
Loop 8: Claude outputs "All tasks complete, project ready"
→ completion_indicators: 4
→ EXIT_SIGNAL: true (Claude confirms done)
→ Result: EXIT with "project_complete"
```
**Other exit conditions:**
- All tasks in `.ralph/fix_plan.md` marked complete
- Multiple consecutive "done" signals from Claude Code
- Too many test-focused loops (indicating feature completeness)
- Claude API 5-hour usage limit reached (with user prompt to wait or exit)
## Enabling Ralph in Existing Projects
The `ralph-enable` command provides an interactive wizard for adding Ralph to existing projects:
```bash
cd my-existing-project
ralph-enable
```
**The wizard:**
1. **Detects Environment** - Identifies project type (TypeScript, Python, etc.) and framework
2. **Selects Task Sources** - Choose from beads, GitHub Issues, or PRD documents
3. **Configures Settings** - Set tool permissions and loop parameters
4. **Generates Files** - Creates `.ralph/` directory and `.ralphrc` configuration
5. **Verifies Setup** - Confirms all files are created correctly
**Non-interactive mode for CI/automation:**
```bash
ralph-enable-ci # Sensible defaults
ralph-enable-ci --from github # Import from GitHub Issues
ralph-enable-ci --project-type typescript # Override detection
ralph-enable-ci --json # Machine-readable output
```
## Importing Existing Requirements
Ralph can convert existing PRDs, specifications, or requirement documents into the proper Ralph format using Claude Code.
### Supported Formats
- **Markdown** (.md) - Product requirements, technical specs
- **Text files** (.txt) - Plain text requirements
- **JSON** (.json) - Structured requirement data
- **Word documents** (.docx) - Business requirements
- **PDFs** (.pdf) - Design documents, specifications
- **Any text-based format** - Ralph will intelligently parse the content
### Usage Examples
```bash
# Convert a markdown PRD
ralph-import product-requirements.md my-app
# Convert a text specification
ralph-import requirements.txt webapp
# Convert a JSON API spec
ralph-import api-spec.json backend-service
# Let Ralph auto-name the project from filename
ralph-import design-doc.pdf
```
### What Gets Generated
Ralph-import creates a complete project with:
- **.ralph/PROMPT.md** - Converted into Ralph development instructions
- **.ralph/fix_plan.md** - Requirements broken down into prioritized tasks
- **.ralph/specs/requirements.md** - Technical specifications extracted from your document
- **.ralphrc** - Project configuration file with tool permissions
- **Standard Ralph structure** - All necessary directories and template files in `.ralph/`
The conversion is intelligent and preserves your original requirements while making them actionable for autonomous development.
## Configuration
### Project Configuration (.ralphrc)
Each Ralph project can have a `.ralphrc` configuration file:
```bash
# .ralphrc - Ralph project configuration
PROJECT_NAME="my-project"
PROJECT_TYPE="typescript"
# Claude Code CLI command (auto-detected, override if needed)
CLAUDE_CODE_CMD="claude"
# CLAUDE_CODE_CMD="npx @anthropic-ai/claude-code" # Alternative: use npx
# Loop settings
MAX_CALLS_PER_HOUR=100
CLAUDE_TIMEOUT_MINUTES=15
CLAUDE_OUTPUT_FORMAT="json"
# Tool permissions
ALLOWED_TOOLS="Write,Read,Edit,Bash(git *),Bash(npm *),Bash(pytest)"
# Session management
SESSION_CONTINUITY=true
SESSION_EXPIRY_HOURS=24
# Circuit breaker thresholds
CB_NO_PROGRESS_THRESHOLD=3
CB_SAME_ERROR_THRESHOLD=5
```
### Rate Limiting & Circuit Breaker
Ralph includes intelligent rate limiting and circuit breaker functionality:
```bash
# Default: 100 calls per hour
ralph --calls 50
# With integrated monitoring
ralph --monitor --calls 50
# Check current usage
ralph --status
```
The circuit breaker automatically:
- Detects API errors and rate limit issues with advanced two-stage filtering
- Opens circuit after 3 loops with no progress or 5 loops with same errors
- Eliminates false positives from JSON fields containing "error"
- Accurately detects stuck loops with multi-line error matching
- Gradually recovers with half-open monitoring state
- **Auto-recovers** after cooldown period (default: 30 minutes) — OPEN → HALF_OPEN → CLOSED
- Provides detailed error tracking and logging with state history
**Auto-recovery options:**
```bash
# Default: 30-minute cooldown before auto-recovery attempt
CB_COOLDOWN_MINUTES=30 # Set in .ralphrc (0 = immediate)
# Auto-reset on startup (for fully unattended operation)
ralph --auto-reset-circuit
# Or set in .ralphrc: CB_AUTO_RESET=true
```
### Claude API 5-Hour Limit
When Claude's 5-hour usage limit is reached, Ralph:
1. Detects the limit using three-layer verification (timeout guard → structural JSON → filtered text fallback)
2. Prompts you to choose:
- **Option 1**: Wait 60 minutes for the limit to reset (with countdown timer)
- **Option 2**: Exit gracefully
3. **Unattended mode**: Auto-waits on prompt timeout (30s) instead of exiting
4. Prevents false positives from echoed file content mentioning "5-hour limit"
### Custom Prompts
```bash
# Use custom prompt file
ralph --prompt my_custom_instructions.md
# With integrated monitoring
ralph --monitor --prompt my_custom_instructions.md
```
### Execution Timeouts
```bash
# Set Claude Code execution timeout (default: 15 minutes)
ralph --timeout 30 # 30-minute timeout for complex tasks
# With monitoring and custom timeout
ralph --monitor --timeout 60 # 60-minute timeout
# Short timeout for quick iterations
ralph --verbose --timeout 5 # 5-minute timeout with progress
```
### Verbose Mode
```bash
# Enable detailed progress updates during execution
ralph --verbose
# Combine with other options
ralph --monitor --verbose --timeout 30
```
### Live Streaming Output
```bash
# Enable real-time visibility into Claude Code execution
ralph --live
# Combine with monitoring for best experience
ralph --monitor --live
# Live output is written to .ralph/live.log
tail -f .ralph/live.log # Watch in another terminal
```
Live streaming mode shows Claude Code's output in real-time as it works, providing visibility into what's happening during each loop iteration.
### Session Continuity
Ralph maintains session context across loop iterations for improved coherence:
```bash
# Sessions are enabled by default with --continue flag
ralph --monitor # Uses session continuity
# Start fresh without session context
ralph --no-continue # Isolated iterations
# Reset session manually (clears context)
ralph --reset-session # Clears current session
# Check session status
cat .ralph/.ralph_session # View current session file
cat .ralph/.ralph_session_history # View session transition history
```
**Session Auto-Reset Triggers:**
- Circuit breaker opens (stagnation detected)
- Manual interrupt (Ctrl+C / SIGINT)
- Project completion (graceful exit)
- Manual circuit breaker reset (`--reset-circuit`)
- Session expiration (default: 24 hours)
Sessions are persisted to `.ralph/.ralph_session` with a configurable expiration (default: 24 hours). The last 50 session transitions are logged to `.ralph/.ralph_session_history` for debugging.
### Exit Thresholds
Modify these variables in `~/.ralph/ralph_loop.sh`:
**Exit Detection Thresholds:**
```bash
MAX_CONSECUTIVE_TEST_LOOPS=3 # Exit after 3 test-only loops
MAX_CONSECUTIVE_DONE_SIGNALS=2 # Exit after 2 "done" signals
TEST_PERCENTAGE_THRESHOLD=30 # Flag if 30%+ loops are test-only
```
**Circuit Breaker Thresholds:**
```bash
CB_NO_PROGRESS_THRESHOLD=3 # Open circuit after 3 loops with no file changes
CB_SAME_ERROR_THRESHOLD=5 # Open circuit after 5 loops with repeated errors
CB_OUTPUT_DECLINE_THRESHOLD=70 # Open circuit if output declines by >70%
CB_COOLDOWN_MINUTES=30 # Minutes before OPEN → HALF_OPEN auto-recovery
CB_AUTO_RESET=false # true = reset to CLOSED on startup (bypasses cooldown)
```
**Completion Indicators with EXIT_SIGNAL Gate:**
| completion_indicators | EXIT_SIGNAL | Result |
|-----------------------|-------------|--------|
| >= 2 | `true` | **Exit** ("project_complete") |
| >= 2 | `false` | **Continue** (Claude still working) |
| >= 2 | missing | **Continue** (defaults to false) |
| < 2 | `true` | **Continue** (threshold not met) |
## Project Structure
Ralph creates a standardized structure for each project with a `.ralph/` subfolder for configuration:
```
my-project/
├── .ralph/ # Ralph configuration and state (hidden folder)
│ ├── PROMPT.md # Main development instructions for Ralph
│ ├── fix_plan.md # Prioritized task list
│ ├── AGENT.md # Build and run instructions
│ ├── specs/ # Project specifications and requirements
│ │ └── stdlib/ # Standard library specifications
│ ├── examples/ # Usage examples and test cases
│ ├── logs/ # Ralph execution logs
│ └── docs/generated/ # Auto-generated documentation
├── .ralphrc # Ralph configuration file (tool permissions, settings)
└── src/ # Source code implementation (at project root)
```
> **Migration**: If you have existing Ralph projects using the old flat structure, run `ralph-migrate` to automatically move files to the `.ralph/` subfolder.
## Best Practices
### Writing Effective Prompts
1. **Be Specific** - Clear requirements lead to better results
2. **Prioritize** - Use `.ralph/fix_plan.md` to guide Ralph's focus
3. **Set Boundaries** - Define what's in/out of scope
4. **Include Examples** - Show expected inputs/outputs
### Project Specifications
- Place detailed requirements in `.ralph/specs/`
- Use `.ralph/fix_plan.md` for prioritized task tracking
- Keep `.ralph/AGENT.md` updated with build instructions
- Document key decisions and architecture
### Monitoring Progress
- Use `ralph-monitor` for live status updates
- Check logs in `.ralph/logs/` for detailed execution history
- Monitor `.ralph/status.json` for programmatic access
- Watch for exit condition signals
## System Requirements
- **Bash 4.0+** - For script execution
- **Claude Code CLI** - `npm install -g @anthropic-ai/claude-code` (or use npx — set `CLAUDE_CODE_CMD` in `.ralphrc`)
- **tmux** - Terminal multiplexer for integrated monitoring (recommended)
- **jq** - JSON processing for status tracking
- **Git** - Version control (projects are initialized as git repos)
- **GNU coreutils** - For the `timeout` command (execution timeouts)
- Linux: Pre-installed on most distributions
- macOS: Install via `brew install coreutils` (provides `gtimeout`)
- **Standard Unix tools** - grep, date, etc.
### Testing Requirements (Development)
See [TESTING.md](TESTING.md) for the comprehensive testing guide.
If you want to run the test suite:
```bash
# Install BATS testing framework
npm install -g bats bats-support bats-assert
# Run all tests (566 tests)
npm test
# Run specific test suites
bats tests/unit/test_rate_limiting.bats
bats tests/unit/test_exit_detection.bats
bats tests/unit/test_json_parsing.bats
bats tests/unit/test_cli_modern.bats
bats tests/unit/test_cli_parsing.bats
bats tests/unit/test_session_continuity.bats
bats tests/unit/test_enable_core.bats
bats tests/unit/test_task_sources.bats
bats tests/unit/test_ralph_enable.bats
bats tests/unit/test_wizard_utils.bats
bats tests/unit/test_circuit_breaker_recovery.bats
bats tests/integration/test_loop_execution.bats
bats tests/integration/test_prd_import.bats
bats tests/integration/test_project_setup.bats
bats tests/integration/test_installation.bats
# Run error detection and circuit breaker tests
./tests/test_error_detection.sh
./tests/test_stuck_loop_detection.sh
```
Current test status:
- **566 tests** across 18 test files
- **100% pass rate** (556/556 passing)
- Comprehensive unit and integration tests
- Specialized tests for JSON parsing, CLI flags, circuit breaker, EXIT_SIGNAL behavior, enable wizard, and installation workflows
> **Note on Coverage**: Bash code coverage measurement with kcov has fundamental limitations when tracing subprocess executions. Test pass rate (100%) is the quality gate. See [bats-core#15](https://github.com/bats-core/bats-core/issues/15) for details.
### Installing tmux
```bash
# Ubuntu/Debian
sudo apt-get install tmux
# macOS
brew install tmux
# CentOS/RHEL
sudo yum install tmux
```
### Installing GNU coreutils (macOS)
Ralph uses the `timeout` command for execution timeouts. On macOS, you need to install GNU coreutils:
```bash
# Install coreutils (provides gtimeout)
brew install coreutils
# Verify installation
gtimeout --version
```
Ralph automatically detects and uses `gtimeout` on macOS. No additional configuration is required after installation.
## Monitoring and Debugging
### Live Dashboard
```bash
# Integrated tmux monitoring (recommended)
ralph --monitor
# Manual monitoring in separate terminal
ralph-monitor
```
Shows real-time:
- Current loop count and status
- API calls used vs. limit
- Recent log entries
- Rate limit countdown
**tmux Controls:**
- `Ctrl+B` then `D` - Detach from session (keeps Ralph running)
- `Ctrl+B` then `←/→` - Switch between panes
- `tmux list-sessions` - View active sessions
- `tmux attach -t <session-name>` - Reattach to session
### Status Checking
```bash
# JSON status output
ralph --status
# Manual log inspection
tail -f .ralph/logs/ralph.log
```
### Common Issues
- **Ralph exits silently on first loop** - Claude Code CLI may not be installed or not in PATH. Ralph validates the command at startup and shows installation instructions. If using npx, add `CLAUDE_CODE_CMD="npx @anthropic-ai/claude-code"` to `.ralphrc`
- **Rate Limits** - Ralph automatically waits and displays countdown
- **5-Hour API Limit** - Ralph detects and prompts for user action (wait or exit)
- **Stuck Loops** - Check `fix_plan.md` for unclear or conflicting tasks
- **Early Exit** - Review exit thresholds if Ralph stops too soon
- **Premature Exit** - Check if Claude is setting `EXIT_SIGNAL: false` (Ralph now respects this)
- **Execution Timeouts** - Increase `--timeout` value for complex operations
- **Missing Dependencies** - Ensure Claude Code CLI and tmux are installed
- **tmux Session Lost** - Use `tmux list-sessions` and `tmux attach` to reconnect
- **Session Expired** - Sessions expire after 24 hours by default; use `--reset-session` to start fresh
- **timeout: command not found (macOS)** - Install GNU coreutils: `brew install coreutils`
- **Permission Denied** - Ralph halts when Claude Code is denied permission for commands:
1. Edit `.ralphrc` and update `ALLOWED_TOOLS` to include required tools
2. Common patterns: `Bash(npm *)`, `Bash(git *)`, `Bash(pytest)`
3. Run `ralph --reset-session` after updating `.ralphrc`
4. Restart with `ralph --monitor`
## Contributing
Ralph is actively seeking contributors! We're working toward v1.0.0 with clear priorities and a detailed roadmap.
**See [CONTRIBUTING.md](CONTRIBUTING.md) for the complete contributor guide** including:
- Getting started and setup instructions
- Development workflow and commit conventions
- Code style guidelines
- Testing requirements (100% pass rate mandatory)
- Pull request process and code review guidelines
- Quality standards and checklists
### Quick Start
```bash
# Fork and clone
git clone https://github.com/YOUR_USERNAME/ralph-claude-code.git
cd ralph-claude-code
# Install dependencies and run tests
npm install
npm test # All 566 tests must pass
```
### Priority Contribution Areas
1. **Test Implementation** - Help expand test coverage
2. **Feature Development** - Log rotation, dry-run mode, metrics
3. **Documentation** - Tutorials, troubleshooting guides, examples
4. **Real-World Testing** - Use Ralph, report bugs, share feedback
**Every contribution matters** - from fixing typos to implementing major features!
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Acknowledgments
- Inspired by the [Ralph technique](https://ghuntley.com/ralph/) created by Geoffrey Huntley
- Built for [Claude Code](https://claude.ai/code) by Anthropic
- Community feedback and contributions
## Related Projects
- [Claude Code](https://claude.ai/code) - The AI coding assistant that powers Ralph
- [Aider](https://github.com/paul-gauthier/aider) - Original Ralph technique implementation
---
## Command Reference
### Installation Commands (Run Once)
```bash
./install.sh # Install Ralph globally
./uninstall.sh # Remove Ralph from system (dedicated script)
./install.sh uninstall # Alternative: Remove Ralph from system
./install.sh --help # Show installation help
ralph-migrate # Migrate existing project to .ralph/ structure
```
### Ralph Loop Options
```bash
ralph [OPTIONS]
-h, --help Show help message
-c, --calls NUM Set max calls per hour (default: 100)
-p, --prompt FILE Set prompt file (default: PROMPT.md)
-s, --status Show current status and exit
-m, --monitor Start with tmux session and live monitor
-v, --verbose Show detailed progress updates during execution
-l, --live Enable live streaming output (real-time Claude Code visibility)
-t, --timeout MIN Set Claude Code execution timeout in minutes (1-120, default: 15)
--output-format FORMAT Set output format: json (default) or text
--allowed-tools TOOLS Set allowed Claude tools (default: Write,Read,Edit,Bash(git *),Bash(npm *),Bash(pytest))
--no-continue Disable session continuity (start fresh each loop)
--reset-circuit Reset the circuit breaker
--circuit-status Show circuit breaker status
--auto-reset-circuit Auto-reset circuit breaker on startup (bypasses cooldown)
--reset-session Reset session state manually
```
### Project Commands (Per Project)
```bash
ralph-setup project-name # Create new Ralph project
ralph-enable # Enable Ralph in existing project (interactive)
ralph-enable-ci # Enable Ralph in existing project (non-interactive)
ralph-import prd.md project # Convert PRD/specs to Ralph project
ralph --monitor # Start with integrated monitoring
ralph --status # Check current loop status
ralph --verbose # Enable detailed progress updates
ralph --timeout 30 # Set 30-minute execution timeout
ralph --calls 50 # Limit to 50 API calls per hour
ralph --reset-session # Reset session state manually
ralph --live # Enable live streaming output
ralph-monitor # Manual monitoring dashboard
```
### tmux Session Management
```bash
tmux list-sessions # View active Ralph sessions
tmux attach -t <name> # Reattach to detached session
# Ctrl+B then D # Detach from session (keeps running)
```
---
## Development Roadmap
Ralph is under active development with a clear path to v1.0.0. See [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) for the complete roadmap.
### Current Status: v0.11.5
**What's Delivered:**
- Core loop functionality with intelligent exit detection
- **Dual-condition exit gate** (completion indicators + EXIT_SIGNAL)
- Rate limiting (100 calls/hour) and circuit breaker pattern
- Response analyzer with semantic understanding
- **556 comprehensive tests** (100% pass rate)
- **Live streaming output mode** for real-time Claude Code visibility
- tmux integration and live monitoring
- PRD import functionality with modern CLI JSON parsing
- Installation system and project templates
- Modern CLI commands with JSON output support
- CI/CD pipeline with GitHub Actions
- **Interactive `ralph-enable` wizard for existing projects**
- **`.ralphrc` configuration file support**
- Session lifecycle management with auto-reset triggers
- Session expiration with configurable timeout
- Dedicated uninstall script
**Test Coverage Breakdown:**
- Unit Tests: 420 (CLI parsing, JSON, exit detection, rate limiting, session continuity, enable wizard, live streaming, circuit breaker recovery, file protection, integrity checks)
- Integration Tests: 136 (loop execution, edge cases, installation, project setup, PRD import)
- Test Files: 18
### Path to v1.0.0 (~4 weeks)
**Enhanced Testing**
- Installation and setup workflow tests
- tmux integration tests
- Monitor dashboard tests
**Core Features**
- Log rotation functionality
- Dry-run mode
**Advanced Features & Polish**
- Metrics and analytics tracking
- Desktop notifications
- Git backup and rollback system
- End-to-end tests
- Final documentation and release prep
See [IMPLEMENTATION_STATUS.md](IMPLEMENTATION_STATUS.md) for detailed progress tracking.
### How to Contribute
Ralph is seeking contributors! See [CONTRIBUTING.md](CONTRIBUTING.md) for the complete guide. Priority areas:
1. **Test Implementation** - Help expand test coverage ([see plan](IMPLEMENTATION_PLAN.md))
2. **Feature Development** - Log rotation, dry-run mode, metrics
3. **Documentation** - Usage examples, tutorials, troubleshooting guides
4. **Bug Reports** - Real-world usage feedback and edge cases
---
**Ready to let AI build your project?** Start with `./install.sh` and let Ralph take it from there!
## Star History
[](https://www.star-history.com/#frankbria/ralph-claude-code&type=date&legend=top-left)
================================================
FILE: SPECIFICATION_WORKSHOP.md
================================================
# Ralph Specification Workshop Guide
**Based on**: Janet Gregory's "Three Amigos" collaborative testing approach
**Purpose**: Facilitate productive specification conversations for new Ralph features
**Audience**: Developers, Testers, Product Owners working on Ralph enhancements
---
## What is a Specification Workshop?
A specification workshop brings together three perspectives ("Three Amigos") to define features before implementation:
1. **Developer** (How to implement) - Technical feasibility and approach
2. **Tester** (How to verify) - Edge cases, validation, quality criteria
3. **Product Owner / User** (What's the value) - Business requirements and success criteria
**Goal**: Produce concrete, testable specifications that prevent bugs and misunderstandings.
---
## Workshop Template
### Feature: [Name]
**Participants**:
- Developer: [Name]
- Tester: [Name]
- Product Owner: [Name]
**Date**: YYYY-MM-DD
**Duration**: 30-60 minutes
---
## 1. User Story
**As a** [role]
**I want** [capability]
**So that** [benefit]
**Example**:
> As a Ralph user
> I want circuit breaker auto-recovery
> So that temporary issues don't require manual intervention
---
## 2. Acceptance Criteria (Product Owner)
What makes this feature "done" and valuable?
**Criteria**:
- [ ] [Measurable criterion 1]
- [ ] [Measurable criterion 2]
- [ ] [Measurable criterion 3]
**Example**:
- [x] Circuit breaker auto-recovers when progress resumes
- [x] User is notified of recovery via log message
- [x] Recovery happens within 1 loop iteration
---
## 3. Questions from Tester
What needs clarification? What could go wrong?
**Tester Questions**:
1. What happens if [edge case 1]?
2. How do we verify [behavior 2]?
3. What's the expected behavior when [scenario 3]?
**Answers**:
1. [Answer to question 1]
2. [Answer to question 2]
3. [Answer to question 3]
**Example**:
**Q**: What happens if circuit opens and closes rapidly (flapping)?
**A**: Circuit requires 2 stable loops in CLOSED before considering fully recovered
**Q**: How do we test auto-recovery?
**A**: Integration test: force HALF_OPEN state, simulate progress, verify CLOSED
---
## 4. Implementation Approach (Developer)
How will this be built? What are the technical constraints?
**Approach**:
- [High-level implementation strategy]
- [Key components to modify]
- [Dependencies or prerequisites]
**Constraints**:
- [Technical limitation 1]
- [Technical limitation 2]
**Example**:
**Approach**:
- Modify `record_loop_result()` to track recovery attempts
- Add `recovery_count` field to circuit breaker state
- Implement recovery validation logic in state transitions
**Constraints**:
- Must maintain backward compatibility with existing state files
- Recovery logic must not slow down normal loop execution
---
## 5. Specification by Example (All Participants)
Concrete scenarios using Given/When/Then format.
### Scenario 1: [Scenario Name]
**Given**:
- [Initial condition 1]
- [Initial condition 2]
**When**: [Action or trigger]
**Then**:
- [Expected outcome 1]
- [Expected outcome 2]
**And**:
- [Additional verification]
**Example**:
### Scenario 1: Auto-Recovery from HALF_OPEN
**Given**:
- Circuit breaker is in HALF_OPEN state
- consecutive_no_progress is 2
- last_progress_loop was loop #10
**When**: Loop #13 completes with 3 files changed
**Then**:
- Circuit breaker transitions to CLOSED state
- consecutive_no_progress resets to 0
- last_progress_loop updates to 13
- Log message: "✅ CIRCUIT BREAKER: Normal Operation - Progress detected, circuit recovered"
**And**:
- Circuit breaker history records the HALF_OPEN → CLOSED transition
- .circuit_breaker_state file contains state: "CLOSED"
---
### Scenario 2: [Another Scenario]
[Repeat format above for 3-5 key scenarios]
---
## 6. Edge Cases and Error Conditions (Tester-Led)
What unusual situations must be handled?
**Edge Cases**:
1. [Edge case 1] → [Expected behavior]
2. [Edge case 2] → [Expected behavior]
3. [Edge case 3] → [Expected behavior]
**Error Conditions**:
1. [Error condition 1] → [Error handling strategy]
2. [Error condition 2] → [Error handling strategy]
**Example**:
**Edge Cases**:
1. Circuit opens and closes in same second → Track transitions, no timestamp collision
2. Recovery during rate limit wait → Allow recovery, don't block on rate limit
3. File changes detected but tests fail → Don't consider full recovery, stay in HALF_OPEN
**Error Conditions**:
1. Circuit state file corrupted → Reinitialize to CLOSED, log warning
2. jq command not available → Fallback to manual parsing or disable circuit breaker
---
## 7. Test Strategy (Tester)
How will we verify this works?
**Unit Tests**:
- [ ] [Unit test 1]
- [ ] [Unit test 2]
**Integration Tests**:
- [ ] [Integration test 1]
- [ ] [Integration test 2]
**Manual Tests**:
- [ ] [Manual verification 1]
**Example**:
**Unit Tests**:
- [x] Test state transition logic: HALF_OPEN + progress → CLOSED
- [x] Test state persistence across function calls
**Integration Tests**:
- [x] Full loop cycle: trigger HALF_OPEN, simulate recovery, verify CLOSED
- [x] Verify log messages appear with correct formatting
- [x] Test recovery with real file changes via git
**Manual Tests**:
- [ ] Run ralph-monitor during recovery and observe state changes
- [ ] Verify .circuit_breaker_history contains transition records
---
## 8. Non-Functional Requirements
Performance, security, usability considerations.
**Performance**:
- [Requirement 1]
- [Requirement 2]
**Security**:
- [Requirement 1]
**Usability**:
- [Requirement 1]
**Example**:
**Performance**:
- Recovery detection must complete in < 100ms
- No memory leaks from repeated state transitions
**Security**:
- State files must not expose sensitive project information
- Circuit breaker must not bypass API rate limits
**Usability**:
- Recovery messages must be clear and actionable
- User should understand why recovery occurred
---
## 9. Definition of Done (All Participants)
When can we consider this feature complete?
**Checklist**:
- [ ] Code implemented and reviewed
- [ ] All unit tests passing
- [ ] All integration tests passing
- [ ] Edge cases handled and tested
- [ ] Documentation updated
- [ ] Examples added
- [ ] Manually tested in realistic scenario
- [ ] Merged to main branch
---
## 10. Follow-Up Actions
What needs to happen next?
**Action Items**:
- [ ] [Person] - [Action] - [Deadline]
- [ ] [Person] - [Action] - [Deadline]
**Example**:
- [x] Developer - Implement recovery logic - 2025-10-02
- [x] Tester - Write integration tests - 2025-10-02
- [x] Product Owner - Review and approve scenarios - 2025-10-03
---
## Example Workshop: Rate Limit Auto-Retry
**Feature**: Automatic retry on API rate limit errors
### 1. User Story
**As a** Ralph user
**I want** automatic retries on temporary API errors
**So that** transient issues don't stop my development workflow
### 2. Acceptance Criteria
- [x] Ralph detects "rate_limit_error" in Claude output
- [x] Ralph waits appropriate time before retry (5 minutes)
- [x] Ralph limits retries to 3 attempts
- [x] Ralph falls back to user prompt on persistent failure
- [x] Retry attempts are logged clearly
### 3. Questions from Tester
**Q**: What counts as a "rate limit error" vs other errors?
**A**: Specific string "rate_limit_error" or "429" status code in output
**Q**: Should retries count against hourly call limit?
**A**: Yes, retry attempts consume call quota
**Q**: What if user Ctrl+C during wait period?
**A**: Graceful shutdown, save state, allow resume
### 4. Implementation Approach
**Approach**:
- Add retry logic to `execute_claude_code()` function
- Implement exponential backoff (5 min → 10 min → 15 min)
- Store retry state in `.retry_state` file
- Add retry counter to status.json
**Constraints**:
- Must work with existing rate limit tracking
- Cannot bypass circuit breaker
- Retries must respect API 5-hour limit
### 5. Specification by Example
**Scenario 1: Successful Retry**
**Given**:
- Ralph executes Claude Code at loop #5
- Claude returns "rate_limit_error: please retry"
- Retry count is 0
**When**: Ralph detects the rate limit error
**Then**:
- Ralph logs "Rate limit detected, attempt 1/3. Waiting 5 minutes..."
- Ralph sleeps for 300 seconds
- Ralph retries Claude Code execution
- If successful: continues normally, resets retry count to 0
**Scenario 2: Persistent Failure**
**Given**:
- Ralph has retried 3 times already
- Each retry resulted in "rate_limit_error"
**When**: 4th execution also returns rate limit error
**Then**:
- Ralph logs "Retry limit exceeded (3 attempts)"
- Ralph prompts user: "Continue waiting? (y/n)"
- User decision determines next action (exit or continue)
### 6. Edge Cases
1. Rate limit error during first loop → Retry works immediately
2. User interrupts during wait → Clean shutdown, state preserved
3. Different error after retry → Handle as normal error, don't increment retry count
4. Rate limit resolves after 1st retry → Reset counter, continue normally
### 7. Test Strategy
**Unit Tests**:
- [x] Test retry detection logic
- [x] Test exponential backoff calculation
- [x] Test retry limit enforcement
**Integration Tests**:
- [x] Mock rate limit error, verify retry happens
- [x] Mock 3 failures, verify fallback to user prompt
- [x] Verify retry state persists across restarts
### 8. Definition of Done
- [x] Code implemented in ralph_loop.sh
- [x] Unit tests added to tests/unit/
- [x] Integration tests added to tests/integration/
- [x] Documentation updated in README.md
- [x] Manually tested with mock API errors
- [x] Merged to main
---
## Workshop Best Practices
### Before the Workshop
1. **Prepare**: Send user story to participants 24 hours ahead
2. **Context**: Provide relevant background (why this feature now?)
3. **Time-box**: Schedule 30-60 minutes max
### During the Workshop
1. **Focus**: One feature at a time
2. **Concrete**: Use real examples, not abstract descriptions
3. **Questions**: Encourage tester to ask "what could go wrong?"
4. **Document**: Capture decisions in real-time
### After the Workshop
1. **Summarize**: Send notes to all participants
2. **Track**: Create tasks for action items
3. **Reference**: Use scenarios for test cases
### Red Flags
❌ "We'll figure it out during implementation"
❌ "That's edge case, we'll handle it later"
❌ Vague accep
gitextract_5qewtfdp/ ├── .claude/ │ └── memories/ │ └── project_memory.json ├── .gitattributes ├── .github/ │ ├── aw/ │ │ └── actions-lock.json │ └── workflows/ │ ├── claude-code-review.yml │ ├── claude.yml │ ├── opencode-review.yml │ ├── test.yml │ ├── triage-incoming-issues.lock.yml │ └── triage-incoming-issues.md ├── .gitignore ├── CLAUDE.md ├── CONTRIBUTING.md ├── IMPLEMENTATION_PLAN.md ├── IMPLEMENTATION_STATUS.md ├── LICENSE ├── README.md ├── SPECIFICATION_WORKSHOP.md ├── TESTING.md ├── create_files.sh ├── docs/ │ ├── archive/ │ │ └── 2025-10-milestones/ │ │ ├── EXPERT_PANEL_REVIEW.md │ │ ├── PHASE1_COMPLETION.md │ │ ├── PHASE2_COMPLETION.md │ │ ├── README.md │ │ ├── STATUS.md │ │ ├── TEST_IMPLEMENTATION_SUMMARY.md │ │ └── USE_CASES.md │ ├── code-review/ │ │ ├── 2026-01-08-cli-parsing-tests-review.md │ │ └── 2026-01-08-phase-1.1-modern-cli-review.md │ ├── generated/ │ │ └── .gitkeep │ └── user-guide/ │ ├── 01-quick-start.md │ ├── 02-understanding-ralph-files.md │ ├── 03-writing-requirements.md │ └── README.md ├── examples/ │ ├── rest-api/ │ │ ├── .ralph/ │ │ │ ├── PROMPT.md │ │ │ ├── fix_plan.md │ │ │ └── specs/ │ │ │ └── api.md │ │ └── README.md │ └── simple-cli-tool/ │ ├── .ralph/ │ │ ├── PROMPT.md │ │ └── fix_plan.md │ └── README.md ├── install.sh ├── lib/ │ ├── circuit_breaker.sh │ ├── date_utils.sh │ ├── enable_core.sh │ ├── file_protection.sh │ ├── response_analyzer.sh │ ├── task_sources.sh │ ├── timeout_utils.sh │ └── wizard_utils.sh ├── logs/ │ └── .gitkeep ├── migrate_to_ralph_folder.sh ├── package.json ├── ralph_enable.sh ├── ralph_enable_ci.sh ├── ralph_import.sh ├── ralph_loop.sh ├── ralph_monitor.sh ├── sample-prd.md ├── setup.sh ├── specs/ │ └── stdlib/ │ └── .gitkeep ├── src/ │ └── .gitkeep ├── templates/ │ ├── .gitignore │ ├── AGENT.md │ ├── PROMPT.md │ ├── fix_plan.md │ ├── ralphrc.template │ └── specs/ │ └── .gitkeep ├── tests/ │ ├── helpers/ │ │ ├── fixtures.bash │ │ ├── mocks.bash │ │ └── test_helper.bash │ ├── integration/ │ │ ├── test_edge_cases.bats │ │ ├── test_installation.bats │ │ ├── test_loop_execution.bats │ │ ├── test_prd_import.bats │ │ └── test_project_setup.bats │ ├── test_error_detection.sh │ ├── test_stuck_loop_detection.sh │ └── unit/ │ ├── test_circuit_breaker_recovery.bats │ ├── test_cli_modern.bats │ ├── test_cli_parsing.bats │ ├── test_enable_core.bats │ ├── test_exit_detection.bats │ ├── test_file_protection.bats │ ├── test_integrity_check.bats │ ├── test_json_parsing.bats │ ├── test_ralph_enable.bats │ ├── test_rate_limiting.bats │ ├── test_session_continuity.bats │ ├── test_task_sources.bats │ └── test_wizard_utils.bats └── uninstall.sh
Condensed preview — 91 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,159K chars).
[
{
"path": ".claude/memories/project_memory.json",
"chars": 349,
"preview": "{\n \"memories\": [],\n \"manual_memories\": [],\n \"realtime_memories\": [\n {\n \"type\": \"message\",\n \"content\": \"C"
},
{
"path": ".gitattributes",
"chars": 63,
"preview": ".github/workflows/*.lock.yml linguist-generated=true merge=ours"
},
{
"path": ".github/aw/actions-lock.json",
"chars": 360,
"preview": "{\n \"entries\": {\n \"actions/github-script@v8\": {\n \"repo\": \"actions/github-script\",\n \"version\": \"v8\",\n \""
},
{
"path": ".github/workflows/claude-code-review.yml",
"chars": 4179,
"preview": "name: Claude Code Review\n\non:\n # Using pull_request_target to run with base repo permissions (access to secrets)\n # Th"
},
{
"path": ".github/workflows/claude.yml",
"chars": 2100,
"preview": "name: Claude Code\n\non:\n issue_comment:\n types: [created]\n pull_request_review_comment:\n types: [created]\n issue"
},
{
"path": ".github/workflows/opencode-review.yml",
"chars": 5202,
"preview": "name: OpenCode PR Review\n\non:\n # Using pull_request (not pull_request_target) because the OpenCode action\n # doesn't s"
},
{
"path": ".github/workflows/test.yml",
"chars": 6321,
"preview": "name: Test Suite\n\non:\n push:\n branches: [ main, develop ]\n pull_request:\n branches: [ main ]\n\nenv:\n # Coverage "
},
{
"path": ".github/workflows/triage-incoming-issues.lock.yml",
"chars": 59404,
"preview": "#\n# ___ _ _ \n# / _ \\ | | (_) \n# | |_| | __ _ ___ _ __ | |_ _ ___ \n#"
},
{
"path": ".github/workflows/triage-incoming-issues.md",
"chars": 1405,
"preview": "---\non:\n issues:\n types: [opened]\n workflow_dispatch:\n roles: all\npermissions:\n contents: read\n actions: read\nsa"
},
{
"path": ".gitignore",
"chars": 892,
"preview": "# Ralph generated files (inside .ralph/ subfolder)\n.ralph/.call_count\n.ralph/.last_reset\n.ralph/.exit_signals\n.ralph/sta"
},
{
"path": "CLAUDE.md",
"chars": 35962,
"preview": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## "
},
{
"path": "CONTRIBUTING.md",
"chars": 16638,
"preview": "# Contributing to Ralph for Claude Code\n\nThank you for your interest in contributing to Ralph! This guide will help you "
},
{
"path": "IMPLEMENTATION_PLAN.md",
"chars": 8477,
"preview": "# Ralph for Claude Code - Implementation Plan\n\n**Version**: v0.9.8 | **Tests**: 276 passing (100% pass rate) | **CI/CD**"
},
{
"path": "IMPLEMENTATION_STATUS.md",
"chars": 8822,
"preview": "# Implementation Status Summary\n\n**Last Updated**: 2026-01-10\n**Version**: v0.9.8\n**Overall Status**: Phase 1 in progres"
},
{
"path": "LICENSE",
"chars": 1067,
"preview": "MIT License\n\nCopyright (c) 2025 Frank Bria\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
},
{
"path": "README.md",
"chars": 36149,
"preview": "# Ralph for Claude Code\n\n[](ht"
},
{
"path": "SPECIFICATION_WORKSHOP.md",
"chars": 11407,
"preview": "# Ralph Specification Workshop Guide\n\n**Based on**: Janet Gregory's \"Three Amigos\" collaborative testing approach\n**Purp"
},
{
"path": "TESTING.md",
"chars": 24116,
"preview": "# Testing Guide for Ralph\n\nThis guide provides comprehensive documentation for the Ralph test suite, helping contributor"
},
{
"path": "create_files.sh",
"chars": 22163,
"preview": "#!/bin/bash\n\n# Quick script to create all Ralph files in your GitHub repo\nset -e\n\necho \"🚀 Creating Ralph for Claude Code"
},
{
"path": "docs/archive/2025-10-milestones/EXPERT_PANEL_REVIEW.md",
"chars": 22022,
"preview": "# 🎯 Expert Panel Review: Ralph Efficiency & Loop Prevention\n\n**Review Date**: 2025-09-30\n**Panel Mode**: Critique & Disc"
},
{
"path": "docs/archive/2025-10-milestones/PHASE1_COMPLETION.md",
"chars": 9564,
"preview": "# Phase 1 Implementation - Complete ✅\n\n**Completion Date**: 2025-10-01\n**Status**: All Phase 1 critical fixes implemente"
},
{
"path": "docs/archive/2025-10-milestones/PHASE2_COMPLETION.md",
"chars": 14467,
"preview": "# Phase 2 Implementation - Complete ✅\n\n**Completion Date**: 2025-10-01\n**Status**: All Phase 2 high-priority enhancement"
},
{
"path": "docs/archive/2025-10-milestones/README.md",
"chars": 1754,
"preview": "# Historical Documentation Archive - October 2025 Milestones\n\n**Archive Date**: 2025-12-31\n**Reason**: Historical milest"
},
{
"path": "docs/archive/2025-10-milestones/STATUS.md",
"chars": 4099,
"preview": "# 🎯 Ralph Test Implementation Status\n\n## Executive Summary\n\n**Completed**: Phase 1-2 Test Infrastructure + Core Unit Tes"
},
{
"path": "docs/archive/2025-10-milestones/TEST_IMPLEMENTATION_SUMMARY.md",
"chars": 8640,
"preview": "# Ralph Test Implementation Summary\n\n**Date**: 2025-09-30\n**Status**: Phase 1 Complete - Test Infrastructure & Core Unit"
},
{
"path": "docs/archive/2025-10-milestones/USE_CASES.md",
"chars": 16710,
"preview": "# Ralph Use Cases\n\n**Author**: Based on Alistair Cockburn's use case methodology\n**Date**: 2025-10-01\n**Purpose**: Defin"
},
{
"path": "docs/code-review/2026-01-08-cli-parsing-tests-review.md",
"chars": 5970,
"preview": "# Code Review Report: CLI Parsing Tests\n\n**Date:** 2026-01-08\n**Reviewer:** Code Review Agent\n**Component:** CLI Argumen"
},
{
"path": "docs/code-review/2026-01-08-phase-1.1-modern-cli-review.md",
"chars": 20948,
"preview": "# Code Review Report: Phase 1.1 Modern CLI Commands\n**Ready for Production**: ⚠️ **Yes, with Recommended Improvements**\n"
},
{
"path": "docs/generated/.gitkeep",
"chars": 183,
"preview": "# This file ensures the docs/generated/ directory is tracked by git\n# Note: Generated documentation files are ignored by"
},
{
"path": "docs/user-guide/01-quick-start.md",
"chars": 5063,
"preview": "# Quick Start: Your First Ralph Project\n\nThis tutorial walks you through enabling Ralph on an existing project and runni"
},
{
"path": "docs/user-guide/02-understanding-ralph-files.md",
"chars": 8304,
"preview": "# Understanding Ralph Files\n\nAfter running `ralph-enable`, `ralph-import`, or `ralph-setup`, you'll have a `.ralph/` dir"
},
{
"path": "docs/user-guide/03-writing-requirements.md",
"chars": 7917,
"preview": "# Writing Effective Requirements\n\nRalph works best when it understands what you want. This guide shows you how to write "
},
{
"path": "docs/user-guide/README.md",
"chars": 1806,
"preview": "# Ralph User Guide\n\nThis guide helps you get started with Ralph and understand how to configure it effectively for your "
},
{
"path": "examples/rest-api/.ralph/PROMPT.md",
"chars": 1107,
"preview": "# Ralph Development Instructions\n\n## Context\nYou are Ralph, building a REST API for a bookstore inventory management sys"
},
{
"path": "examples/rest-api/.ralph/fix_plan.md",
"chars": 1175,
"preview": "# Fix Plan - Bookstore API\n\n## Priority 1: Foundation\n- [ ] Set up FastAPI application structure with proper folder orga"
},
{
"path": "examples/rest-api/.ralph/specs/api.md",
"chars": 4412,
"preview": "# API Specification\n\n## Base URL\nAll endpoints are prefixed with `/api/v1`\n\n## Authentication\n- POST, PUT, DELETE endpoi"
},
{
"path": "examples/rest-api/README.md",
"chars": 2732,
"preview": "# Example: REST API with Specifications\n\nThis example shows a medium-complexity Ralph configuration for a bookstore REST"
},
{
"path": "examples/simple-cli-tool/.ralph/PROMPT.md",
"chars": 1603,
"preview": "# Ralph Development Instructions\n\n## Context\nYou are Ralph, building a command-line todo application in Node.js. This is"
},
{
"path": "examples/simple-cli-tool/.ralph/fix_plan.md",
"chars": 822,
"preview": "# Fix Plan - Todo CLI\n\n## Priority 1: Foundation\n- [ ] Set up package.json with commander and jest dependencies\n- [ ] Cr"
},
{
"path": "examples/simple-cli-tool/README.md",
"chars": 1697,
"preview": "# Example: Simple CLI Tool\n\nThis example shows a minimal Ralph configuration for a command-line todo application built w"
},
{
"path": "install.sh",
"chars": 10440,
"preview": "#!/bin/bash\n\n# Ralph for Claude Code - Global Installation Script\nset -e\n\n# Configuration\nINSTALL_DIR=\"$HOME/.local/bin\""
},
{
"path": "lib/circuit_breaker.sh",
"chars": 19064,
"preview": "#!/bin/bash\n# Circuit Breaker Component for Ralph\n# Prevents runaway token consumption by detecting stagnation\n# Based o"
},
{
"path": "lib/date_utils.sh",
"chars": 3637,
"preview": "#!/usr/bin/env bash\n\n# date_utils.sh - Cross-platform date utility functions\n# Provides consistent date formatting and a"
},
{
"path": "lib/enable_core.sh",
"chars": 25066,
"preview": "#!/usr/bin/env bash\n\n# enable_core.sh - Shared logic for ralph enable commands\n# Provides idempotency checks, safe file "
},
{
"path": "lib/file_protection.sh",
"chars": 1627,
"preview": "#!/usr/bin/env bash\n\n# file_protection.sh - File integrity validation for Ralph projects\n# Validates that critical Ralph"
},
{
"path": "lib/response_analyzer.sh",
"chars": 40157,
"preview": "#!/bin/bash\n# Response Analyzer Component for Ralph\n# Analyzes Claude Code output to detect completion signals, test-onl"
},
{
"path": "lib/task_sources.sh",
"chars": 16215,
"preview": "#!/usr/bin/env bash\n\n# task_sources.sh - Task import utilities for Ralph enable\n# Supports importing tasks from beads, G"
},
{
"path": "lib/timeout_utils.sh",
"chars": 4213,
"preview": "#!/usr/bin/env bash\n\n# timeout_utils.sh - Cross-platform timeout utility functions\n# Provides consistent timeout command"
},
{
"path": "lib/wizard_utils.sh",
"chars": 14955,
"preview": "#!/usr/bin/env bash\n\n# wizard_utils.sh - Interactive prompt utilities for Ralph enable wizard\n# Provides consistent, use"
},
{
"path": "logs/.gitkeep",
"chars": 160,
"preview": "# This file ensures the logs/ directory is tracked by git\n# Note: Actual log files are ignored by .gitignore\n# This dire"
},
{
"path": "migrate_to_ralph_folder.sh",
"chars": 14644,
"preview": "#!/bin/bash\n\n# Migration script for Ralph projects from flat structure to .ralph/ subfolder\n# Version: 2.0.0\n#\n# This sc"
},
{
"path": "package.json",
"chars": 896,
"preview": "{\n \"name\": \"ralph-claude-code\",\n \"version\": \"1.0.0\",\n \"description\": \"> **Autonomous AI development loop with intelli"
},
{
"path": "ralph_enable.sh",
"chars": 18293,
"preview": "#!/bin/bash\n\n# Ralph Enable - Interactive Wizard for Existing Projects\n# Adds Ralph configuration to an existing codebas"
},
{
"path": "ralph_enable_ci.sh",
"chars": 12553,
"preview": "#!/bin/bash\n\n# Ralph Enable CI - Non-Interactive Version for Automation\n# Adds Ralph configuration with sensible default"
},
{
"path": "ralph_import.sh",
"chars": 21743,
"preview": "#!/bin/bash\n\n# Ralph Import - Convert PRDs to Ralph format using Claude Code\n# Version: 0.9.8 - Modern CLI support with "
},
{
"path": "ralph_loop.sh",
"chars": 90553,
"preview": "#!/bin/bash\n\n# Claude Code Ralph Loop with Rate Limiting and Documentation\n# Adaptation of the Ralph technique for Claud"
},
{
"path": "ralph_monitor.sh",
"chars": 4724,
"preview": "#!/bin/bash\n\n# Ralph Status Monitor - Live terminal dashboard for the Ralph loop\n# Note: set -e intentionally removed — "
},
{
"path": "sample-prd.md",
"chars": 1667,
"preview": "# Task Management Web App - Product Requirements Document\n\n## Overview\nBuild a modern task management web application si"
},
{
"path": "setup.sh",
"chars": 4489,
"preview": "#!/bin/bash\n\n# Ralph Project Setup Script\n# Creates project structure with Ralph-specific files in .ralph/ subfolder\nset"
},
{
"path": "specs/stdlib/.gitkeep",
"chars": 124,
"preview": "# This file ensures the specs/stdlib/ directory is tracked by git\n# Remove this file when you add actual specification f"
},
{
"path": "src/.gitkeep",
"chars": 108,
"preview": "# This file ensures the src/ directory is tracked by git\n# Remove this file when you add actual source files"
},
{
"path": "templates/.gitignore",
"chars": 781,
"preview": "# Ralph generated files (inside .ralph/ subfolder)\n.ralph/.call_count\n.ralph/.last_reset\n.ralph/.exit_signals\n.ralph/sta"
},
{
"path": "templates/AGENT.md",
"chars": 5235,
"preview": "# Agent Build Instructions\n\n## Project Setup\n```bash\n# Install dependencies (example for Node.js project)\nnpm install\n\n#"
},
{
"path": "templates/PROMPT.md",
"chars": 8672,
"preview": "# Ralph Development Instructions\n\n## Context\nYou are Ralph, an autonomous AI development agent working on a [YOUR PROJEC"
},
{
"path": "templates/fix_plan.md",
"chars": 707,
"preview": "# Ralph Fix Plan\n\n## High Priority\n- [ ] Set up basic project structure and build system\n- [ ] Define core data structur"
},
{
"path": "templates/ralphrc.template",
"chars": 4522,
"preview": "# .ralphrc - Ralph project configuration\n# Generated by: ralph enable\n# Documentation: https://github.com/frankbria/ralp"
},
{
"path": "templates/specs/.gitkeep",
"chars": 136,
"preview": "# This file ensures the templates/specs/ directory is tracked by git\n# Remove this file when you add actual template spe"
},
{
"path": "tests/helpers/fixtures.bash",
"chars": 11155,
"preview": "#!/usr/bin/env bash\n# Fixture Data for Ralph Test Suite\n\n# Sample PRD Document (Markdown)\ncreate_sample_prd_md() {\n l"
},
{
"path": "tests/helpers/mocks.bash",
"chars": 6723,
"preview": "#!/usr/bin/env bash\n# Mock Functions for Ralph Test Suite\n\n# Mock Claude Code CLI\nexport MOCK_CLAUDE_SUCCESS=true\nexport"
},
{
"path": "tests/helpers/test_helper.bash",
"chars": 5378,
"preview": "#!/usr/bin/env bash\n# Test Helper Utilities for Ralph Test Suite\n\n# Helper: Fail with message (for use in assertions)\nfa"
},
{
"path": "tests/integration/test_edge_cases.bats",
"chars": 17945,
"preview": "#!/usr/bin/env bats\n# Edge case tests for Ralph loop execution\n# Tests boundary conditions, error scenarios, and unusual"
},
{
"path": "tests/integration/test_installation.bats",
"chars": 17479,
"preview": "#!/usr/bin/env bats\n# Integration tests for Ralph install.sh - Global Installation Script\n\nload '../helpers/test_helper'"
},
{
"path": "tests/integration/test_loop_execution.bats",
"chars": 13704,
"preview": "#!/usr/bin/env bats\n# Integration tests for Ralph loop execution with response analysis and circuit breaker\n\nload '../he"
},
{
"path": "tests/integration/test_prd_import.bats",
"chars": 33700,
"preview": "#!/usr/bin/env bats\n# Integration tests for ralph-import command functionality\n# Tests PRD to Ralph format conversion wi"
},
{
"path": "tests/integration/test_project_setup.bats",
"chars": 18450,
"preview": "#!/usr/bin/env bats\n# Integration tests for Ralph project setup (setup.sh)\n# Tests directory creation, template copying,"
},
{
"path": "tests/test_error_detection.sh",
"chars": 6489,
"preview": "#!/bin/bash\n# Test script for error detection fix\n# Validates that JSON field names don't trigger false positives\n#\n# TE"
},
{
"path": "tests/test_stuck_loop_detection.sh",
"chars": 6832,
"preview": "#!/bin/bash\n# Test script for detect_stuck_loop function\n# Validates that the stuck loop detection uses two-stage filter"
},
{
"path": "tests/unit/test_circuit_breaker_recovery.bats",
"chars": 14409,
"preview": "#!/usr/bin/env bats\n# Unit Tests for Circuit Breaker Auto-Recovery (Issue #160)\n# Tests cooldown timer, auto-reset, and "
},
{
"path": "tests/unit/test_cli_modern.bats",
"chars": 65978,
"preview": "#!/usr/bin/env bats\n# Unit tests for modern CLI command enhancements\n# TDD: Write tests first, then implement\n\nload '../"
},
{
"path": "tests/unit/test_cli_parsing.bats",
"chars": 15570,
"preview": "#!/usr/bin/env bats\n# Unit tests for CLI argument parsing in ralph_loop.sh\n# Linked to GitHub Issue #10\n# TDD: Tests wri"
},
{
"path": "tests/unit/test_enable_core.bats",
"chars": 13837,
"preview": "#!/usr/bin/env bats\n# Unit tests for lib/enable_core.sh\n# Tests idempotency, safe file creation, project detection, and "
},
{
"path": "tests/unit/test_exit_detection.bats",
"chars": 44061,
"preview": "#!/usr/bin/env bats\n# Unit Tests for Exit Detection Logic\n\nload '../helpers/test_helper'\n\nsetup() {\n # Source helper "
},
{
"path": "tests/unit/test_file_protection.bats",
"chars": 5673,
"preview": "#!/usr/bin/env bats\n# Unit tests for lib/file_protection.sh\n# Tests file integrity validation and reporting for Ralph pr"
},
{
"path": "tests/unit/test_integrity_check.bats",
"chars": 4497,
"preview": "#!/usr/bin/env bats\n# Unit tests for pre-loop integrity check in ralph_loop.sh (Issue #149)\n# Verifies that the loop hal"
},
{
"path": "tests/unit/test_json_parsing.bats",
"chars": 32555,
"preview": "#!/usr/bin/env bats\n# Unit tests for JSON output parsing in response_analyzer.sh\n# TDD: Write tests first, then implemen"
},
{
"path": "tests/unit/test_ralph_enable.bats",
"chars": 9539,
"preview": "#!/usr/bin/env bats\n# Integration tests for ralph_enable.sh and ralph_enable_ci.sh\n# Tests the full enable wizard flow a"
},
{
"path": "tests/unit/test_rate_limiting.bats",
"chars": 4460,
"preview": "#!/usr/bin/env bats\n# Unit Tests for Rate Limiting Logic\n\nload '../helpers/test_helper'\n\n# Source ralph functions (we ne"
},
{
"path": "tests/unit/test_session_continuity.bats",
"chars": 17920,
"preview": "#!/usr/bin/env bats\n# Unit tests for session continuity enhancements\n# TDD: Tests for session lifecycle management acros"
},
{
"path": "tests/unit/test_task_sources.bats",
"chars": 6655,
"preview": "#!/usr/bin/env bats\n# Unit tests for lib/task_sources.sh\n# Tests beads integration, GitHub integration, PRD extraction, "
},
{
"path": "tests/unit/test_wizard_utils.bats",
"chars": 7112,
"preview": "#!/usr/bin/env bats\n# Unit tests for wizard_utils.sh\n# Tests for stdout/stderr separation to prevent ANSI code capture i"
},
{
"path": "uninstall.sh",
"chars": 5540,
"preview": "#!/bin/bash\n\n# Ralph for Claude Code - Uninstallation Script\nset -e\n\n# Configuration\nINSTALL_DIR=\"$HOME/.local/bin\"\nRALP"
}
]
About this extraction
This page contains the full source code of the frankbria/ralph-claude-code GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 91 files (1.0 MB), approximately 276.1k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.