Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/opencode/specs/effect-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ Individual tools, ordered by value:
- [ ] `batch.ts` — MEDIUM: parallel execution, per-call error recovery → Effect.all
- [ ] `task.ts` — MEDIUM: task state management
- [ ] `ls.ts` — MEDIUM: bounded directory listing over ripgrep-backed traversal
- [ ] `multiedit.ts` — MEDIUM: sequential edit orchestration over `edit.ts`
- [ ] `glob.ts` — LOW: simple async generator
- [ ] `lsp.ts` — LOW: dispatch switch over LSP operations
- [ ] `question.ts` — LOW: prompt wrapper
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/config/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const normalize = (agent: AgentInput): AgentInfo => {
const permission: ConfigPermission.Info = {}
for (const [tool, enabled] of Object.entries(tools ?? {})) {
const action = enabled ? "allow" : "deny"
if (tool === "write" || tool === "edit" || tool === "patch" || tool === "multiedit") {
if (tool === "write" || tool === "edit" || tool === "patch") {
permission.edit = action
continue
}
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ const rawLayer = Layer.effect(
const perms: Record<string, ConfigPermission.Action> = {}
for (const [tool, enabled] of Object.entries(result.tools)) {
const action: ConfigPermission.Action = enabled ? "allow" : "deny"
if (tool === "write" || tool === "edit" || tool === "patch" || tool === "multiedit") {
if (tool === "write" || tool === "edit" || tool === "patch") {
perms.edit = action
continue
}
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/permission/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ export namespace Permission {
return rulesets.flat()
}

const EDIT_TOOLS = ["edit", "write", "apply_patch", "multiedit"]
const EDIT_TOOLS = ["edit", "write", "apply_patch"]

export function disabled(tools: string[], ruleset: Ruleset): Set<string> {
const result = new Set<string>()
Expand Down
5 changes: 2 additions & 3 deletions packages/opencode/src/tool/bash.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Before executing the command, please follow these steps:
- For example, before running "mkdir foo/bar", first use `ls foo` to check that "foo" exists and is the intended parent directory

2. Command Execution:
- Always quote file paths that contain spaces with double quotes (e.g., rm "path with spaces/file.txt")
- Always quote file paths that contain spaces with double quotes (e.g., mkdir "/Users/name/path with spaces")
Comment thread
Astro-Han marked this conversation as resolved.
- Examples of proper quoting:
- mkdir "/Users/name/My Documents" (correct)
- mkdir /Users/name/My Documents (incorrect - will fail)
Expand All @@ -35,6 +35,7 @@ Usage notes:
- Edit files: Use Edit (NOT sed/awk)
- Write files: Use Write (NOT echo >/cat <<EOF)
- Communication: Output text directly (NOT echo/printf)
- File deletion: Use the trash tool, NOT `rm`/`del` (rm permanently deletes; trash is reversible)
- When issuing multiple commands:
- If the commands are independent and can run in parallel, make multiple Bash tool calls in a single message. For example, if you need to run "git status" and "git diff", send a single message with two Bash tool calls in parallel.
- ${chaining}
Expand Down Expand Up @@ -83,7 +84,6 @@ Git Safety Protocol:

Important notes:
- NEVER run additional commands to read or explore code, besides git bash commands
- NEVER use the TodoWrite or Task tools
- DO NOT push to the remote repository unless the user explicitly asks you to do so
- IMPORTANT: Never use git commands with the -i flag (like git rebase -i or git add -i) since they require interactive input which is not supported.
- If there are no changes to commit (i.e., no untracked files and no modifications), do not create an empty commit
Expand All @@ -110,7 +110,6 @@ gh pr create --title "the pr title" --body "$(cat <<'EOF'
</example>

Important:
- DO NOT use the TodoWrite or Task tools
- Return the PR URL when you're done, so the user can see it

# Other common operations
Expand Down
1 change: 1 addition & 0 deletions packages/opencode/src/tool/edit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ Usage:
- The edit will FAIL if `oldString` is not found in the file with an error "oldString not found in content".
- The edit will FAIL if `oldString` is found multiple times in the file with an error "Found multiple matches for oldString. Provide more surrounding lines in oldString to identify the correct match." Either provide a larger string with more surrounding context to make it unique or use `replaceAll` to change every instance of `oldString`.
- Use `replaceAll` for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance.
- To delete a line cleanly, include the trailing newline character (`\n`) in `oldString` and pass an empty string as `newString` (e.g., `oldString: "line to delete\n"`, `newString: ""`). Without that trailing newline, the line content is removed but a stray blank line remains at the deleted position.
2 changes: 1 addition & 1 deletion packages/opencode/src/tool/glob.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
- Returns matching file paths sorted by modification time
- Use this tool when you need to find files by name patterns
- When you are doing an open-ended search that may require multiple rounds of globbing and grepping, use the Task tool instead
- You have the capability to call multiple tools in a single response. It is always better to speculatively perform multiple searches as a batch that are potentially useful.
- You have the capability to call multiple tools in a single response.
61 changes: 0 additions & 61 deletions packages/opencode/src/tool/multiedit.ts

This file was deleted.

41 changes: 0 additions & 41 deletions packages/opencode/src/tool/multiedit.txt

This file was deleted.

4 changes: 2 additions & 2 deletions packages/opencode/src/tool/skill.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Load a specialized skill when the task at hand matches one of the skills listed in the system prompt.
Load a specialized skill when the task at hand matches one of the skills listed below.

Use this tool to inject the skill's instructions and resources into current conversation. The output may contain detailed workflow guidance as well as references to scripts, files, etc in the same directory as the skill.

The skill name must match one of the skills listed in your system prompt.
The skill name must match one of the skills listed below.
48 changes: 5 additions & 43 deletions packages/opencode/src/tool/task.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,49 +9,11 @@ When NOT to use the Task tool:
- If you want to read a specific file path, use the Read or Glob tool instead of the Task tool, to find the match more quickly
- If you are searching for a specific class definition like "class Foo", use the Glob tool instead, to find the match more quickly
- If you are searching for code within a specific file or set of 2-3 files, use the Read tool instead of the Task tool, to find the match more quickly
- Other tasks that are not related to the agent descriptions above
- Other tasks that are not related to the available agents


Usage notes:
1. Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses
2. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result. The output includes a task_id you can reuse later to continue the same subagent session.
3. Each agent invocation starts with a fresh context unless you provide task_id to resume the same subagent session (which continues with its previous messages and tool outputs). When starting fresh, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.
4. The agent's outputs should generally be trusted
5. Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent. Tell it how to verify its work if possible (e.g., relevant test commands).
6. If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.

Example usage (NOTE: The agents below are fictional examples for illustration only - use the actual agents listed above):

<example_agent_descriptions>
"code-reviewer": use this agent after you are done writing a significant piece of code
"greeting-responder": use this agent when to respond to user greetings with a friendly joke
</example_agent_description>

<example>
user: "Please write a function that checks if a number is prime"
assistant: Sure let me write a function that checks if a number is prime
assistant: First let me use the Write tool to write a function that checks if a number is prime
assistant: I'm going to use the Write tool to write the following code:
<code>
function isPrime(n) {
if (n <= 1) return false
for (let i = 2; i * i <= n; i++) {
if (n % i === 0) return false
}
return true
}
</code>
<commentary>
Since a significant piece of code was written and the task was completed, now use the code-reviewer agent to review the code
</commentary>
assistant: Now let me use the code-reviewer agent to review the code
assistant: Uses the Task tool to launch the code-reviewer agent
</example>

<example>
user: "Hello"
<commentary>
Since the user is greeting, use the greeting-responder agent to respond with a friendly joke
</commentary>
assistant: "I'm going to use the Task tool to launch the with the greeting-responder agent"
</example>
1. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result. The output includes a task_id you can reuse later to continue the same subagent session.
2. Each agent invocation starts with a fresh context unless you provide task_id to resume the same subagent session (which continues with its previous messages and tool outputs). When starting fresh, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.
Comment thread
Astro-Han marked this conversation as resolved.
3. Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent. Tell it how to verify its work if possible (e.g., relevant test commands).
4. If the proactive trigger applies to the available agents, you should try your best to use it without the user having to ask for it first. Use your judgement.
4 changes: 1 addition & 3 deletions packages/opencode/src/tool/todowrite.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
Use this tool to create and manage a structured task list for your current coding session. This helps you track progress and organize complex tasks.
It also helps the user understand the progress of the task and overall progress of their requests.

## When to Use This Tool
Expand Down Expand Up @@ -163,5 +163,3 @@ The assistant did not use the todo list because this is a single command executi
- Break complex tasks into smaller, manageable steps
- Use clear, descriptive task names

When in doubt, use this tool. Being proactive with task management demonstrates attentiveness and ensures you complete all requirements successfully.

5 changes: 4 additions & 1 deletion packages/opencode/src/tool/trash.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
Moves a file or directory to the system Trash.

Use this instead of shell deletion commands like `rm`.
Use this for file or directory deletion. Trash is reversible; items moved to Trash can be restored from the system Trash UI.

Do not use shell deletion commands. Those are permanent and unrecoverable. PawWork's permission system blocks the `rm`-family commands (`rm`, `rmdir`, `unlink`, `find -delete`) by default; Windows shell deletion (`del`, `erase`, `Remove-Item`) is not yet blocked but should still be avoided.

Accepts a single file or directory path, absolute or relative to the current project directory.
2 changes: 1 addition & 1 deletion packages/opencode/test/agent/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ test("legacy tools config converts to permissions", async () => {
})
})

test("legacy tools config maps write/edit/patch/multiedit to edit permission", async () => {
test("legacy tools.write config maps to edit permission", async () => {
await using tmp = await tmpdir({
config: {
agent: {
Expand Down
29 changes: 0 additions & 29 deletions packages/opencode/test/config/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2003,35 +2003,6 @@ test("migrates legacy patch tool to edit permission", async () => {
})
})

test("migrates legacy multiedit tool to edit permission", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Filesystem.write(
path.join(dir, "opencode.json"),
JSON.stringify({
$schema: "https://opencode.ai/config.json",
agent: {
test: {
tools: {
multiedit: false,
},
},
},
}),
)
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const config = await load()
expect(config.agent?.["test"]?.permission).toEqual({
edit: "deny",
})
},
})
})

test("migrates mixed legacy tools config", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
Expand Down
5 changes: 2 additions & 3 deletions packages/opencode/test/permission/next.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,9 @@ test("disabled - disables tool when denied", () => {
expect(result.has("read")).toBe(false)
})

test("disabled - disables edit/write/apply_patch/multiedit when edit denied", () => {
test("disabled - disables edit/write/apply_patch when edit denied", () => {
const result = Permission.disabled(
["edit", "write", "apply_patch", "multiedit", "bash"],
["edit", "write", "apply_patch", "bash"],
[
{ permission: "*", pattern: "*", action: "allow" },
{ permission: "edit", pattern: "*", action: "deny" },
Expand All @@ -398,7 +398,6 @@ test("disabled - disables edit/write/apply_patch/multiedit when edit denied", ()
expect(result.has("edit")).toBe(true)
expect(result.has("write")).toBe(true)
expect(result.has("apply_patch")).toBe(true)
expect(result.has("multiedit")).toBe(true)
expect(result.has("bash")).toBe(false)
})

Expand Down
Loading