Skip to main content
Loom provides three search tools for navigating and exploring codebases: file pattern matching, content search, and directory listing. Searches for files matching a glob pattern. Results are sorted by modification time (most recent first).
pattern
string
required
Glob pattern to match files. Examples:
  • "**/*.ex" - All Elixir files
  • "lib/**/*.ex" - Elixir files in lib/
  • "test/*_test.exs" - Test files in test/ (non-recursive)
  • "*.{ex,exs}" - Files with multiple extensions
path
string
Directory to search in, relative to project root. Defaults to project root.

Returns

Success response includes:
  • Count of matching files
  • List of relative file paths (sorted by modification time, newest first)
Found 12 file(s):
lib/loom/tools/file_read.ex
lib/loom/tools/file_write.ex
lib/loom/tools/file_edit.ex
...
If no files match:
No files matched pattern: **/*.py

Excluded Directories

The following directories are automatically excluded from search:
  • .git
  • _build
  • deps
  • node_modules
  • .elixir_ls
  • .lexical

Usage Examples

{:ok, result} = Loom.Tools.FileSearch.run(
  %{pattern: "**/*.ex"},
  %{project_path: "/home/user/project"}
)
Results are sorted by modification time (newest first), making it easy to find recently changed files.

Searches file contents for lines matching a regex pattern. Returns matches with file paths and line numbers.
pattern
string
required
Regex pattern to search for. Supports full Elixir/PCRE regex syntax:
  • "defmodule.*Router" - Modules containing “Router”
  • "def \\w+" - Function definitions
  • "TODO|FIXME" - Multiple alternatives
  • "@spec.*String.t" - Type specs with String
path
string
Directory to search in, relative to project root. Defaults to project root.
glob
string
default:"**/*"
File filter glob pattern:
  • "*.ex" - Only .ex files
  • "*.{ex,exs}" - Multiple extensions
  • "*_test.exs" - Test files
If glob doesn’t contain / or start with **, it’s automatically prefixed with **/.

Returns

Success response includes:
  • Count of matches
  • Truncation notice if 100+ matches found
  • Matches formatted as file:line_number:content
Found 5 match(es):
lib/loom/router.ex:12:  defmodule Loom.Router do
lib/my_app/router.ex:1:defmodule MyApp.Router do
test/router_test.exs:5:  alias Loom.Router
...

Limits

Results are capped at 100 matches to prevent overwhelming output. The response indicates if results were truncated:
Found 100 match(es) (truncated at 100):

Usage Examples

{:ok, result} = Loom.Tools.ContentSearch.run(
  %{pattern: "def \\w+\\("},
  %{project_path: "/home/user/project"}
)

Error Handling

Invalid regex patterns return descriptive errors:
Loom.Tools.ContentSearch.run(
  %{pattern: "def (unclosed"},
  context
)

# Returns:
{:error, "Invalid regex pattern: missing )"}

directory_list

Lists directory contents with file metadata (type, size, modification time).
path
string
required
Directory path relative to project root

Returns

Success response includes:
  • Directory path and entry count
  • Formatted listing with metadata
lib/loom/tools/ (10 entries)
  file     1.2KB  2024-01-15 10:30  file_read.ex
  file     0.8KB  2024-01-15 10:28  file_write.ex
  file     1.5KB  2024-01-15 10:32  file_edit.ex
   dir         0  2024-01-10 09:00  helpers/
  link       128  2024-01-12 14:20  alias.ex

Format Details

  • file - Regular file
  • dir - Directory (shown with trailing /)
  • link - Symbolic link
  • ??? - Unknown type
  • Bytes: 123B
  • Kilobytes: 45KB (1024+ bytes)
  • Megabytes: 1.2MB (1048576+ bytes)
Format: YYYY-MM-DD HH:MMBased on file modification time (mtime).

Usage Examples

{:ok, result} = Loom.Tools.DirectoryList.run(
  %{path: "."},
  %{project_path: "/home/user/project"}
)

Error Cases

enoent
Directory not found
{:error, "Directory not found: lib/nonexistent"}
enotdir
Path is a file, not a directory
{:error, "Not a directory: lib/my_app/router.ex"}
Use directory_list before file_write to verify target directories exist and check for conflicting files.

Common Search Patterns

Find Module Definitions

ContentSearch.run(
  %{pattern: "defmodule \\w+\\.Router"},
  context
)

Find Test Files

FileSearch.run(
  %{pattern: "**/*_test.exs"},
  context
)

Find Config Files

FileSearch.run(
  %{pattern: "config/*.exs"},
  context
)

Find Documentation

ContentSearch.run(
  %{
    pattern: "@moduledoc|@doc",
    glob: "*.ex"
  },
  context
)

Implementation Details

Search tools are implemented in lib/loom/tools/:

Build docs developers (and LLMs) love