Skip to content

Tools

Keen Code provides a set of built-in tools that the LLM can use to interact with the codebase. Tools are registered in a central registry and exposed to the LLM with their schemas.

Tool Registry

// internal/tools/tool.go
type Tool interface {
    Name() string
    Description() string
    InputSchema() map[string]any
    Execute(ctx context.Context, input any) (any, error)
}

type Registry struct {
    tools map[string]Tool
}

The registry manages all available tools and converts them to provider-specific tool formats (Anthropic, OpenAI, etc.).

Available Tools

Tool Purpose Key Parameters
read_file Read file contents path, offset, limit
write_file Create/overwrite files path, content
edit_file Targeted string replacement path, oldString, newString
glob Find files by pattern pattern, path
grep Search file contents pattern, path, include
bash Execute shell commands command, isDangerous, summary
web_fetch Fetch content from a URL url
call_mcp_tool Call a tool on an MCP server server, tool, arguments

read_file

Reads a UTF-8 text file with permission checks and validation.

type ReadFileTool struct {
    guard               *filesystem.Guard
    permissionRequester PermissionRequester
}

Parameters: - path (string, required): Absolute or relative path to the file - offset (integer, optional): 1-based line number to start reading from (defaults to 1) - limit (integer, optional): Maximum number of lines to return (defaults to 2000)

Validation: - File must be valid UTF-8 text - File must be under 10MB - Binary files are rejected

Returns:

{
  "path": "/absolute/path/to/file",
  "content": "file contents...",
  "bytes_read": 1234
}

write_file

Creates a new file or overwrites existing content.

type WriteFileTool struct {
    guard               *filesystem.Guard
    diffEmitter         DiffEmitter
    permissionRequester PermissionRequester
}

Parameters: - path (string, required): Target file path - content (string, required): Content to write

Behavior: - Creates parent directories if needed - Overwrites existing files completely - Emits diff for display via DiffEmitter

Returns:

{
  "path": "/absolute/path/to/file",
  "bytes_written": 1234,
  "created": true
}

edit_file

Performs targeted string replacement in existing files.

type EditFileTool struct {
    guard               *filesystem.Guard
    diffEmitter         DiffEmitter
    permissionRequester PermissionRequester
}

Parameters: - path (string, required): Target file path - oldString (string, required): Exact text to find and replace - newString (string, required): Replacement text - shouldReplaceAll (boolean, optional): Replace all occurrences (default: false)

Behavior: - File must already exist - oldString must match exactly (including whitespace) - Uses go-udiff for unified diff output - Emits diff via DiffEmitter

Returns:

{
  "success": true,
  "path": "/absolute/path/to/file",
  "replacementCount": 1
}

glob

Finds files matching a glob pattern.

type GlobTool struct {
    guard               *filesystem.Guard
    permissionRequester PermissionRequester
}

Parameters: - pattern (string, required): Glob pattern (e.g., *.go, **/*.md) - path (string, optional): Base directory (defaults to working directory)

Limits: - Maximum 1000 files returned

Returns:

{
  "pattern": "*.go",
  "base_path": "/project",
  "files": ["/project/main.go", "/project/pkg/foo.go"],
  "count": 2
}

grep

Searches file contents using regular expressions.

type GrepTool struct {
    guard               *filesystem.Guard
    permissionRequester PermissionRequester
}

Parameters: - pattern (string, required): Regex pattern (Go/RE2 syntax) - path (string, optional): Base directory - include (string, optional): Glob filter for file types - output_mode (string, optional): "file" or "content" (default)

Limits: - Maximum 1000 matches

Returns (content mode):

{
  "pattern": "func foo",
  "base_path": "/project",
  "output_mode": "content",
  "matches": [
    {"file": "/project/main.go", "line_number": 10, "line": "func foo() {"},
    {"file": "/project/main.go", "line_number": 25, "line": "func foo() error {"}
  ],
  "count": 2
}

bash

Executes shell commands with timeout and output limits.

type BashTool struct {
    guard               *filesystem.Guard
    permissionRequester PermissionRequester
}

Parameters: - command (string, required): Bash command to execute - isDangerous (boolean, optional): Always prompts for permission if true - summary (string, optional): Brief description for the UI

Limits: - Timeout: 180 seconds - Output: 10MB max (truncated if exceeded)

Dangerous commands (always prompt): - File removal (rm, rm -rf) - Git operations that modify repo (git commit, git push, git reset, git rebase) - Process termination (kill) - System modifications

Returns:

{
  "command": "go test ./...",
  "exit_code": 0,
  "stdout": "PASS\nok      github.com/user/keen-code    0.015s",
  "stderr": "",
  "summary": "Run Go tests"
}

web_fetch

Fetches content from a URL and returns it as text.

type WebFetchTool struct{}

Parameters: - url (string, required): The URL to fetch

Behavior: - HTML pages are automatically converted to Markdown for readability - Other content types (JSON, plain text, XML) are returned as-is - JavaScript-rendered pages (SPAs) return the pre-JS skeleton only

Limits: - Timeout: 30 seconds - Maximum response size: 128KB (truncated if exceeded)

Returns:

{
  "url": "https://example.com",
  "status_code": 200,
  "content": "markdown or raw content..."
}

call_mcp_tool

Calls a tool on a connected MCP (Model Context Protocol) server.

type CallMCPTool struct {
    manager             keenmcp.Runtime
    permissionRequester PermissionRequester
}

Parameters: - server (string, required): The MCP server name as configured - tool (string, required): The exact tool name to call on the server - arguments (object, optional): Key-value arguments matching the tool's input schema - checkCache (boolean, optional): Reserved for future caching; set to false or omit

Behavior: - Requires user permission before execution - Server name must match a configured MCP server - Arguments must match the tool's input schema exactly - Skill file at ~/.keen/skills/mcp:<server>/SKILL.md describes available tools - Schema file at ~/.keen/skills/mcp:<server>/schemas/<tool>.json describes required arguments

Returns:

{
  "server": "server-name",
  "tool": "tool-name",
  "content": "tool output text"
}

DiffEmitter

The DiffEmitter interface allows tools to emit diff output for display:

// internal/tools/diff.go
type DiffEmitter interface {
    EmitDiff(lines []EditDiffLine)
}

type EditDiffLine struct {
    Kind       EditDiffLineKind
    OldLineNum int
    NewLineNum int
    Content    string
}

const (
    DiffLineContext EditDiffLineKind = iota
    DiffLineAdded
    DiffLineRemoved
    DiffLineHunk
)

Permission Integration

All tools integrate with the permission system through PermissionRequester:

// internal/tools/permission.go
type PermissionRequester interface {
    RequestPermission(ctx context.Context, toolName, path, resolvedPath string, isDangerous bool) (bool, error)
}

Tools check permissions before execution and may request user approval for: - Paths outside the working directory - Dangerous operations (marked with isDangerous=true) - First-time access to certain paths