Filesystem Query Plugin

Read-only tools for exploring the filesystem. Find files with glob patterns and search content with regular expressions. Auto-approved and background-capable.

Name filesystem_query
Type Tool Plugin (Registry-managed)
Tools Provided glob_files, grep_content
User Commands None
Auto-approved All tools (read-only)

Features

  • Glob Patterns: Find files with patterns like **/*.py
  • Regex Search: Search file contents with regular expressions
  • Structured Output: JSON responses with metadata
  • Smart Exclusions: Skips node_modules, __pycache__, etc.
  • Background Support: Auto-backgrounds long searches
  • Configurable: Customize exclusions, limits, and timeouts

Primary Use Case

Enables models to be self-sufficient when locating files without requiring users to provide exact paths. The model can explore the codebase to find relevant files before reading or editing them.

Performance Trade-offs

Let's be honest: Native CLI tools (find, grep) are faster—they're written in C and highly optimized. This plugin typically runs 2-5x slower than equivalent CLI commands.

Why It's Still Worth It

BenefitCLI Toolsfilesystem_query
Output format Plain text, needs parsing Structured JSON with metadata
Exclusions Manual --exclude flags Built-in (node_modules, .git, etc.)
Shell escaping Complex quoting rules Direct patterns, no escaping
Permissions Requires approval Auto-approved (read-only)
Binary files Can output garbage Automatically skipped

When Exclusions Help

Automatic exclusions can make this plugin faster than naive CLI usage. When users forget --exclude-dir=node_modules, they pay the price.

Benchmark: glob_files vs find
Find all Python files (500 files):
glob_files:  avg=0.025s
find:        avg=0.009s
Ratio: 2.7x slower
Exclusion efficiency
Find JS files (with node_modules):
glob_files (auto-exclude):  0.031s  (50 files)
find (no exclusions):       0.089s  (250 files)
find (with exclusions):     0.028s  (50 files)

When node_modules is heavy, auto-exclusions
can actually be faster than naive CLI usage.
Run benchmarks
pytest shared/plugins/filesystem_query/tests/test_benchmarks.py -v -s
When to use CLI instead
❌ Performance-critical batch operations
❌ Multi-gigabyte directories
❌ Simple one-off human searches

✅ Model autonomously exploring code
✅ Projects with heavy node_modules
✅ When structured output matters
✅ Safe, no-permission-needed discovery

Configuration

Configuration can come from three sources (in priority order):

  1. Runtime config passed to expose_tool()
  2. Config file at .jaato/filesystem_query.json
  3. Hardcoded defaults

exclude_patterns

Additional glob patterns to exclude from searches.

Typelist[str]
Default[]

exclude_mode

How to handle exclusions.

Type"extend" | "replace"
Default"extend"

extend adds to defaults; replace uses only your patterns.

include_patterns

Force-include patterns that override exclusions.

Typelist[str]
Default[]

max_results

Maximum files or matches to return.

Typeint
Default500

max_file_size_kb

Skip files larger than this for grep (in KB).

Typeint
Default1024 (1MB)

timeout_seconds

Auto-background threshold for long searches.

Typeint
Default30
Config file example
// .jaato/filesystem_query.json
{
  "version": "1.0",
  "exclude_patterns": ["vendor", "third_party"],
  "exclude_mode": "extend",
  "include_patterns": ["node_modules/@mycompany"],
  "max_results": 500,
  "max_file_size_kb": 1024,
  "timeout_seconds": 30,
  "context_lines": 2
}
Default exclusions
Version control:
  .git, .svn, .hg, .bzr

JavaScript/Node:
  node_modules, bower_components

Python:
  __pycache__, .venv, venv, .tox
  .mypy_cache, .pytest_cache

Build artifacts:
  dist, build, out, target

IDEs:
  .idea, .vscode

Minified:
  *.min.js, *.min.css
Override exclusions
# Add to defaults
config={
    'exclude_patterns': ['custom_dir'],
    'exclude_mode': 'extend',
}

# Replace all defaults
config={
    'exclude_patterns': ['only_this'],
    'exclude_mode': 'replace',
}

# Force-include despite exclusions
config={
    'include_patterns': ['node_modules/@company'],
}

glob_files Tool

Find files matching a glob pattern.

Parameters

NameTypeRequiredDescription
pattern string Yes Glob pattern (e.g., **/*.py)
root string No Root directory (default: cwd)
max_results int No Max files to return
include_hidden bool No Include hidden files (default: false)

Response Fields

FieldTypeDescription
filesarrayMatching files with metadata
totalintTotal matches found
returnedintFiles returned (may be less if truncated)
truncatedboolTrue if results were limited
rootstringSearch root directory
patternstringPattern used

File Object

FieldTypeDescription
pathstringRelative path from root
absolute_pathstringFull path
sizeintFile size in bytes
modifiedstringISO timestamp
Example: Find Python files
glob_files(pattern="**/*.py")
Response
{
  "files": [
    {
      "path": "src/main.py",
      "absolute_path": "/home/user/project/src/main.py",
      "size": 1234,
      "modified": "2025-01-15T10:30:00"
    },
    {
      "path": "tests/test_main.py",
      "absolute_path": "/home/user/project/tests/test_main.py",
      "size": 856,
      "modified": "2025-01-14T15:45:00"
    }
  ],
  "total": 2,
  "returned": 2,
  "truncated": false,
  "root": "/home/user/project",
  "pattern": "**/*.py"
}
Common patterns
# All Python files
glob_files(pattern="**/*.py")

# Test files
glob_files(pattern="**/test_*.py")

# Config files
glob_files(pattern="**/*.{json,yaml,toml}")

# In specific directory
glob_files(pattern="src/**/*.ts")

# Include hidden files
glob_files(pattern="**/*", include_hidden=True)

grep_content Tool

Search file contents using regular expressions.

Parameters

NameTypeRequiredDescription
pattern string Yes Regex pattern to search
path string No File or directory to search (default: cwd)
file_glob string No Only search matching files
context_lines int No Lines of context (default: 2)
case_sensitive bool No Case-sensitive (default: true)
max_results int No Max matches to return

Response Fields

FieldTypeDescription
matchesarrayMatching lines with context
total_matchesintTotal matches found
files_with_matchesintFiles containing matches
files_searchedintTotal files searched
truncatedboolTrue if results were limited

Match Object

FieldTypeDescription
filestringRelative file path
lineintLine number (1-indexed)
columnintColumn of match start
textstringFull line content
matchstringMatched text
context_beforearrayLines before match
context_afterarrayLines after match
Example: Find function definitions
grep_content(
    pattern=r"def process_\w+",
    file_glob="*.py",
    context_lines=2
)
Response
{
  "matches": [
    {
      "file": "src/utils.py",
      "absolute_path": "/home/user/project/src/utils.py",
      "line": 42,
      "column": 1,
      "text": "def process_data(input):",
      "match": "def process_data",
      "context_before": ["", "class DataProcessor:"],
      "context_after": ["    '''Process input data.'''", "    return transform(input)"]
    }
  ],
  "total_matches": 1,
  "files_with_matches": 1,
  "files_searched": 15,
  "truncated": false,
  "pattern": "def process_\\w+",
  "path": "/home/user/project",
  "file_glob": "*.py"
}
Common searches
# Find class definitions
grep_content(pattern=r"class\s+\w+")

# Find TODO comments
grep_content(pattern="TODO|FIXME|HACK")

# Find imports
grep_content(pattern=r"import\s+requests")

# Case-insensitive search
grep_content(
    pattern="error",
    case_sensitive=False
)

# Search specific file types
grep_content(
    pattern="async def",
    file_glob="*.py"
)

Background Execution

Both tools support background execution for long-running searches. If a search exceeds the configured timeout threshold, it automatically moves to background execution.

How It Works

  1. Search starts in foreground
  2. If timeout exceeded, moves to background
  3. Returns a task handle for status checking
  4. Model can poll for results

Configuration

Set timeout_seconds to control when auto-backgrounding triggers. Default is 30 seconds.

Configure background threshold
# Longer threshold for patient users
registry.expose_tool('filesystem_query', config={
    'timeout_seconds': 60,
})

# Shorter threshold for responsiveness
registry.expose_tool('filesystem_query', config={
    'timeout_seconds': 10,
})