| Crates.io | grepapp_haystack |
| lib.rs | grepapp_haystack |
| version | 1.5.1 |
| created_at | 2026-01-20 10:53:31.217431+00 |
| updated_at | 2026-01-20 10:53:31.217431+00 |
| description | Grep.app integration for searching code across GitHub repositories |
| homepage | |
| repository | https://github.com/terraphim/terraphim-ai |
| max_upload_size | |
| id | 2056325 |
| size | 80,536 |
Grep.app integration for Terraphim AI, enabling code search across millions of GitHub repositories.
This crate provides a haystack provider for grep.app, a code search engine by Vercel that indexes millions of public GitHub repositories. It allows you to search for code patterns, functions, and implementations across a massive codebase directly from Terraphim AI.
Add to your Cargo.toml:
[dependencies]
grepapp_haystack = { path = "../haystack_grepapp" }
haystack_core = { path = "../haystack_core" }
terraphim_types = { path = "../terraphim_types" }
use grepapp_haystack::GrepAppHaystack;
use haystack_core::HaystackProvider;
use terraphim_types::SearchQuery;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let haystack = GrepAppHaystack::new()?;
let query = SearchQuery {
search_term: "async fn tokio::spawn".into(),
..Default::default()
};
let documents = haystack.search(&query).await?;
for doc in documents {
println!("{} - {}", doc.title, doc.url);
}
Ok(())
}
use grepapp_haystack::GrepAppHaystack;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create haystack with default filters
let haystack = GrepAppHaystack::with_filters(
Some("Rust".to_string()), // Language filter
Some("tokio-rs/tokio".to_string()), // Repository filter
Some("tokio/src/".to_string()), // Path filter
)?;
let query = SearchQuery {
search_term: "JoinHandle".into(),
..Default::default()
};
let documents = haystack.search(&query).await?;
Ok(())
}
use grepapp_haystack::{GrepAppClient, SearchParams};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = GrepAppClient::new()?;
let params = SearchParams {
query: "tokio spawn".to_string(),
language: Some("Rust".to_string()),
repo: None,
path: None,
};
let hits = client.search(¶ms).await?;
for hit in hits {
println!("Repo: {}", hit.source.repo.raw);
println!("File: {}", hit.source.path.raw);
println!("Branch: {}", hit.source.branch.raw);
println!("Snippet: {}", hit.source.content.snippet);
}
Ok(())
}
Add grep.app as a haystack in your role configuration:
{
"name": "Code Search Engineer",
"relevance_function": "BM25",
"theme": "default",
"haystacks": [
{
"name": "GitHub Code Search",
"service": "GrepApp",
"extra_parameters": {
"language": "Rust",
"repo": "",
"path": ""
}
}
]
}
query (required): Search query string (max 1000 characters)language (optional): Programming language filter (e.g., "Rust", "Python", "JavaScript")repo (optional): Repository filter in "owner/repo" format (e.g., "tokio-rs/tokio")path (optional): Path filter for directory-specific searches (e.g., "src/")Each search result is converted to a Document with:
id: Unique identifier (format: repo:branch:path)url: GitHub blob URL to the filetitle: Formatted as "repo - filename"body: Code snippet with matches (HTML tags stripped)description: Human-readable descriptiontags: Repository name and filenameThe client handles various error conditions:
Run the test suite:
# Run all tests
cargo test -p grepapp_haystack
# Run with output
cargo test -p grepapp_haystack -- --nocapture
# Run specific test
cargo test -p grepapp_haystack test_search_success
let haystack = GrepAppHaystack::with_filters(
Some("Rust".to_string()),
None,
None,
)?;
let query = SearchQuery {
search_term: "Result<T, E>".into(),
..Default::default()
};
let documents = haystack.search(&query).await?;
let haystack = GrepAppHaystack::with_filters(
Some("Go".to_string()),
Some("kubernetes/kubernetes".to_string()),
Some("pkg/".to_string()),
)?;
let query = SearchQuery {
search_term: "func NewController".into(),
..Default::default()
};
let documents = haystack.search(&query).await?;
grep.app uses the following API endpoint:
https://grep.app/api/searchq, f.lang, f.repo, f.pathfacets and hitsFor more details, see the models.rs file for the complete response structure.
When extending this crate:
tracing for logging, not println!MIT