Search
Two search modes are available inside the workspace:
- Content search - powered by ripgrep, searches file contents with regex, whole-word, and context line support
- Filename search - built-in filesystem search that matches against file paths
Requires the internal server to be enabled. Content search requires ripgrep - use the install endpoint to set it up.
Content search
Search file contents using ripgrep. Results are grouped by file with line numbers and match context.
const results = await ws.search.content('ws_a1b2c3d4', {
query: 'handleRequest',
path: '/app/src',
contextLines: 2,
maxResults: 100,
});
for (const file of results.results) {
console.log(file.path);
for (const match of file.matches) {
console.log(` Line ${match.line}: ${match.text}`);
}
}GET https://workspace.oblien.com/files/search?q=handleRequest&path=/app/src&context_lines=2&max_results=100
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/files/search?q=handleRequest&path=/app/src&context_lines=2&max_results=100" \
-H "Authorization: Bearer $GATEWAY_JWT"Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search query (max 1000 characters) |
path | string | No | Directory or file to search in. Default / |
case_sensitive | boolean | No | Case-sensitive matching. Default false |
regex | boolean | No | Treat query as a regex pattern. Default false |
whole_word | boolean | No | Match whole words only. Default false |
max_results | integer | No | Maximum number of matches. Default 100 |
timeout | integer | No | Timeout in seconds (max 60). Default 10 |
context_lines | integer | No | Lines of context around matches (0–10). Default 0 |
file_types | string | No | Comma-separated file extension filters (e.g. go,js,py). Converted to glob patterns internally |
include_hidden | boolean | No | Include hidden files/directories. Default false |
no_gitignore | boolean | No | Ignore .gitignore rules. Default false |
ignore_patterns | string | No | Comma-separated glob patterns to skip |
Response
Results are returned as an object keyed by file path, with each value being an array of matches:
{
"success": true,
"query": "handleRequest",
"path": "/app/src",
"results": {
"src/server.go": [
{
"line": 42,
"column": 6,
"text": "func handleRequest(w http.ResponseWriter, r *http.Request) {"
},
{
"line": 105,
"column": 2,
"text": "\thandleRequest(w, r)"
}
],
"src/router.go": [
{
"line": 18,
"column": 12,
"text": "\trouter.HandleFunc(\"/\", handleRequest)"
}
]
},
"total_matches": 3,
"total_files": 2,
"capped": false
}| Field | Description |
|---|---|
results | Object mapping file paths to arrays of matches |
total_matches | Total number of matching lines across all files |
total_files | Number of files with at least one match |
capped | true if max_results was reached before all matches were found |
Filename search
Search for files by name. Uses a fast filesystem walk with substring matching on relative paths.
const results = await ws.search.files('ws_a1b2c3d4', {
query: 'controller',
path: '/app/src',
maxResults: 50,
});
console.log(results.files); // ["auth/controller.go", "user/controller.go"]
console.log(results.total_files); // 2GET https://workspace.oblien.com/files/search/files?q=controller&path=/app/src&max_results=50
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/files/search/files?q=controller&path=/app/src&max_results=50" \
-H "Authorization: Bearer $GATEWAY_JWT"Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search query - matches against relative file paths (max 1000 characters) |
path | string | No | Directory to search in. Default / |
case_sensitive | boolean | No | Case-sensitive matching. Default false |
include_hidden | boolean | No | Include hidden files/directories. Default false |
max_results | integer | No | Maximum number of results. Default 200 |
ignore_patterns | string | No | Comma-separated glob patterns to skip |
Response
{
"success": true,
"query": "controller",
"path": "/app/src",
"files": [
"auth/controller.go",
"user/controller.go"
],
"total_files": 2
}Filename search does not require ripgrep - it works out of the box with no additional setup.
Ripgrep status
Check if ripgrep is installed and available for content search.
const status = await ws.search.status('ws_a1b2c3d4');
console.log(status.installed); // true or false
console.log(status.version); // "ripgrep 14.1.0" or nullGET https://workspace.oblien.com/files/search/init
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/files/search/init" \
-H "Authorization: Bearer $GATEWAY_JWT"Response
When ripgrep is installed:
{
"success": true,
"installed": true,
"path": "/usr/local/bin/rg",
"version": "ripgrep 14.1.0"
}When not installed:
{
"success": true,
"installed": false,
"message": "ripgrep is not installed - use POST /files/search/init to install"
}Install ripgrep
Download and install ripgrep from GitHub releases. This is a one-time setup per workspace.
const result = await ws.search.init('ws_a1b2c3d4');
console.log(result.installed); // true
console.log(result.version); // "14.1.1"POST https://workspace.oblien.com/files/search/init
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl -X POST "https://workspace.oblien.com/files/search/init" \
-H "Authorization: Bearer $GATEWAY_JWT"Response
{
"success": true,
"version": "ripgrep 14.1.0",
"path": "/usr/local/bin/rg"
}If ripgrep is already installed, the endpoint returns the current installation info without re-downloading.
Installation requires internet access from inside the workspace to download from GitHub releases. The binary is installed to /usr/local/bin/rg.
Error responses
| Status | Meaning |
|---|---|
400 | Missing q parameter, query too long, or path is not a directory |
401 | Missing or invalid token |
404 | Search path not found |
409 | Ripgrep installation already in progress |
503 | Content search requested but ripgrep is not installed |
504 | Search timed out |