find data types: inputs and outputs
Both find tools are driven by plain, serde-derived structs that double as
the JSON schema for the MCP tool arguments. This page is the reference for
those types. It is organized in three parts:
- Request types — what you pass in to
globandgrep. - Config structs — the internal
Glob/Grepoption bundles. - Response types — what you get back.
Request types
GlobInput — the find_glob arguments
pub struct GlobInput {
pub pattern: String, // e.g. "**/*.rs", "src/**", "*.toml"
pub path: Option<String>, // a root, glob, or literal file/dir
pub paths: Option<Vec<String>>, // multiple targets; overrides `path`
pub file_type: Option<String>, // "file" | "dir" | "symlink"
pub recursive: Option<bool>, // default: derived from pattern shape
pub hidden: Option<bool>, // effective default: true
pub max_results: Option<u32>, // default 200, ceiling 200
pub gitignore: Option<bool>, // effective default: true
pub sort_by_mtime: Option<bool>,// default: true (most recent first)
pub format: Option<String>, // "flat" | "grouped" | "tree"
pub timeout_ms: Option<u32>, // default 5000; partials on expiry
}
pattern and path/paths are both optional in effect: when a target carries
its own glob characters (src/*.rs), the target’s glob wins and pattern is
ignored. When the target is a plain directory, pattern applies within it.
See glob for the full rules.
GrepInput — the find_grep arguments
pub struct GrepInput {
pub pattern: String, // regex to match in file contents
pub path: String, // root directory to search
pub paths: Option<Vec<String>>, // multiple targets; overrides `path`
pub line_range: Option<String>, // "start-end", 1-based inclusive, single-file only
pub glob: Option<String>, // restrict by file-name glob, e.g. "*.rs"
pub file_type: Option<String>, // restrict by language, e.g. "rust"
pub ignore_case: Option<bool>, // default: false
pub max_count: Option<u32>, // match cap; disables file-window paging
pub skip: Option<u32>, // files to skip — page past the window
pub context_before: Option<u32>,// context lines before each match
pub context_after: Option<u32>, // context lines after each match
pub hidden: Option<bool>, // effective default: true
pub gitignore: Option<bool>, // effective default: true
pub timeout_ms: Option<u32>, // default 5000; partials on expiry
}
Config structs
Glob and Grep are the internal option bundles the free functions accept.
They mirror the input fields above (minus pattern/path, which are separate
arguments) and implement Default so you can build them incrementally:
let glob = Glob { file_type: Some("dir".into()), max_results: Some(20), ..Default::default() };
cosh_tools::find::glob(&glob, "**", "src")?;
Caveat: the free-function structs are raw config. Fields you leave
Nonefall through to the SDK’s own defaults, which differ from theFindwrapper’s reference defaults for glob:hiddendefaults tofalseand results are uncapped (nomax_resultsceiling, nolimit_reached). The wrapper (Find) applieshidden: trueand the200/200cap; prefer it unless you are deliberately tuning the raw engine.
GlobCallOptions is the schema-driven bundle for Find::glob_full, so the
call signature stays small as the schema grows. It carries file_type,
hidden, gitignore, max_results, format, sort_by_mtime, and
timeout_ms — each Option, falling back to the builder value, then to the
tool default.
Response types
GlobEntry and GlobOutput
pub struct GlobEntry {
pub path: String, // CWD-relative (or root-relative), `/`-separated
pub file_type: String, // "file" | "dir" | "symlink"
pub mtime_ms: Option<f64>, // mtime as ms since the Unix epoch
pub size_bytes: Option<f64>, // file size; None for dirs/symlinks
}
pub struct GlobOutput {
pub matches: Vec<GlobEntry>,
pub total: u32,
pub limit_reached: Option<bool>, // cap cut the list; more may exist
pub timed_out: Option<bool>, // partial results; incomplete scan
pub note: Option<String>,
pub useless: Option<bool>, // zero matches, no timeout
pub missing_paths: Option<Vec<String>>, // skipped missing targets
pub formatted: String, // paths in flat/grouped/tree layout
pub scope: String, // directory the search was scoped to
pub cwd: Option<String>, // working dir paths are relative to
}
formatted is always present, even for empty results — the model never has
to reconstruct grouping from the structured entries. When no format was
requested it is the plain newline-joined paths. Directories are rendered with a
trailing /.
scope is the directory the search was scoped to, in the same relative form as
the match paths (., src/, crates/…); cwd lets the TUI renderer resolve
match paths to absolute paths for file hyperlinks.
GrepMatchEntry, ContextEntry, GrepFileEntry, GrepOutput
pub struct ContextEntry {
pub line_number: u32, // 1-indexed
pub line: String,
}
pub struct GrepMatchEntry {
pub path: String, // absolute (single-file) or root/ancestor-relative
pub line_number: u32, // 1-indexed
pub line: String,
pub truncated: Option<bool>, // line was cut to the 200-char column limit
pub context_before: Vec<ContextEntry>,
pub context_after: Vec<ContextEntry>,
}
pub struct GrepFileEntry {
pub path: String, // same form as the match paths
pub file_hash: String, // 4-hex tag — the `file_hash` for `fs_edit`
pub header: String, // "¶abs/path#TAG" — the hashline anchor
}
pub struct GrepOutput {
pub matches: Vec<GrepMatchEntry>,
pub total_matches: u32, // dedup per-line union (lower bound if capped)
pub files_with_matches: u32,
pub files_searched: u32,
pub file_limit_reached: bool, // more files matched than the shown window
pub per_file_limit_reached: bool, // a hot file exceeded its match cap
pub note: Option<String>,
pub useless: Option<bool>,
pub files: Vec<GrepFileEntry>, // hashline anchors for shown files
pub timed_out: Option<bool>,
}
total_matches is the deduplicated per-line union across targets before the
per-file caps and window trim (so two matches on the same line of the same file
count once; itself bounded by the engine’s per-file fetch and per-target
ceiling) — a reliable lower bound even when matches were trimmed. With
line_range, it is the count of in-range matches.
The files array is the bridge to editing: each shown file within the anchor
window (the first 20 in encounter order) carries a path, a file_hash, and a
header like ¶/abs/path#TAG. Pair a match’s path with the matching
file_hash and pass both to fs_edit — no re-read needed. See
grep.