OpenCode tools: stop blind trust with permission checks

Blog 13 min read

OpenCode has drawn a large developer following by mid-2026, yet its default configuration grants unrestricted tool access without permission checks.

The platform's rapid ascent to over 170,000 GitHub stars highlights its dominance, but this scale amplifies the risk of unauthorized actions when tool permissions remain unconfigured. By default, the system allows any LLM to run shell commands or overwrite files via the write tool without user approval. Understanding these mechanics is critical because the difference between a helpful agent and a compromised repository often lies in a single configuration flag.

Readers will learn to replace blind trust with granular control by configuring permission fields to require approval for sensitive operations. Mastering these settings ensures that the automation powering your development workflow remains a servant to your security policy rather than a threat vector.

The Role of Tools and MCP Servers in OpenCode Architecture

Defining OpenCode Tools: Built-in Bash, Edit, and LSP Functions

OpenCode defines a tool as a specific function call that permits an LLM to execute actions like file editing or shell commands within a codebase. The platform ships with a reliable suite of built-in utilities: bash, edit, write, read, grep, glob, lsp, apply_patch, skill, todowrite, and webfetch. The edit tool acts as the primary mechanism for code modification, applying exact string replacements to existing files rather than rewriting entire blocks. For broader environmental interaction, bash executes shell commands such as dependency installation or version control operations directly in the project context.

Developers extend functionality beyond these defaults by integrating MCP servers or defining custom tools. The lsp utility provides code intelligence features like definition lookup and reference finding by interacting with configured Language Server Protocol servers. Custom tools keyed by name override built-in equivalents, permitting targeted behavioral adjustments without altering the core binary. All of these tools are enabled by default and do not require permission to run, so restricting them is an explicit act of configuration rather than a state the installation ships in.

Applying Custom Tools and MCP Servers for Database Access

Extending OpenCode beyond file manipulation requires defining custom tools or connecting MCP servers for external service integration. This architectural approach allows the system to interact with external resources through standardized server connections rather than relying solely on local file operations. Operators configure these extensions in opencode.json, where custom definitions keyed by name take precedence over default behaviors. This allows teams to wrap complex SQL queries or API calls into safe, parameterized functions that the LLM invokes via function calling.

Feature Built-in Tools Custom/MCP Tools
Scope Filesystem and Shell External APIs, Databases
Execution Local environment External service integration
Config Enabled by default Requires definition

The platform supports connectivity to more than 75 different LLM providers, allowing for extensive model agnosticism. Broader automation capabilities demand clear permission schemas to manage access to external resources effectively.

Security Risks of Arbitrary Code Execution in Custom OpenCode Tools

Custom tools function as user-set functions capable of executing code within the host environment. Custom definitions keyed by name take precedence over built-in utilities, allowing potential override of safe defaults.

The platform emphasizes safety and control through its permission model, where tool behavior is explicitly managed via configuration. Without strict separation of reasoning and execution, an agent could perform unauthorized actions if a custom function lacks proper guardrails. OpenCode has accumulated over 170,000 stars on GitHub by mid-2026, reflecting its widespread adoption and scrutiny. The development community consists of over 900 contributors who have collaborated on the codebase. Builders must treat custom function definitions as trusted entry points requiring rigorous validation before deployment.

Internal Mechanics of Search Execution and Patch Application

Ripgrep Pattern Matching and Gitignore Exclusion Logic

Search requests from the grep and glob tools route directly to ripgrep, which automatically respects .gitignore patterns to filter out listed files. Operators can override this default exclusion logic by placing a .ignore file in the project root, explicitly re-including directories like node_modules or dist when full-context analysis becomes necessary. While grep matches file content using regular expressions, glob operates strictly on file paths using syntax such as /*.ts. The apply_patch tool functions differently by consuming patchText containing embedded markers like * Update File rather than performing pattern matching. This separation means search tools define the context window, while patching tools apply deterministic changes. Strict adherence to .gitignore improves signal-to-noise ratios for code queries but risks blinding the agent to configuration files often excluded by default. Developers must verify their ignore rules do not inadvertently hide critical infrastructure definitions from the LLM's view.

Configuring .ignore Files to Include node_modules and dist

Users can create a .ignore file in the project root to include normally ignored files. Built-in tools respect .gitignore patterns to filter noise, yet specific debugging sessions often require visibility into node_modules or dist directories. Placing inversion rules like !node_modules/ and !dist/ in this local configuration allows ripgrep to search within those directories even if they are listed in .gitignore. This approach resolves the common failure mode where dependency code remains invisible to grep queries. Modifying the shared .gitignore risks breaking builds for collaborators, whereas the .ignore file acts as a local override layer. This distinction allows operators to maintain clean repository standards while granting temporary, deep-scope access for specific analysis tasks. The mechanism relies on ripgrep using these local files to expand search visibility beyond standard git-set exclusions. Flexibility introduces a risk of context pollution if broad wildcards are applied indiscriminately. Searching entire dependency trees can increase the volume of data processed, potentially impacting performance. Operators should scope these overrides to specific subdirectories rather than inverting entire hierarchies.

Developers enforcing consistent workflow rules across a team might instead apply AGENTS.md files to define persistent guardrails that survive session restarts. Temporary search depth does not permanently alter the project's exclusion logic with this separation. Immediate investigative power conflicts with long-term signal-to-noise ratio maintenance. Precise control over search scope prevents the agent from hallucinating requirements based on transitive dependencies.

Edit Tool String Replacement Versus Write Tool Overwrite

The edit tool modifies existing files using exact string replacements, whereas write creates new files or overwrites existing ones entirely. This mechanical distinction determines how the LLM interacts with the codebase during patch application. Edit operates as a surgical instrument, requiring the target text to match the source exactly to succeed, making it the primary method for refactoring logic without altering file metadata. Write functions as a blunt replacement mechanism; if a file already exists, the tool discards the original content completely before saving the new version.

Write carries a higher risk of accidental data loss if the LLM misidentifies a file's necessity, as it does not merge changes. The edit tool requires exact matches to function, failing if the target text differs from the source. Edit struggles with large-scale structural changes where context shifting makes exact matching improbable. The system relies on apply_patch to handle complex diffs using its embedded marker lines relative to the project root in these scenarios. This separation enforces a boundary between reasoning and execution, ensuring AI agents operate within the permissions set in opencode.json. Builders should default to edit for iterative improvements and reserve write for initial scaffolding or when a complete file reset is the intended outcome.

Configuring Tool Permissions and Security Boundaries

Defining opencode.json Permission Modes: Allow, Deny, and Ask

The permission field inside opencode.json draws a hard line between model reasoning and actual system execution. Engineers map specific tool names to explicit access states to enforce safety policies before any code modification occurs. Three distinct modes govern this behavior: allow grants immediate execution, deny blocks the action entirely, and ask requires manual approval for every single invocation. This model prevents unauthorized shell access while keeping workflow fluid for safe operations like reading files. Teams explicitly set permissions for utilities like bash or write to manage environment interactions during autonomous runs.

Using Wildcards to Secure MCP Servers and Bash Tools

Wildcard patterns like "mymcp_*": "ask" instantly gate entire MCP server toolsets behind manual approval. This configuration prevents unauthorized execution across flexible integrations by grouping tools under a single permission rule. Operators configure dangerous utilities like bash to ask rather than allow, forcing human verification before the LLM runs shell commands such as npm install or git status. The bash tool executes shell commands in the project environment, while the write tool creates new files or overwrites existing ones.

  1. Define the permission object in opencode.json to establish your security baseline.
  2. Apply wildcard syntax to target specific MCP server prefixes without listing individual tools.
  3. Set high-risk tools to ask to ensure every execution requires explicit user consent.

This approach treats the permission model as a scalable filter rather than a static list, which matters most when one MCP server exposes dozens of tools at once.

Validating Read, Grep, and Glob Tool Access Rules

Verify read, grep, and glob scoping to manage data access before enabling write capabilities. These tools form the observation layer, and their configuration determines exactly how agents inspect the codebase.

  1. Configure read permissions, noting the tool supports reading specific line ranges for large files.
  2. Configure grep to apply full regex syntax and file pattern filtering for fast content searches.
  3. Use glob patterns like /*.js or src//*.ts to find files, with results sorted by modification time.
Tool Primary Function Configuration Note
read Read file contents Supports specific line ranges
grep Search file contents Uses full regex syntax
glob Find files by pattern Returns paths sorted by time

The operational balance lies between debugging depth and access scope; broadening search paths aids the agent in resolving dependencies but increases the volume of accessible data. Unlike write operations, read-only tools like read, grep, and glob do not modify code, yet they provide visibility into the project structure. Internally, tools like grep and glob apply ripgrep, which respects .gitignore patterns by default, excluding listed files and directories from searches unless overridden by a .ignore file.

Extending Functionality with Custom Tools and Web Integrations

Defining Custom Tool Functions in Config Files

Defining custom tool functions in the config file extends the LLM's execution boundary beyond built-in capabilities like read or bash. These user-set functions, declared within opencode.json or the global ~/.config/opencode/tools/ directory, enable the agent to execute arbitrary code tailored to specific project workflows. Unlike static built-ins, custom tools keyed by name take precedence over default behaviors, allowing developers to override standard operations with specialized logic. This precedence rule ensures that project-specific guardrails always supersede generic defaults when naming conflicts occur. Implementation relies on the tool helper to maintain type safety while defining these executable signatures. A significant architectural consequence involves the merger of settings from multiple sources, where managed organization settings override project-level .opencode directories, which in turn override global configs. This hierarchy means a custom tool set globally might be silently replaced by a project manager, requiring operators to audit the full configuration chain before deployment.

Source Level Precedence Scope
Managed Settings Highest Organization-wide
Project Config Medium Repository-specific
Global Config Lowest User environment

Configuration directories apply specific pluralized subdirectories including agents/, commands/, modes/, plugins/, skills/, tools/, and themes/ for organized management. For further guidance on structuring these definitions, refer to the documentation on creating custom tools. As noted by industry trends, this modular approach prevents vendor lock-in by decoupling tool logic from the underlying model provider.

Application: Integrating Database Access via MCP Servers

Connect external databases by registering MCP servers to expose live schema context directly to the coding agent. This integration replaces static documentation with flexible tool discovery, allowing the LLM to query table structures before generating SQL. Unlike custom flows that consume excessive tokens, standardized server connections reduce overhead while expanding the agent's operational boundary. Operators must explicitly configure opencode.json to gate database modifications behind manual approval workflows.

  1. Define the MCP server connection in the configuration file to establish the transport layer.
  2. Apply wildcard rules like "db_mcp_*": "ask" to force human verification on write operations.
  3. Restrict webfetch capabilities separately to control the agent's ability to fetch external content.

Since session persistence relies on local SQLite databases, conversation history containing sensitive connection strings never leaves the user environment, yet the execution path remains vulnerable to prompt injection without strict tool gating.

Configuration Mode Effect on MCP Tools Risk Profile
allow Immediate execution High
ask Requires approval Medium
deny Blocks access None

Neglecting this granular control allows an agent to execute arbitrary code via exposed custom tools, potentially compromising the entire host environment.

Economic Advantages of Bring-Your-Own-Key Models

OpenCode avoids the $20/month subscription fee common to IDEs like Cursor by using a bring-your-own-key financial structure. This model decouples tool management from inference costs, ensuring developers pay only for token usage via external providers while the core software remains free under an MIT license. Unlike Claude Code, which restricts users to Anthropic models, this approach allows selection of specific providers to optimize price-performance ratios based on project needs. The ability to select specific providers allows teams to route traffic through cheaper APIs during bulk operations, a flexibility absent in bundled offerings. However, this cost efficiency shifts the burden of key management and usage monitoring entirely to the developer, requiring disciplined tracking to prevent unexpected bills from external providers. Integrating strict permission controls helps mitigate risks associated with unrestricted tool execution in this decentralized model.

About

Marcus Chen, Lead Agent Engineer at AI Agents News, brings deep practical expertise to the analysis of OpenCode's tool management system. Having shipped production multi-agent systems, Chen understands that effective orchestration relies heavily on how agents access and execute external functions. His daily work involves evaluating frameworks like CrewAI and AutoGen, where tool calling mechanics often determine system reliability. This article dissects OpenCode's permission structures and MCP server integrations, reflecting Chen's focus on concrete engineering controls rather than theoretical capabilities. At AI Agents News, the mission is to provide technical founders and engineers with actionable insights on autonomous agents. By connecting OpenCode's configuration options to real-world deployment scenarios, Chen helps readers navigate the complexities of function calling security and extensibility. His analysis ensures builders can make informed decisions about integrating these tools into their own coding agent workflows without falling for vendor hype.

Conclusion

The default posture of OpenCode is open: every tool runs, nothing asks. That default is what makes the platform quick to adopt, and it is also what lets a single custom definition keyed over a built-in name, or one unattended bash call, reach the host environment directly. The permission field is the only boundary between model reasoning and system execution, and it stays inert until somebody writes it.

Adopt OpenCode only if your team sets that boundary before the first autonomous run: allow for read-only observation tools like grep, ask for anything that writes files or executes shell commands, deny for what the agent has no business touching. Bring-your-own-key pricing removes the subscription line item, but it adds nothing to this boundary.

Start by configuring wildcard rules to force human verification on all write operations before connecting any external model provider. This single step establishes the necessary boundary between agent autonomy and system integrity, ensuring that the flexibility of custom tools does not compromise your host environment.

Frequently Asked Questions

All tools run without permission checks by default. This exposes the entire developer community to potential unauthorized code execution if configurations remain unchanged.

Set permission fields to deny or ask in your config file. This protects active users by preventing automatic shell commands or file overwrites.

Yes. Permission keys are matched as wildcard patterns, so one rule can gate an entire MCP server toolset behind manual approval instead of naming each tool separately.

You gain code intelligence like definitions and references. The lsp tool provides this by interacting with configured Language Server Protocol servers, so the agent resolves a symbol instead of inferring it from raw search hits.

Custom definitions keyed by name take precedence over built-in utilities. Configuration also merges by source, where managed organization settings override project directories, which override global configs, so a globally defined tool can be replaced further up that chain without warning.

References