Install
$ agentstack add skill-timmy6942025-opencode-builder-skill-opencode-tools ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ● Filesystem access Used
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
OpenCode Tools
> 📚 Official Docs: For the latest information, always refer to the official documentation: > https://opencode.ai/docs/tools/ and https://opencode.ai/docs/custom-tools/
OpenCode provides a set of built-in tools that let LLMs interact with your codebase. You can extend functionality with [custom tools](#custom-tools) or [MCP server integrations](#mcp-tools). All tools are enabled by default and don't require permission unless configured otherwise.
Tools allow the LLM to perform actions: reading files, editing code, running shell commands, searching content, fetching web pages, asking questions, and more. Permissions control which actions require approval.
Table of Contents
- [Built-in Tools](#built-in-tools)
- [bash](#bash)
- [edit](#edit)
- [write](#write)
- [read](#read)
- [grep](#grep)
- [glob](#glob)
- [lsp (experimental)](#lsp-experimental)
- [applypatch](#applypatch)
- [skill](#skill)
- [todowrite](#todowrite)
- [webfetch](#webfetch)
- [websearch](#websearch)
- [question](#question)
- [Permission Configuration](#permission-configuration)
- [Actions](#actions)
- [Global Configuration](#global-configuration)
- [Granular Rules (Object Syntax)](#granular-rules-object-syntax)
- [Wildcards](#wildcards)
- [Home Directory Expansion](#home-directory-expansion)
- [External Directories](#external-directories)
- [Doom Loop Detection](#doom-loop-detection)
- [Available Permission Keys](#available-permission-keys)
- [Defaults](#defaults)
- [What "Ask" Does](#what-ask-does)
- [Agent Permissions](#agent-permissions)
- [Custom Tools](#custom-tools)
- [Location](#location)
- [Structure](#structure)
- [Multiple Tools Per File](#multiple-tools-per-file)
- [Name Collisions with Built-in Tools](#name-collisions-with-built-in-tools)
- [Arguments (Zod Schema)](#arguments-zod-schema)
- [Context Object](#context-object)
- [Invoking Scripts in Any Language](#invoking-scripts-in-any-language)
- [Complete Examples](#complete-examples)
- [MCP Tools](#mcp-tools)
- [Internals](#internals)
- [Ripgrep Integration](#ripgrep-integration)
- [Ignore Patterns](#ignore-patterns)
- [Tool Precedence](#tool-precedence)
- [Defaults Summary](#defaults-summary)
Built-in Tools
bash
Permission key: bash Matches against: Parsed command string
Execute shell commands in your project environment. This tool allows the LLM to run terminal commands like npm install, git status, python3 script.py, or any other shell command.
Permission rules match against the parsed command string. For example, "git status --porcelain" is matched against the pattern.
{ "permission": { "bash": "allow" } }
Granular example — allow git and npm, deny rm, ask for everything else:
{
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"npm *": "allow",
"rm *": "deny",
"grep *": "allow"
}
}
}
Important: Commands with arguments require explicit patterns. "grep *" allows grep pattern file.txt, while "grep" alone (without wildcard) would block commands with arguments. Commands like git status work for default behavior but need "git status *" when arguments are passed.
edit
Permission key: edit Matches against: File path
Modify existing files using exact string replacements. This is the primary way the LLM modifies code — it finds an exact string in a file and replaces it with new content.
The edit permission also controls write and apply_patch. All file modifications share the edit permission key.
{ "permission": { "edit": "allow" } }
Granular example — deny edits globally, allow only docs:
{
"permission": {
"edit": {
"*": "deny",
"packages/web/src/content/docs/*.mdx": "allow"
}
}
}
write
Permission key: edit (shared with edit and apply_patch) Matches against: File path
Create new files or overwrite existing ones. This is separate from edit in functionality (full file creation/overwrite vs. string replacement) but shares the same permission key.
There is no separate write permission key — it is controlled entirely by the edit permission.
{ "permission": { "edit": "allow" } }
read
Permission key: read Matches against: File path
Read file contents from your codebase. Supports reading specific line ranges for large files using offset and limit parameters. Returns file contents with line numbers.
{ "permission": { "read": "allow" } }
.env files are denied by default. The default read permission is:
{
"permission": {
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow"
}
}
}
grep
Permission key: grep Matches against: Regex pattern
Search file contents using regular expressions. Uses ripgrep under the hood for fast content search across your codebase. Supports full regex syntax and file pattern filtering (include/exclude).
{ "permission": { "grep": "allow" } }
glob
Permission key: glob Matches against: Glob pattern
Find files by pattern matching using glob patterns like **/*.js or src/**/*.ts. Uses ripgrep under the hood. Returns matching file paths sorted by modification time (most recent first).
{ "permission": { "glob": "allow" } }
lsp (experimental)
Permission key: lsp Matches against: Non-granular
Interact with configured LSP servers for code intelligence features. Provides operations like finding definitions, references, hover information, call hierarchy, and symbol search.
Requires the environment variable OPENCODE_EXPERIMENTAL_LSP_TOOL=true (or the broader OPENCODE_EXPERIMENTAL=true). This tool is not available by default.
{ "permission": { "lsp": "allow" } }
Supported operations:
| Operation | Description | |---|---| | goToDefinition | Jump to the definition of a symbol | | findReferences | Find all references to a symbol | | hover | Get hover information for a symbol | | documentSymbol | List symbols in the current document | | workspaceSymbol | Search for symbols across the workspace | | goToImplementation | Jump to the implementation of an interface/trait | | prepareCallHierarchy | Prepare call hierarchy for a symbol | | incomingCalls | Get incoming calls to a function | | outgoingCalls | Get outgoing calls from a function |
To configure which LSP servers are available, see LSP Servers.
apply_patch
Permission key: edit (shared with edit and write) Matches against: Embedded path markers in patch text
Apply patches and diffs to files. Useful for applying changes from various sources. Unlike edit which uses filePath, apply_patch uses patchText with embedded marker lines that specify paths relative to the project root.
{ "permission": { "edit": "allow" } }
Patch format — paths are embedded as marker lines in patchText:
*** Add File: src/new-file.ts
*** Update File: src/existing.ts
*** Move to: src/renamed.ts
*** Delete File: src/obsolete.ts
Hook integration: When handling tool.execute.before or tool.execute.after hooks, check input.tool === "apply_patch" (not "patch"). Use output.args.patchText to access the patch content, not output.args.filePath.
The apply_patch tool is controlled by the edit permission, which covers all file modifications (edit, write, apply_patch).
skill
Permission key: skill Matches against: Skill name
Load a skill (a SKILL.md file) and return its content in the conversation. Permission rules match against the skill name.
{ "permission": { "skill": "allow" } }
todowrite
Permission key: todowrite Matches against: Non-granular
Manage todo lists during coding sessions. Creates and updates task lists to track progress during complex, multi-step operations. The LLM uses this tool to organize work, track completed items, and manage pending tasks.
{ "permission": { "todowrite": "allow" } }
Note: This tool is disabled for subagents by default, but you can enable it manually. See [Agent Permissions](#agent-permissions).
webfetch
Permission key: webfetch Matches against: URL
Fetch and read web pages. Allows the LLM to retrieve content from specific URLs. Useful for looking up documentation, researching online resources, or reading API responses.
Permission rules match against the full URL.
{ "permission": { "webfetch": "allow" } }
websearch
Permission key: websearch Matches against: Query string
Search the web using Exa AI. Performs web searches to find relevant information online. Useful for researching topics, finding current events, or gathering information beyond the training data cutoff.
Availability: Only available when using the OpenCode provider or when the OPENCODE_ENABLE_EXA environment variable is set to any truthy value (true, 1).
{ "permission": { "websearch": "allow" } }
Enabling:
OPENCODE_ENABLE_EXA=1 opencode
No API key is required — the tool connects directly to Exa AI's hosted MCP service without authentication.
Tip: Use websearch when you need to find information (discovery), and webfetch when you need to retrieve content from a specific URL (retrieval).
question
Permission key: question Matches against: Non-granular
Ask the user questions during execution. This tool allows the LLM to interactively gather input from the user mid-task. Each question includes a header, question text, and a list of options. Users can select from the provided options or type a custom answer.
{ "permission": { "question": "allow" } }
Use cases:
- Gathering user preferences or requirements
- Clarifying ambiguous instructions
- Getting decisions on implementation choices
- Offering choices about what direction to take
When there are multiple questions, users can navigate between them before submitting all answers.
Permission Configuration
Actions
Each permission rule resolves to one of three actions:
| Action | Behavior | |---|---| | "allow" | Run without approval | | "ask" | Prompt for approval before running | | "deny" | Block the action entirely |
Global Configuration
Set a single action for all tools:
{
"$schema": "https://opencode.ai/config.json",
"permission": "allow"
}
Set a default with per-tool overrides:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask",
"bash": "allow",
"edit": "deny"
}
}
Granular Rules (Object Syntax)
For most permissions, you can use an object to apply different actions based on the tool input. Rules are evaluated by pattern match, with the last matching rule winning. A common pattern is to put the catch-all "*" rule first, and more specific rules after it.
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"npm *": "allow",
"rm *": "deny",
"grep *": "allow"
},
"edit": {
"*": "deny",
"packages/web/src/content/docs/*.mdx": "allow"
}
}
}
Rule evaluation order: The last matching pattern wins. This means you can layer broad catch-all rules with increasingly specific overrides.
Wildcards
Permission patterns use simple wildcard matching:
| Character | Meaning | |---|---| | * | Matches zero or more of any character | | ? | Matches exactly one character | | All other characters | Match literally |
Examples:
"git *"— matchesgit status,git commit -m "msg",git push origin main"git ?*"— matchesgit statusbut notgitalone"*.md"— matchesREADME.md,docs/guide.md"rm *"— matchesrm file.txt,rm -rf dir/
Home Directory Expansion
Use ~ or $HOME at the start of a pattern to reference your home directory. This is particularly useful for external_directory rules.
| Pattern | Expands To | |---|---| | ~/projects/* | /Users/username/projects/* | | $HOME/projects/* | /Users/username/projects/* | | ~ | /Users/username |
External Directories
Use external_directory to allow tool calls that touch paths outside the working directory where OpenCode was started. This applies to any tool that takes a path as input (e.g., read, edit, glob, grep, and many bash commands).
Home expansion (~/...) only affects how a pattern is written — it does not make an external path part of the current workspace. Paths outside the working directory must still be allowed via external_directory.
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow"
}
}
}
Any directory allowed here inherits the same defaults as the current workspace. Since read defaults to "allow", reads are also allowed for entries under external_directory unless overridden. Layer extra rules when tools should be restricted:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow"
},
"edit": {
"~/projects/personal/**": "deny"
}
}
}
Keep the list focused on trusted paths, and layer extra allow or deny rules as needed for other tools (e.g., bash).
Doom Loop Detection
The doom_loop permission triggers when the same tool call repeats 3 times with identical input. This prevents infinite loops where the LLM repeatedly attempts the same failing operation.
Default: "ask" — prompts for approval when a doom loop is detected.
Available Permission Keys
| Key | Matches Against | Description | |---|---|---| | read | File path | Reading file contents | | edit | File path | All file modifications (covers edit, write, apply_patch) | | glob | Glob pattern | File pattern matching | | grep | Regex pattern | Content search | | bash | Parsed command string | Shell command execution | | task | Subagent type | Launching subagents | | skill | Skill name | Loading SKILL.md files | | lsp | Non-granular | LSP server queries | | question | Non-granular | Asking user questions | | webfetch | URL | Fetching web content | | websearch | Query string | Web search via Exa AI | | external_directory | Path outside working directory | Access to paths outside the project | | doom_loop | Repeated identical input | Infinite loop detection |
Defaults
If you don't specify anything, OpenCode starts from permissive defaults:
| Permission | Default | |---|---| | Most tools | "allow" | | read | "allow" (.env files denied by default) | | doom_loop | "ask" | | external_directory | "ask" | | todowrite (subagents) | Disabled | | lsp | Requires OPENCODE_EXPERIMENTAL_LSP_TOOL=true | | websearch | Requires OpenCode provider or OPENCODE_ENABLE_EXA=true |
.env file defaults:
{
"permission": {
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow"
}
}
}
What "Ask" Does
When OpenCode prompts for approval, the UI offers three outcomes:
| Option | Behavior | |---|---| | once | Approve just this request | | always | Approve future requests matching the suggested patterns (for the rest of the current session) | | reject | Deny the request
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Timmy6942025
- Source: Timmy6942025/opencode-builder-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.