Skip to content

Add cross-repo tool with PR #18 patterns#21

Closed
ask-bonk[bot] wants to merge 2 commits intomainfrom
opencode/issue20-20260103192526
Closed

Add cross-repo tool with PR #18 patterns#21
ask-bonk[bot] wants to merge 2 commits intomainfrom
opencode/issue20-20260103192526

Conversation

@ask-bonk
Copy link
Contributor

@ask-bonk ask-bonk bot commented Jan 3, 2026

I've created the cross-repo tool at .config/opencode/tool/cross-repo.ts based on the gist, applying the best practices from PR #18 (worktree plugin).

Summary

Created: .config/opencode/tool/cross-repo.ts - A tool for operating on GitHub repositories other than the current working directory.

Key Features

  • 9 Operations: clone, read, write, list, branch, commit, push, pr, exec
  • Session-scoped state: Repos tracked per {sessionID}/{owner}/{repo} to prevent conflicts between concurrent agents
  • Context-aware authentication: OIDC (GitHub Actions) -> gh CLI -> GH_TOKEN/GITHUB_TOKEN

Best Practices Applied (per PR #18 guidance)

Practice Implementation
Crash Resilience Top-level try/catch in execute(), errors returned as { success: false, error }
Safe Shell Execution Bun.spawn with array args (avoids shell interpolation)
Input Validation validateRepoName() and validateBranchName() reject shell metacharacters
Path Traversal Protection File ops validate resolved paths stay within repo root
Structured Logging log(sessionID, action, detail) format
Non-Interactive Mode GIT_TERMINAL_PROMPT=0, stdin: "ignore", timeout handling
JSON Output Results stringified for tool validation

Improvements Over Original Gist

  1. Replaced most bash -c patterns with direct Bun.spawn array args
  2. Added explicit timeout handling via Promise.race
  3. Added input validation for owner/repo/branch names
  4. Added structured logging functions
  5. Improved error messages with session context

Closes #20

github run

@ask-bonk ask-bonk bot mentioned this pull request Jan 3, 2026
@elithrar
Copy link
Owner

elithrar commented Jan 3, 2026

/bonk review our implementation against the changes in anomalyco/opencode#6302 - e.g. whether installing dependencies takes effect as expected / Bun.install runs per subdirectory under opencode/

@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Jan 3, 2026

Now I have a clear picture. Let me analyze the implementation against PR #6302's changes:

Review: Cross-Repo Tool vs PR #6302 (Local Plugin Dependencies)

Summary of PR #6302's Changes

PR #6302 adds support for local plugin dependencies by running Bun.install in the config directory (packages/opencode/src/config/config.ts):

// Install any additional dependencies defined in the package.json
// This allows local plugins and custom tools to use external packages
await BunProc.run(["install"], { cwd: dir }).catch(() => {})

This runs once at startup in the config directory (e.g., .opencode/ or .config/opencode/).

Your Implementation Analysis

Does dependency installation take effect as expected?

Yes. Your setup is correctly structured:

Aspect Status Details
package.json location Correct .config/opencode/package.json exists at the config root
shescape dependency Correct Listed as "shescape": "^2.1.7"
Import in cross-repo.ts Correct Line 27: import { Shescape } from "shescape"

Does Bun.install run per subdirectory under opencode/?

No, and that's by design. PR #6302 runs Bun.install only once in the config directory root (dir), not recursively in subdirectories. This matches your structure:

.config/opencode/
├── package.json         ← Bun.install runs here
├── tool/
│   └── cross-repo.ts    ← Imports shescape from parent's node_modules
├── skill/
├── command/
└── opencode.jsonc

Node/Bun module resolution naturally finds shescape in the parent directory's node_modules/, so tools in subdirectories like tool/ don't need their own package.json.

Potential Issue

There's one subtle concern: if node_modules doesn't exist yet at runtime (first run, CI environment, etc.), the import will fail before Bun.install completes. However, PR #6302's implementation runs Bun.install before loading plugins/tools:

  1. Bun.install runs during Config.info() initialization
  2. Plugins/tools are loaded after config initialization

So the timing should be correct.

Verification Checklist

Your implementation correctly follows PR #6302's pattern:

  • Single package.json at config root
  • Dependencies listed for external packages (shescape)
  • No need for per-subdirectory package.json files
  • Imports use standard module resolution (relative imports would need local node_modules)

Recommendation

No changes needed - your implementation aligns with PR #6302's design. The shescape dependency will be installed when OpenCode initializes the config directory, and cross-repo.ts will successfully import it via Node's module resolution climbing up to find node_modules in the parent config directory.

github run

@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Jan 3, 2026

Bonk workflow was cancelled.

View workflow run

@elithrar elithrar self-assigned this Jan 3, 2026
@elithrar elithrar force-pushed the opencode/issue20-20260103192526 branch from 6590079 to 7e3b16a Compare January 4, 2026 12:57
@elithrar
Copy link
Owner

elithrar commented Jan 4, 2026

/bonk investigate further:

  • does opencode (and Bun, underneath) use the node_modules in the global config correctly?
  • where are plugin failures / dependency issues logged?
  • you mention a “subtle concern” and then say “timing should be correct” - expand on this. do not say “should” related to a concern. you can verify by looking at the anomalyco/opencode codebase - the cross-repo tool itself will allow you to clone it and search.

@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Jan 4, 2026

Bonk workflow was cancelled.

View workflow run

@elithrar

This comment was marked as outdated.

@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Jan 4, 2026

error: Your local changes to the following files would be overwritten by checkout:
.opencode/package.json
Please commit your changes or stash them before you switch branches.
Aborting

github run

@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Jan 4, 2026

Bonk workflow failed. Check the logs for details.

View workflow run

- Implements clone, read, write, list, branch, commit, push, pr, exec operations
- Session-scoped repo state prevents concurrent agent conflicts
- Context-aware auth: OIDC (GitHub Actions), gh CLI, or env tokens
- Crash-resistant: all errors returned as results, never thrown
- Input validation prevents shell injection and path traversal
- Structured logging for debugging

Closes #20
@elithrar elithrar force-pushed the opencode/issue20-20260103192526 branch from 7e3b16a to a3aa4f8 Compare January 4, 2026 14:59
@elithrar
Copy link
Owner

elithrar commented Jan 4, 2026

/bonk make logging and SDK changes per 1387dce to cross-repo as we did for git-worktree

Co-authored-by: elithrar <elithrar@users.noreply.github.com>
@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Jan 4, 2026

I've applied the logging and SDK changes from commit 1387dce to cross-repo.ts, mirroring what was done for git-worktree.ts:

Summary of Changes

  1. Replaced standalone log() and logError() functions with a LogFn type that uses the SDK's client.app.log() method

  2. Updated all operation functions to accept log: LogFn as their first parameter:

    • cloneRepo()
    • createBranch()
    • commitChanges()
    • pushBranch()
    • createPR()
    • readFile()
    • writeFile()
    • listFiles()
    • execCommand()
  3. Created the log helper in execute() using the SDK:

    const log: LogFn = async (level, message, extra) => {
      await client.app.log({
        service: "cross-repo",
        level,
        message,
        extra,
      }).catch(() => {})
    }
  4. Changed log message format from the old format:

    [cross-repo] session=xxx action=clone repo=owner/repo path=/tmp/...
    

    To structured SDK logging with descriptive messages and extra context:

    await log("info", "Repository cloned", { sessionID, owner, repo, path, defaultBranch })
  5. Removed the unused ToolClient import that was accidentally added

github run

@elithrar
Copy link
Owner

elithrar commented Jan 4, 2026

/bonk passing LogFn around is noisy. Can we avoid that?

  • define a class?
  • just call the SDK’s logger with a constant for SERVICE - ?
  • just wrap the callsites? (preferred!)

@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Jan 4, 2026

error: Your local changes to the following files would be overwritten by checkout:
.opencode/package.json
Please commit your changes or stash them before you switch branches.
Aborting

github run

@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Jan 4, 2026

Bonk workflow failed. Check the logs for details.

View workflow run

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.

cross repo tool

1 participant