These enhancements transform recur from a hierarchical file search tool into a lightweight code intelligence platform, supporting workflows like "find definition → find callers → trace usage".
Common workflow in large codebases:
- Find a method definition:
recur find "DeleteGameComponentAsync" - Find who calls it: Manual grep/search through results
- Trace call chain: Repeat for each caller
This is tedious and requires multiple search operations.
Find function calls and invocations within hierarchical scopes.
Find all locations that call a given function/method.
# Find who calls DeleteGameComponentAsync within DynamicGameComponentService
recur callers "DeleteGameComponentAsync" \
--scope "User Level Up Services\\DynamicGameComponentService.*" \
--ext ".cs"Output:
User Level Up Services\DynamicGameComponentService.Handlers.cs:42
await DeleteGameComponentAsync(componentId);
User Level Up Services\DynamicGameComponentService.Cleanup.cs:87
result = DeleteGameComponentAsync(id, force: true);
Found 2 call sites
Find all functions/methods called by a given function.
# Find what ApplyAiContent calls
recur callees "ApplyAiContent" \
--scope "User Level Up\\Controllers\\LevelController.*" \
--ext ".cs"Output:
User Level Up\Controllers\LevelController.CreateWizard3.cs:156
→ ValidateAiContent(content)
→ ProcessQuestions(aiData.Questions)
→ SaveToDatabase(processed)
Found 3 callees in ApplyAiContent
Heuristic-based (Phase 1):
- Regex patterns for common call syntax:
- C#:
methodName(...),await methodName(...),object.methodName(...) - JavaScript:
functionName(...),obj.method(...) - Python:
function_name(...),self.method(...)
- C#:
- Fast, no compilation required
- ~80% accuracy (good enough for exploration)
AST-based (Phase 2 - Future):
- Use tree-sitter for accurate parsing
- Language-specific parsers
- 99% accuracy
- Slower, requires language detection
recur callers <SYMBOL> [OPTIONS]
Find call sites for a function/method
Arguments:
<SYMBOL> Function/method name to find callers for
Options:
--scope <PATTERN> Limit search to hierarchical scope
--ext <EXT> Filter by file extension
-C <NUM> Show N lines of context
--json Output as JSON
-d, --dir <DIR> Directory to search
--language <LANG> Hint language (auto-detected if omitted)
-h, --help Print help
recur callees <SYMBOL> [OPTIONS]
Find what a function/method calls
Arguments:
<SYMBOL> Function/method name to find callees of
Options:
(same as callers)
{
"symbol": "DeleteGameComponentAsync",
"call_sites": [
{
"file": "User Level Up Services\\DynamicGameComponentService.Handlers.cs",
"line": 42,
"column": 10,
"context": "await DeleteGameComponentAsync(componentId);",
"caller_function": "ProcessDeletion"
}
],
"total_sites": 2
}Finding where a symbol is defined requires:
- Manual grep for "class SymbolName" or "function SymbolName"
- Filtering through results
- Multiple patterns for different languages
Lightweight symbol indexing - "ctags-lite" with hierarchical scoping.
Find definition(s) of a symbol.
# Find where DeleteGameComponentAsync is defined
recur def "DeleteGameComponentAsync"Output:
User Level Up Services\DynamicGameComponentService.cs:234
public async Task DeleteGameComponentAsync(int id)
Found 1 definition
With context:
recur def "DeleteGameComponentAsync" -C 3Output:
User Level Up Services\DynamicGameComponentService.cs:232-237
232 /// <summary>Soft-deletes a game component</summary>
233 /// <param name="id">Component ID</param>
234: public async Task DeleteGameComponentAsync(int id)
235 {
236 var component = await _db.Components.FindAsync(id);
237 component.IsDeleted = true;
Find all references/usages of a symbol.
# Find all usages of DeleteGameComponentAsync
recur refs "DeleteGameComponentAsync"Output:
User Level Up Services\DynamicGameComponentService.cs:234
[DEFINITION] public async Task DeleteGameComponentAsync(int id)
User Level Up Services\DynamicGameComponentService.Handlers.cs:42
[CALL] await DeleteGameComponentAsync(componentId);
User Level Up Services\DynamicGameComponentService.Tests.cs:156
[CALL] await service.DeleteGameComponentAsync(testId);
Found 1 definition, 2 references
recur def <SYMBOL> [OPTIONS]
Find definition(s) of a symbol
Arguments:
<SYMBOL> Symbol name (class, function, method, etc.)
Options:
--scope <PATTERN> Limit search to hierarchical scope
--ext <EXT> Filter by file extension
-C <NUM> Show N lines of context
--json Output as JSON
--all Show all definitions (don't stop at first)
-d, --dir <DIR> Directory to search
-h, --help Print help
recur refs <SYMBOL> [OPTIONS]
Find all references to a symbol
Arguments:
<SYMBOL> Symbol name to find references for
Options:
(same as def, plus:)
--include-def Include definition in results (default: true)
--only-calls Only show call sites, not definitions
Phase 1: Regex-based
- Pattern matching for common definition syntax:
- C#:
class|interface|struct SymbolName,public.*SymbolName\( - JavaScript:
class SymbolName,function SymbolName,const SymbolName = - Python:
class SymbolName:,def symbol_name(
- C#:
- Fast, no dependencies
- ~75% accuracy
Phase 2: Symbol Index
- Build lightweight index on first run:
.recur/symbol-index.db - SQLite database with:
(symbol, file, line, type, scope) - Incremental updates based on file modification times
- Near-instant lookups
Phase 3: LSP Integration
- Leverage Language Server Protocol for 100% accuracy
- Optional, requires LSP server for language
- Perfect for IDE integration
{
"symbol": "DeleteGameComponentAsync",
"definitions": [
{
"file": "User Level Up Services\\DynamicGameComponentService.cs",
"line": 234,
"column": 25,
"type": "method",
"signature": "public async Task DeleteGameComponentAsync(int id)",
"scope": "DynamicGameComponentService"
}
],
"references": [
{
"file": "User Level Up Services\\DynamicGameComponentService.Handlers.cs",
"line": 42,
"column": 10,
"type": "call",
"context": "await DeleteGameComponentAsync(componentId);"
}
],
"total_definitions": 1,
"total_references": 2
}Repeatedly typing long hierarchical patterns is tedious:
User Level Up Services\\DynamicGameComponentService.*User Level Up\\Controllers\\LevelController.CreateWizard3.*
This slows down interactive workflows.
Define shortcuts for frequently-used scope patterns.
Create a named alias for a scope pattern.
# Define alias 'dgc' for DynamicGameComponentService
recur scope add dgc "User Level Up Services\\DynamicGameComponentService.*"
# Define alias 'cw3' for CreateWizard3 controller
recur scope add cw3 "User Level Up\\Controllers\\LevelController.CreateWizard3.*"
# Define alias 'ulu' for all User Level Up
recur scope add ulu "User Level Up**"List all defined scope aliases.
recur scope listOutput:
Defined scopes:
dgc → User Level Up Services\DynamicGameComponentService.*
cw3 → User Level Up\Controllers\LevelController.CreateWizard3.*
ulu → User Level Up**
Use with: recur find "pattern" --scope <alias>
Remove a scope alias.
recur scope remove dgcOnce defined, use aliases in any command:
# Find "Soft delete" within CreateWizard3 controller
recur find "Soft delete" --scope cw3 --ext ".cs"
# Find all files in DynamicGameComponentService
recur files --scope dgc
# Find callers within scope
recur callers "DeleteAsync" --scope dgc
# Tree view of scope
recur tree --scope ulurecur scope <SUBCOMMAND>
Manage scope aliases for hierarchical patterns
Subcommands:
add <NAME> <PATTERN> Create a scope alias
remove <NAME> Remove a scope alias
list List all scope aliases
show <NAME> Show expansion of a scope alias
Options:
--global Store globally (~/.recur/scopes)
--local Store in .recur/scopes (project-specific)
-h, --help Print help
Project-specific scopes (default):
- Stored in:
.recur/scopes.toml - Committed to version control
- Shared across team
Global scopes:
- Stored in:
~/.config/recur/scopes.toml(Linux/Mac) or%APPDATA%\recur\scopes.toml(Windows) - Personal shortcuts
Format (.recur/scopes.toml):
[scopes]
dgc = "User Level Up Services\\DynamicGameComponentService.*"
cw3 = "User Level Up\\Controllers\\LevelController.CreateWizard3.*"
ulu = "User Level Up**"# Setup (once per project)
recur scope add services "Services\\**"
recur scope add controllers "Controllers\\**"
recur scope add tests "**.Tests"
# Daily usage
recur find "async" --scope services
recur files --scope controllers --ext .cs
recur gaps --scope services
recur stats --scope testsCurrent JSON output varies by command, making it hard to:
- Parse consistently in scripts
- Build VS Code extensions
- Integrate with other tools
All commands support --json with consistent structure.
Base structure (all commands):
{
"command": "find",
"pattern": "DeleteGameComponentAsync",
"scope": "DynamicGameComponentService.*",
"options": {
"ext": ".cs",
"context_lines": 2
},
"results": [...],
"summary": {
"total_results": 42,
"total_files": 5,
"execution_time_ms": 127
}
}recur find --json:
{
"command": "find",
"pattern": "Soft delete",
"results": [
{
"file": "Services\\DynamicGameComponentService.cs",
"line": 234,
"column": 15,
"match_start": 15,
"match_end": 26,
"match_type": "literal",
"line_content": " // Soft delete the component",
"context_before": [
" if (component == null) return NotFound();",
""
],
"context_after": [
" component.IsDeleted = true;",
" await _db.SaveChangesAsync();"
]
}
],
"summary": {
"total_matches": 1,
"total_files": 1,
"execution_time_ms": 45
}
}recur files --json:
{
"command": "files",
"pattern": "UserService.**",
"results": [
{
"file": "Services\\UserService.cs",
"relative_path": "Services\\UserService.cs",
"depth": 0,
"extension": ".cs",
"size_bytes": 4521,
"modified": "2026-01-09T10:30:00Z"
},
{
"file": "Services\\UserService.Handlers.cs",
"relative_path": "Services\\UserService.Handlers.cs",
"depth": 1,
"extension": ".cs",
"size_bytes": 2341,
"modified": "2026-01-08T15:20:00Z"
}
],
"summary": {
"total_files": 2,
"execution_time_ms": 12
}
}recur def --json:
{
"command": "def",
"symbol": "DeleteGameComponentAsync",
"results": [
{
"file": "Services\\DynamicGameComponentService.cs",
"line": 234,
"column": 25,
"definition_type": "method",
"signature": "public async Task DeleteGameComponentAsync(int id)",
"scope": "DynamicGameComponentService",
"modifiers": ["public", "async"],
"return_type": "Task",
"parameters": [
{"name": "id", "type": "int"}
],
"snippet": "public async Task DeleteGameComponentAsync(int id)\n{\n var component = await _db.Components.FindAsync(id);"
}
],
"summary": {
"total_definitions": 1,
"execution_time_ms": 23
}
}recur gaps --json:
{
"command": "gaps",
"pattern": "**",
"results": [
{
"hierarchy_root": "README",
"gaps": [
{
"missing_file": "README.CORE.md",
"depth": 1,
"parent": {
"file": "README.md",
"depth": 0
},
"children": [
{
"file": "README.CORE.SECTION.md",
"depth": 2
}
]
}
]
}
],
"summary": {
"total_gaps": 1,
"total_missing_files": 1,
"execution_time_ms": 67
}
}- Consistent parsing - Same top-level structure across commands
- Rich metadata - File size, modified time, depth, etc.
- Tooling-friendly - Easy to consume in scripts/extensions
- Type-safe - Clear schema for code generation
- Extensible - Can add fields without breaking parsers
// TypeScript interface for recur JSON output
interface RecurResult {
command: string;
pattern: string;
scope?: string;
options: Record<string, any>;
results: Array<{
file: string;
line: number;
column?: number;
match_type?: string;
line_content?: string;
}>;
summary: {
total_results: number;
execution_time_ms: number;
};
}
// Parse recur output
const result: RecurResult = JSON.parse(stdout);
// Jump to first result
const firstMatch = result.results[0];
vscode.window.showTextDocument(
vscode.Uri.file(firstMatch.file),
{ selection: new vscode.Range(firstMatch.line, 0, firstMatch.line, 0) }
);When working with semantic/hierarchical naming in code (like keys):
ulu.lifecycle.deletedquestion.*,answer.*Section.*.visible
You need to:
- Find all occurrences
- Group by scope/file
- Count usage
- Ensure governance of naming conventions
Enhanced identifier search with tree visualization and usage counts.
Show hierarchical identifiers and their usage, grouped by scope.
# Show all 'ulu.lifecycle.*' keys and usage counts
recur id-tree "ulu.lifecycle.*" --ext ".cs"Output:
ulu.lifecycle
├── deleted (23 usages)
│ ├── DynamicGameComponentService.cs: 12
│ ├── ComponentCleanup.cs: 8
│ └── Tests.cs: 3
├── created (15 usages)
│ ├── ComponentFactory.cs: 10
│ └── Tests.cs: 5
└── updated (8 usages)
└── ComponentUpdater.cs: 8
Total: 3 identifier patterns, 46 total usages
Statistics on identifier usage patterns.
# Stats on question/answer keys
recur id-stats "question.*,answer.*" --ext ".cs"Output:
Identifier Statistics:
question.* (34 identifiers, 156 usages)
Most used: question.text (45), question.type (32), question.id (28)
Files: 12
Scopes: LevelController.*, QuestionService.*
answer.* (28 identifiers, 98 usages)
Most used: answer.text (38), answer.isCorrect (25), answer.id (20)
Files: 8
Scopes: LevelController.*, AnswerService.*
Section (12 usages)
Files: 4
Scopes: LevelController.CreateWizard3.*
recur id-tree <PATTERN> [OPTIONS]
Show hierarchical identifier usage in tree format
Arguments:
<PATTERN> Identifier pattern (e.g., "ulu.lifecycle.*")
Options:
--scope <PATTERN> Limit to hierarchical file scope
--ext <EXT> Filter by file extension
--min-usage <N> Only show identifiers used N+ times
--sort-by <FIELD> Sort by: usage|name|scope (default: usage)
--json Output as JSON
-d, --dir <DIR> Directory to search
-h, --help Print help
recur id-stats <PATTERNS> [OPTIONS]
Show usage statistics for identifier patterns
Arguments:
<PATTERNS> Comma-separated patterns (e.g., "question.*,answer.*")
Options:
(same as id-tree)
{
"command": "id-tree",
"pattern": "ulu.lifecycle.*",
"results": {
"ulu.lifecycle.deleted": {
"total_usages": 23,
"files": [
{
"file": "DynamicGameComponentService.cs",
"usages": 12,
"lines": [45, 67, 89, 123, ...]
},
{
"file": "ComponentCleanup.cs",
"usages": 8,
"lines": [23, 45, 67, 78, ...]
}
]
},
"ulu.lifecycle.created": {
"total_usages": 15,
"files": [...]
}
},
"summary": {
"total_identifiers": 3,
"total_usages": 46,
"total_files": 5
}
}Enforce naming conventions for semantic keys:
# Find all 'ulu.*' keys and ensure they follow convention
recur id-tree "ulu.*" --ext ".cs" --json > ulu-keys.json
# Script to validate:
# - All keys start with 'ulu.'
# - Second segment is valid category (lifecycle, state, config)
# - No orphaned single-usage keys (might be typos)- Scope aliases - Simple TOML storage, big productivity win
- Enhanced JSON output - Refactor existing JSON to consistent schema
recur def(regex-based) - Heuristic definition search
recur callers/callees(regex-based) - Heuristic call graphrecur refs(regex-based) - Combined def + usagesrecur id-tree- Identifier tree visualization
- Symbol index - SQLite-based caching for fast lookups
- AST-based parsing - Tree-sitter integration for accuracy
- LSP integration - Optional for 100% accuracy
| Feature | Benefit | Complexity |
|---|---|---|
callers/callees |
Fast call graph exploration | Medium |
def/refs |
Quick symbol navigation | Medium |
| Scope aliases | Productivity boost for repetitive scopes | Low |
| Consistent JSON | Enables VS Code extensions, automation | Low |
id-tree |
Governance for semantic naming | Medium |
- README.md - Main documentation
- FEATURE-gaps.md - Gap detection feature
- COMPARISON-powershell.md - PowerShell vs recur
These enhancements transform recur from a search tool into a lightweight code intelligence platform that:
- Understands code structure - Not just files, but symbols and calls
- Supports workflows - Definition → callers → callees → trace
- Boosts productivity - Scope aliases eliminate repetitive typing
- Enables automation - Consistent JSON for tooling
- Enforces governance - Track identifier usage patterns
The result is a tool that bridges the gap between simple text search (grep) and full IDEs (VS Code), optimized for hierarchical codebases.