Installation #

Install ez-search globally to use the CLI, or as a project dependency for the library API.

Global (CLI)

$ npm install -g @ez-corp/ez-search

Project dependency (Library)

$ npm install @ez-corp/ez-search

Requires Node.js >= 20. ESM only.

Quick Start #

1 Install

npm install -g @ez-corp/ez-search

2 Index

ez-search index .

3 Search

ez-search query "authentication logic"

ez-search index #

Index a directory for semantic search. Scans files, splits them into chunks, and generates embeddings stored locally in .ez-search/.

ez-search index <path>

Flags

--no-ignore
Disable .gitignore and .cursorignore filtering
--type <type>
Filter files by type: code | text | image
--quiet, -q
Suppress status output
--clear
Remove existing index before indexing
--format <mode>
Output format: json (default) or text
Default: json

Examples

Index the current directory

ez-search index .

Index only code files

ez-search index . --type code

Fresh re-index with quiet output

ez-search index . --clear -q

ez-search query #

Search the index with a natural language query. Returns ranked results grouped by type (code, text, image).

ez-search query <text>

Flags

--top-k <n>, -k
Number of results to return
Default: 10
--dir <path>
Scope search to a subdirectory
--threshold <score>
Minimum relevance score (0-1) to include
--type <type>
Search specific type only: code | text | image
--no-auto-index
Disable automatic indexing when no index exists
--format <mode>
Output format: json (default) or text
Default: json

Examples

Search for authentication logic

ez-search query "authentication logic"

Top 5 code results in src/

ez-search query "error handling" --type code -k 5 --dir src

High-confidence results only

ez-search query "database connection" --threshold 0.7

ez-search status #

Show indexing status for the current directory, including file counts, staleness, and per-type breakdown.

ez-search status

Flags

--no-ignore
Disable .gitignore and .cursorignore filtering
--format <mode>
Output format: json (default) or text
Default: json

Examples

Check index status

ez-search status

Status as text

ez-search status --format text

index() #

Index a directory for semantic search. Returns statistics about what was scanned, indexed, and stored.

async function index(
  targetPath: string,
  options?: IndexOptions
): Promise<IndexStats>

Parameters

targetPath
string
Directory to index
options.ignore?
boolean
Respect .gitignore (default: true)
options.type?
'code' | 'text' | 'image'
Filter by file type
options.clear?
boolean
Wipe existing index before indexing

Returns

Promise<IndexStats> — Statistics about indexed files, chunks created/reused, and duration.

Examples

Basic indexing

import { index } from '@ez-corp/ez-search';

const stats = await index('/path/to/project');
console.log(`Indexed ${stats.filesIndexed} files in ${stats.durationMs}ms`);

Index only code files with fresh start

const stats = await index('.', { type: 'code', clear: true });

query() #

Search the index with a natural language query. Returns grouped results with code, text, and image arrays.

async function query(
  text: string,
  options?: QueryOptions
): Promise<QueryResult>

Parameters

text
string
Natural language search query
options.projectDir?
string
Project directory (default: cwd)
options.topK?
number
Results per type (default: 10)
options.dir?
string
Scope to a subdirectory
options.threshold?
number
Minimum relevance 0-1
options.type?
'code' | 'text' | 'image'
Search specific type only
options.autoIndex?
boolean
Auto-index if missing (default: true)

Returns

Promise<QueryResult> — Results grouped by type, with scores and file locations.

Examples

Search and display code results

import { query } from '@ez-corp/ez-search';

const results = await query('authentication logic', {
  projectDir: '/path/to/project',
  topK: 5,
});

for (const match of results.code) {
  console.log(`${match.file}:${match.lines.start}-${match.lines.end} (score: ${match.score})`);
}

Search with threshold filter

const results = await query('database connection', {
  threshold: 0.7,
  type: 'code',
});

status() #

Get indexing status for a project directory. Returns file/chunk counts, staleness info, and per-type breakdown.

async function status(
  options?: StatusOptions
): Promise<StatusResult>

Parameters

options.projectDir?
string
Project directory (default: cwd)
options.ignore?
boolean
Respect .gitignore (default: true)

Returns

Promise<StatusResult> — Index status with file counts, storage size, and type breakdown.

Examples

Check index health

import { status } from '@ez-corp/ez-search';

const info = await status({ projectDir: '/path/to/project' });
console.log(`${info.fileCount} files, ${info.chunkCount} chunks`);
console.log(`Last indexed: ${info.lastIndexed}`);

if (info.staleFileCount > 0) {
  console.warn(`${info.staleFileCount} files have changed since last index`);
}

Error Handling #

Library functions throw EzSearchError on failure. Each error includes a machine-readable code and a human-readable suggestion.

import { index, EzSearchError } from '@ez-corp/ez-search';

try {
  await index('/path/to/project');
} catch (err) {
  if (err instanceof EzSearchError) {
    console.error(`[${err.code}] ${err.message}`);
    console.error(`Suggestion: ${err.suggestion}`);
  } else {
    throw err;
  }
}

Error Codes

NO_INDEX
No index found for the project
Run index() or ez-search index first
EMPTY_DIR
No supported files found in directory
Check the path and file extensions
UNSUPPORTED_TYPE
Invalid file type filter
Use "code", "text", or "image"
CORRUPT_MANIFEST
Index manifest exists but data is missing
Re-index with --clear flag
GENERAL_ERROR
Unexpected error during operation
Check the error message for details

Types #

All types are exported from the package and available for TypeScript projects.

IndexStats

interface IndexStats {
  status: string;
  path: string;
  filesScanned: number;
  filesIndexed: number;
  filesSkipped: number;
  chunksCreated: number;
  chunksReused: number;
  chunksRemoved: number;
  durationMs: number;
  storageDir: string;
}

IndexOptions

interface IndexOptions {
  ignore?: boolean;
  type?: 'code' | 'text' | 'image';
  clear?: boolean;
}

QueryResult

interface QueryResult {
  query: string;
  totalIndexed: number;
  searchScope: string;
  indexing?: { status: string; filesIndexed: number; durationMs: number };
  stale?: boolean;
  staleFileCount?: number;
  code: CodeQueryResult[];
  text: TextQueryResult[];
  image: ImageQueryResult[];
}

CodeQueryResult

interface CodeQueryResult {
  file: string;
  lines: { start: number; end: number };
  score: number;
  text: string;
}

TextQueryResult

interface TextQueryResult {
  file: string;
  score: number;
  text: string;
}

ImageQueryResult

interface ImageQueryResult {
  file: string;
  score: number;
}

QueryOptions

interface QueryOptions {
  projectDir?: string;
  topK?: number;
  dir?: string;
  threshold?: number;
  type?: 'code' | 'text' | 'image';
  autoIndex?: boolean;
}

StatusResult

interface StatusResult {
  fileCount: number;
  chunkCount: number;
  lastIndexed: string;
  modelTypes: string[];
  indexSizeBytes: number;
  storagePath: string;
  staleFileCount: number;
  byType: Record<'code' | 'text' | 'image', TypeBreakdown>;
  warning?: string;
  suggestion?: string;
}

TypeBreakdown

interface TypeBreakdown {
  files: number;
  chunks: number;
}

StatusOptions

interface StatusOptions {
  projectDir?: string;
  ignore?: boolean;
}

EzSearchError

class EzSearchError extends Error {
  readonly code: ErrorCode;
  readonly suggestion: string;

  constructor(code: ErrorCode, message: string, suggestion: string);
}

ErrorCode

type ErrorCode =
  | 'NO_INDEX'
  | 'EMPTY_DIR'
  | 'UNSUPPORTED_TYPE'
  | 'CORRUPT_MANIFEST'
  | 'GENERAL_ERROR';

FileType

type FileType = 'code' | 'text' | 'image';

Supported File Types #

ez-search categorizes files into three types based on extension.

TypeExtensions
Code.ts .tsx .js .jsx .py .go .rs .java .c .cpp .h .hpp .rb .php .swift .kt .scala .sh .bash .zsh .css .scss .html .json .yaml .yml .toml
Text.md .mdx .txt .rst .csv .pdf
Image.jpg .jpeg .png .gif .webp .svg

Built-in Exclusions

These paths and patterns are always excluded from indexing:

node_modules.gitdistbuild.next.nuxt.cachecoverage.nyc_output*.lock.DS_StoreThumbs.db*.min.js*.min.css*.map.ez-search

Storage #

ez-search stores all index data locally in a .ez-search/ directory at the root of your project.

.ez-search/
├── manifest.json    # File metadata and hashes
├── code.bin         # Code embedding vectors
├── text.bin         # Text embedding vectors
└── image.bin        # Image embedding vectors
  • - Add .ez-search/ to your .gitignore — it should not be committed.
  • - Delete .ez-search/ to remove all index data. Re-run ez-search index to rebuild.
  • - Index data is machine-local. Embeddings are not portable across different machines.