{
"name": "ct-tree",
"description": "Walk a directory for chosen file types and report the effective file tree with per-file line, word, and character counts. Select files with --base/--name/--ext (--ext is a comma list of extensions added to --name as alternatives), filter with metric predicates (--min-lines/--max-lines/--min-words/--max-words/--min-chars/--max-chars) and per-folder predicates (--min-files-per-folder/--max-files-per-folder, counting matching files in a file's immediate directory), sort by path|name|lines|words|chars|ext (--desc for descending), and choose a summarisation level: --tree (indented tree with per-file counts and per-folder subtotals; default), --flat (one file per line: lines words chars path; best for ranked lists), or --summary (aggregates grouped by --group ext|dir|none). --json emits {tool, base, files:[{path,ext,lines,words,chars}], by_ext, totals}. Exit: 0 if any file is in the report, 1 if none, 2 on error. Read-only. Invoke as `ct tree ...` or `ct-tree ...`. Example: all *.rs files over 5000 lines sorted by line count descending = --ext rs --min-lines 5001 --flat --sort lines --desc.",
"input_schema": {
"type": "object",
"properties": {
"base": {
"type": "string",
"description": "Root directory to walk, relative or absolute. Default '.'.",
"default": "."
},
"name": {
"type": "string",
"description": "File-name pattern; '|'-separated alternatives, each substring->glob->regex promoted and anchored to the whole name."
},
"ext": {
"type": "array",
"items": { "type": "string" },
"description": "Restrict to these extensions (no dots), e.g. ['rs','toml']. Added to --name as alternatives. May be comma-joined."
},
"hidden": {
"type": "boolean",
"description": "Include dot-entries (names starting with '.'). Default: skipped."
},
"follow": {
"type": "boolean",
"description": "Follow symlinks while traversing."
},
"min-lines": { "type": "integer", "description": "Only include files with at least N lines." },
"max-lines": { "type": "integer", "description": "Only include files with at most N lines." },
"min-words": { "type": "integer", "description": "Only include files with at least N words." },
"max-words": { "type": "integer", "description": "Only include files with at most N words." },
"min-chars": { "type": "integer", "description": "Only include files with at least N characters." },
"max-chars": { "type": "integer", "description": "Only include files with at most N characters." },
"min-files-per-folder": {
"type": "integer",
"description": "Only include folders that directly contain at least N matching files."
},
"max-files-per-folder": {
"type": "integer",
"description": "Only include folders that directly contain at most N matching files."
},
"sort": {
"type": "string",
"enum": ["path", "name", "lines", "words", "chars", "ext"],
"description": "Sort key. Default 'path'. In --flat the sort is global; in --tree it orders entries within each folder."
},
"desc": {
"type": "boolean",
"description": "Sort descending instead of ascending."
},
"tree": {
"type": "boolean",
"description": "Output mode: indented file tree with per-file counts and per-folder subtotals. This is the default mode."
},
"flat": {
"type": "boolean",
"description": "Output mode: one matching file per line with its counts. Mutually exclusive with the other modes."
},
"summary": {
"type": "boolean",
"description": "Output mode: aggregate counts only, grouped by --group. Mutually exclusive with the other modes."
},
"group": {
"type": "string",
"enum": ["ext", "dir", "none"],
"description": "Grouping for --summary: by extension (default), by immediate directory, or a single grand total."
},
"json": {
"type": "boolean",
"description": "Emit a structured JSON result instead of text."
},
"timeout": {
"type": "number",
"description": "Abort with exit 2 (and a one-line message) if the report exceeds SECS seconds (fractional allowed)."
},
"heartbeat": {
"type": "number",
"description": "Print a liveness pulse every SECS seconds (fractional allowed) while the run is in progress."
},
"heartbeat-emit": {
"type": "string",
"description": "Heartbeat line template. Tokens: {ELAPSED} (whole seconds so far) {TOOL}. Default: \"[{ELAPSED}s]\"."
},
"heartbeat-to": {
"type": "string",
"enum": ["stderr", "stdout"],
"description": "Stream heartbeat pulses are written to. Default: stderr."
}
},
"required": []
}
}