Skip to content

feat: Add OpenCode support#21

Merged
johnlindquist merged 2 commits into
johnlindquist:mainfrom
JosXa:opencode
Oct 27, 2025
Merged

feat: Add OpenCode support#21
johnlindquist merged 2 commits into
johnlindquist:mainfrom
JosXa:opencode

Conversation

@JosXa

@JosXa JosXa commented Oct 13, 2025

Copy link
Copy Markdown
Contributor

Summary

Added complete OpenCode support to dotagent following established patterns for AI tool integration.

Changes Made

  • Type definitions: Added opencode format to src/types.ts
  • Import functionality: Created importOpenCode() function in src/importers.ts
  • Export functionality: Created exportToOpenCode() function in src/exporters.ts
  • CLI integration: Updated src/cli.ts with OpenCode format detection
  • Module exports: Updated src/index.ts to export new functions
  • Documentation: Added OpenCode to supported formats in README.md
  • Testing: Created comprehensive test suite in test/opencode.test.ts (7 tests)
  • Integration: Updated existing export and roundtrip tests

Implementation Details

  • Follows existing patterns used for Claude, Cursor, and other AI tools
  • Handles OpenCode's specific format: .opencode/ directory with rules.md
  • Supports both import and export operations
  • Includes proper error handling and validation
  • Full test coverage for all functionality

Test Results

  • All 7 OpenCode-specific tests pass
  • Integration tests pass
  • Build succeeds
  • Ready for production use

Files Modified

  • src/types.ts - Added opencode format
  • src/importers.ts - Added importOpenCode() function
  • src/exporters.ts - Added exportToOpenCode() function
  • src/cli.ts - Updated CLI integration
  • src/index.ts - Updated exports
  • README.md - Added to supported formats
  • test/opencode.test.ts - New test suite
  • test/export-functionality.test.ts - Added opencode tests
  • test/integration/roundtrip.test.ts - Added opencode roundtrip tests

Summary by CodeRabbit

  • New Features

    • Added OpenCode as a supported import/export format across interactive CLI, auto-detect, and full export flows; batch exports now produce an AGENTS.opencode.md output.
  • Documentation

    • README and public API reference updated to list OpenCode as an available import/export option and example format.
  • Tests

    • Added comprehensive OpenCode tests covering import/export, roundtrip, private rules, conditional/context rules, and preservation of formatting.

@coderabbitai

coderabbitai Bot commented Oct 13, 2025

Copy link
Copy Markdown

Walkthrough

Adds OpenCode format support across docs, types, index exports, CLI, import/export implementations, and tests. Introduces importOpenCode and exportToOpenCode, extends type unions to include 'opencode', wires OpenCode into importAll/exportAll flows, and adds unit and integration tests for the format.

Changes

Cohort / File(s) Summary
Documentation updates
README.md
Adds OpenCode to Supported Formats, CLI examples, private rules mappings, and API reference; documents importOpenCode and exportToOpenCode.
Types & barrel exports
src/types.ts, src/index.ts
Adds 'opencode' to ImportResult.format and ExportOptions.format unions; re-exports importOpenCode and exportToOpenCode from index.
CLI integration
src/cli.ts
Imports new APIs, adds opencode to valid formats/help text/auto-detect hints and interactive listings, and handles import/export cases for OpenCode.
Importers
src/importers.ts
Adds importOpenCode(filePath) returning ImportResult(format='opencode', rules, metadata); integrates detection of AGENTS.md / AGENTS.opencode.md into importAll with error collection.
Exporters
src/exporters.ts
Adds exportSingleFileWithHeaders helper; refactors Codex/ClaudeCode exports to reuse it; adds exportToOpenCode(rules, outputPath, options?); wires OpenCode into exportAll to emit AGENTS.opencode.md.
Tests
test/opencode.test.ts, test/export-functionality.test.ts, test/integration/roundtrip.test.ts
Adds comprehensive OpenCode tests (import/export, privacy handling, formatting, conditional/context sections), includes OpenCode in exporter map and roundtrip expectations.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI
  participant Importers as importOpenCode
  participant Exporters as exportToOpenCode
  participant FS as FileSystem

  rect rgba(200,230,255,0.25)
    note right of CLI: CLI gains -f opencode handling
    User->>CLI: run convert/export with -f opencode
    alt Import path
      CLI->>Importers: importOpenCode(filePath)
      Importers->>FS: read AGENTS.opencode.md / AGENTS.md
      Importers-->>CLI: ImportResult(format="opencode", rules, metadata)
    else Export path
      CLI->>Exporters: exportToOpenCode(rules, outputPath, options)
      Exporters->>FS: write AGENTS.opencode.md (headers/sections)
      Exporters-->>CLI: success
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

A rabbit taps code with a nimble nose,
“OpenCode,” it hums, where new AGENTS grow. 🐇
Headers flutter, imports align,
CLI lists sparkle, tests all fine.
Hop—commit—export—the docs now glow.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat: Add OpenCode support" directly and accurately summarizes the main change across the changeset. The title clearly indicates that OpenCode format support is being added to the project, which aligns with the comprehensive changes across type definitions, importers, exporters, CLI integration, module exports, documentation, and tests. The title is concise, specific, and uses conventional commit format ("feat:") to indicate a feature addition, making it immediately clear to teammates scanning the history what the primary objective of this PR is.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (3)
src/exporters.ts (1)

403-423: Code duplication detected.

The exportToOpenCode function is identical to exportToClaudeCode (lines 381-401) and exportToCodex (lines 340-360), differing only in name. Consider extracting a shared helper function to reduce duplication and improve maintainability.

Example refactor:

+function exportSingleFileWithHeaders(
+  rules: RuleBlock[],
+  outputPath: string,
+  options?: ExportOptions
+): void {
+  const filteredRules = rules.filter(rule => !rule.metadata.private || options?.includePrivate)
+  const alwaysApplyRules = filteredRules.filter(r => r.metadata.alwaysApply !== false)
+  const conditionalSection = generateConditionalRulesSection(filteredRules, dirname(outputPath))
+  
+  const mainContent = alwaysApplyRules
+    .map(rule => {
+      const header = rule.metadata.description ? `# ${rule.metadata.description}\n\n` : ''
+      return header + rule.content
+    })
+    .join('\n\n')
+  
+  const fullContent = conditionalSection 
+    ? `${mainContent}\n\n${conditionalSection}`
+    : mainContent
+
+  ensureDirectoryExists(outputPath)
+  writeFileSync(outputPath, fullContent, 'utf-8')
+}
+
 export function exportToCodex(rules: RuleBlock[], outputPath: string, options?: ExportOptions): void {
-  // ... existing implementation
+  exportSingleFileWithHeaders(rules, outputPath, options)
 }

 export function exportToClaudeCode(rules: RuleBlock[], outputPath: string, options?: ExportOptions): void {
-  // ... existing implementation
+  exportSingleFileWithHeaders(rules, outputPath, options)
 }

 export function exportToOpenCode(rules: RuleBlock[], outputPath: string, options?: ExportOptions): void {
-  // ... existing implementation
+  exportSingleFileWithHeaders(rules, outputPath, options)
 }
test/opencode.test.ts (2)

105-130: Consider more specific assertion for header absence.

The test correctly validates rules without descriptions, but the assertion expect(exported).not.toContain('#') is brittle—it would fail if the rule content legitimately contained a # character (e.g., in Markdown formatting, comments, or technical content).

Consider a more precise assertion:

-      // Should not have a header if no description
-      expect(exported).not.toContain('#')
+      // Should not have a generated header if no description
+      expect(exported.split('\n')[0]).not.toMatch(/^#\s/)
       expect(exported.trim()).toBe('Always use TypeScript')

This checks specifically that the first line doesn't start with a Markdown header, allowing # to appear elsewhere in the content if needed.


132-174: Consider more comprehensive formatting preservation checks.

The test validates content preservation but only checks for string presence, not structural integrity. It doesn't verify that Markdown elements (code blocks, lists, blockquotes) remain intact after the roundtrip.

Add assertions to verify formatting is preserved:

       expect(exported).toContain('# OpenCode agents and instructions')
       expect(exported).toContain('Always validate inputs')
       expect(exported).toContain('Clean code is better than clever code')
+      // Verify Markdown structures are preserved
+      expect(exported).toMatch(/```[\s\S]*?```/)  // Code blocks
+      expect(exported).toMatch(/^\d+\.\s/m)       // Ordered lists
+      expect(exported).toMatch(/^>\s/m)           // Blockquotes
     } finally {

This ensures formatting elements survive the import/export cycle, not just text content.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cdf4b11 and 50aef86.

📒 Files selected for processing (9)
  • README.md (5 hunks)
  • src/cli.ts (7 hunks)
  • src/exporters.ts (2 hunks)
  • src/importers.ts (2 hunks)
  • src/index.ts (2 hunks)
  • src/types.ts (2 hunks)
  • test/export-functionality.test.ts (2 hunks)
  • test/integration/roundtrip.test.ts (1 hunks)
  • test/opencode.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
src/exporters.ts (1)
src/types.ts (2)
  • RuleBlock (14-21)
  • ExportOptions (35-41)
test/export-functionality.test.ts (2)
src/exporters.ts (1)
  • exportToOpenCode (403-423)
src/index.ts (1)
  • exportToOpenCode (37-37)
src/cli.ts (3)
src/exporters.ts (1)
  • exportToOpenCode (403-423)
src/index.ts (2)
  • exportToOpenCode (37-37)
  • importOpenCode (18-18)
src/importers.ts (1)
  • importOpenCode (661-686)
test/opencode.test.ts (4)
src/importers.ts (1)
  • importOpenCode (661-686)
src/index.ts (3)
  • importOpenCode (18-18)
  • RuleBlock (48-48)
  • exportToOpenCode (37-37)
src/types.ts (1)
  • RuleBlock (14-21)
src/exporters.ts (1)
  • exportToOpenCode (403-423)
src/importers.ts (2)
src/index.ts (3)
  • importOpenCode (18-18)
  • ImportResult (49-49)
  • RuleBlock (48-48)
src/types.ts (2)
  • ImportResult (23-28)
  • RuleBlock (14-21)
🔇 Additional comments (17)
src/types.ts (1)

24-24: LGTM!

The addition of 'opencode' to the format union types is consistent with the existing pattern and correctly enables type-level support for the new format.

Also applies to: 36-36

test/integration/roundtrip.test.ts (1)

131-131: LGTM!

The addition of the 'opencode' format expectation correctly extends the integration test to cover the new format.

src/index.ts (1)

18-18: LGTM!

The exports of importOpenCode and exportToOpenCode correctly extend the public API surface for the new OpenCode format support.

Also applies to: 37-37

src/cli.ts (4)

6-6: LGTM!

The imports of importOpenCode and exportToOpenCode correctly integrate the new OpenCode format support into the CLI.


45-45: LGTM!

The CLI help text, format lists, and hints have been correctly updated to include OpenCode as a supported format.

Also applies to: 106-106, 218-218, 387-387


197-198: LGTM!

The interactive export format menu correctly includes OpenCode with appropriate labeling that shows it uses AGENTS.md.


424-426: LGTM!

The import case for OpenCode correctly handles the conversion flow.

src/importers.ts (2)

157-160: Acknowledge file naming conflict.

The comment correctly identifies that both OpenCode and OpenAI Codex use AGENTS.md, creating ambiguity. However, the current implementation doesn't add an OpenCode import case to importAll, meaning OpenCode files won't be automatically detected.

Additionally, the comment mentions making this configurable, but no configuration mechanism exists yet.

Consider these options:

  1. Use distinct filenames: AGENTS.md for Codex, AGENTS.opencode.md for OpenCode (aligns with exportAll line 583)
  2. Add format detection logic: Analyze file content to distinguish formats
  3. Make it configurable: Add a user preference for AGENTS.md interpretation

The first option (distinct filenames) is the simplest and most reliable. This would require updating:

  • CLI export path for OpenCode (src/cli.ts line 303)
  • Documentation (README.md line 29)
  • Test format map (test/export-functionality.test.ts line 153)
  • Adding import case for AGENTS.opencode.md in importAll

661-686: LGTM!

The importOpenCode function correctly follows the established pattern for single-file format importers. It properly handles privacy detection and constructs the expected ImportResult structure.

README.md (2)

106-106: LGTM!

The CLI format flag documentation correctly includes OpenCode in the list of supported formats.


320-320: LGTM!

The API reference correctly documents the new importOpenCode and exportToOpenCode functions, following the established documentation pattern for other format handlers.

Also applies to: 337-337

test/opencode.test.ts (6)

1-6: LGTM! Clean test imports.

The imports are well-structured and include all necessary dependencies for testing OpenCode format functionality.


9-50: LGTM! Comprehensive import test.

The test properly validates import functionality with appropriate assertions for format, metadata, and content preservation. Cleanup is correctly handled.


52-103: LGTM! Well-structured export test.

The test properly validates export functionality with multiple rules, verifying header generation, content preservation, and proper rule separation. The setup and assertions align with the expected export behavior.


176-200: LGTM! Proper private rule detection test.

The test correctly validates that files matching the private pattern (.local.md) are imported with the private metadata flag set.


202-241: LGTM! Comprehensive private rule filtering test.

The test properly validates both default filtering behavior (excluding private rules) and explicit inclusion via the includePrivate option. The assertions correctly verify the expected content in each scenario.


243-278: <!-- [scratchpad]
[task review_file_1/1 review_test_7/7 verify_implementation_1/1]
[observations]

  • No standalone generateConditionalRulesSection found; conditional section built in src/exporters.ts.
  • Line 56 in src/exporters.ts: sections.push(\When working with files matching \`${scope}\`, also apply:`)`.
  • Test at line 274 expects 'When working with files matching \src/components/**`'` (prefix only).
    [analysis]
  • Implementation’s string includes the test’s expected substring.
  • toContain check passes as substring before comma matches.
    [pending]
  • None.
    [actions]
  • Conclude that the test and implementation align.
    [done]
    ]

Conditional rules section format is correct. The implementation uses “When working with files matching ${scope}, also apply:”, and the test’s substring check covers the expected content.

Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread src/cli.ts
Comment on lines +302 to +306
case 'opencode':
exportPath = join(outputDir, 'AGENTS.md')
if (!isDryRun) exportToOpenCode(rules, exportPath, options)
exportedPaths.push('AGENTS.md')
break

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: File naming inconsistency and format collision.

The CLI exports OpenCode to AGENTS.md (line 303), but:

  1. exportAll exports to AGENTS.opencode.md (src/exporters.ts line 583)
  2. OpenAI Codex format also uses AGENTS.md (line 283)

This creates two critical issues:

  • Inconsistency: Individual exports via CLI produce different filenames than exportAll
  • Collision: When exporting both Codex and OpenCode formats, one will overwrite the other

The auto-detect logic (line 379) also can't distinguish between Codex and OpenCode when both use AGENTS.md.

Resolve by choosing a consistent, unique filename. Recommended approach:

 case 'opencode':
-  exportPath = join(outputDir, 'AGENTS.md')
+  exportPath = join(outputDir, 'AGENTS.opencode.md')
   if (!isDryRun) exportToOpenCode(rules, exportPath, options)
-  exportedPaths.push('AGENTS.md')
+  exportedPaths.push('AGENTS.opencode.md')
   break

Then update the auto-detect logic to handle the new filename:

 else if (inputPath.endsWith('AGENTS.md')) format = 'codex'
+else if (inputPath.endsWith('AGENTS.opencode.md')) format = 'opencode'

Also update the export formats menu (line 198) and documentation accordingly.

🤖 Prompt for AI Agents
In src/cli.ts around lines 302-306, the CLI currently writes OpenCode exports to
AGENTS.md causing filename inconsistency and collisions with Codex exports and
exportAll; change the OpenCode export filename to a unique, consistent name
(e.g., AGENTS.opencode.md) so it matches exportAll, update the exportedPaths
entry accordingly, then modify the auto-detect logic (around line 379) to detect
the new AGENTS.opencode.md filename separately from AGENTS.md (Codex) and ensure
both formats are distinguished; finally update the export formats menu (around
line 198) and corresponding documentation to list the new filename for OpenCode.

Comment thread src/exporters.ts Outdated
Comment thread test/export-functionality.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 655f2f4 and 5d8fef1.

📒 Files selected for processing (4)
  • README.md (5 hunks)
  • src/exporters.ts (4 hunks)
  • src/importers.ts (2 hunks)
  • test/opencode.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/exporters.ts
  • README.md
🧰 Additional context used
🧬 Code graph analysis (2)
src/importers.ts (2)
src/index.ts (3)
  • importOpenCode (18-18)
  • ImportResult (49-49)
  • RuleBlock (48-48)
src/types.ts (2)
  • ImportResult (23-28)
  • RuleBlock (14-21)
test/opencode.test.ts (3)
src/importers.ts (1)
  • importOpenCode (671-696)
src/types.ts (1)
  • RuleBlock (14-21)
src/exporters.ts (1)
  • exportToOpenCode (392-394)
🔇 Additional comments (1)
test/opencode.test.ts (1)

1-283: Tests are comprehensive; update file paths after fixing importAll bug.

The test suite provides excellent coverage of OpenCode import/export/roundtrip/privacy/conditional scenarios. However, the tests use AGENTS.md paths, which aligns with the current (buggy) implementation but conflicts with the PR objectives.

Once you fix the critical bug in src/importers.ts to use .opencode/rules.md instead of AGENTS.md, update the test file paths accordingly. For example:

-    const agentsPath = join(tempDir, 'AGENTS.md')
+    const opencodeDir = join(tempDir, '.opencode')
+    mkdirSync(opencodeDir, { recursive: true })
+    const rulesPath = join(opencodeDir, 'rules.md')

Additionally, add an integration test for importAll to verify OpenCode and Codex imports don't produce duplicates:

it('should not create duplicate entries for different formats', async () => {
  const tempDir = mkdtempSync(join(tmpdir(), 'import-all-test-'))
  
  // Create both Codex and OpenCode files
  writeFileSync(join(tempDir, 'AGENTS.md'), '# Codex rules', 'utf8')
  const opencodeDir = join(tempDir, '.opencode')
  mkdirSync(opencodeDir, { recursive: true })
  writeFileSync(join(opencodeDir, 'rules.md'), '# OpenCode rules', 'utf8')
  
  try {
    const { results } = await importAll(tempDir)
    
    // Should have one entry for each format, not duplicates
    const codexResults = results.filter(r => r.format === 'codex')
    const opencodeResults = results.filter(r => r.format === 'opencode')
    
    expect(codexResults).toHaveLength(1)
    expect(opencodeResults).toHaveLength(1)
    expect(results).toHaveLength(2)
  } finally {
    rmSync(tempDir, { recursive: true, force: true })
  }
})

Comment thread src/importers.ts
Comment on lines +157 to +165
// Check for AGENTS.md (OpenCode)
const opencodeMd = join(repoPath, 'AGENTS.md')
if (existsSync(opencodeMd)) {
try {
results.push(importOpenCode(opencodeMd))
} catch (e) {
errors.push({ file: opencodeMd, error: String(e) })
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Duplicate imports of AGENTS.md causing incorrect results.

Lines 127-135 already import AGENTS.md as format 'codex', and now lines 157-165 import the identical file again as format 'opencode'. When importAll runs, it produces two ImportResult entries for the same file with conflicting formats, breaking downstream consumers that expect one canonical format per file.

According to the PR objectives, OpenCode should use a .opencode/ directory structure with rules.md, not AGENTS.md. This would eliminate the conflict entirely.

Apply this diff to use the correct OpenCode file path:

-  // Check for AGENTS.md (OpenCode)
-  const opencodeMd = join(repoPath, 'AGENTS.md')
-  if (existsSync(opencodeMd)) {
+  // Check for OpenCode rules (.opencode/rules.md)
+  const opencodeRules = join(repoPath, '.opencode', 'rules.md')
+  if (existsSync(opencodeRules)) {
     try {
-      results.push(importOpenCode(opencodeMd))
+      results.push(importOpenCode(opencodeRules))
     } catch (e) {
-      errors.push({ file: opencodeMd, error: String(e) })
+      errors.push({ file: opencodeRules, error: String(e) })
     }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Check for AGENTS.md (OpenCode)
const opencodeMd = join(repoPath, 'AGENTS.md')
if (existsSync(opencodeMd)) {
try {
results.push(importOpenCode(opencodeMd))
} catch (e) {
errors.push({ file: opencodeMd, error: String(e) })
}
}
// Check for OpenCode rules (.opencode/rules.md)
const opencodeRules = join(repoPath, '.opencode', 'rules.md')
if (existsSync(opencodeRules)) {
try {
results.push(importOpenCode(opencodeRules))
} catch (e) {
errors.push({ file: opencodeRules, error: String(e) })
}
}
🤖 Prompt for AI Agents
In src/importers.ts around lines 157 to 165, the code incorrectly re-checks
AGENTS.md (causing duplicate imports with different formats); change the check
to target the OpenCode canonical path join(repoPath, '.opencode', 'rules.md')
and call importOpenCode on that path (and push its result) instead of AGENTS.md;
ensure the new path exists check uses existsSync and that errors.push records
that .opencode/rules.md path on failure so the file is only imported once under
the correct OpenCode location and format.

Comment thread src/importers.ts
Comment on lines +167 to +171
// Check for AGENTS.md (OpenAI Codex) - Note: This conflicts with OpenCode,
// so we need to handle this carefully. For now, we'll prioritize OpenAI Codex
// since it was implemented first, but this could be made configurable.
// Users can explicitly specify the format using the CLI if needed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Remove obsolete comment after fixing the conflict.

This comment acknowledges the AGENTS.md conflict but the code still imports both. Once the critical issue above is resolved by using .opencode/rules.md, remove this comment entirely.

🤖 Prompt for AI Agents
In src/importers.ts around lines 167 to 171, remove the obsolete multi-line
comment about AGENTS.md/OpenAI Codex conflict (the block that begins with "//
Check for AGENTS.md (OpenAI Codex) ...") now that the conflict has been resolved
by using .opencode/rules.md; delete the entire comment block and any stray blank
lines left behind, and verify there are no other references to AGENTS.md in this
file that need updating to .opencode/rules.md.

Comment thread src/importers.ts
Comment on lines +671 to +696
export function importOpenCode(filePath: string): ImportResult {
const content = readFileSync(filePath, 'utf-8')
const isPrivateFile = isPrivateRule(filePath)

const metadata: any = {
id: 'opencode-agents',
alwaysApply: true,
description: 'OpenCode agents and instructions'
}

if (isPrivateFile) {
metadata.private = true
}

const rules: RuleBlock[] = [{
metadata,
content: content.trim()
}]

return {
format: 'opencode',
filePath,
rules,
raw: content
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Function implementation is correct; integration bug is in importAll.

The importOpenCode function itself follows the established pattern and correctly constructs an ImportResult. The critical issue is in importAll (lines 157-165), which imports AGENTS.md twice—once for Codex and once for OpenCode—creating duplicates.

After fixing the file path in importAll to use .opencode/rules.md, verify that:

  1. OpenCode rules are imported correctly from the new path
  2. No duplicate entries appear in importAll results
  3. Existing Codex imports remain unaffected

Run this script to confirm no overlap:


🏁 Script executed:

#!/bin/bash
# Description: Verify OpenCode and Codex use distinct file paths

# Search for importOpenCode calls
echo "=== importOpenCode usage ==="
rg -nP 'importOpenCode\(' --type=ts -A2

# Search for importCodex calls  
echo -e "\n=== importCodex usage ==="
rg -nP 'importCodex\(' --type=ts -A2

# Verify .opencode directory references
echo -e "\n=== .opencode directory checks ==="
rg -nP '\.opencode' --type=ts -C2

Length of output: 1958


🏁 Script executed:

#!/bin/bash
# Extract importAll implementation to verify file paths and potential duplicates
rg -nP 'function importAll\(' -C10 --type=ts src/importers.ts

Length of output: 910


🏁 Script executed:

#!/bin/bash
# Extract importAll continuation to inspect file paths for Codex and OpenCode
sed -n '130,260p' src/importers.ts

Length of output: 3738


🏁 Script executed:

#!/bin/bash
# Find where agentsMd is defined for importCodex
rg -nP 'const agentsMd' -C3 --type=ts src/importers.ts

# Extract surrounding lines to see context of importCodex's AGENTS.md
sed -n '100,130p' src/importers.ts

Length of output: 992


Fix duplicate AGENTS.md imports in importAll

In src/importers.ts’s importAll, both the Codex and OpenCode checks use join(repoPath, 'AGENTS.md'). Change the OpenCode branch to join(repoPath, '.opencode/rules.md') to avoid importing the same file twice.

🤖 Prompt for AI Agents
In src/importers.ts around lines 671 to 696, the OpenCode import branch is
incorrectly using join(repoPath, 'AGENTS.md') which duplicates the Codex import;
change the OpenCode branch to use join(repoPath, '.opencode/rules.md') instead
so OpenCode imports come from .opencode/rules.md. Update any related existence
checks or file reads to reference the new path and ensure the code still guards
against missing files before calling importOpenCode.

@johnlindquist johnlindquist merged commit ef66926 into johnlindquist:main Oct 27, 2025
1 of 2 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.10.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@JosXa JosXa deleted the opencode branch October 27, 2025 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants