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
| Benefit | CLI Tools | filesystem_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.
Find all Python files (500 files):
glob_files: avg=0.025s
find: avg=0.009s
Ratio: 2.7x slower
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.
pytest shared/plugins/filesystem_query/tests/test_benchmarks.py -v -s
❌ 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):
- Runtime config passed to
expose_tool() - Config file at
.jaato/filesystem_query.json - Hardcoded defaults
exclude_patterns
Additional glob patterns to exclude from searches.
| Type | list[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.
| Type | list[str] |
| Default | [] |
max_results
Maximum files or matches to return.
| Type | int |
| Default | 500 |
max_file_size_kb
Skip files larger than this for grep (in KB).
| Type | int |
| Default | 1024 (1MB) |
timeout_seconds
Auto-background threshold for long searches.
| Type | int |
| Default | 30 |
// .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
}
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
# 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
| Name | Type | Required | Description |
|---|---|---|---|
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
| Field | Type | Description |
|---|---|---|
files | array | Matching files with metadata |
total | int | Total matches found |
returned | int | Files returned (may be less if truncated) |
truncated | bool | True if results were limited |
root | string | Search root directory |
pattern | string | Pattern used |
File Object
| Field | Type | Description |
|---|---|---|
path | string | Relative path from root |
absolute_path | string | Full path |
size | int | File size in bytes |
modified | string | ISO timestamp |
glob_files(pattern="**/*.py")
{
"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"
}
# 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
| Name | Type | Required | Description |
|---|---|---|---|
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
| Field | Type | Description |
|---|---|---|
matches | array | Matching lines with context |
total_matches | int | Total matches found |
files_with_matches | int | Files containing matches |
files_searched | int | Total files searched |
truncated | bool | True if results were limited |
Match Object
| Field | Type | Description |
|---|---|---|
file | string | Relative file path |
line | int | Line number (1-indexed) |
column | int | Column of match start |
text | string | Full line content |
match | string | Matched text |
context_before | array | Lines before match |
context_after | array | Lines after match |
grep_content(
pattern=r"def process_\w+",
file_glob="*.py",
context_lines=2
)
{
"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"
}
# 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
- Search starts in foreground
- If timeout exceeded, moves to background
- Returns a task handle for status checking
- Model can poll for results
Configuration
Set timeout_seconds to control when auto-backgrounding
triggers. Default is 30 seconds.
# 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,
})