Skip to content

コマンドとファイル読み取りツール:ExecuteCommand / ReadFile / SearchFiles / ListFiles

源码版本v4.0.10

役割

このページでは Cline の四つの「能力系」読み取り専用/実行ツールを説明する。すべて IFullyManagedTool インターフェースに登録され、ToolExecutor が統一的に调度する:

  • ExecuteCommandToolHandler(ClineDefaultTool.BASH):ターミナルでシェルコマンドを一つ実行する。タイムアウト、マルチワークスペース、権限検証を伴う(class declaration:58)。
  • ReadFileToolHandler(ClineDefaultTool.FILE_READ):単一ファイルを読み取り、1 始まりの行番号を付ける。start_line/end_line によるスライス、画像ファイルの場合は image block を返す(class declaration:142)。
  • SearchFilesToolHandler(ClineDefaultTool.SEARCH):ripgrep ベースの正規検索。マルチワークスペース並列検索、file_pattern によるフィルタをサポート(class declaration:21)。
  • ListFilesToolHandler(ClineDefaultTool.LIST_FILES):ディレクトリをリストアップ。再帰サポート、200 件上限で打ち切る(class declaration:17)。

この四つのツールはインタラクションのパターンを共有する:handlePartialBlock が UI に事前プッシュして「モデルが X を読んでいる」ことをユーザーに見せ、execute が検証(clineignore + パス + パラメータ)→ 承認 → PreToolUse hook → 実行 → テレメトリを行う。いずれも config.isSubagentExecution を尊重し、子 agent 実行時は一部の UI プッシュと ask をスキップして直接仕事をする。

WriteToFileToolHandler との根本的な差は「読み取り専用または外部副作用」であるという点 —— 読む、リストする、検索するはファイルシステムの状態を変えない。execute_command は状態を変えるが terminal を通すため diff ビューに入らず、だからこのツール群には diff / userEdits の還流パスが無い。

設計動機

  • mistake 計数の統一ルール:各ツールはパラメータ欠けや clineignore ヒット時に consecutiveMistakeCount++ し、コア操作が成功した後に = 0 にする。YOLO モードの連続エラー上限をツール横断で累積できる(reset counter:377)。
  • コマンド分類タイムアウト:execute_command はよくある長時間実行コマンド(npm install、cargo build、pytest など)をマッチして 300 秒タイムアウト、その他は 30 秒とする。短いコマンドが長いタイムアウトに引きずられないようにする(LONG_RUNNING patterns:22-34)。
  • コマンド権限の二重ゲート:CLINE_COMMAND_PERMISSIONS 環境変数による segment レベルのホワイトリスト + clineignore のパス検証、二層で独立して拒否する(permission checks:162-190)。
  • 読みファイル重複排除キャッシュ:fileReadCache はメタデータ(readCount + mtime + imageBlock)のみを保存し、内容は保存しない。ヒットして mtime が変わっていなければ「既に読んだ」ヒントを直接返し、モデルが同じファイルを繰り返し読んでトークンを消費するのを防ぐ(dedup cache:298-314)。
  • 行番号付き表示:formatFileContentWithLineNumbers は各行に N | プレフィックスを付け、continuation ヒントを添える。モデルが start_line で正確に続きを読めるようにする(formatFileContentWithLineNumbers:79)。
  • マルチワークスペース並列検索:SearchFilesToolHandler はマルチワークスペースモードで searchPaths をすべて並列 Promise.all で実行し、workspace 名ごとにバケット分けして集計する(parallel search:279-285)。
  • ListFiles の 200 上限:listFiles の第三パラメータ limit=200、超過すると didHitLimit=true を返し、formatFilesList が末尾にヒントを付けてモデルに「もっと具体的な path で絞れ」と促す(listFiles call:100)。

主要ファイル

  • LONG_RUNNING patterns:22-34 — 長時間実行コマンドの正規配列。npm/cargo/pytest/docker build/torchrun など。
  • timeout resolution:36-56isLikelyLongRunningCommand + resolveCommandTimeoutSeconds。モデルが与えた timeout パラメータを優先する。
  • ExecuteCommand class:58name = ClineDefaultTool.BASH、handlePartialBlock は auto-approve 時に完全な block を待ってから say する。
  • workspace hint:135-159 — コマンドのプレフィックス @workspace:command を解析し、executionDir を対応する workspace ルートに変える。
  • permission checks:162-190commandPermissionController.validateCommand + clineIgnoreController.validateCommand
  • approval flow:223-279 — auto-approve には !requiresApprovalPerLLM && autoApproveSafe または risky コマンドの autoApproveSafe && autoApproveAll の二重ゲートが必要。
  • cache clear:319-327 — コマンド実行後に fileReadCache 全体を clear() する。sed/git checkout/mv などがファイルを予測不能に変更する可能性があるため。
  • formatFileContentWithLineNumbers:79 — スライス、行番号付与、「Showing lines X-Y of Z」ヒントを添える。
  • ReadFile class:142name = ClineDefaultTool.FILE_READ
  • dedup cache:298-356 — mtime 比較 + readCount 累積、3 回目からは DUPLICATE READ 警告を返す。
  • extract + cache:359-373extractFileContent を呼ぶ(画像は imageBlock を返す)。失敗時は tool error にし、上位に例外を投げない。
  • determineSearchPaths:35 — マルチワークスペース下で hint または全ワークスペースを基に検索パスを展開する。
  • executeSearch:74regexSearchFiles(ripgrep)を呼び、clineIgnoreController で結果をフィルタする。
  • formatSearchResults:120 — マルチワークスペース時は workspace 名でバケット分け、単一ワークスペース時は直接返す。
  • listFiles call:100listFiles(absolutePath, recursive, 200) が [files, didHitLimit] を返す。

データフロー

ExecuteCommand は四つの中で最も複雑で、核心は承認ゲートとタイムアウト解決にある。モデルが与えた requires_approval + command 文字列がどの承認パスを通るかを決める:

typescript
// apps/vscode/src/core/task/tools/handlers/ExecuteCommandToolHandler.ts
timeoutSeconds = resolveCommandTimeoutSeconds(
    command,
    timeoutParam,
    config.yoloModeToggled || config.vscodeTerminalExecutionMode === "backgroundExec",
)
// ...
if (
    config.isSubagentExecution ||
    (!requiresApprovalPerLLM && autoApproveSafe) ||
    (requiresApprovalPerLLM && autoApproveSafe && autoApproveAll)
) {
    // Auto-approve flow
    await config.callbacks.removeLastPartialMessageIfExistsWithType("ask", "command")
    await config.callbacks.say("command", actualCommand, undefined, undefined, false)
    didAutoApprove = true
} else {
    // Manual approval flow
    const didApprove = await ToolResultUtils.askApprovalAndPushFeedback(
        "command",
        actualCommand + `${autoApproveSafe && requiresApprovalPerLLM ? COMMAND_REQ_APP_STRING : ""}`,
        config,
    )
    if (!didApprove) {
        return formatResponse.toolDenied()
    }
}

autoApprover.shouldAutoApproveTool[autoApproveSafe, autoApproveAll] のタプルを返す:前者は「safe コマンド自動承認」、後者は「all コマンド自動承認」。モデルが risky(requires_approval=true)と言い、かつ safe 自動承認しか設定されていない時は、手動承認に回り、コマンドの後に強い承認プロンプト文字列を追加する(auto-approve logic:223-227)。承認が通った後、PreToolUse hook、そして 30 秒通知タイマー(自動承認 + 通知オン時のみ設定)、最後に executeCommandTool(finalCommand, timeoutSeconds) が terminal で走る。完了後、fileReadCache が全体クリアされる。

ReadFileToolHandler の核心はキャッシュによる重複排除:

typescript
// apps/vscode/src/core/task/tools/handlers/ReadFileToolHandler.ts
const cacheKey = absolutePath.toLowerCase()
const cached = config.taskState.fileReadCache.get(cacheKey)
if (cached) {
    try {
        const stat = await import("node:fs/promises").then((fs) => fs.stat(absolutePath))
        if (stat.mtimeMs !== cached.mtime) {
            config.taskState.fileReadCache.delete(cacheKey)
        }
    } catch {
        config.taskState.fileReadCache.delete(cacheKey)
    }
}

mtime が変われば(ユーザーがエディタで手動編集したなど)evict し、変わらなければキャッシュを再利用する。キャッシュには内容を保存せずメモリを節約し、ヒット時もディスクから読み直す。readCount が 3 回を超えると DUPLICATE READ の強いヒントを返す。新規読み取り成功後、extractFileContent で内容を取得し(画像ファイルは imageBlock を userMessageContent にプッシュ)、mtime + readCount=1 をキャッシュに保存する。

SearchFiles と ListFiles はどちらもパス解決 + clineignore + 承認 + 実行 + フォーマットを行い、コード構造が似ている。SearchFiles はマルチワークスペース並列が追加されている:

typescript
// apps/vscode/src/core/task/tools/handlers/SearchFilesToolHandler.ts
const searchPromises = searchPaths.map(({ absolutePath, workspaceName, workspaceRoot }) =>
    this.executeSearch(config, absolutePath, workspaceName, workspaceRoot, regex, filePattern),
)
const searchResults = await Promise.all(searchPromises)
const results = this.formatSearchResults(config, searchResults, searchPaths)

regexSearchFiles は内部で ripgrep を呼び、結果は workspace 名でバケット分けして集計される。

境界と失敗

  • パラメータ欠け:execute_command で command / requires_approval が無い、read/search/list で path が無い、search で regex が無い場合はすべて consecutiveMistakeCount++ + sayAndCreateMissingParamError に進む(missing params:100-112)。
  • コマンド拒否:CLINE_COMMAND_PERMISSIONS が拒否した時は permissionDeniedError を返し、failedSegment や matchedPattern を付けてモデルが修正できる情報を提供する(permission denied:162-181)。
  • 長時間コマンド通知:auto-approve + 通知オン時、30 秒後に「Command is still running」のシステム通知を出し、ユーザーがフリーズしたと勘違いするのを防ぐ(timeout notification:294-303)。
  • 読みファイルが存在しない:extractFileContent が投げたエラーは toolError("Error reading file: ...") に catch され、Task 上層に投げない。モデルがエラーを見て自分でパスを修正する(read error:361-373)。
  • キャッシュの mtime 不一致:stat が失敗または mtime が変わった場合はどちらもキャッシュを evict し、次回は最新の内容を読めるようにする(mtime check:304-313)。
  • search path 解決失敗:parseWorkspaceInlinePath がエラーを投げた時は Error resolving search path: ... を返し、mistake++ する(path resolution error:233-242)。
  • list files 上限超過:listFiles がエラーを投げる、またはパスが不正な場合は Error listing files: ... を返す。成功時の didHitLimit は formatFilesList がヒントに変換する(list error:101-105)。
  • 子 agent は UI をスキップ:四つの handler はすべて isSubagentExecution 時に partial say と ask フローをスキップし、直接最後まで仕事をして返す(subagent skip:155-157)。

まとめ

この四つの handler は Cline の「目と手」である:ExecuteCommand はシェルを走らせ、ReadFile はディスクを読み、SearchFiles は ripgrep を走らせ、ListFiles はディレクトリをリストする。「検証 → 承認 → hook → 実行 → テレメトリ」という骨格を共有し、違いは実行詳細にある:execute_command にはコマンド分類タイムアウトと二重承認ゲートがあり、read_file には mtime 重複排除キャッシュがあり、search はマルチワークスペース並列をサポートし、list には 200 件上限がある。すべてのツールで consecutiveMistakeCount は成功後にゼロになり、失敗が累積して YOLO 上限に達すると停止する。

さらに掘り下げるなら次へ:

  • 書き込みツール:/edit-tools/write-to-file
  • 複数ファイルパッチ:/edit-tools/apply-patch
  • ブラウザツール:/cap-tools/browser
  • Web fetch/search:/cap-tools/web

公式資料:Cline 文档 · README