Drupal Contrib Code Search
Powered by zoekt, an open-source full text search engine. Indexing 670024 files from 11928 repositories.
Query Syntax
Basic Search
Queries are regular expressions parsed by Go's regexp package. A single term like hook_form_alter searches across all file contents and filenames.
Multiple space-separated terms are conjunctive by default: class needle returns files containing both "class" and "needle". Each term is matched independently and results show lines matching any individual term, but only from files that contain all of them.
Phrases & Escaping
"class Needle"— match the exact phrase (wrap in double quotes)foo\ bar— escape a space to treat it as literal
Boolean Logic
foo or bar— match files containing either termfoo (bar or baz)— grouping with parenthesesfoo -bar— match "foo" but exclude files containing "bar"-(Path File) Stream— exclude files containing both "Path" and "File", require "Stream"
Case Sensitivity
By default, terms with uppercase letters are case-sensitive; all-lowercase terms are case-insensitive. Use case:yes or case:no to override.
Prefix Filters
| Prefix | Alias | Description | Example |
|---|---|---|---|
file: |
f: |
Match filenames (regex) | f:\.module$ |
-file: |
-f: |
Exclude filenames | hook -file:test |
content: |
c: |
Match file contents only (not filenames) | c:README |
repo: |
r: |
Filter by repository name | hook_form_alter r:views |
-repo: |
-r: |
Exclude repositories | r:views -r:commerce |
branch: |
b: |
Filter by branch name | hook b:HEAD |
lang: |
Filter by language (case-insensitive) | hook_form_alter lang:php |
|
sym: |
Match symbol definitions (ctags) | sym:main |
|
case: |
Force case sensitivity (yes / no / auto) |
class Needle case:yes |
|
archived: |
Filter archived repos (yes / no) |
hook archived:no |
|
fork: |
Filter forked repos (yes / no) |
hook fork:no |
|
public: |
Filter public repos (yes / no) |
hook public:no |
Listing Repositories
Use r: alone (without a content search term) to list matching repositories:
r:views— list repos whose name contains "views"r:commerce -r:stripe— list repos matching "commerce" but not "stripe"
Regex Examples
| Query | Meaning |
|---|---|
foo.*bar |
"foo" followed by "bar" on the same line |
f:\.module$ |
Files ending in .module |
\bfunction\b lang:php |
Whole-word "function" in PHP files |
[[:upper:]]{3} |
Three consecutive uppercase letters |
JSON API
Base URL: https://api.tresbien.tech/v1/search. Two GET endpoints returning JSON. Full API reference →
Important: query terms are Go regexp patterns. Escape special characters with a backslash: . → \., ( → \(, ) → \). Example: to search for .once( use q=\.once\(.
Search code: GET /v1/search/code
Search file contents. Returns matching files with chunk-level matches. Content is base64-encoded.
curl 'https://api.tresbien.tech/v1/search/code?q=hook_form_alter+r:webform&num=5'
| Parameter | Type | Description |
|---|---|---|
q | string | Search query (required). Same syntax as web UI. |
num | int | Maximum number of file results to return |
context | int | Number of context lines around each match |
maxmatches | int | Stop after this many total matches |
chunks | bool | Return ChunkMatches (default: true) or LineMatches (false) |
Response structure:
{
"Result": {
"Files": [
{
"FileName": "webform.api.php",
"Repository": "webform",
"Branches": ["6.3.x"],
"Language": "PHP",
"ChunkMatches": [
{
"Content": "<base64-encoded content>",
"ContentStart": {"ByteOffset": 13463, "LineNumber": 368, "Column": 1},
"Ranges": [
{
"Start": {"ByteOffset": 13492, "LineNumber": 368, "Column": 30},
"End": {"ByteOffset": 13507, "LineNumber": 368, "Column": 45}
}
]
}
]
}
],
"MatchCount": 47,
"FileCount": 38
}
}
Each file in Result.Files contains:
Repository- Module machine name (e.g.
"webform") FileName- Path relative to the repo root
Branches- Array of branches where this file matched
Language- Detected language (e.g.
"PHP","YAML") ChunkMatches- Array of matching chunks with base64-encoded
Content,ContentStartposition, andRangesarray with preciseStart/Endpositions (each withByteOffset,LineNumber,Column)
List repositories: GET /v1/search/repo
Returns the full list of all indexed repositories with metadata including branches, core compatibility, usage stats, and security coverage. Use this to get install counts and Drupal metadata for modules.
curl 'https://api.tresbien.tech/v1/search/repo'
Response structure:
{
"List": {
"Repos": [
{
"Repository": {
"Name": "admin_toolbar",
"URL": "https://git.drupalcode.org/project/admin_toolbar",
"Branches": [{"Name": "3.x", "Version": "f0a73d2..."}],
"RawConfig": {
"drupal-core": "3.5.x:^9.5 || ^10 || ^11;3.6.x:^9.5 || ^10 || ^11",
"drupal-usage": "3.5.x:42092;3.6.x:167949",
"drupal-security": "covered",
"priority": "210041"
},
"HasSymbols": true,
"LatestCommitDate": "2026-02-07T01:36:41Z"
}
}
]
}
}
Each repository's RawConfig contains Drupal-specific metadata:
| Key | Format | Description |
|---|---|---|
drupal-core |
branch:constraint;... |
Core compatibility per branch (e.g. 6.2.x:^10 || ^11). Multiple branches separated by ; |
drupal-usage |
branch:count;... |
Active installs per branch (e.g. 3.6.x:167949). Multiple branches separated by ; |
drupal-security |
covered |
Present and set to "covered" if the project is covered by the Drupal Security Team. Absent otherwise. |
priority |
integer string | Total active installs across supported branches. Use this to rank modules by popularity. |
Example: find the 5 most installed modules using .once(
- Search (escape regex:
.once(→\.once\():GET https://api.tresbien.tech/v1/search/code?q=\.once\(&num=500 - Collect unique repo names from
Result.Files[].Repositoryin the response. - Fetch the full repo list (no parameters):
GET https://api.tresbien.tech/v1/search/repo - Look up each repo by name in
List.Repos[], readRepository.RawConfig.priority(total active installs as a string). - Sort by
prioritydescending, take top 5.