opencode-repo-local
v0.2.3
Published
OpenCode plugin to clone or update repositories locally for built-in tooling
Readme
opencode-repo-local
OpenCode plugin that ensures a repository exists locally (clone or update) and returns an absolute path so you can use OpenCode built-in tools directly.
What it does
- Exposes one custom tool:
repo_ensure_local - Clones missing repositories into a deterministic local root
- Updates existing repositories with safe, non-destructive defaults
- Returns structured output including
local_pathfor immediateRead/Glob/Grep/Bashusage
Installation
From npm
Add the package to your OpenCode config:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-repo-local"]
}Local development
- Install dependencies:
bun install- For local OpenCode testing in this repo, use the included local plugin wiring:
.opencode/plugins/repo-local-plugin.tsimportssrc/index.tsdirectly for fast iteration (no build step required).opencode/package.jsoninstalls plugin runtime dependencies for OpenCode
For a publishable artifact check, run
bun run buildbefore release.Or publish and install via npm for regular usage.
To run OpenCode with the npm-installed plugin (without this repo's local shim), use:
bun run opencode:npmThis launches OpenCode in an isolated sandbox directory with opencode-repo-local injected via OPENCODE_CONFIG_CONTENT.
Quick verification:
bun run opencode:npm:configExpected plugin list includes opencode-repo-local and does not include .opencode/plugins/repo-local-plugin.ts.
Tool: repo_ensure_local
Arguments:
repo(required): repository reference in one of these forms:https://host/owner/repo(.git)git@host:owner/repo.git(whenallow_sshis true)
host/owner/repoowner/repo(GitHub shorthand)ref(optional): branch/tag/SHA to checkout after clone/fetchdepth(optional): shallow clone depthupdate_mode(optional):ff-only(default),fetch-only,reset-cleanallow_ssh(optional): allowgit@host:owner/repo.gitURLsauth_mode(optional):auto(default),https,ssh
Output fields:
status:cloned|updated|already-current|fetchedrepo_urllocal_pathcurrent_refdefault_branchhead_shacomparison_refremote_head_shaahead_bybehind_byfreshness:current|stale|ahead|diverged|unknownactionsinstructions
Freshness semantics:
- Default
update_mode=ff-onlyis the recommended one-call path for agents: it updates when safe and returns freshness metadata. - Use
update_mode=fetch-onlywhen you explicitly want non-mutating freshness/version checks.
Auth mode semantics:
- Default
auth_mode=autouses HTTPS first and falls back to SSH on auth failures when SSH URL derivation is possible. - Use
auth_mode=httpsto force HTTPS-only behavior. - Use
auth_mode=sshto force SSH-only behavior.
Environment variables
OPENCODE_REPO_CLONE_ROOT: env-only clone root override for testing/CI (fallback is~/.opencode/repos)OPENCODE_REPO_ALLOW_SSH=true: default SSH URL allowanceOPENCODE_REPO_TELEMETRY_PATH: optional telemetry JSONL path override
Private repository auth
- Git commands run in non-interactive mode to avoid blocking OpenCode sessions on credential prompts.
- For HTTPS auth, configure GitHub credentials once:
gh auth login
gh auth setup-git- For SSH auth, either:
- pass
auth_mode=ssh(orallow_ssh=true) and usegit@host:owner/repo.git, or - set
OPENCODE_REPO_ALLOW_SSH=trueto allow SSH inputs by default.
- pass
Telemetry
repo_ensure_localwrites invocation telemetry on every run.- Default file:
~/.local/share/opencode/plugins/opencode-repo-local/telemetry.jsonl - Event fields include
repo_input,canonical_repo_url,status,local_path, and error metadata.
OpenCode permissions
- This repo includes
opencode.jsonwith:permission.external_directory["~/.opencode/repos/**"] = "allow"
- This lets OpenCode built-in tools access cloned repos under
~/.opencode/reposwithout repeated approval prompts. - Recommended for users of this plugin: add the same permission rule to your own global or project OpenCode config.
- If you already have other
permission.external_directoryrules, add~/.opencode/repos/**to that same object after broader patterns you want it to override, because the last matching rule wins.
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"*": "ask",
"~/projects/personal/**": "allow",
"~/.opencode/repos/**": "allow"
}
}
}Local OpenCode smoke test
Use this to validate the plugin in a real OpenCode session.
- Confirm OpenCode loads the local plugin shim:
opencode debug configVerify plugin list includes .opencode/plugins/repo-local-plugin.ts.
- Forced tool smoke test (deterministic):
opencode run "You must call repo_ensure_local first. Use repo='Aureatus/opencode-repo-local' and update_mode='fetch-only'. Then report only: status, repo_url, local_path, head_sha."- Natural-intent smoke test (agent should choose the tool):
opencode run "Please inspect ghoulr/opencode-websearch-cited, find the custom tool it exports, and report the file path where it is defined."Important:
- Run the natural-intent test against a repo that is not your current workspace.
- If you reference the current repo, OpenCode may correctly skip
repo_ensure_localbecause local files are already available.
Expected behavior:
- OpenCode chooses
repo_ensure_localfor external repo references. - Output includes a valid
local_pathunder~/.opencode/repos/.... - Follow-up inspection uses built-in tools (
Read,Glob,Grep,Bash) against that local path.
Safety behavior
- Rejects malformed/unsupported repo URLs
- Prevents clone path escape outside clone root
- Validates existing clone remote against requested repository
- Avoids destructive sync by default (
ff-only)
Development
bun install
bun run fix
bun run check
bun run lint
bun run typecheck
bun run test
bun run test:integration
bun run test:e2e
bun run buildReleasing
- This project uses tag-driven publishing to npm via GitHub Actions.
- Use release helper scripts:
bun run release:verifybun run release:patch|minor|majorbun run release:beta:first/bun run release:beta:next
- Push version commit and tag with
git push origin main --follow-tags. - GitHub Release notes are created automatically from pushed release tags.
- Full runbook: see
RELEASING.md.
Integration script notes:
- Default run validates multiple allowed input formats against
Aureatus/opencode-repo-local. - Override to a single repo input:
bun run test:integration -- https://github.com/OWNER/REPO.git - Keep clone directory for inspection:
OPENCODE_REPO_INTEGRATION_KEEP=true bun run test:integration - Set custom clone root:
OPENCODE_REPO_INTEGRATION_ROOT=/abs/path bun run test:integration - Private auth integration is opt-in:
bun run test:integration:private - Configure private targets with env vars:
OPENCODE_REPO_PRIVATE_HTTPS_REPO=https://host/owner/private-repo.gitOPENCODE_REPO_PRIVATE_SSH_REPO=git@host:owner/private-repo.git
- Optional expectations (
successor an error code likeGIT_AUTH):OPENCODE_REPO_PRIVATE_EXPECT_HTTPS=successOPENCODE_REPO_PRIVATE_EXPECT_AUTO=successOPENCODE_REPO_PRIVATE_EXPECT_SSH=success
E2E script notes:
bun run test:e2eruns realopencode runprompts and asserts tool usage via telemetry.bun run test:e2e:npmruns the same E2E suite in npm mode (isolated sandbox +opencode-repo-localinjected via config override, without local shim plugin).- It validates all supported repo input formats across two required targets:
Aureatus/opencode-repo-localghoulr/opencode-websearch-cited
- It checks each target's formats resolve to one normalized local path.
- Keep temporary artifacts for inspection:
OPENCODE_REPO_E2E_KEEP=true bun run test:e2e - The test is valid because each run uses:
- a fresh temporary clone root (
/tmp/opencode-repo-e2e-.../clones), not the current workspace, - a run-specific telemetry file,
- real OpenCode prompts that must trigger
repo_ensure_local.
- a fresh temporary clone root (
- This verifies end-to-end behavior (tool invocation, clone/update, and normalized path resolution) without depending on local workspace files.
Git hooks
- This repo uses Husky for pre-commit and pre-push hooks.
- Full local check command:
bun run check(runs no-ignore guard,lint,typecheck,test,build, andtest:integrationin parallel where possible). - Build command:
bun run build(tsdown --fail-on-warn, warnings fail the build). - Lint command:
bun run lint(Ultracite/Biome with--error-on-warnings). - Fix command:
bun run fix(Ultracite safe + unsafe fixes, then no-ignore guard). - Pre-commit command:
bun run check. - Pre-push command:
bun run check. - Hooks are installed by running
bun installvia thepreparescript.
