on main help sign in
refactor: put tool descriptions in markdown files (#1077)

Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>

commitfa34edc67f1c25328b3a54e01a7243ec9a64c93f authorCarlos Alexandro Becker <caarlos0@users.noreply.github.com> dateFri 19 Sep 2025, 09:19 (1 year ago) parent91b6b31
24 files changed+776−640
internal/llm/tools/bash.go+31−144 internal/llm/tools/bash.md+161 internal/llm/tools/diagnostics.go+6−25 internal/llm/tools/diagnostics.md+21 internal/llm/tools/download.go+6−33 internal/llm/tools/download.md+34 internal/llm/tools/edit.go+5−58 internal/llm/tools/edit.md+60 internal/llm/tools/fetch.go+6−33 internal/llm/tools/fetch.md+34 internal/llm/tools/glob.go+6−43 internal/llm/tools/glob.md+46 internal/llm/tools/grep.go+6−50 internal/llm/tools/grep.md+54 internal/llm/tools/ls.go+7−37 internal/llm/tools/ls.md+40 internal/llm/tools/multiedit.go+6−46 internal/llm/tools/multiedit.md+48 internal/llm/tools/sourcegraph.go+6−98 internal/llm/tools/sourcegraph.md+102 internal/llm/tools/view.go+5−37 internal/llm/tools/view.md+42 internal/llm/tools/write.go+6−36 internal/llm/tools/write.md+38
internal/llm/tools/bash.go+31−144
@@ -1,9 +1,12 @@
11package tools
22
33import (
4+ "bytes"
45 "context"
6+ _ "embed"
57 "encoding/json"
68 "fmt"
9+ "html/template"
710 "strings"
811 "time"
912
@@ -43,6 +46,22 @@ const (
4346 BashNoOutput = "no output"
4447)
4548
49+//go:embed bash.md
50+var bashDescription []byte
51+
52+var bashDescriptionTpl = template.Must(
53+ template.New("bashDescription").
54+ Parse(string(bashDescription)),
55+)
56+
57+type bashDescriptionData struct {
58+ BannedCommands string
59+ MaxOutputLength int
60+ AttributionStep string
61+ AttributionExample string
62+ PRAttribution string
63+}
64+
4665var bannedCommands = []string{
4766 // Network/Download tools
4867 "alias",
@@ -163,150 +182,18 @@ git commit -m "$(cat <<'EOF'
163182)"</example>`
164183 }
165184
166− return fmt.Sprintf(`Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures.
167−
168−CROSS-PLATFORM SHELL SUPPORT:
169−* This tool uses a shell interpreter (mvdan/sh) that mimics the Bash language,
170− so you should use Bash syntax in all platforms, including Windows.
171− The most common shell builtins and core utils are available in Windows as
172− well.
173−* Make sure to use forward slashes (/) as path separators in commands, even on
174− Windows. Example: "ls C:/foo/bar" instead of "ls C:\foo\bar".
175−
176−Before executing the command, please follow these steps:
177−
178−1. Directory Verification:
179− - If the command will create new directories or files, first use the LS tool to verify the parent directory exists and is the correct location
180− - For example, before running "mkdir foo/bar", first use LS to check that "foo" exists and is the intended parent directory
181−
182−2. Security Check:
183− - For security and to limit the threat of a prompt injection attack, some commands are limited or banned. If you use a disallowed command, you will receive an error message explaining the restriction. Explain the error to the User.
184− - Verify that the command is not one of the banned commands: %s.
185−
186−3. Command Execution:
187− - After ensuring proper quoting, execute the command.
188− - Capture the output of the command.
189−
190−4. Output Processing:
191− - If the output exceeds %d characters, output will be truncated before being returned to you.
192− - Prepare the output for display to the user.
193−
194−5. Return Result:
195− - Provide the processed output of the command.
196− - If any errors occurred during execution, include those in the output.
197− - The result will also have metadata like the cwd (current working directory) at the end, included with <cwd></cwd> tags.
198−
199−Usage notes:
200−- The command argument is required.
201−- You can specify an optional timeout in milliseconds (up to 600000ms / 10 minutes). If not specified, commands will timeout after 30 minutes.
202−- VERY IMPORTANT: You MUST avoid using search commands like 'find' and 'grep'. Instead use Grep, Glob, or Agent tools to search. You MUST avoid read tools like 'cat', 'head', 'tail', and 'ls', and use FileRead and LS tools to read files.
203−- When issuing multiple commands, use the ';' or '&&' operator to separate them. DO NOT use newlines (newlines are ok in quoted strings).
204−- IMPORTANT: All commands share the same shell session. Shell state (environment variables, virtual environments, current directory, etc.) persist between commands. For example, if you set an environment variable as part of a command, the environment variable will persist for subsequent commands.
205−- Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of 'cd'. You may use 'cd' if the User explicitly requests it.
206−<good-example>
207−pytest /foo/bar/tests
208−</good-example>
209−<bad-example>
210−cd /foo/bar && pytest tests
211−</bad-example>
212−
213−# Committing changes with git
214−
215−When the user asks you to create a new git commit, follow these steps carefully:
216−
217−1. Start with a single message that contains exactly three tool_use blocks that do the following (it is VERY IMPORTANT that you send these tool_use blocks in a single message, otherwise it will feel slow to the user!):
218− - Run a git status command to see all untracked files.
219− - Run a git diff command to see both staged and unstaged changes that will be committed.
220− - Run a git log command to see recent commit messages, so that you can follow this repository's commit message style.
221−
222−2. Use the git context at the start of this conversation to determine which files are relevant to your commit. Add relevant untracked files to the staging area. Do not commit files that were already modified at the start of this conversation, if they are not relevant to your commit.
223−
224−3. Analyze all staged changes (both previously staged and newly added) and draft a commit message. Wrap your analysis process in <commit_analysis> tags:
225−
226−<commit_analysis>
227−- List the files that have been changed or added
228−- Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.)
229−- Brainstorm the purpose or motivation behind these changes
230−- Do not use tools to explore code, beyond what is available in the git context
231−- Assess the impact of these changes on the overall project
232−- Check for any sensitive information that shouldn't be committed
233−- Draft a concise (1-2 sentences) commit message that focuses on the "why" rather than the "what"
234−- Ensure your language is clear, concise, and to the point
235−- Ensure the message accurately reflects the changes and their purpose (i.e. "add" means a wholly new feature, "update" means an enhancement to an existing feature, "fix" means a bug fix, etc.)
236−- Ensure the message is not generic (avoid words like "Update" or "Fix" without context)
237−- Review the draft message to ensure it accurately reflects the changes and their purpose
238−</commit_analysis>
239−
240−%s
241−
242−- In order to ensure good formatting, ALWAYS pass the commit message via a HEREDOC, a la this example:
243−%s
244−
245−5. If the commit fails due to pre-commit hook changes, retry the commit ONCE to include these automated changes. If it fails again, it usually means a pre-commit hook is preventing the commit. If the commit succeeds but you notice that files were modified by the pre-commit hook, you MUST amend your commit to include them.
246−
247−6. Finally, run git status to make sure the commit succeeded.
248−
249−Important notes:
250−- When possible, combine the "git add" and "git commit" commands into a single "git commit -am" command, to speed things up
251−- However, be careful not to stage files (e.g. with 'git add .') for commits that aren't part of the change, they may have untracked files they want to keep around, but not commit.
252−- NEVER update the git config
253−- DO NOT push to the remote repository
254−- 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.
255−- If there are no changes to commit (i.e., no untracked files and no modifications), do not create an empty commit
256−- Ensure your commit message is meaningful and concise. It should explain the purpose of the changes, not just describe them.
257−- Return an empty response - the user will see the git output directly
258−
259−# Creating pull requests
260−Use the gh command via the Bash tool for ALL GitHub-related tasks including working with issues, pull requests, checks, and releases. If given a Github URL use the gh command to get the information needed.
261−
262−IMPORTANT: When the user asks you to create a pull request, follow these steps carefully:
263−
264−1. Understand the current state of the branch. Remember to send a single message that contains multiple tool_use blocks (it is VERY IMPORTANT that you do this in a single message, otherwise it will feel slow to the user!):
265− - Run a git status command to see all untracked files.
266− - Run a git diff command to see both staged and unstaged changes that will be committed.
267− - Check if the current branch tracks a remote branch and is up to date with the remote, so you know if you need to push to the remote
268− - Run a git log command and 'git diff main...HEAD' to understand the full commit history for the current branch (from the time it diverged from the 'main' branch.)
269−
270−2. Create new branch if needed
271−
272−3. Commit changes if needed
273−
274−4. Push to remote with -u flag if needed
275−
276−5. Analyze all changes that will be included in the pull request, making sure to look at all relevant commits (not just the latest commit, but all commits that will be included in the pull request!), and draft a pull request summary. Wrap your analysis process in <pr_analysis> tags:
277−
278−<pr_analysis>
279−- List the commits since diverging from the main branch
280−- Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.)
281−- Brainstorm the purpose or motivation behind these changes
282−- Assess the impact of these changes on the overall project
283−- Do not use tools to explore code, beyond what is available in the git context
284−- Check for any sensitive information that shouldn't be committed
285−- Draft a concise (1-2 bullet points) pull request summary that focuses on the "why" rather than the "what"
286−- Ensure the summary accurately reflects all changes since diverging from the main branch
287−- Ensure your language is clear, concise, and to the point
288−- Ensure the summary accurately reflects the changes and their purpose (ie. "add" means a wholly new feature, "update" means an enhancement to an existing feature, "fix" means a bug fix, etc.)
289−- Ensure the summary is not generic (avoid words like "Update" or "Fix" without context)
290−- Review the draft summary to ensure it accurately reflects the changes and their purpose
291−</pr_analysis>
292−
293−6. Create PR using gh pr create with the format below. Use a HEREDOC to pass the body to ensure correct formatting.
294−<example>
295−gh pr create --title "the pr title" --body "$(cat <<'EOF'
296−## Summary
297−<1-3 bullet points>
298−
299−## Test plan
300−[Checklist of TODOs for testing the pull request...]
301−
302−%s
303−EOF
304−)"
305−</example>
306−
307−Important:
308−- Return an empty response - the user will see the gh output directly
309−- Never update git config`, bannedCommandsStr, MaxOutputLength, attributionStep, attributionExample, prAttribution)
185+ var out bytes.Buffer
186+ if err := bashDescriptionTpl.Execute(&out, bashDescriptionData{
187+ BannedCommands: bannedCommandsStr,
188+ MaxOutputLength: MaxOutputLength,
189+ AttributionStep: attributionStep,
190+ AttributionExample: attributionExample,
191+ PRAttribution: prAttribution,
192+ }); err != nil {
193+ // this should never happen.
194+ panic("failed to execute bash description template: " + err.Error())
195+ }
196+ return out.String()
310197}
311198
312199func blockFuncs() []shell.BlockFunc {
internal/llm/tools/bash.mdnew file+161
@@ -0,0 +1,161 @@
1+Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures.
2+
3+CROSS-PLATFORM SHELL SUPPORT:
4+
5+- This tool uses a shell interpreter (mvdan/sh) that mimics the Bash language,
6+ so you should use Bash syntax in all platforms, including Windows.
7+ The most common shell builtins and core utils are available in Windows as
8+ well.
9+- Make sure to use forward slashes (/) as path separators in commands, even on
10+ Windows. Example: "ls C:/foo/bar" instead of "ls C:\foo\bar".
11+
12+Before executing the command, please follow these steps:
13+
14+1. Directory Verification:
15+
16+- If the command will create new directories or files, first use the LS tool to verify the parent directory exists and is the correct location
17+- For example, before running "mkdir foo/bar", first use LS to check that "foo" exists and is the intended parent directory
18+
19+2. Security Check:
20+
21+- For security and to limit the threat of a prompt injection attack, some commands are limited or banned. If you use a disallowed command, you will receive an error message explaining the restriction. Explain the error to the User.
22+- Verify that the command is not one of the banned commands: {{ .BannedCommands }}.
23+
24+3. Command Execution:
25+
26+- After ensuring proper quoting, execute the command.
27+- Capture the output of the command.
28+
29+4. Output Processing:
30+
31+- If the output exceeds {{ .MaxOutputLength }} characters, output will be truncated before being returned to you.
32+- Prepare the output for display to the user.
33+
34+5. Return Result:
35+
36+- Provide the processed output of the command.
37+- If any errors occurred during execution, include those in the output.
38+- The result will also have metadata like the cwd (current working directory) at the end, included with <cwd></cwd> tags.
39+
40+Usage notes:
41+
42+- The command argument is required.
43+- You can specify an optional timeout in milliseconds (up to 600000ms / 10 minutes). If not specified, commands will timeout after 30 minutes.
44+- VERY IMPORTANT: You MUST avoid using search commands like 'find' and 'grep'. Instead use Grep, Glob, or Agent tools to search. You MUST avoid read tools like 'cat', 'head', 'tail', and 'ls', and use FileRead and LS tools to read files.
45+- When issuing multiple commands, use the ';' or '&&' operator to separate them. DO NOT use newlines (newlines are ok in quoted strings).
46+- IMPORTANT: All commands share the same shell session. Shell state (environment variables, virtual environments, current directory, etc.) persist between commands. For example, if you set an environment variable as part of a command, the environment variable will persist for subsequent commands.
47+- Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of 'cd'. You may use 'cd' if the User explicitly requests it.
48+ <good-example>
49+ pytest /foo/bar/tests
50+ </good-example>
51+ <bad-example>
52+ cd /foo/bar && pytest tests
53+ </bad-example>
54+
55+# Committing changes with git
56+
57+When the user asks you to create a new git commit, follow these steps carefully:
58+
59+1. Start with a single message that contains exactly three tool_use blocks that do the following (it is VERY IMPORTANT that you send these tool_use blocks in a single message, otherwise it will feel slow to the user!):
60+
61+- Run a git status command to see all untracked files.
62+- Run a git diff command to see both staged and unstaged changes that will be committed.
63+- Run a git log command to see recent commit messages, so that you can follow this repository's commit message style.
64+
65+2. Use the git context at the start of this conversation to determine which files are relevant to your commit. Add relevant untracked files to the staging area. Do not commit files that were already modified at the start of this conversation, if they are not relevant to your commit.
66+
67+3. Analyze all staged changes (both previously staged and newly added) and draft a commit message. Wrap your analysis process in <commit_analysis> tags:
68+
69+<commit_analysis>
70+
71+- List the files that have been changed or added
72+- Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.)
73+- Brainstorm the purpose or motivation behind these changes
74+- Do not use tools to explore code, beyond what is available in the git context
75+- Assess the impact of these changes on the overall project
76+- Check for any sensitive information that shouldn't be committed
77+- Draft a concise (1-2 sentences) commit message that focuses on the "why" rather than the "what"
78+- Ensure your language is clear, concise, and to the point
79+- Ensure the message accurately reflects the changes and their purpose (i.e. "add" means a wholly new feature, "update" means an enhancement to an existing feature, "fix" means a bug fix, etc.)
80+- Ensure the message is not generic (avoid words like "Update" or "Fix" without context)
81+- Review the draft message to ensure it accurately reflects the changes and their purpose
82+ </commit_analysis>
83+
84+{{ .AttributionStep }}
85+
86+- In order to ensure good formatting, ALWAYS pass the commit message via a HEREDOC, a la this example:
87+ {{ .AttributionExample }}
88+
89+5. If the commit fails due to pre-commit hook changes, retry the commit ONCE to include these automated changes. If it fails again, it usually means a pre-commit hook is preventing the commit. If the commit succeeds but you notice that files were modified by the pre-commit hook, you MUST amend your commit to include them.
90+
91+6. Finally, run git status to make sure the commit succeeded.
92+
93+Important notes:
94+
95+- When possible, combine the "git add" and "git commit" commands into a single "git commit -am" command, to speed things up
96+- However, be careful not to stage files (e.g. with 'git add .') for commits that aren't part of the change, they may have untracked files they want to keep around, but not commit.
97+- NEVER update the git config
98+- DO NOT push to the remote repository
99+- 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.
100+- If there are no changes to commit (i.e., no untracked files and no modifications), do not create an empty commit
101+- Ensure your commit message is meaningful and concise. It should explain the purpose of the changes, not just describe them.
102+- Return an empty response - the user will see the git output directly
103+
104+# Creating pull requests
105+
106+Use the gh command via the Bash tool for ALL GitHub-related tasks including working with issues, pull requests, checks, and releases. If given a Github URL use the gh command to get the information needed.
107+
108+IMPORTANT: When the user asks you to create a pull request, follow these steps carefully:
109+
110+1. Understand the current state of the branch. Remember to send a single message that contains multiple tool_use blocks (it is VERY IMPORTANT that you do this in a single message, otherwise it will feel slow to the user!):
111+
112+- Run a git status command to see all untracked files.
113+- Run a git diff command to see both staged and unstaged changes that will be committed.
114+- Check if the current branch tracks a remote branch and is up to date with the remote, so you know if you need to push to the remote
115+- Run a git log command and 'git diff main...HEAD' to understand the full commit history for the current branch (from the time it diverged from the 'main' branch.)
116+
117+2. Create new branch if needed
118+
119+3. Commit changes if needed
120+
121+4. Push to remote with -u flag if needed
122+
123+5. Analyze all changes that will be included in the pull request, making sure to look at all relevant commits (not just the latest commit, but all commits that will be included in the pull request!), and draft a pull request summary. Wrap your analysis process in <pr_analysis> tags:
124+
125+<pr_analysis>
126+
127+- List the commits since diverging from the main branch
128+- Summarize the nature of the changes (eg. new feature, enhancement to an existing feature, bug fix, refactoring, test, docs, etc.)
129+- Brainstorm the purpose or motivation behind these changes
130+- Assess the impact of these changes on the overall project
131+- Do not use tools to explore code, beyond what is available in the git context
132+- Check for any sensitive information that shouldn't be committed
133+- Draft a concise (1-2 bullet points) pull request summary that focuses on the "why" rather than the "what"
134+- Ensure the summary accurately reflects all changes since diverging from the main branch
135+- Ensure your language is clear, concise, and to the point
136+- Ensure the summary accurately reflects the changes and their purpose (ie. "add" means a wholly new feature, "update" means an enhancement to an existing feature, "fix" means a bug fix, etc.)
137+- Ensure the summary is not generic (avoid words like "Update" or "Fix" without context)
138+- Review the draft summary to ensure it accurately reflects the changes and their purpose
139+ </pr_analysis>
140+
141+6. Create PR using gh pr create with the format below. Use a HEREDOC to pass the body to ensure correct formatting.
142+ <example>
143+ gh pr create --title "the pr title" --body "$(cat <<'EOF'
144+
145+## Summary
146+
147+<1-3 bullet points>
148+
149+## Test plan
150+
151+[Checklist of TODOs for testing the pull request...]
152+
153+{{ .PRAttribution }}
154+EOF
155+)"
156+</example>
157+
158+Important:
159+
160+- Return an empty response - the user will see the gh output directly
161+- Never update git config
internal/llm/tools/diagnostics.go+6−25
@@ -2,6 +2,7 @@ package tools
22
33import (
44 "context"
5+ _ "embed"
56 "encoding/json"
67 "fmt"
78 "log/slog"
@@ -22,30 +23,10 @@ type diagnosticsTool struct {
2223 lspClients *csync.Map[string, *lsp.Client]
2324}
2425
25−const (
26− DiagnosticsToolName = "diagnostics"
27− diagnosticsDescription = `Get diagnostics for a file and/or project.
28−WHEN TO USE THIS TOOL:
29−- Use when you need to check for errors or warnings in your code
30−- Helpful for debugging and ensuring code quality
31−- Good for getting a quick overview of issues in a file or project
32−HOW TO USE:
33−- Provide a path to a file to get diagnostics for that file
34−- Leave the path empty to get diagnostics for the entire project
35−- Results are displayed in a structured format with severity levels
36−FEATURES:
37−- Displays errors, warnings, and hints
38−- Groups diagnostics by severity
39−- Provides detailed information about each diagnostic
40−LIMITATIONS:
41−- Results are limited to the diagnostics provided by the LSP clients
42−- May not cover all possible issues in the code
43−- Does not provide suggestions for fixing issues
44−TIPS:
45−- Use in conjunction with other tools for a comprehensive code review
46−- Combine with the LSP client for real-time diagnostics
47−`
48−)
26+const DiagnosticsToolName = "diagnostics"
27+
28+//go:embed diagnostics.md
29+var diagnosticsDescription []byte
4930
5031func NewDiagnosticsTool(lspClients *csync.Map[string, *lsp.Client]) BaseTool {
5132 return &diagnosticsTool{
@@ -60,7 +41,7 @@ func (b *diagnosticsTool) Name() string {
6041func (b *diagnosticsTool) Info() ToolInfo {
6142 return ToolInfo{
6243 Name: DiagnosticsToolName,
63− Description: diagnosticsDescription,
44+ Description: string(diagnosticsDescription),
6445 Parameters: map[string]any{
6546 "file_path": map[string]any{
6647 "type": "string",
internal/llm/tools/diagnostics.mdnew file+21
@@ -0,0 +1,21 @@
1+Get diagnostics for a file and/or project.
2+WHEN TO USE THIS TOOL:
3+
4+- Use when you need to check for errors or warnings in your code
5+- Helpful for debugging and ensuring code quality
6+- Good for getting a quick overview of issues in a file or project
7+ HOW TO USE:
8+- Provide a path to a file to get diagnostics for that file
9+- Leave the path empty to get diagnostics for the entire project
10+- Results are displayed in a structured format with severity levels
11+ FEATURES:
12+- Displays errors, warnings, and hints
13+- Groups diagnostics by severity
14+- Provides detailed information about each diagnostic
15+ LIMITATIONS:
16+- Results are limited to the diagnostics provided by the LSP clients
17+- May not cover all possible issues in the code
18+- Does not provide suggestions for fixing issues
19+ TIPS:
20+- Use in conjunction with other tools for a comprehensive code review
21+- Combine with the LSP client for real-time diagnostics
internal/llm/tools/download.go+6−33
@@ -2,6 +2,7 @@ package tools
22
33import (
44 "context"
5+ _ "embed"
56 "encoding/json"
67 "fmt"
78 "io"
@@ -32,38 +33,10 @@ type downloadTool struct {
3233 workingDir string
3334}
3435
35−const (
36− DownloadToolName = "download"
37− downloadToolDescription = `Downloads binary data from a URL and saves it to a local file.
38−
39−WHEN TO USE THIS TOOL:
40−- Use when you need to download files, images, or other binary data from URLs
41−- Helpful for downloading assets, documents, or any file type
42−- Useful for saving remote content locally for processing or storage
43−
44−HOW TO USE:
45−- Provide the URL to download from
46−- Specify the local file path where the content should be saved
47−- Optionally set a timeout for the request
48−
49−FEATURES:
50−- Downloads any file type (binary or text)
51−- Automatically creates parent directories if they don't exist
52−- Handles large files efficiently with streaming
53−- Sets reasonable timeouts to prevent hanging
54−- Validates input parameters before making requests
55−
56−LIMITATIONS:
57−- Maximum file size is 100MB
58−- Only supports HTTP and HTTPS protocols
59−- Cannot handle authentication or cookies
60−- Some websites may block automated requests
61−- Will overwrite existing files without warning
62−
63−TIPS:
64−- Use absolute paths or paths relative to the working directory
65−- Set appropriate timeouts for large files or slow connections`
66−)
36+const DownloadToolName = "download"
37+
38+//go:embed download.md
39+var downloadDescription []byte
6740
6841func NewDownloadTool(permissions permission.Service, workingDir string) BaseTool {
6942 return &downloadTool{
@@ -87,7 +60,7 @@ func (t *downloadTool) Name() string {
8760func (t *downloadTool) Info() ToolInfo {
8861 return ToolInfo{
8962 Name: DownloadToolName,
90− Description: downloadToolDescription,
63+ Description: string(downloadDescription),
9164 Parameters: map[string]any{
9265 "url": map[string]any{
9366 "type": "string",
internal/llm/tools/download.mdnew file+34
@@ -0,0 +1,34 @@
1+Downloads binary data from a URL and saves it to a local file.
2+
3+WHEN TO USE THIS TOOL:
4+
5+- Use when you need to download files, images, or other binary data from URLs
6+- Helpful for downloading assets, documents, or any file type
7+- Useful for saving remote content locally for processing or storage
8+
9+HOW TO USE:
10+
11+- Provide the URL to download from
12+- Specify the local file path where the content should be saved
13+- Optionally set a timeout for the request
14+
15+FEATURES:
16+
17+- Downloads any file type (binary or text)
18+- Automatically creates parent directories if they don't exist
19+- Handles large files efficiently with streaming
20+- Sets reasonable timeouts to prevent hanging
21+- Validates input parameters before making requests
22+
23+LIMITATIONS:
24+
25+- Maximum file size is 100MB
26+- Only supports HTTP and HTTPS protocols
27+- Cannot handle authentication or cookies
28+- Some websites may block automated requests
29+- Will overwrite existing files without warning
30+
31+TIPS:
32+
33+- Use absolute paths or paths relative to the working directory
34+- Set appropriate timeouts for large files or slow connections
internal/llm/tools/edit.go+5−58
@@ -2,6 +2,7 @@ package tools
22
33import (
44 "context"
5+ _ "embed"
56 "encoding/json"
67 "fmt"
78 "log/slog"
@@ -46,64 +47,10 @@ type editTool struct {
4647 workingDir string
4748}
4849
49−const (
50− EditToolName = "edit"
51− editDescription = `Edits files by replacing text, creating new files, or deleting content. For moving or renaming files, use the Bash tool with the 'mv' command instead. For larger file edits, use the FileWrite tool to overwrite files.
50+const EditToolName = "edit"
5251
53−Before using this tool:
54−
55−1. Use the FileRead tool to understand the file's contents and context
56−
57−2. Verify the directory path is correct (only applicable when creating new files):
58− - Use the LS tool to verify the parent directory exists and is the correct location
59−
60−To make a file edit, provide the following:
61−1. file_path: The absolute path to the file to modify (must be absolute, not relative)
62−2. old_string: The text to replace (must be unique within the file, and must match the file contents exactly, including all whitespace and indentation)
63−3. new_string: The edited text to replace the old_string
64−4. replace_all: Replace all occurrences of old_string (default false)
65−
66−Special cases:
67−- To create a new file: provide file_path and new_string, leave old_string empty
68−- To delete content: provide file_path and old_string, leave new_string empty
69−
70−The tool will replace ONE occurrence of old_string with new_string in the specified file by default. Set replace_all to true to replace all occurrences.
71−
72−CRITICAL REQUIREMENTS FOR USING THIS TOOL:
73−
74−1. UNIQUENESS: When replace_all is false (default), the old_string MUST uniquely identify the specific instance you want to change. This means:
75− - Include AT LEAST 3-5 lines of context BEFORE the change point
76− - Include AT LEAST 3-5 lines of context AFTER the change point
77− - Include all whitespace, indentation, and surrounding code exactly as it appears in the file
78−
79−2. SINGLE INSTANCE: When replace_all is false, this tool can only change ONE instance at a time. If you need to change multiple instances:
80− - Set replace_all to true to replace all occurrences at once
81− - Or make separate calls to this tool for each instance
82− - Each call must uniquely identify its specific instance using extensive context
83−
84−3. VERIFICATION: Before using this tool:
85− - Check how many instances of the target text exist in the file
86− - If multiple instances exist and replace_all is false, gather enough context to uniquely identify each one
87− - Plan separate tool calls for each instance or use replace_all
88−
89−WARNING: If you do not follow these requirements:
90− - The tool will fail if old_string matches multiple locations and replace_all is false
91− - The tool will fail if old_string doesn't match exactly (including whitespace)
92− - You may change the wrong instance if you don't include enough context
93−
94−When making edits:
95− - Ensure the edit results in idiomatic, correct code
96− - Do not leave the code in a broken state
97− - Always use absolute file paths (starting with /)
98−
99−WINDOWS NOTES:
100−- File paths should use forward slashes (/) for cross-platform compatibility
101−- On Windows, absolute paths start with drive letters (C:/) but forward slashes work throughout
102−- File permissions are handled automatically by the Go runtime
103−- Always assumes \n for line endings. The tool will handle \r\n conversion automatically if needed.
104−
105−Remember: when making multiple file edits in a row to the same file, you should prefer to send all edits in a single message with multiple calls to this tool, rather than multiple messages with a single call each.`
106−)
52+//go:embed edit.md
53+var editDescription []byte
10754
10855func NewEditTool(lspClients *csync.Map[string, *lsp.Client], permissions permission.Service, files history.Service, workingDir string) BaseTool {
10956 return &editTool{
@@ -121,7 +68,7 @@ func (e *editTool) Name() string {
12168func (e *editTool) Info() ToolInfo {
12269 return ToolInfo{
12370 Name: EditToolName,
124− Description: editDescription,
71+ Description: string(editDescription),
12572 Parameters: map[string]any{
12673 "file_path": map[string]any{
12774 "type": "string",
internal/llm/tools/edit.mdnew file+60
@@ -0,0 +1,60 @@
1+Edits files by replacing text, creating new files, or deleting content. For moving or renaming files, use the Bash tool with the 'mv' command instead. For larger file edits, use the FileWrite tool to overwrite files.
2+
3+Before using this tool:
4+
5+1. Use the FileRead tool to understand the file's contents and context
6+
7+2. Verify the directory path is correct (only applicable when creating new files):
8+ - Use the LS tool to verify the parent directory exists and is the correct location
9+
10+To make a file edit, provide the following:
11+
12+1. file_path: The absolute path to the file to modify (must be absolute, not relative)
13+2. old_string: The text to replace (must be unique within the file, and must match the file contents exactly, including all whitespace and indentation)
14+3. new_string: The edited text to replace the old_string
15+4. replace_all: Replace all occurrences of old_string (default false)
16+
17+Special cases:
18+
19+- To create a new file: provide file_path and new_string, leave old_string empty
20+- To delete content: provide file_path and old_string, leave new_string empty
21+
22+The tool will replace ONE occurrence of old_string with new_string in the specified file by default. Set replace_all to true to replace all occurrences.
23+
24+CRITICAL REQUIREMENTS FOR USING THIS TOOL:
25+
26+1. UNIQUENESS: When replace_all is false (default), the old_string MUST uniquely identify the specific instance you want to change. This means:
27+ - Include AT LEAST 3-5 lines of context BEFORE the change point
28+ - Include AT LEAST 3-5 lines of context AFTER the change point
29+ - Include all whitespace, indentation, and surrounding code exactly as it appears in the file
30+
31+2. SINGLE INSTANCE: When replace_all is false, this tool can only change ONE instance at a time. If you need to change multiple instances:
32+ - Set replace_all to true to replace all occurrences at once
33+ - Or make separate calls to this tool for each instance
34+ - Each call must uniquely identify its specific instance using extensive context
35+
36+3. VERIFICATION: Before using this tool:
37+ - Check how many instances of the target text exist in the file
38+ - If multiple instances exist and replace_all is false, gather enough context to uniquely identify each one
39+ - Plan separate tool calls for each instance or use replace_all
40+
41+WARNING: If you do not follow these requirements:
42+
43+- The tool will fail if old_string matches multiple locations and replace_all is false
44+- The tool will fail if old_string doesn't match exactly (including whitespace)
45+- You may change the wrong instance if you don't include enough context
46+
47+When making edits:
48+
49+- Ensure the edit results in idiomatic, correct code
50+- Do not leave the code in a broken state
51+- Always use absolute file paths (starting with /)
52+
53+WINDOWS NOTES:
54+
55+- File paths should use forward slashes (/) for cross-platform compatibility
56+- On Windows, absolute paths start with drive letters (C:/) but forward slashes work throughout
57+- File permissions are handled automatically by the Go runtime
58+- Always assumes \n for line endings. The tool will handle \r\n conversion automatically if needed.
59+
60+Remember: when making multiple file edits in a row to the same file, you should prefer to send all edits in a single message with multiple calls to this tool, rather than multiple messages with a single call each.
internal/llm/tools/fetch.go+6−33
@@ -2,6 +2,7 @@ package tools
22
33import (
44 "context"
5+ _ "embed"
56 "encoding/json"
67 "fmt"
78 "io"
@@ -33,38 +34,10 @@ type fetchTool struct {
3334 workingDir string
3435}
3536
36−const (
37− FetchToolName = "fetch"
38− fetchToolDescription = `Fetches content from a URL and returns it in the specified format.
39−
40−WHEN TO USE THIS TOOL:
41−- Use when you need to download content from a URL
42−- Helpful for retrieving documentation, API responses, or web content
43−- Useful for getting external information to assist with tasks
44−
45−HOW TO USE:
46−- Provide the URL to fetch content from
47−- Specify the desired output format (text, markdown, or html)
48−- Optionally set a timeout for the request
49−
50−FEATURES:
51−- Supports three output formats: text, markdown, and html
52−- Automatically handles HTTP redirects
53−- Sets reasonable timeouts to prevent hanging
54−- Validates input parameters before making requests
55−
56−LIMITATIONS:
57−- Maximum response size is 5MB
58−- Only supports HTTP and HTTPS protocols
59−- Cannot handle authentication or cookies
60−- Some websites may block automated requests
61−
62−TIPS:
63−- Use text format for plain text content or simple API responses
64−- Use markdown format for content that should be rendered with formatting
65−- Use html format when you need the raw HTML structure
66−- Set appropriate timeouts for potentially slow websites`
67−)
37+const FetchToolName = "fetch"
38+
39+//go:embed fetch.md
40+var fetchDescription []byte
6841
6942func NewFetchTool(permissions permission.Service, workingDir string) BaseTool {
7043 return &fetchTool{
@@ -88,7 +61,7 @@ func (t *fetchTool) Name() string {
8861func (t *fetchTool) Info() ToolInfo {
8962 return ToolInfo{
9063 Name: FetchToolName,
91− Description: fetchToolDescription,
64+ Description: string(fetchDescription),
9265 Parameters: map[string]any{
9366 "url": map[string]any{
9467 "type": "string",
internal/llm/tools/fetch.mdnew file+34
@@ -0,0 +1,34 @@
1+Fetches content from a URL and returns it in the specified format.
2+
3+WHEN TO USE THIS TOOL:
4+
5+- Use when you need to download content from a URL
6+- Helpful for retrieving documentation, API responses, or web content
7+- Useful for getting external information to assist with tasks
8+
9+HOW TO USE:
10+
11+- Provide the URL to fetch content from
12+- Specify the desired output format (text, markdown, or html)
13+- Optionally set a timeout for the request
14+
15+FEATURES:
16+
17+- Supports three output formats: text, markdown, and html
18+- Automatically handles HTTP redirects
19+- Sets reasonable timeouts to prevent hanging
20+- Validates input parameters before making requests
21+
22+LIMITATIONS:
23+
24+- Maximum response size is 5MB
25+- Only supports HTTP and HTTPS protocols
26+- Cannot handle authentication or cookies
27+- Some websites may block automated requests
28+
29+TIPS:
30+
31+- Use text format for plain text content or simple API responses
32+- Use markdown format for content that should be rendered with formatting
33+- Use html format when you need the raw HTML structure
34+- Set appropriate timeouts for potentially slow websites
internal/llm/tools/glob.go+6−43
@@ -3,6 +3,7 @@ package tools
33import (
44 "bytes"
55 "context"
6+ _ "embed"
67 "encoding/json"
78 "fmt"
89 "log/slog"
@@ -14,48 +15,10 @@ import (
1415 "github.com/charmbracelet/crush/internal/fsext"
1516)
1617
17−const (
18− GlobToolName = "glob"
19− globDescription = `Fast file pattern matching tool that finds files by name and pattern, returning matching paths sorted by modification time (newest first).
20−
21−WHEN TO USE THIS TOOL:
22−- Use when you need to find files by name patterns or extensions
23−- Great for finding specific file types across a directory structure
24−- Useful for discovering files that match certain naming conventions
25−
26−HOW TO USE:
27−- Provide a glob pattern to match against file paths
28−- Optionally specify a starting directory (defaults to current working directory)
29−- Results are sorted with most recently modified files first
30−
31−GLOB PATTERN SYNTAX:
32−- '*' matches any sequence of non-separator characters
33−- '**' matches any sequence of characters, including separators
34−- '?' matches any single non-separator character
35−- '[...]' matches any character in the brackets
36−- '[!...]' matches any character not in the brackets
37−
38−COMMON PATTERN EXAMPLES:
39−- '*.js' - Find all JavaScript files in the current directory
40−- '**/*.js' - Find all JavaScript files in any subdirectory
41−- 'src/**/*.{ts,tsx}' - Find all TypeScript files in the src directory
42−- '*.{html,css,js}' - Find all HTML, CSS, and JS files
43−
44−LIMITATIONS:
45−- Results are limited to 100 files (newest first)
46−- Does not search file contents (use Grep tool for that)
47−- Hidden files (starting with '.') are skipped
48−
49−WINDOWS NOTES:
50−- Path separators are handled automatically (both / and \ work)
51−- Uses ripgrep (rg) command if available, otherwise falls back to built-in Go implementation
52−
53−TIPS:
54−- Patterns should use forward slashes (/) for cross-platform compatibility
55−- For the most useful results, combine with the Grep tool: first find files with Glob, then search their contents with Grep
56−- When doing iterative exploration that may require multiple rounds of searching, consider using the Agent tool instead
57−- Always check if results are truncated and refine your search pattern if needed`
58−)
18+const GlobToolName = "glob"
19+
20+//go:embed glob.md
21+var globDescription []byte
5922
6023type GlobParams struct {
6124 Pattern string `json:"pattern"`
@@ -84,7 +47,7 @@ func (g *globTool) Name() string {
8447func (g *globTool) Info() ToolInfo {
8548 return ToolInfo{
8649 Name: GlobToolName,
87− Description: globDescription,
50+ Description: string(globDescription),
8851 Parameters: map[string]any{
8952 "pattern": map[string]any{
9053 "type": "string",
internal/llm/tools/glob.mdnew file+46
@@ -0,0 +1,46 @@
1+Fast file pattern matching tool that finds files by name and pattern, returning matching paths sorted by modification time (newest first).
2+
3+WHEN TO USE THIS TOOL:
4+
5+- Use when you need to find files by name patterns or extensions
6+- Great for finding specific file types across a directory structure
7+- Useful for discovering files that match certain naming conventions
8+
9+HOW TO USE:
10+
11+- Provide a glob pattern to match against file paths
12+- Optionally specify a starting directory (defaults to current working directory)
13+- Results are sorted with most recently modified files first
14+
15+GLOB PATTERN SYNTAX:
16+
17+- '\*' matches any sequence of non-separator characters
18+- '\*\*' matches any sequence of characters, including separators
19+- '?' matches any single non-separator character
20+- '[...]' matches any character in the brackets
21+- '[!...]' matches any character not in the brackets
22+
23+COMMON PATTERN EXAMPLES:
24+
25+- '\*.js' - Find all JavaScript files in the current directory
26+- '\*_/_.js' - Find all JavaScript files in any subdirectory
27+- 'src/\*_/_.{ts,tsx}' - Find all TypeScript files in the src directory
28+- '\*.{html,css,js}' - Find all HTML, CSS, and JS files
29+
30+LIMITATIONS:
31+
32+- Results are limited to 100 files (newest first)
33+- Does not search file contents (use Grep tool for that)
34+- Hidden files (starting with '.') are skipped
35+
36+WINDOWS NOTES:
37+
38+- Path separators are handled automatically (both / and \ work)
39+- Uses ripgrep (rg) command if available, otherwise falls back to built-in Go implementation
40+
41+TIPS:
42+
43+- Patterns should use forward slashes (/) for cross-platform compatibility
44+- For the most useful results, combine with the Grep tool: first find files with Glob, then search their contents with Grep
45+- When doing iterative exploration that may require multiple rounds of searching, consider using the Agent tool instead
46+- Always check if results are truncated and refine your search pattern if needed
internal/llm/tools/grep.go+6−50
@@ -3,6 +3,7 @@ package tools
33import (
44 "bufio"
55 "context"
6+ _ "embed"
67 "encoding/json"
78 "fmt"
89 "io"
@@ -92,55 +93,10 @@ type grepTool struct {
9293 workingDir string
9394}
9495
95−const (
96− GrepToolName = "grep"
97− grepDescription = `Fast content search tool that finds files containing specific text or patterns, returning matching file paths sorted by modification time (newest first).
98−
99−WHEN TO USE THIS TOOL:
100−- Use when you need to find files containing specific text or patterns
101−- Great for searching code bases for function names, variable declarations, or error messages
102−- Useful for finding all files that use a particular API or pattern
103−
104−HOW TO USE:
105−- Provide a regex pattern to search for within file contents
106−- Set literal_text=true if you want to search for the exact text with special characters (recommended for non-regex users)
107−- Optionally specify a starting directory (defaults to current working directory)
108−- Optionally provide an include pattern to filter which files to search
109−- Results are sorted with most recently modified files first
110−
111−REGEX PATTERN SYNTAX (when literal_text=false):
112−- Supports standard regular expression syntax
113−- 'function' searches for the literal text "function"
114−- 'log\..*Error' finds text starting with "log." and ending with "Error"
115−- 'import\s+.*\s+from' finds import statements in JavaScript/TypeScript
116−
117−COMMON INCLUDE PATTERN EXAMPLES:
118−- '*.js' - Only search JavaScript files
119−- '*.{ts,tsx}' - Only search TypeScript files
120−- '*.go' - Only search Go files
121−
122−LIMITATIONS:
123−- Results are limited to 100 files (newest first)
124−- Performance depends on the number of files being searched
125−- Very large binary files may be skipped
126−- Hidden files (starting with '.') are skipped
127−
128−IGNORE FILE SUPPORT:
129−- Respects .gitignore patterns to skip ignored files and directories
130−- Respects .crushignore patterns for additional ignore rules
131−- Both ignore files are automatically detected in the search root directory
132−
133−CROSS-PLATFORM NOTES:
134−- Uses ripgrep (rg) command if available for better performance
135−- Falls back to built-in Go implementation if ripgrep is not available
136−- File paths are normalized automatically for cross-platform compatibility
137−
138−TIPS:
139−- For faster, more targeted searches, first use Glob to find relevant files, then use Grep
140−- When doing iterative exploration that may require multiple rounds of searching, consider using the Agent tool instead
141−- Always check if results are truncated and refine your search pattern if needed
142−- Use literal_text=true when searching for exact text containing special characters like dots, parentheses, etc.`
143−)
96+const GrepToolName = "grep"
97+
98+//go:embed grep.md
99+var grepDescription []byte
144100
145101func NewGrepTool(workingDir string) BaseTool {
146102 return &grepTool{
@@ -155,7 +111,7 @@ func (g *grepTool) Name() string {
155111func (g *grepTool) Info() ToolInfo {
156112 return ToolInfo{
157113 Name: GrepToolName,
158− Description: grepDescription,
114+ Description: string(grepDescription),
159115 Parameters: map[string]any{
160116 "pattern": map[string]any{
161117 "type": "string",
internal/llm/tools/grep.mdnew file+54
@@ -0,0 +1,54 @@
1+Fast content search tool that finds files containing specific text or patterns, returning matching file paths sorted by modification time (newest first).
2+
3+WHEN TO USE THIS TOOL:
4+
5+- Use when you need to find files containing specific text or patterns
6+- Great for searching code bases for function names, variable declarations, or error messages
7+- Useful for finding all files that use a particular API or pattern
8+
9+HOW TO USE:
10+
11+- Provide a regex pattern to search for within file contents
12+- Set literal_text=true if you want to search for the exact text with special characters (recommended for non-regex users)
13+- Optionally specify a starting directory (defaults to current working directory)
14+- Optionally provide an include pattern to filter which files to search
15+- Results are sorted with most recently modified files first
16+
17+REGEX PATTERN SYNTAX (when literal_text=false):
18+
19+- Supports standard regular expression syntax
20+- 'function' searches for the literal text "function"
21+- 'log\..\*Error' finds text starting with "log." and ending with "Error"
22+- 'import\s+.\*\s+from' finds import statements in JavaScript/TypeScript
23+
24+COMMON INCLUDE PATTERN EXAMPLES:
25+
26+- '\*.js' - Only search JavaScript files
27+- '\*.{ts,tsx}' - Only search TypeScript files
28+- '\*.go' - Only search Go files
29+
30+LIMITATIONS:
31+
32+- Results are limited to 100 files (newest first)
33+- Performance depends on the number of files being searched
34+- Very large binary files may be skipped
35+- Hidden files (starting with '.') are skipped
36+
37+IGNORE FILE SUPPORT:
38+
39+- Respects .gitignore patterns to skip ignored files and directories
40+- Respects .crushignore patterns for additional ignore rules
41+- Both ignore files are automatically detected in the search root directory
42+
43+CROSS-PLATFORM NOTES:
44+
45+- Uses ripgrep (rg) command if available for better performance
46+- Falls back to built-in Go implementation if ripgrep is not available
47+- File paths are normalized automatically for cross-platform compatibility
48+
49+TIPS:
50+
51+- For faster, more targeted searches, first use Glob to find relevant files, then use Grep
52+- When doing iterative exploration that may require multiple rounds of searching, consider using the Agent tool instead
53+- Always check if results are truncated and refine your search pattern if needed
54+- Use literal_text=true when searching for exact text containing special characters like dots, parentheses, etc.
internal/llm/tools/ls.go+7−37
@@ -2,6 +2,7 @@ package tools
22
33import (
44 "context"
5+ _ "embed"
56 "encoding/json"
67 "fmt"
78 "os"
@@ -40,44 +41,13 @@ type lsTool struct {
4041}
4142
4243const (
43− LSToolName = "ls"
44− MaxLSFiles = 1000
45− lsDescription = `Directory listing tool that shows files and subdirectories in a tree structure, helping you explore and understand the project organization.
46−
47−WHEN TO USE THIS TOOL:
48−- Use when you need to explore the structure of a directory
49−- Helpful for understanding the organization of a project
50−- Good first step when getting familiar with a new codebase
51−
52−HOW TO USE:
53−- Provide a path to list (defaults to current working directory)
54−- Optionally specify glob patterns to ignore
55−- Results are displayed in a tree structure
56−
57−FEATURES:
58−- Displays a hierarchical view of files and directories
59−- Automatically skips hidden files/directories (starting with '.')
60−- Skips common system directories like __pycache__
61−- Can filter out files matching specific patterns
62−
63−LIMITATIONS:
64−- Results are limited to 1000 files
65−- Very large directories will be truncated
66−- Does not show file sizes or permissions
67−- Cannot recursively list all directories in a large project
68−
69−WINDOWS NOTES:
70−- Hidden file detection uses Unix convention (files starting with '.')
71−- Windows-specific hidden files (with hidden attribute) are not automatically skipped
72−- Common Windows directories like System32, Program Files are not in default ignore list
73−- Path separators are handled automatically (both / and \ work)
74−
75−TIPS:
76−- Use Glob tool for finding files by name patterns instead of browsing
77−- Use Grep tool for searching file contents
78−- Combine with other tools for more effective exploration`
44+ LSToolName = "ls"
45+ MaxLSFiles = 1000
7946)
8047
48+//go:embed ls.md
49+var lsDescription []byte
50+
8151func NewLsTool(permissions permission.Service, workingDir string) BaseTool {
8252 return &lsTool{
8353 workingDir: workingDir,
@@ -92,7 +62,7 @@ func (l *lsTool) Name() string {
9262func (l *lsTool) Info() ToolInfo {
9363 return ToolInfo{
9464 Name: LSToolName,
95− Description: lsDescription,
65+ Description: string(lsDescription),
9666 Parameters: map[string]any{
9767 "path": map[string]any{
9868 "type": "string",
internal/llm/tools/ls.mdnew file+40
@@ -0,0 +1,40 @@
1+Directory listing tool that shows files and subdirectories in a tree structure, helping you explore and understand the project organization.
2+
3+WHEN TO USE THIS TOOL:
4+
5+- Use when you need to explore the structure of a directory
6+- Helpful for understanding the organization of a project
7+- Good first step when getting familiar with a new codebase
8+
9+HOW TO USE:
10+
11+- Provide a path to list (defaults to current working directory)
12+- Optionally specify glob patterns to ignore
13+- Results are displayed in a tree structure
14+
15+FEATURES:
16+
17+- Displays a hierarchical view of files and directories
18+- Automatically skips hidden files/directories (starting with '.')
19+- Skips common system directories like **pycache**
20+- Can filter out files matching specific patterns
21+
22+LIMITATIONS:
23+
24+- Results are limited to 1000 files
25+- Very large directories will be truncated
26+- Does not show file sizes or permissions
27+- Cannot recursively list all directories in a large project
28+
29+WINDOWS NOTES:
30+
31+- Hidden file detection uses Unix convention (files starting with '.')
32+- Windows-specific hidden files (with hidden attribute) are not automatically skipped
33+- Common Windows directories like System32, Program Files are not in default ignore list
34+- Path separators are handled automatically (both / and \ work)
35+
36+TIPS:
37+
38+- Use Glob tool for finding files by name patterns instead of browsing
39+- Use Grep tool for searching file contents
40+- Combine with other tools for more effective exploration
internal/llm/tools/multiedit.go+6−46
@@ -2,6 +2,7 @@ package tools
22
33import (
44 "context"
5+ _ "embed"
56 "encoding/json"
67 "fmt"
78 "log/slog"
@@ -50,51 +51,10 @@ type multiEditTool struct {
5051 workingDir string
5152}
5253
53−const (
54− MultiEditToolName = "multiedit"
55− multiEditDescription = `This is a tool for making multiple edits to a single file in one operation. It is built on top of the Edit tool and allows you to perform multiple find-and-replace operations efficiently. Prefer this tool over the Edit tool when you need to make multiple edits to the same file.
56−
57−Before using this tool:
58−
59−1. Use the Read tool to understand the file's contents and context
60−
61−2. Verify the directory path is correct
62−
63−To make multiple file edits, provide the following:
64−1. file_path: The absolute path to the file to modify (must be absolute, not relative)
65−2. edits: An array of edit operations to perform, where each edit contains:
66− - old_string: The text to replace (must match the file contents exactly, including all whitespace and indentation)
67− - new_string: The edited text to replace the old_string
68− - replace_all: Replace all occurrences of old_string. This parameter is optional and defaults to false.
69−
70−IMPORTANT:
71−- All edits are applied in sequence, in the order they are provided
72−- Each edit operates on the result of the previous edit
73−- All edits must be valid for the operation to succeed - if any edit fails, none will be applied
74−- This tool is ideal when you need to make several changes to different parts of the same file
75−
76−CRITICAL REQUIREMENTS:
77−1. All edits follow the same requirements as the single Edit tool
78−2. The edits are atomic - either all succeed or none are applied
79−3. Plan your edits carefully to avoid conflicts between sequential operations
80−
81−WARNING:
82−- The tool will fail if edits.old_string doesn't match the file contents exactly (including whitespace)
83−- The tool will fail if edits.old_string and edits.new_string are the same
84−- Since edits are applied in sequence, ensure that earlier edits don't affect the text that later edits are trying to find
85−
86−When making edits:
87−- Ensure all edits result in idiomatic, correct code
88−- Do not leave the code in a broken state
89−- Always use absolute file paths (starting with /)
90−- Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.
91−- Use replace_all for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance.
92−
93−If you want to create a new file, use:
94−- A new file path, including dir name if needed
95−- First edit: empty old_string and the new file's contents as new_string
96−- Subsequent edits: normal edit operations on the created content`
97−)
54+const MultiEditToolName = "multiedit"
55+
56+//go:embed multiedit.md
57+var multieditDescription []byte
9858
9959func NewMultiEditTool(lspClients *csync.Map[string, *lsp.Client], permissions permission.Service, files history.Service, workingDir string) BaseTool {
10060 return &multiEditTool{
@@ -112,7 +72,7 @@ func (m *multiEditTool) Name() string {
11272func (m *multiEditTool) Info() ToolInfo {
11373 return ToolInfo{
11474 Name: MultiEditToolName,
115− Description: multiEditDescription,
75+ Description: string(multieditDescription),
11676 Parameters: map[string]any{
11777 "file_path": map[string]any{
11878 "type": "string",
internal/llm/tools/multiedit.mdnew file+48
@@ -0,0 +1,48 @@
1+This is a tool for making multiple edits to a single file in one operation. It is built on top of the Edit tool and allows you to perform multiple find-and-replace operations efficiently. Prefer this tool over the Edit tool when you need to make multiple edits to the same file.
2+
3+Before using this tool:
4+
5+1. Use the Read tool to understand the file's contents and context
6+
7+2. Verify the directory path is correct
8+
9+To make multiple file edits, provide the following:
10+
11+1. file_path: The absolute path to the file to modify (must be absolute, not relative)
12+2. edits: An array of edit operations to perform, where each edit contains:
13+ - old_string: The text to replace (must match the file contents exactly, including all whitespace and indentation)
14+ - new_string: The edited text to replace the old_string
15+ - replace_all: Replace all occurrences of old_string. This parameter is optional and defaults to false.
16+
17+IMPORTANT:
18+
19+- All edits are applied in sequence, in the order they are provided
20+- Each edit operates on the result of the previous edit
21+- All edits must be valid for the operation to succeed - if any edit fails, none will be applied
22+- This tool is ideal when you need to make several changes to different parts of the same file
23+
24+CRITICAL REQUIREMENTS:
25+
26+1. All edits follow the same requirements as the single Edit tool
27+2. The edits are atomic - either all succeed or none are applied
28+3. Plan your edits carefully to avoid conflicts between sequential operations
29+
30+WARNING:
31+
32+- The tool will fail if edits.old_string doesn't match the file contents exactly (including whitespace)
33+- The tool will fail if edits.old_string and edits.new_string are the same
34+- Since edits are applied in sequence, ensure that earlier edits don't affect the text that later edits are trying to find
35+
36+When making edits:
37+
38+- Ensure all edits result in idiomatic, correct code
39+- Do not leave the code in a broken state
40+- Always use absolute file paths (starting with /)
41+- Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.
42+- Use replace_all for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance.
43+
44+If you want to create a new file, use:
45+
46+- A new file path, including dir name if needed
47+- First edit: empty old_string and the new file's contents as new_string
48+- Subsequent edits: normal edit operations on the created content
internal/llm/tools/sourcegraph.go+6−98
@@ -3,6 +3,7 @@ package tools
33import (
44 "bytes"
55 "context"
6+ _ "embed"
67 "encoding/json"
78 "fmt"
89 "io"
@@ -27,103 +28,10 @@ type sourcegraphTool struct {
2728 client *http.Client
2829}
2930
30−const (
31− SourcegraphToolName = "sourcegraph"
32− sourcegraphToolDescription = `Search code across public repositories using Sourcegraph's GraphQL API.
33−
34−WHEN TO USE THIS TOOL:
35−- Use when you need to find code examples or implementations across public repositories
36−- Helpful for researching how others have solved similar problems
37−- Useful for discovering patterns and best practices in open source code
38−
39−HOW TO USE:
40−- Provide a search query using Sourcegraph's query syntax
41−- Optionally specify the number of results to return (default: 10)
42−- Optionally set a timeout for the request
43−
44−QUERY SYNTAX:
45−- Basic search: "fmt.Println" searches for exact matches
46−- File filters: "file:.go fmt.Println" limits to Go files
47−- Repository filters: "repo:^github\.com/golang/go$ fmt.Println" limits to specific repos
48−- Language filters: "lang:go fmt.Println" limits to Go code
49−- Boolean operators: "fmt.Println AND log.Fatal" for combined terms
50−- Regular expressions: "fmt\.(Print|Printf|Println)" for pattern matching
51−- Quoted strings: "\"exact phrase\"" for exact phrase matching
52−- Exclude filters: "-file:test" or "-repo:forks" to exclude matches
53−
54−ADVANCED FILTERS:
55−- Repository filters:
56− * "repo:name" - Match repositories with name containing "name"
57− * "repo:^github\.com/org/repo$" - Exact repository match
58− * "repo:org/repo@branch" - Search specific branch
59− * "repo:org/repo rev:branch" - Alternative branch syntax
60− * "-repo:name" - Exclude repositories
61− * "fork:yes" or "fork:only" - Include or only show forks
62− * "archived:yes" or "archived:only" - Include or only show archived repos
63− * "visibility:public" or "visibility:private" - Filter by visibility
64−
65−- File filters:
66− * "file:\.js$" - Files with .js extension
67− * "file:internal/" - Files in internal directory
68− * "-file:test" - Exclude test files
69− * "file:has.content(Copyright)" - Files containing "Copyright"
70− * "file:has.contributor([email protected])" - Files with specific contributor
71−
72−- Content filters:
73− * "content:\"exact string\"" - Search for exact string
74− * "-content:\"unwanted\"" - Exclude files with unwanted content
75− * "case:yes" - Case-sensitive search
76−
77−- Type filters:
78− * "type:symbol" - Search for symbols (functions, classes, etc.)
79− * "type:file" - Search file content only
80− * "type:path" - Search filenames only
81− * "type:diff" - Search code changes
82− * "type:commit" - Search commit messages
83−
84−- Commit/diff search:
85− * "after:\"1 month ago\"" - Commits after date
86− * "before:\"2023-01-01\"" - Commits before date
87− * "author:name" - Commits by author
88− * "message:\"fix bug\"" - Commits with message
89−
90−- Result selection:
91− * "select:repo" - Show only repository names
92− * "select:file" - Show only file paths
93− * "select:content" - Show only matching content
94− * "select:symbol" - Show only matching symbols
95−
96−- Result control:
97− * "count:100" - Return up to 100 results
98− * "count:all" - Return all results
99− * "timeout:30s" - Set search timeout
100−
101−EXAMPLES:
102−- "file:.go context.WithTimeout" - Find Go code using context.WithTimeout
103−- "lang:typescript useState type:symbol" - Find TypeScript React useState hooks
104−- "repo:^github\.com/kubernetes/kubernetes$ pod list type:file" - Find Kubernetes files related to pod listing
105−- "repo:sourcegraph/sourcegraph$ after:\"3 months ago\" type:diff database" - Recent changes to database code
106−- "file:Dockerfile (alpine OR ubuntu) -content:alpine:latest" - Dockerfiles with specific base images
107−- "repo:has.path(\.py) file:requirements.txt tensorflow" - Python projects using TensorFlow
108−
109−BOOLEAN OPERATORS:
110−- "term1 AND term2" - Results containing both terms
111−- "term1 OR term2" - Results containing either term
112−- "term1 NOT term2" - Results with term1 but not term2
113−- "term1 and (term2 or term3)" - Grouping with parentheses
114−
115−LIMITATIONS:
116−- Only searches public repositories
117−- Rate limits may apply
118−- Complex queries may take longer to execute
119−- Maximum of 20 results per query
120−
121−TIPS:
122−- Use specific file extensions to narrow results
123−- Add repo: filters for more targeted searches
124−- Use type:symbol to find function/method definitions
125−- Use type:file to find relevant files`
126−)
31+const SourcegraphToolName = "sourcegraph"
32+
33+//go:embed sourcegraph.md
34+var sourcegraphDescription []byte
12735
12836func NewSourcegraphTool() BaseTool {
12937 return &sourcegraphTool{
@@ -145,7 +53,7 @@ func (t *sourcegraphTool) Name() string {
14553func (t *sourcegraphTool) Info() ToolInfo {
14654 return ToolInfo{
14755 Name: SourcegraphToolName,
148− Description: sourcegraphToolDescription,
56+ Description: string(sourcegraphDescription),
14957 Parameters: map[string]any{
15058 "query": map[string]any{
15159 "type": "string",
internal/llm/tools/sourcegraph.mdnew file+102
@@ -0,0 +1,102 @@
1+Search code across public repositories using Sourcegraph's GraphQL API.
2+
3+WHEN TO USE THIS TOOL:
4+
5+- Use when you need to find code examples or implementations across public repositories
6+- Helpful for researching how others have solved similar problems
7+- Useful for discovering patterns and best practices in open source code
8+
9+HOW TO USE:
10+
11+- Provide a search query using Sourcegraph's query syntax
12+- Optionally specify the number of results to return (default: 10)
13+- Optionally set a timeout for the request
14+
15+QUERY SYNTAX:
16+
17+- Basic search: "fmt.Println" searches for exact matches
18+- File filters: "file:.go fmt.Println" limits to Go files
19+- Repository filters: "repo:^github\.com/golang/go$ fmt.Println" limits to specific repos
20+- Language filters: "lang:go fmt.Println" limits to Go code
21+- Boolean operators: "fmt.Println AND log.Fatal" for combined terms
22+- Regular expressions: "fmt\.(Print|Printf|Println)" for pattern matching
23+- Quoted strings: "\"exact phrase\"" for exact phrase matching
24+- Exclude filters: "-file:test" or "-repo:forks" to exclude matches
25+
26+ADVANCED FILTERS:
27+
28+- Repository filters:
29+ - "repo:name" - Match repositories with name containing "name"
30+ - "repo:^github\.com/org/repo$" - Exact repository match
31+ - "repo:org/repo@branch" - Search specific branch
32+ - "repo:org/repo rev:branch" - Alternative branch syntax
33+ - "-repo:name" - Exclude repositories
34+ - "fork:yes" or "fork:only" - Include or only show forks
35+ - "archived:yes" or "archived:only" - Include or only show archived repos
36+ - "visibility:public" or "visibility:private" - Filter by visibility
37+
38+- File filters:
39+ - "file:\.js$" - Files with .js extension
40+ - "file:internal/" - Files in internal directory
41+ - "-file:test" - Exclude test files
42+ - "file:has.content(Copyright)" - Files containing "Copyright"
43+ - "file:has.contributor([email protected])" - Files with specific contributor
44+
45+- Content filters:
46+ - "content:\"exact string\"" - Search for exact string
47+ - "-content:\"unwanted\"" - Exclude files with unwanted content
48+ - "case:yes" - Case-sensitive search
49+
50+- Type filters:
51+ - "type:symbol" - Search for symbols (functions, classes, etc.)
52+ - "type:file" - Search file content only
53+ - "type:path" - Search filenames only
54+ - "type:diff" - Search code changes
55+ - "type:commit" - Search commit messages
56+
57+- Commit/diff search:
58+ - "after:\"1 month ago\"" - Commits after date
59+ - "before:\"2023-01-01\"" - Commits before date
60+ - "author:name" - Commits by author
61+ - "message:\"fix bug\"" - Commits with message
62+
63+- Result selection:
64+ - "select:repo" - Show only repository names
65+ - "select:file" - Show only file paths
66+ - "select:content" - Show only matching content
67+ - "select:symbol" - Show only matching symbols
68+
69+- Result control:
70+ - "count:100" - Return up to 100 results
71+ - "count:all" - Return all results
72+ - "timeout:30s" - Set search timeout
73+
74+EXAMPLES:
75+
76+- "file:.go context.WithTimeout" - Find Go code using context.WithTimeout
77+- "lang:typescript useState type:symbol" - Find TypeScript React useState hooks
78+- "repo:^github\.com/kubernetes/kubernetes$ pod list type:file" - Find Kubernetes files related to pod listing
79+- "repo:sourcegraph/sourcegraph$ after:\"3 months ago\" type:diff database" - Recent changes to database code
80+- "file:Dockerfile (alpine OR ubuntu) -content:alpine:latest" - Dockerfiles with specific base images
81+- "repo:has.path(\.py) file:requirements.txt tensorflow" - Python projects using TensorFlow
82+
83+BOOLEAN OPERATORS:
84+
85+- "term1 AND term2" - Results containing both terms
86+- "term1 OR term2" - Results containing either term
87+- "term1 NOT term2" - Results with term1 but not term2
88+- "term1 and (term2 or term3)" - Grouping with parentheses
89+
90+LIMITATIONS:
91+
92+- Only searches public repositories
93+- Rate limits may apply
94+- Complex queries may take longer to execute
95+- Maximum of 20 results per query
96+
97+TIPS:
98+
99+- Use specific file extensions to narrow results
100+- Add repo: filters for more targeted searches
101+- Use type:symbol to find function/method definitions
102+- Use type:file to find relevant files
internal/llm/tools/view.go+5−37
@@ -3,6 +3,7 @@ package tools
33import (
44 "bufio"
55 "context"
6+ _ "embed"
67 "encoding/json"
78 "fmt"
89 "io"
@@ -16,6 +17,9 @@ import (
1617 "github.com/charmbracelet/crush/internal/permission"
1718)
1819
20+//go:embed view.md
21+var viewDescription []byte
22+
1923type ViewParams struct {
2024 FilePath string `json:"file_path"`
2125 Offset int `json:"offset"`
@@ -44,42 +48,6 @@ const (
4448 MaxReadSize = 250 * 1024
4549 DefaultReadLimit = 2000
4650 MaxLineLength = 2000
47− viewDescription = `File viewing tool that reads and displays the contents of files with line numbers, allowing you to examine code, logs, or text data.
48−
49−WHEN TO USE THIS TOOL:
50−- Use when you need to read the contents of a specific file
51−- Helpful for examining source code, configuration files, or log files
52−- Perfect for looking at text-based file formats
53−
54−HOW TO USE:
55−- Provide the path to the file you want to view
56−- Optionally specify an offset to start reading from a specific line
57−- Optionally specify a limit to control how many lines are read
58−- Do not use this for directories use the ls tool instead
59−
60−FEATURES:
61−- Displays file contents with line numbers for easy reference
62−- Can read from any position in a file using the offset parameter
63−- Handles large files by limiting the number of lines read
64−- Automatically truncates very long lines for better display
65−- Suggests similar file names when the requested file isn't found
66−
67−LIMITATIONS:
68−- Maximum file size is 250KB
69−- Default reading limit is 2000 lines
70−- Lines longer than 2000 characters are truncated
71−- Cannot display binary files or images
72−- Images can be identified but not displayed
73−
74−WINDOWS NOTES:
75−- Handles both Windows (CRLF) and Unix (LF) line endings automatically
76−- File paths work with both forward slashes (/) and backslashes (\)
77−- Text encoding is detected automatically for most common formats
78−
79−TIPS:
80−- Use with Glob tool to first find files you want to view
81−- For code exploration, first use Grep to find relevant files, then View to examine them
82−- When viewing large files, use the offset parameter to read specific sections`
8351)
8452
8553func NewViewTool(lspClients *csync.Map[string, *lsp.Client], permissions permission.Service, workingDir string) BaseTool {
@@ -97,7 +65,7 @@ func (v *viewTool) Name() string {
9765func (v *viewTool) Info() ToolInfo {
9866 return ToolInfo{
9967 Name: ViewToolName,
100− Description: viewDescription,
68+ Description: string(viewDescription),
10169 Parameters: map[string]any{
10270 "file_path": map[string]any{
10371 "type": "string",
internal/llm/tools/view.mdnew file+42
@@ -0,0 +1,42 @@
1+File viewing tool that reads and displays the contents of files with line numbers, allowing you to examine code, logs, or text data.
2+
3+WHEN TO USE THIS TOOL:
4+
5+- Use when you need to read the contents of a specific file
6+- Helpful for examining source code, configuration files, or log files
7+- Perfect for looking at text-based file formats
8+
9+HOW TO USE:
10+
11+- Provide the path to the file you want to view
12+- Optionally specify an offset to start reading from a specific line
13+- Optionally specify a limit to control how many lines are read
14+- Do not use this for directories use the ls tool instead
15+
16+FEATURES:
17+
18+- Displays file contents with line numbers for easy reference
19+- Can read from any position in a file using the offset parameter
20+- Handles large files by limiting the number of lines read
21+- Automatically truncates very long lines for better display
22+- Suggests similar file names when the requested file isn't found
23+
24+LIMITATIONS:
25+
26+- Maximum file size is 250KB
27+- Default reading limit is 2000 lines
28+- Lines longer than 2000 characters are truncated
29+- Cannot display binary files or images
30+- Images can be identified but not displayed
31+
32+WINDOWS NOTES:
33+
34+- Handles both Windows (CRLF) and Unix (LF) line endings automatically
35+- File paths work with both forward slashes (/) and backslashes (\)
36+- Text encoding is detected automatically for most common formats
37+
38+TIPS:
39+
40+- Use with Glob tool to first find files you want to view
41+- For code exploration, first use Grep to find relevant files, then View to examine them
42+- When viewing large files, use the offset parameter to read specific sections
internal/llm/tools/write.go+6−36
@@ -2,6 +2,7 @@ package tools
22
33import (
44 "context"
5+ _ "embed"
56 "encoding/json"
67 "fmt"
78 "log/slog"
@@ -19,6 +20,9 @@ import (
1920 "github.com/charmbracelet/crush/internal/permission"
2021)
2122
23+//go:embed write.md
24+var writeDescription []byte
25+
2226type WriteParams struct {
2327 FilePath string `json:"file_path"`
2428 Content string `json:"content"`
@@ -43,41 +47,7 @@ type WriteResponseMetadata struct {
4347 Removals int `json:"removals"`
4448}
4549
46−const (
47− WriteToolName = "write"
48− writeDescription = `File writing tool that creates or updates files in the filesystem, allowing you to save or modify text content.
49−
50−WHEN TO USE THIS TOOL:
51−- Use when you need to create a new file
52−- Helpful for updating existing files with modified content
53−- Perfect for saving generated code, configurations, or text data
54−
55−HOW TO USE:
56−- Provide the path to the file you want to write
57−- Include the content to be written to the file
58−- The tool will create any necessary parent directories
59−
60−FEATURES:
61−- Can create new files or overwrite existing ones
62−- Creates parent directories automatically if they don't exist
63−- Checks if the file has been modified since last read for safety
64−- Avoids unnecessary writes when content hasn't changed
65−
66−LIMITATIONS:
67−- You should read a file before writing to it to avoid conflicts
68−- Cannot append to files (rewrites the entire file)
69−
70−WINDOWS NOTES:
71−- File permissions (0o755, 0o644) are Unix-style but work on Windows with appropriate translations
72−- Use forward slashes (/) in paths for cross-platform compatibility
73−- Windows file attributes and permissions are handled automatically by the Go runtime
74−
75−TIPS:
76−- Use the View tool first to examine existing files before modifying them
77−- Use the LS tool to verify the correct location when creating new files
78−- Combine with Glob and Grep tools to find and modify multiple files
79−- Always include descriptive comments when making changes to existing code`
80−)
50+const WriteToolName = "write"
8151
8252func NewWriteTool(lspClients *csync.Map[string, *lsp.Client], permissions permission.Service, files history.Service, workingDir string) BaseTool {
8353 return &writeTool{
@@ -95,7 +65,7 @@ func (w *writeTool) Name() string {
9565func (w *writeTool) Info() ToolInfo {
9666 return ToolInfo{
9767 Name: WriteToolName,
98− Description: writeDescription,
68+ Description: string(writeDescription),
9969 Parameters: map[string]any{
10070 "file_path": map[string]any{
10171 "type": "string",
internal/llm/tools/write.mdnew file+38
@@ -0,0 +1,38 @@
1+File writing tool that creates or updates files in the filesystem, allowing you to save or modify text content.
2+
3+WHEN TO USE THIS TOOL:
4+
5+- Use when you need to create a new file
6+- Helpful for updating existing files with modified content
7+- Perfect for saving generated code, configurations, or text data
8+
9+HOW TO USE:
10+
11+- Provide the path to the file you want to write
12+- Include the content to be written to the file
13+- The tool will create any necessary parent directories
14+
15+FEATURES:
16+
17+- Can create new files or overwrite existing ones
18+- Creates parent directories automatically if they don't exist
19+- Checks if the file has been modified since last read for safety
20+- Avoids unnecessary writes when content hasn't changed
21+
22+LIMITATIONS:
23+
24+- You should read a file before writing to it to avoid conflicts
25+- Cannot append to files (rewrites the entire file)
26+
27+WINDOWS NOTES:
28+
29+- File permissions (0o755, 0o644) are Unix-style but work on Windows with appropriate translations
30+- Use forward slashes (/) in paths for cross-platform compatibility
31+- Windows file attributes and permissions are handled automatically by the Go runtime
32+
33+TIPS:
34+
35+- Use the View tool first to examine existing files before modifying them
36+- Use the LS tool to verify the correct location when creating new files
37+- Combine with Glob and Grep tools to find and modify multiple files
38+- Always include descriptive comments when making changes to existing code