Skip to content

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Dec 22, 2025

Summary

  • Build+ and Plan+ now properly inherit OpenCode's base prompts
  • Plan+ dynamically extracts plan.txt from OpenCode binary during setup
  • Default build and plan agents disabled to avoid Tab cycle confusion
  • Plan+ appears before Build+ in Tab order

Changes

  • Build+: Added note explaining OpenCode auto-injects base prompts (no duplication needed)
  • Plan+: Added placeholder markers for dynamic plan.txt injection
  • extract-opencode-prompts.sh: New script to extract prompts from OpenCode binary
  • generate-opencode-agents.sh: Disables default agents, sets Plan+ before Build+
  • setup.sh: Calls extraction before deployment, injects content into Plan+

How it works

When users update OpenCode and run ./setup.sh:

  1. Prompts are extracted from the OpenCode binary
  2. Cached in ~/.aidevops/cache/opencode-prompts/
  3. Plan+ gets the latest plan.txt content injected automatically

Summary by CodeRabbit

  • Chores
    • Updated Plan+ agent workflow configuration with new output constraints and planning guidance.
    • Reordered agent initialization priority with Plan+ now primary.
    • Disabled legacy agent variants.
    • Added infrastructure scripts for system integration and configuration management.

✏️ Tip: You can customize this high-level summary in your review settings.

- Build+: Remove redundant inherited content (OpenCode auto-injects base prompts)
- Plan+: Add placeholder for dynamic plan.txt injection from OpenCode binary
- Add extract-opencode-prompts.sh to extract prompts from OpenCode binary
- Update setup.sh to extract prompts before deployment and inject into Plan+
- Disable default 'build' and 'plan' agents in favor of Build+ and Plan+

When users update OpenCode and run setup.sh, Plan+ automatically gets the
latest plan.txt system-reminder content, ensuring compatibility with
OpenCode updates.
@marcusquinn marcusquinn merged commit 3b7b990 into main Dec 22, 2025
5 of 7 checks passed
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

These changes introduce prompt extraction automation and agent configuration updates. A new utility script extracts OpenCode model-specific prompts to a cache directory; setup automation injects extracted content into Plan+ and reorders agent precedence, with legacy agents disabled by default.

Changes

Cohort / File(s) Summary
Agent Documentation
.agent/build-plus.md, .agent/plan-plus.md
build-plus.md: Adds informational HTML comment noting OpenCode-injected base prompts. plan-plus.md: Introduces plan-awareness block with read-only constraints, rewrites CRITICAL notice to softer NOTE, adds Output Constraints section for plan generation style.
Agent Configuration
.agent/scripts/generate-opencode-agents.sh
Reorders AGENT_ORDER to prioritize Plan+ before Build+; disables legacy Build+ and Plan+ agents (marked with {"disable": True}) in two locations with user-facing confirmation.
Prompt Extraction Utility
.agent/scripts/extract-opencode-prompts.sh
New Bash script that locates opencode binary (searches bun, system paths, and symlinks), extracts embedded prompts (plan_default, build_switch_default, max_steps_default) between delimiters, writes to ~/.aidevops/cache/opencode-prompts, captures version, and logs status with colored output.
Setup Automation
setup.sh
Adds extract_opencode_prompts() function invoking .agent/scripts/extract-opencode-prompts.sh; invokes extraction after cleanup and before deployment; conditionally injects plan-reminder.txt content into Plan+ via awk if placeholder OPENCODE-PLAN-REMINDER-INJECT is present.

Sequence Diagram

sequenceDiagram
    participant Setup as setup.sh
    participant Extract as extract-opencode-prompts.sh
    participant OpenCode as opencode binary
    participant Cache as ~/.aidevops/cache
    participant PlanPlus as plan-plus.md
    
    Setup->>Setup: Main sequence begins
    Setup->>Extract: Call extract_opencode_prompts()
    Extract->>Extract: Locate opencode binary
    Extract->>OpenCode: Query --version
    OpenCode-->>Extract: Return version
    Extract->>Extract: Extract prompts from binary<br/>(plan_default, build_switch_default)
    Extract->>Cache: Write prompts, version, timestamp
    Extract-->>Setup: Return success (non-fatal on error)
    Setup->>Setup: Continue setup flow
    Setup->>PlanPlus: Inject plan-reminder content<br/>(if placeholder exists)
    PlanPlus->>PlanPlus: Replace OPENCODE-PLAN-REMINDER-INJECT
    Setup->>Setup: Complete setup with injected agents
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Heterogeneous changes spanning documentation updates, new utility script, agent configuration reordering, and setup automation with conditional injection logic. The prompt extraction and injection flows introduce new logic requiring careful review of path handling, cache management, and awk-based string replacement.

Poem

✨ Prompts extracted, cached, and true,

Setup automation flows anew,

Plan+ awakened with careful grace,

Legacy agents know their place,

DevOps dreams in bash—we brew! 🚀

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/inherit-opencode-agent-prompts

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b9e9e7 and ba6cbde.

📒 Files selected for processing (5)
  • .agent/build-plus.md
  • .agent/plan-plus.md
  • .agent/scripts/extract-opencode-prompts.sh
  • .agent/scripts/generate-opencode-agents.sh
  • setup.sh

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@marcusquinn marcusquinn deleted the feature/inherit-opencode-agent-prompts branch December 22, 2025 22:47
@gemini-code-assist
Copy link

Summary of Changes

Hello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Build+ and Plan+ agents by integrating them more deeply with the core OpenCode system. It introduces a robust mechanism to dynamically extract and inject OpenCode's base prompts, ensuring these enhanced agents always use the latest foundational instructions. Additionally, it refines the agent selection experience by reordering and disabling redundant default agents, streamlining the user workflow and improving overall clarity.

Highlights

  • Prompt Inheritance: Build+ and Plan+ agents now correctly inherit base prompts from OpenCode, ensuring consistency and up-to-date behavior with the core system.
  • Dynamic Plan+ Prompts: The Plan+ agent dynamically extracts its plan.txt system reminder directly from the OpenCode binary during setup, eliminating manual synchronization and ensuring it always uses the latest instructions.
  • Agent Order and Disablement: The tab order for agents is adjusted to place Plan+ before Build+, and the default build and plan agents are disabled to prevent confusion with their enhanced Build+ and Plan+ counterparts.
  • New Prompt Extraction Script: A new shell script, extract-opencode-prompts.sh, has been introduced to locate the OpenCode binary and extract embedded prompts like plan_default, build_switch_default, and max_steps_default.
  • Automated Setup Integration: The setup.sh script is updated to automatically run the new prompt extraction process and inject the extracted plan.txt content into the Plan+ agent's definition during deployment.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@sonarqubecloud
Copy link

@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 148 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Mon Dec 22 22:47:25 UTC 2025: Code review monitoring started
Mon Dec 22 22:47:25 UTC 2025: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 148
Mon Dec 22 22:47:25 UTC 2025: Qlty - 0 issues found, auto-formatting applied
Mon Dec 22 22:47:27 UTC 2025: Codacy analysis completed with auto-fixes

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 148
  • VULNERABILITIES: 0

Generated on: Mon Dec 22 22:48:00 UTC 2025


Generated by AI DevOps Framework Code Review Monitoring

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a mechanism to dynamically inherit prompts from the OpenCode binary for the Build+ and Plan+ agents. This is achieved by a new script that extracts prompts from the binary during setup, and another script modification to inject this content. My review focuses on the robustness and maintainability of these new scripts. I've identified a few areas for improvement in the new shell scripts, particularly concerning the fragility of the prompt extraction logic and potential data corruption during content injection. I've provided suggestions to make these scripts more robust and portable.

Comment on lines +68 to +75
strings "$OPENCODE_BIN" | \
grep -A 500 "^${start_marker}" | \
head -n 100 | \
sed "s/^${start_marker}//" | \
sed '/^var init_/q' | \
sed '/^var init_/d' | \
sed 's/`$//' \
> "$CACHE_DIR/$output_file"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This extraction logic is very brittle as it relies on parsing the string table of the compiled opencode binary. This approach can easily break with:

  • Future versions of OpenCode.
  • Changes in Go compiler versions.
  • Different build flags.
  • Simple refactoring of variable names in the OpenCode source.

The script's assumptions about variable names (plan_default, init_...) and their order are risky.

For long-term stability, a more robust solution would be for OpenCode to provide a command to export these prompts (e.g., opencode internal export-prompts). While that's likely outside the scope of this PR, I strongly recommend adding a comment to this script highlighting the fragility of this approach for future maintainers.

Comment on lines +972 to +979
local reminder_content
reminder_content=$(cat "$plan_reminder")
# Use awk to replace the placeholder section
awk -v content="$reminder_content" '
/<!-- OPENCODE-PLAN-REMINDER-INJECT-START -->/ { print; print content; skip=1; next }
/<!-- OPENCODE-PLAN-REMINDER-INJECT-END -->/ { skip=0 }
!skip { print }
' "$plan_plus" > "$plan_plus.tmp" && mv "$plan_plus.tmp" "$plan_plus"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using awk -v content="$reminder_content" where reminder_content is read from a file can be risky. The content of the variable is interpreted as a string by awk, and any backslash escape sequences will be processed. This can lead to data corruption if the prompt text contains backslashes (e.g., in file paths or regular expressions).

A more robust method is to have awk read the content directly from the reminder file. This avoids any shell or awk variable interpolation issues.

Suggested change
local reminder_content
reminder_content=$(cat "$plan_reminder")
# Use awk to replace the placeholder section
awk -v content="$reminder_content" '
/<!-- OPENCODE-PLAN-REMINDER-INJECT-START -->/ { print; print content; skip=1; next }
/<!-- OPENCODE-PLAN-REMINDER-INJECT-END -->/ { skip=0 }
!skip { print }
' "$plan_plus" > "$plan_plus.tmp" && mv "$plan_plus.tmp" "$plan_plus"
# Use awk to replace the placeholder section, reading content from the file directly to avoid issues with special characters.
awk -v reminder_file="$plan_reminder" '
/<!-- OPENCODE-PLAN-REMINDER-INJECT-START -->/ {
print
while ((getline line < reminder_file) > 0) {
print line
}
close(reminder_file)
skip=1
next
}
/<!-- OPENCODE-PLAN-REMINDER-INJECT-END -->/ { skip=0 }
!skip { print }
' "$plan_plus" > "$plan_plus.tmp" && mv "$plan_plus.tmp" "$plan_plus"

Comment on lines +26 to +58
find_opencode_binary() {
local locations=(
"$HOME/.bun/install/global/node_modules/opencode-darwin-arm64/bin/opencode"
"$HOME/.bun/install/global/node_modules/opencode-darwin-x64/bin/opencode"
"$HOME/.bun/install/global/node_modules/opencode-linux-x64/bin/opencode"
"$HOME/.bun/install/global/node_modules/opencode-linux-arm64/bin/opencode"
"/usr/local/bin/opencode"
"$HOME/.local/bin/opencode"
)

for loc in "${locations[@]}"; do
if [[ -f "$loc" ]]; then
OPENCODE_BIN="$loc"
return 0
fi
done

# Try which as fallback
if command -v opencode &>/dev/null; then
local bin_path
bin_path=$(which opencode)
# Follow symlinks to find actual binary
if [[ -L "$bin_path" ]]; then
bin_path=$(readlink -f "$bin_path" 2>/dev/null || readlink "$bin_path")
fi
if [[ -f "$bin_path" ]]; then
OPENCODE_BIN="$bin_path"
return 0
fi
fi

return 1
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The function find_opencode_binary has a side effect of modifying the global variable OPENCODE_BIN. While this works, it's generally better practice to avoid modifying global state from within functions to improve modularity and make the code easier to reason about.

Consider refactoring this function to print the found path to standard output. The calling function (main) can then capture this output into a variable. This makes the data flow explicit and the function more reusable. For example, you would change lines like OPENCODE_BIN="$loc" to echo "$loc" and then in main you would call it like OPENCODE_BIN=$(find_opencode_binary).

bin_path=$(which opencode)
# Follow symlinks to find actual binary
if [[ -L "$bin_path" ]]; then
bin_path=$(readlink -f "$bin_path" 2>/dev/null || readlink "$bin_path")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of readlink -f is not portable to macOS, where it's part of coreutils and not installed by default. The fallback readlink "$bin_path" is not a full replacement, as it only resolves one level of symbolic links, whereas -f resolves them recursively. This could cause the script to fail in finding the opencode binary if it's located behind multiple nested symlinks. For better portability, consider a loop to resolve symlinks until a real file is found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants