> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reasonos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Search SDK

> Full-text content search, fuzzy file finder, and real-time file watching APIs built into the RBS platform

# Search SDK

RBS includes a powerful search engine built into every branch server. Search file contents, find files by name, and receive real-time file change notifications — all through a consistent API accessible from your editor or custom tooling.

## Overview

| Feature               | Description                                              | Protocol  |
| --------------------- | -------------------------------------------------------- | --------- |
| **Content search**    | Search text or regex patterns across file contents.      | REST API  |
| **Fuzzy file search** | Quick file finder by name (like `Cmd+P` in your editor). | REST API  |
| **Streaming search**  | Real-time search results via Server-Sent Events.         | SSE       |
| **File watcher**      | Real-time file change notifications.                     | WebSocket |

***

## Content search

Search for text or regex patterns across all files in your workspace. Results include line numbers, column positions, and configurable context lines.

### Basic search

```bash theme={null}
# Simple text search
rbs search "TODO"

# Search with file type filter
rbs search "TODO" --include "*.py"

# Regex search
rbs search "func\s+\w+" --regex --include "*.go"
```

### API: `POST /api/search`

Full search with all options via JSON body:

```json theme={null}
{
  "query": "TODO|FIXME",
  "path": "src/",
  "is_regex": true,
  "case_sensitive": false,
  "whole_word": false,
  "include_glob": "*.{ts,tsx}",
  "exclude_glob": "*_test.ts",
  "max_results": 100,
  "context_lines": 2,
  "max_file_size": 1048576
}
```

### Parameters

| Field            | Type    | Default      | Description                                             |
| ---------------- | ------- | ------------ | ------------------------------------------------------- |
| `query`          | string  | **required** | Search pattern (text or regex).                         |
| `path`           | string  | `.`          | Directory to search (relative to workspace root).       |
| `is_regex`       | boolean | `false`      | Treat query as a regular expression.                    |
| `case_sensitive` | boolean | `false`      | Enable case-sensitive matching.                         |
| `whole_word`     | boolean | `false`      | Match whole words only.                                 |
| `include_glob`   | string  | —            | Only search files matching this glob pattern.           |
| `exclude_glob`   | string  | —            | Skip files matching this glob pattern.                  |
| `max_results`    | number  | `1000`       | Maximum total matches to return.                        |
| `context_lines`  | number  | `0`          | Number of lines to include before and after each match. |
| `max_file_size`  | number  | `1048576`    | Skip files larger than this size (in bytes).            |

### Response

```json theme={null}
{
  "results": [
    {
      "path": "src/utils/helper.ts",
      "matches": [
        {
          "line": 42,
          "column": 4,
          "end_column": 8,
          "content": "    // TODO: implement caching",
          "match_text": "TODO",
          "pre_context": ["function getData() {", "  const data = fetch('/api');"],
          "post_context": ["  return data;", "}"]
        }
      ],
      "truncated": false
    }
  ],
  "total_matches": 15,
  "total_files": 8,
  "files_searched": 234,
  "duration": "45ms",
  "truncated": false
}
```

### API: `GET /api/search` (quick search)

Search via query parameters for simple lookups:

```
GET /api/search?q=TODO&include=*.ts&context=2&max=50
```

| Parameter | Aliases          | Description            |
| --------- | ---------------- | ---------------------- |
| `q`       | `query`          | Search pattern.        |
| `path`    | —                | Directory to search.   |
| `regex`   | `is_regex`       | Enable regex mode.     |
| `case`    | `case_sensitive` | Case-sensitive search. |
| `word`    | `whole_word`     | Whole word matching.   |
| `include` | `include_glob`   | Include glob pattern.  |
| `exclude` | `exclude_glob`   | Exclude glob pattern.  |
| `max`     | `max_results`    | Max results.           |
| `context` | `context_lines`  | Context lines.         |

***

## Streaming search

For large workspaces, use the streaming endpoint to receive results in real-time via Server-Sent Events (SSE):

```
GET /api/search/stream?query=error&include=*.log
```

Results arrive as they're found:

```
data: {"path":"app.log","matches":[{"line":1,"content":"Error: connection failed"}]}

data: {"path":"error.log","matches":[...]}

data: {"type":"done","total_matches":42,"total_files":5,"files_searched":100,"duration":"120ms","truncated":false}
```

***

## Fuzzy file search

Find files quickly by name using fuzzy matching — the same experience as `Cmd+P` / `Ctrl+P` in your editor.

### API: `GET /api/files/fuzzy`

```
GET /api/files/fuzzy?q=srvts&types=ts,tsx&max=20
```

| Parameter      | Description                                | Default   |
| -------------- | ------------------------------------------ | --------- |
| `q` or `query` | Fuzzy search query.                        | —         |
| `types`        | Comma-separated file extensions to filter. | All types |
| `max`          | Maximum results.                           | `50`      |

### Response

```json theme={null}
{
  "results": [
    {
      "path": "src/server.ts",
      "name": "server.ts",
      "directory": "src",
      "score": 4.5,
      "highlights": [0, 1, 2, 6, 7],
      "is_dir": false,
      "extension": ".ts",
      "mod_time": 1706040000
    }
  ],
  "query": "srvts",
  "total": 1,
  "duration": "3ms",
  "cached": true
}
```

<Tip>An **empty query** returns recently modified files sorted by modification time — useful for "recent files" functionality.</Tip>

### How fuzzy matching works

The fuzzy matcher scores results based on:

1. **Character matching** — all query characters must appear in order in the filename.
2. **Consecutive bonus** — higher score for consecutive character matches.
3. **Word boundary bonus** — higher score for matches at word boundaries (`/`, `_`, `-`, `.`, camelCase).
4. **Prefix bonus** — higher score for matches at the start of the filename.
5. **Exact match bonus** — highest score for exact matches.
6. **Length penalty** — shorter filenames score higher.

| Query     | Matches      | Why                                |
| --------- | ------------ | ---------------------------------- |
| `main.go` | `main.go`    | Exact match (highest score)        |
| `main`    | `main.go`    | Prefix match                       |
| `mg`      | `main.go`    | Character matching                 |
| `srvts`   | `server.ts`  | Word boundary + character matching |
| `btn`     | `Button.tsx` | Word boundary (camelCase)          |

### Refresh the file index

The file index refreshes automatically every 30 seconds. To force a refresh:

```
POST /api/files/index/refresh
```

```json theme={null}
{
  "message": "file index refreshed",
  "files_count": 1234
}
```

***

## File watcher

Receive real-time notifications when files change in the workspace via WebSocket.

### Connect

```
WebSocket: /ws/watcher
```

On connection, you'll receive a confirmation message:

```json theme={null}
{
  "type": "connected",
  "workspace": "/workspace/my-project",
  "message": "File watcher connected"
}
```

### Event types

| Type     | Description                      |
| -------- | -------------------------------- |
| `create` | A file or directory was created. |
| `write`  | A file's content was modified.   |
| `remove` | A file or directory was deleted. |
| `rename` | A file or directory was renamed. |
| `chmod`  | File permissions were changed.   |

### Event format

```json theme={null}
{
  "type": "write",
  "path": "src/app.ts",
  "name": "app.ts",
  "is_dir": false,
  "timestamp": 1706040001
}
```

For rename events, an additional `old_path` field is included:

```json theme={null}
{
  "type": "rename",
  "path": "src/new-name.ts",
  "name": "new-name.ts",
  "old_path": "src/old-name.ts",
  "is_dir": false,
  "timestamp": 1706040003
}
```

### Debouncing

File events are debounced (100ms) to prevent rapid-fire notifications when editors auto-save, build tools generate multiple files, or external tools batch-modify files.

### REST endpoints

| Method | Endpoint              | Description                     |
| ------ | --------------------- | ------------------------------- |
| `GET`  | `/api/watcher`        | Watcher info and configuration. |
| `GET`  | `/api/watcher/status` | Connection status.              |

***

## Default ignored patterns

All search and watcher features automatically skip:

* `.git`, `.hg`, `.svn` directories
* `node_modules`, `vendor`, `__pycache__`
* `.venv`, `venv`, `.env`
* `dist`, `build`, `target`
* `.idea`, `.vscode`, `.rbs`
* Binary files (images, executables, archives)
* Files matching `.gitignore` patterns

***

## Glob pattern examples

| Pattern       | Matches                                 |
| ------------- | --------------------------------------- |
| `*.py`        | All Python files                        |
| `*.{ts,tsx}`  | TypeScript and TSX files                |
| `test_*.py`   | Python test files starting with `test_` |
| `src/**/*.go` | All Go files under `src/`               |

***

## Editor SDK integration

If you're building a custom editor integration, use the Search SDK client:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { RBSSearchClient } from "@rbs/editor-sdk";

    const client = new RBSSearchClient("https://your-project.rbs.dev");

    // Content search
    const results = await client.search({
      query: "TODO",
      includeGlob: "*.ts",
      contextLines: 2,
    });
    console.log(`Found ${results.total_matches} matches`);

    // Streaming search
    const cancel = client.searchStream(
      "error",
      (result) => console.log(`Found in ${result.path}`),
      (summary) => console.log(`Done: ${summary.total_matches} matches`)
    );

    // Fuzzy file search
    const files = await client.fuzzySearch("srvts", { max: 10 });
    console.log(files.results.map((f) => f.path));

    // File watcher
    client.connectWatcher();
    client.onFileChange((event) => {
      console.log(`${event.type}: ${event.path}`);
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # Content search
    curl -X POST https://your-project.rbs.dev/api/search \
      -H "Authorization: Bearer $RBS_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"query": "TODO", "include_glob": "*.py"}'

    # Quick search
    curl "https://your-project.rbs.dev/api/search?q=error&include=*.log&max=50" \
      -H "Authorization: Bearer $RBS_TOKEN"

    # Fuzzy file search
    curl "https://your-project.rbs.dev/api/files/fuzzy?q=main&max=10" \
      -H "Authorization: Bearer $RBS_TOKEN"

    # Streaming search
    curl -N "https://your-project.rbs.dev/api/search/stream?query=TODO" \
      -H "Authorization: Bearer $RBS_TOKEN"

    # Watcher status
    curl "https://your-project.rbs.dev/api/watcher/status" \
      -H "Authorization: Bearer $RBS_TOKEN"
    ```
  </Tab>
</Tabs>

***

## Performance tips

1. **Use glob filters** — always specify `include_glob` when you know the file type.
2. **Limit results** — set a reasonable `max_results` for UI responsiveness.
3. **Use streaming for large searches** — the SSE endpoint returns results as they're found.
4. **Debounce user input** — wait 100–200ms before sending search requests when building a search UI.
5. **Leverage the cache** — fuzzy file search results are cached and respond in milliseconds.
6. **Connect the watcher once** — reuse a single WebSocket connection for file change events.
