Conversation
Add a TypeScript plugin for OpenCode that reuses the existing protect_directories.py protection logic via tool.execute.before hook. Intercepts edit, write, bash, and patch tools. +semver: minor https://claude.ai/code/session_011KMGYhQjWHZKReC4TS4xa8
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📝 WalkthroughWalkthroughAdds OpenCode integration: a new TypeScript BlockPlugin (opencode/index.ts) that calls the shared Python hook (hooks/protect_directories.py), package metadata (opencode/package.json), documentation updates (CLAUDE.md, README.md), CI changes (.github/workflows/ci.yml), and testing additions (pytest dev dependency, testing docs). Changes
Sequence Diagram(s)sequenceDiagram
participant OC as OpenCode Agent
participant Plugin as BlockPlugin
participant Python as protect_directories.py
participant FS as File System / Process
OC->>Plugin: Invoke protected tool (edit/write/patch/bash)
activate Plugin
Plugin->>Plugin: Filter tool & build tool_input
Plugin->>Plugin: Build JSON hook payload
Plugin->>FS: Resolve Python script path
Plugin->>Python: Execute `python3` with JSON on stdin
activate Python
Python->>Python: Parse input, evaluate rules
Python-->>Plugin: Return JSON decision (allow/block + reason)
deactivate Python
alt decision == "block"
Plugin-->>OC: Throw error with reason (block)
else decision == "allow"
Plugin-->>OC: Return null / allow operation
end
deactivate Plugin
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (5)
opencode/index.ts (4)
11-11:dirnameis imported but never used.
import.meta.diris used directly on Line 68, making thedirnameimport dead code.✏️ Proposed fix
-import { resolve, dirname } from "path"; +import { resolve } from "path";🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@opencode/index.ts` at line 11, The import list includes an unused symbol "dirname" (import { resolve, dirname } from "path") while the code uses import.meta.dir directly; remove "dirname" from the import to eliminate dead code and keep only the needed "resolve" import in opencode/index.ts (update the import statement to import { resolve } from "path").
67-70:import.meta.diris a Bun-specific extension.
import.meta.diris not part of the ECMAScript or WinterCG standards — it is a Bun proprietary addition. OpenCode uses Bun to install and run npm plugins, with packages cached in~/.cache/opencode/node_modules/, so this works today. Document this runtime dependency assumption to prevent confusion if OpenCode ever changes its runtime or if someone tries to adapt the plugin elsewhere.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@opencode/index.ts` around lines 67 - 70, The function findScript uses the Bun-only extension import.meta.dir to locate protect_directories.py, which is a nonstandard runtime assumption; update the codebase by adding a clear comment above findScript documenting that import.meta.dir is Bun-specific and that OpenCode expects packages under ~/.cache/opencode/node_modules/, add a short runtime-check or warning (referencing findScript and import.meta.dir) that logs a helpful message if import.meta.dir is unavailable, and add the same note to the project README or plugin docs so future maintainers know the Bun dependency and where packages are cached.
72-104:tool.execute.beforedoes not fire for subagent tool calls — protection can be bypassed.Plugin hooks using
tool.execute.beforesuccessfully block tool calls from primary agents but do not intercept tool calls from subagents spawned via the task tool, allowing security policies to be completely bypassed. Users relying on this plugin for security-sensitive protection should be made aware of this limitation in the README.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@opencode/index.ts` around lines 72 - 104, BlockPlugin's current hook on "tool.execute.before" (in BlockPlugin) only catches primary-agent tool calls and can be bypassed by subagents spawned via the task tool; update the code and docs: add a clear README note describing this limitation and recommend users not rely on BlockPlugin for subagent enforcement, and update the runtime enforcement by either registering the same protection check for the subagent execution path (e.g., also listen for the broader "tool.execute" or the task-spawn execution event) or instrument the task/tool runner to call buildHookInput and the BlockPlugin check before spawning subagents; reference BlockPlugin, PROTECTED_TOOLS, buildHookInput and the "tool.execute.before" hook when making the change so the protection logic is invoked for subagent tool calls as well.
43-52: Remove unused field name fallbacks or document compatibility intent.The canonical field names are documented in the code comments:
commandfor bash andfile_pathfor file operations (lines 31–32). All test cases exclusively use these canonical names; no tests passcmd,filePath, orfileas alternatives. Either these fallbacks are dead code and should be removed, or they exist to handle backwards compatibility with Claude Code's original naming convention (referenced in the comment at line 18). Add a comment explaining the compatibility rationale if the fallbacks are intentional, or remove them if they serve no purpose.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@opencode/index.ts` around lines 43 - 52, The code currently reads alternate legacy field names (args.cmd, args.filePath, args.file) but tests and comments use canonical names (command and file_path); remove the dead compatibility fallbacks so the bash branch only reads args.command and the file branch only reads args.file_path, and set toolInput.command = args.command and toolInput.file_path = args.file_path directly (remove references to cmd, filePath, file and their local variable aliases). If you intend to preserve backward compatibility instead, add a short comment above these branches explaining they intentionally accept legacy Claude Code names (cmd, filePath, file) for compatibility; otherwise delete the fallback checks and local variables.opencode/package.json (1)
3-3: Version skew between packages is large and unexplained.
opencode/package.jsondeclares1.1.14whilepyproject.tomlis at1.1.6. These are separate packages so independent versioning is fine, but starting 8 versions ahead of the Python package may confuse users or downstream tooling that expects them to track each other.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@opencode/package.json` at line 3, The package.json "version" field is eight releases ahead of the Python package's version in pyproject.toml which will confuse users; either sync the two versions or explicitly document independent versioning. Fix by updating the "version" field in package.json to match the pyproject.toml version (or vice‑versa), and update release notes/changelog and any CI/release scripts that rely on matching versions; alternatively, add a short note in the repo README explaining that the JS package ("version" in package.json) and the Python package (version in pyproject.toml) use independent versioning and why, so downstream tooling/users are not surprised.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@opencode/index.ts`:
- Around line 85-102: The try/catch around the shell invocation of python3 (the
$`echo ${hookInput} | python3 ${scriptPath}` call that assigns result and parses
stdout into decision) must gracefully handle infrastructure-level failures like
"python3 not found"; update the catch to detect these errors (e.g., err.code ===
'ENOENT' or err.message includes 'not found' / 'python3') and, instead of
re-throwing, log a warning and return so the operation proceeds, while
preserving the existing behavior of re-throwing actual block errors (when
decision.decision === "block") and other unexpected failures.
- Line 10: The import path for the Plugin type is wrong: replace the bare
specifier import type { Plugin } from "opencode/plugin" with the documented
package import from "@opencode-ai/plugin" so the TypeScript type resolution
matches the OpenCode API; update the import statement in opencode/index.ts to
import the Plugin type from "@opencode-ai/plugin" (referencing the Plugin
symbol) and run type-check to ensure no other import sites need the same change.
In `@opencode/package.json`:
- Around line 20-23: The package currently lists
"../hooks/protect_directories.py" in the package.json "files" array which npm
will drop; either copy hooks/protect_directories.py into the opencode/ package
directory and change the "files" entry to "protect_directories.py" and update
the findScript() in index.ts to resolve "./protect_directories.py", or add a
prepack/npm script that copies ../hooks/protect_directories.py into the package
dir at build time, keep the files entry pointing to the copied path, and ensure
findScript() in index.ts resolves the packaged path (not a parent-dir path) so
the file is present after npm publish.
In `@README.md`:
- Line 52: The README's manual copy instruction is incomplete: clarify that
opencode/index.ts depends on findScript() which resolves the Python file at
../hooks/protect_directories.py, so you must copy the entire opencode directory
tree preserving the sibling hooks/ directory (i.e., place hooks/ alongside
plugin/), not just opencode/index.ts; update the text to explicitly instruct
copying both the plugin/ folder and its sibling hooks/ folder (or provide the
full required directory layout) so the relative path used by findScript()
remains valid.
---
Nitpick comments:
In `@opencode/index.ts`:
- Line 11: The import list includes an unused symbol "dirname" (import {
resolve, dirname } from "path") while the code uses import.meta.dir directly;
remove "dirname" from the import to eliminate dead code and keep only the needed
"resolve" import in opencode/index.ts (update the import statement to import {
resolve } from "path").
- Around line 67-70: The function findScript uses the Bun-only extension
import.meta.dir to locate protect_directories.py, which is a nonstandard runtime
assumption; update the codebase by adding a clear comment above findScript
documenting that import.meta.dir is Bun-specific and that OpenCode expects
packages under ~/.cache/opencode/node_modules/, add a short runtime-check or
warning (referencing findScript and import.meta.dir) that logs a helpful message
if import.meta.dir is unavailable, and add the same note to the project README
or plugin docs so future maintainers know the Bun dependency and where packages
are cached.
- Around line 72-104: BlockPlugin's current hook on "tool.execute.before" (in
BlockPlugin) only catches primary-agent tool calls and can be bypassed by
subagents spawned via the task tool; update the code and docs: add a clear
README note describing this limitation and recommend users not rely on
BlockPlugin for subagent enforcement, and update the runtime enforcement by
either registering the same protection check for the subagent execution path
(e.g., also listen for the broader "tool.execute" or the task-spawn execution
event) or instrument the task/tool runner to call buildHookInput and the
BlockPlugin check before spawning subagents; reference BlockPlugin,
PROTECTED_TOOLS, buildHookInput and the "tool.execute.before" hook when making
the change so the protection logic is invoked for subagent tool calls as well.
- Around line 43-52: The code currently reads alternate legacy field names
(args.cmd, args.filePath, args.file) but tests and comments use canonical names
(command and file_path); remove the dead compatibility fallbacks so the bash
branch only reads args.command and the file branch only reads args.file_path,
and set toolInput.command = args.command and toolInput.file_path =
args.file_path directly (remove references to cmd, filePath, file and their
local variable aliases). If you intend to preserve backward compatibility
instead, add a short comment above these branches explaining they intentionally
accept legacy Claude Code names (cmd, filePath, file) for compatibility;
otherwise delete the fallback checks and local variables.
In `@opencode/package.json`:
- Line 3: The package.json "version" field is eight releases ahead of the Python
package's version in pyproject.toml which will confuse users; either sync the
two versions or explicitly document independent versioning. Fix by updating the
"version" field in package.json to match the pyproject.toml version (or
vice‑versa), and update release notes/changelog and any CI/release scripts that
rely on matching versions; alternatively, add a short note in the repo README
explaining that the JS package ("version" in package.json) and the Python
package (version in pyproject.toml) use independent versioning and why, so
downstream tooling/users are not surprised.
- Fix import path: opencode/plugin → @opencode-ai/plugin - Remove unused dirname import - Handle python3-not-found gracefully (warn and allow operation) - Add prepack script to copy protect_directories.py for npm publish - Use canonical OpenCode arg names (filePath, command) without fallbacks - Add Bun-specific comment on import.meta.dir - Clarify README manual setup with required directory layout - Document subagent limitation for tool.execute.before hook https://claude.ai/code/session_011KMGYhQjWHZKReC4TS4xa8
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@opencode/package.json`:
- Around line 7-8: The prepack/postpack npm scripts use POSIX-only commands
(`cp` and `rm -f`) which fail on Windows; update the package.json scripts
`prepack` and `postpack` to use cross-platform `shx` equivalents (e.g., `shx cp
../hooks/protect_directories.py protect_directories.py` and `shx rm -f
protect_directories.py`) and add `shx` as a devDependency so the commands are
available across platforms; ensure the referenced file name
`protect_directories.py` remains the same.
- Around line 1-28: The package.json is missing a dependencies section for the
runtime import used in index.ts; add a "dependencies" object to package.json and
declare "@opencode-ai/plugin" with an appropriate semver (e.g., a caret-range
matching the plugin API you built against) so that when Bun/npm installs this
package it also installs `@opencode-ai/plugin`; update the "files" or other
metadata only if necessary, but the main fix is adding the dependencies entry
referencing "@opencode-ai/plugin" so the import in index.ts resolves at runtime.
In `@README.md`:
- Line 54: The README's fenced code block containing the directory-tree snippet
(the block showing "your-project/") lacks a language specifier; update that
fence to include a language tag such as text or plaintext (e.g., change the
opening ``` to ```text) so the directory-tree code block satisfies MD040 and
renders as plain text.
- Around line 38-42: The README shows the opencode.json key as "plugins"
(plural) but OpenCode expects "plugin" (singular); update both occurrences of
the key in the README examples so the JSON uses "plugin" and keeps the array
value intact (i.e., replace "plugins" with "plugin" in the opencode.json sample
blocks and any other examples referencing that key).
---
Duplicate comments:
In `@opencode/package.json`:
- Around line 24-27: The package.json "files" field currently lists "index.ts"
and "protect_directories.py", but to ensure the packaged artifact is correct you
must keep "protect_directories.py" as the local copy created by the prepack
script and ensure the prepack/postpack scripts actually perform the copy and
cleanup; specifically verify the prepack script copies
../hooks/protect_directories.py into the package root before packing and the
postpack script removes that local copy afterward so the "files" field (in
package.json) correctly references the prepack-copied protect_directories.py and
index.ts.
| { | ||
| "name": "opencode-block", | ||
| "version": "1.1.14", | ||
| "description": "File and directory protection for OpenCode using .block marker files with pattern matching", | ||
| "main": "index.ts", | ||
| "scripts": { | ||
| "prepack": "cp ../hooks/protect_directories.py protect_directories.py", | ||
| "postpack": "rm -f protect_directories.py" | ||
| }, | ||
| "keywords": [ | ||
| "opencode", | ||
| "opencode-plugin", | ||
| "protection", | ||
| "security", | ||
| "file-blocking", | ||
| "directory-lock" | ||
| ], | ||
| "author": "Iiro Rahkonen", | ||
| "license": "MIT", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/kodroi/block" | ||
| }, | ||
| "files": [ | ||
| "index.ts", | ||
| "protect_directories.py" | ||
| ] | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's verify the package.json location and content
find . -name "package.json" -path "*/opencode/*" | head -20Repository: kodroi/block
Length of output: 79
🏁 Script executed:
# Also, let's look for the index.ts file
find . -name "index.ts" -path "*/opencode/*" | head -20Repository: kodroi/block
Length of output: 75
🏁 Script executed:
# Check the repository structure to understand the layout
git ls-files | grep -E "(opencode|package\.json|index\.ts)" | head -30Repository: kodroi/block
Length of output: 95
🏁 Script executed:
# Read the index.ts file to verify imports
cat -n ./opencode/index.tsRepository: kodroi/block
Length of output: 5285
🏁 Script executed:
# Read package.json to verify its current state
cat -n ./opencode/package.jsonRepository: kodroi/block
Length of output: 916
🏁 Script executed:
# Search for any OpenCode documentation or examples about plugin dependencies
find . -type f -name "*.md" -o -name "*.txt" | xargs grep -l "opencode-ai/plugin\|plugin.*dependency" 2>/dev/null | head -10Repository: kodroi/block
Length of output: 38
🏁 Script executed:
# Check if there are other plugin examples in the repository
find . -type f -name "package.json" | xargs grep -l "@opencode-ai/plugin\|opencode-plugin" | head -10Repository: kodroi/block
Length of output: 79
🏁 Script executed:
# Look for any tsconfig or build configuration that might indicate how plugins are compiled
find . -name "tsconfig.json" -o -name "bunfig.toml" -o -name ".bun*" | head -10Repository: kodroi/block
Length of output: 38
🏁 Script executed:
# Check if `@opencode-ai/plugin` is used elsewhere in the repo
rg "@opencode-ai/plugin" --type ts --type jsonRepository: kodroi/block
Length of output: 124
🌐 Web query:
OpenCode plugin dependencies @opencode-ai/plugin how to declare
💡 Result:
To declare dependencies for an OpenCode plugin (using @opencode-ai/plugin), you do it via package.json—where you put that package.json depends on whether your plugin is local or an npm package.
1) Local plugin (.opencode/plugins/*)
Create a package.json in your OpenCode config directory (commonly .opencode/package.json in the project), and list the npm deps you want your plugin to import:
{
"dependencies": {
"@opencode-ai/plugin": "^1.1.34",
"zod": "^4.1.8"
}
}OpenCode will run bun install at startup, and your plugin can then import those packages. (opencode.ai)
Example TypeScript usage:
import type { Plugin } from "@opencode-ai/plugin"2) Plugin published to npm (loaded via opencode.json)
You publish your plugin as a normal npm package with its own package.json dependencies, then load it in opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["@my-org/custom-plugin"]
}Citations:
- 1: https://opencode.ai/docs/plugins/?utm_source=openai
- 2: https://opencode.ai/docs/plugins/?utm_source=openai
- 3: https://opencode.ai/docs/plugins/?utm_source=openai
🌐 Web query:
OpenCode npm plugin installation Bun dependency resolution
💡 Result:
Installing OpenCode plugins from npm
- Add the package name(s) to
pluginin youropencode.json:{ "$schema": "https://opencode.ai/config.json", "plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"] } - Restart OpenCode. It installs npm plugins automatically using Bun at startup and caches them under
~/.cache/opencode/node_modules/. [1]
If you’re writing a local plugin and need dependencies
- Put your plugin in
.opencode/plugins/(project) or~/.config/opencode/plugins/(global). [1] - Add a
package.jsonin the OpenCode config directory (commonly.opencode/package.json) with your dependencies, e.g.:OpenCode will run{ "dependencies": { "shescape": "^2.1.0" } }bun installat startup so your plugin can import them. [1]
Bun dependency resolution knobs (when something won’t resolve / wrong transitive version)
- Use
overrides(npm) orresolutions(Yarn-style) in that samepackage.jsonto force transitive (“metadependency”) versions; Bun supports both. [2][3]{ "dependencies": { "your-dep": "^1" }, "overrides": { "problem-transitive": "1.2.3" } }
If installs fail due to lifecycle scripts (postinstall/native builds)
- Bun may block lifecycle scripts by default; allow them by adding the package to
trustedDependencies(or runbun pm trust <pkg>), then reinstall. [4]
Sources: OpenCode plugin docs [1]; Bun overrides/resolutions docs [2][3]; Bun trusted dependencies docs [4].
🏁 Script executed:
# Check the README for any setup or installation instructions
cat -n README.md 2>/dev/null || echo "No README.md found"Repository: kodroi/block
Length of output: 8663
🏁 Script executed:
# Look for any GitHub workflow or CI configuration that might show how plugins are tested
find . -type f \( -name "*.yml" -o -name "*.yaml" \) | head -5 | xargs cat 2>/dev/nullRepository: kodroi/block
Length of output: 17569
Add missing @opencode-ai/plugin dependency declaration.
The package has no dependencies field. index.ts imports from @opencode-ai/plugin (line 10), but it isn't declared in package.json. When Bun installs this plugin from npm, it won't install @opencode-ai/plugin alongside it, causing a Cannot find module "@opencode-ai/plugin" error at runtime.
For npm-published plugins, dependencies must be declared in the plugin's own package.json. Add:
📦 Proposed fix
+ "dependencies": {
+ "@opencode-ai/plugin": "latest"
+ },📝 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.
| { | |
| "name": "opencode-block", | |
| "version": "1.1.14", | |
| "description": "File and directory protection for OpenCode using .block marker files with pattern matching", | |
| "main": "index.ts", | |
| "scripts": { | |
| "prepack": "cp ../hooks/protect_directories.py protect_directories.py", | |
| "postpack": "rm -f protect_directories.py" | |
| }, | |
| "keywords": [ | |
| "opencode", | |
| "opencode-plugin", | |
| "protection", | |
| "security", | |
| "file-blocking", | |
| "directory-lock" | |
| ], | |
| "author": "Iiro Rahkonen", | |
| "license": "MIT", | |
| "repository": { | |
| "type": "git", | |
| "url": "https://github.com/kodroi/block" | |
| }, | |
| "files": [ | |
| "index.ts", | |
| "protect_directories.py" | |
| ] | |
| } | |
| { | |
| "name": "opencode-block", | |
| "version": "1.1.14", | |
| "description": "File and directory protection for OpenCode using .block marker files with pattern matching", | |
| "main": "index.ts", | |
| "scripts": { | |
| "prepack": "cp ../hooks/protect_directories.py protect_directories.py", | |
| "postpack": "rm -f protect_directories.py" | |
| }, | |
| "dependencies": { | |
| "@opencode-ai/plugin": "latest" | |
| }, | |
| "keywords": [ | |
| "opencode", | |
| "opencode-plugin", | |
| "protection", | |
| "security", | |
| "file-blocking", | |
| "directory-lock" | |
| ], | |
| "author": "Iiro Rahkonen", | |
| "license": "MIT", | |
| "repository": { | |
| "type": "git", | |
| "url": "https://github.com/kodroi/block" | |
| }, | |
| "files": [ | |
| "index.ts", | |
| "protect_directories.py" | |
| ] | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@opencode/package.json` around lines 1 - 28, The package.json is missing a
dependencies section for the runtime import used in index.ts; add a
"dependencies" object to package.json and declare "@opencode-ai/plugin" with an
appropriate semver (e.g., a caret-range matching the plugin API you built
against) so that when Bun/npm installs this package it also installs
`@opencode-ai/plugin`; update the "files" or other metadata only if necessary, but
the main fix is adding the dependencies entry referencing "@opencode-ai/plugin"
so the import in index.ts resolves at runtime.
| ```json | ||
| { | ||
| "plugins": ["opencode-block"] | ||
| } | ||
| ``` |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
OpenCode configuration schema opencode.json plugin key
💡 Result:
In OpenCode’s opencode.json / opencode.jsonc config, the key for plugins is:
"plugin": an array of plugin identifiers (npm package names, including scoped packages; you can also pin versions likename@x.y.z). (opencode.ai)
Example:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"]
}Schema URL (for editor validation/autocomplete):
"$schema": "https://opencode.ai/config.json"(opencode.ai)
Citations:
- 1: https://opencode.ai/docs/plugins/?utm_source=openai
- 2: https://opencode.ai/docs/plugins/?utm_source=openai
- 3: https://opencode.ai/docs/config?utm_source=openai
🏁 Script executed:
grep -n "plugins" README.md | head -20Repository: kodroi/block
Length of output: 150
opencode.json config key should be "plugin" (singular), not "plugins" (plural).
OpenCode's configuration schema uses "plugin" for the plugins array. The README incorrectly shows "plugins" (plural) in two places (lines 40 and 48), which won't be recognized and the plugin won't load.
Proposed fixes
Line 40:
{
- "plugins": ["opencode-block"]
+ "plugin": ["opencode-block"]
}Line 48:
{
- "plugins": ["file:///path/to/block/opencode/index.ts"]
+ "plugin": ["file:///path/to/block/opencode/index.ts"]
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@README.md` around lines 38 - 42, The README shows the opencode.json key as
"plugins" (plural) but OpenCode expects "plugin" (singular); update both
occurrences of the key in the README examples so the JSON uses "plugin" and
keeps the array value intact (i.e., replace "plugins" with "plugin" in the
opencode.json sample blocks and any other examples referencing that key).
|
|
||
| You can also set up the plugin manually by copying files into your project. The plugin expects `hooks/protect_directories.py` to be a sibling of the directory containing `index.ts`: | ||
|
|
||
| ``` |
There was a problem hiding this comment.
Add a language specifier to the fenced code block (MD040).
The directory-tree code block on line 54 is missing a language tag; use text or plaintext.
📝 Proposed fix
-```
+```text
your-project/🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 54-54: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@README.md` at line 54, The README's fenced code block containing the
directory-tree snippet (the block showing "your-project/") lacks a language
specifier; update that fence to include a language tag such as text or plaintext
(e.g., change the opening ``` to ```text) so the directory-tree code block
satisfies MD040 and renders as plain text.
Add publish-npm job to CI that publishes to npm after tagging. Sync opencode/package.json version in the tag job and include opencode/** in the versionable paths filter. Requires NPM_TOKEN repository secret. https://claude.ai/code/session_011KMGYhQjWHZKReC4TS4xa8
Replace long-lived NPM_TOKEN secret with GitHub Actions OIDC id-token permission for secure, tokenless npm publishing. Provenance attestations are generated automatically. https://claude.ai/code/session_011KMGYhQjWHZKReC4TS4xa8
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/ci.yml:
- Around line 548-551: The "Update package version" step in the publish-npm job
runs npm version with the same version already committed and causes "Version not
changed" failures; remove that step entirely (the tag job already updated and
pushed opencode/package.json) or, if you need a local-only bump, change the
operation to either run npm version with --allow-same-version or read the
version from package.json (e.g., with jq) and skip npm version. Update the
publish-npm job to rely on the checked-out main's package.json instead of
re-running npm version.
- Around line 527-556: The publish-npm job currently uses Node 20 which ships
npm 10.x and will fail Trusted Publishing OIDC; before publishing update npm to
at least 11.5.1 (e.g., run npm install -g npm@^11.5.1 or npm@latest in the Setup
Node.js step), run npm ci inside opencode to install/build so prepack/prepublish
scripts run (add an Install/Build step before Update package version or before
Publish to npm), and add the provenance flag to the publish command (use npm
publish --access public --provenance or set NPM_CONFIG_PROVENANCE=true) in the
Publish to npm step; also ensure the first-time publish uses a traditional npm
token (Trusted Publisher must be configured afterward on npmjs.com) so the OIDC
flow succeeds later.
| publish-npm: | ||
| name: Publish to npm | ||
| runs-on: ubuntu-latest | ||
| needs: [version, tag] | ||
| if: github.ref == 'refs/heads/main' | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: main | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| registry-url: 'https://registry.npmjs.org' | ||
|
|
||
| - name: Update package version | ||
| run: | | ||
| cd opencode | ||
| npm version ${{ needs.version.outputs.majorMinorPatch }} --no-git-tag-version | ||
|
|
||
| - name: Publish to npm | ||
| run: | | ||
| cd opencode | ||
| npm publish --access public |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd -g 'package.json' opencode/ --exec cat {}Repository: kodroi/block
Length of output: 720
🌐 Web query:
npm version bundled with Node.js 20 LTS
💡 Result:
For the current Node.js 20 LTS (20.20.0, released Jan 12, 2026), the bundled npm version is npm 10.8.2. [1][2]
Note: The bundled npm version can vary across Node 20.x releases; the Node.js v20 download archive lists the npm version per release. [1]
Sources: [1] [2]
🌐 Web query:
npm trusted publishing OIDC registry-url conflict Node.js actions/setup-node
💡 Result:
When you set registry-url in actions/setup-node, it writes a project-local .npmrc (including an auth line like //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}), which can override/conflict with other npm-auth flows in the same job (notably tools like semantic-release) and can also “stick” if you switch registries multiple times in one workflow/job. [2], [3]
What to do (depending on your setup)
-
If you’re using npm Trusted Publishing (OIDC) +
semantic-release: don’t setregistry-url
semantic-releaseexplicitly warns thatregistry-urlcan cause.npmrcconflicts andEINVALIDNPMTOKEN. Configure registry via your repo.npmrc(if needed) and letsemantic-releasehandle auth. [3] -
If you’re using npm Trusted Publishing (OIDC) without
semantic-release: keepregistry-urlon npm’s registry and don’t provide a publish token
npm’s own Trusted Publishing example usesregistry-url: 'https://registry.npmjs.org'and then runsnpm publishwithid-token: writepermissions (noNODE_AUTH_TOKENfor publish). [1] -
If you must use a token for installs (private deps), scope it to the install step only
Trusted Publishing only coversnpm publish; installs may still need a (read-only) token. UseNODE_AUTH_TOKENonly onnpm ci, not globally. [1]
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
registry-url: https://registry.npmjs.org
- run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_READ_TOKEN }} # install only
- run: npm publish # OIDC is used here (no NODE_AUTH_TOKEN)- If your issue is “registry switching” within one job
There are known cases where changingregistry-urlacross multiplesetup-nodeinvocations doesn’t take effect as expected; a practical workaround is to avoid switching registries in the same job (split into separate jobs) or explicitly manage the.npmrcyou want for each publish. [4]
Sources: npm Trusted Publishing docs [1]; GitHub docs on setup-node creating .npmrc from registry-url/NODE_AUTH_TOKEN [2]; semantic-release guidance to avoid registry-url [3]; setup-node registry switching issue [4].
🌐 Web query:
npm CLI version requirement trusted publishing npm 11.5.1
💡 Result:
npm Trusted Publishing (OIDC) requires:
- npm CLI: v11.5.1 or later
- Node.js: v22.14.0 or later [1]
To verify your CLI version:
npm -vTo upgrade npm (example):
npm i -g npm@^11.5.1Sources: npm Trusted Publishing docs [1].
publish-npm job has one critical issue and several gaps to address
1. npm CLI version is below the Trusted Publishing requirement (critical)
Trusted Publishing requires npm CLI v11.5.1 or later, but Node.js 20 bundles npm 10.8.2. Add npm install -g npm@latest (or pin to ≥11.5.1) before the publish step. Without this upgrade, the OIDC token exchange will fail.
2. npm ci before publish is recommended practice
The workflow lacks npm ci before npm publish. While opencode/package.json has no prepare or prepublishOnly scripts, running npm ci ensures prepack lifecycle scripts execute reliably (this package copies files via prepack). Add a build/install step for robustness.
3. Consider adding --provenance explicitly
Even though Trusted Publishing doesn't strictly require --provenance, several users report that adding the flag made the initial publish succeed and produces clearer error messages. Add npm publish --access public --provenance or set NPM_CONFIG_PROVENANCE=true.
4. Trusted Publisher must be pre-configured on npmjs.com
npm requires the package to exist before a Trusted Publisher can be configured; the first publish must use a traditional token. After that initial publish, OIDC can be enabled. Ensure this setup is complete before merging.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/ci.yml around lines 527 - 556, The publish-npm job
currently uses Node 20 which ships npm 10.x and will fail Trusted Publishing
OIDC; before publishing update npm to at least 11.5.1 (e.g., run npm install -g
npm@^11.5.1 or npm@latest in the Setup Node.js step), run npm ci inside opencode
to install/build so prepack/prepublish scripts run (add an Install/Build step
before Update package version or before Publish to npm), and add the provenance
flag to the publish command (use npm publish --access public --provenance or set
NPM_CONFIG_PROVENANCE=true) in the Publish to npm step; also ensure the
first-time publish uses a traditional npm token (Trusted Publisher must be
configured afterward on npmjs.com) so the OIDC flow succeeds later.
Replace cp/rm with Node.js fs calls so npm pack works on Windows. https://claude.ai/code/session_011KMGYhQjWHZKReC4TS4xa8
Copy README.md from repo root during prepack so it appears on the npm package page. https://claude.ai/code/session_011KMGYhQjWHZKReC4TS4xa8
- Remove redundant npm version step (tag job already updates package.json) - Upgrade npm to 11.5+ (Node 20's npm 10.x lacks OIDC support) - Add --provenance flag for supply chain attestations https://claude.ai/code/session_011KMGYhQjWHZKReC4TS4xa8
Add a TypeScript plugin for OpenCode that reuses the existing
protect_directories.py protection logic via tool.execute.before hook.
Intercepts edit, write, bash, and patch tools. +semver: minor
https://claude.ai/code/session_011KMGYhQjWHZKReC4TS4xa8
Summary by CodeRabbit
New Features
Documentation
Tests
Chores