HTTP API for integrating gnaw with web applications and services.
http://localhost:8080/api
All API endpoints require authentication via API key:
curl -H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
http://localhost:8080/api/search
Search for patterns in files or directories.
Request:
{
"pattern": "ERROR",
"path": "/var/log/app.log",
"options": {
"recursive": true,
"ignore_case": false,
"context": 2,
"json": true
}
}
Response:
{
"search_term": "ERROR",
"time_taken": "0.123s",
"results": [
{
"file_name": "/var/log/app.log",
"line_number": 42,
"line": "2023-03-15 12:34:58,789 ERROR django.request: Internal Server Error"
}
]
}
Options:
recursive: Search directories recursively (default: false)ignore_case: Case insensitive search (default: false)context: Number of context lines (default: 0)json: Return JSON format (default: true)stream: Stream results as found (default: false)count: Return count only (default: false)Natural language search using chat mode.
Request:
{
"query": "Find all error messages in log files",
"path": "/var/log",
"options": {
"dry_run": false,
"json": true
}
}
Response:
{
"query": "Find all error messages in log files",
"generated_command": "gnaw -r \"ERROR\" /var/log",
"results": [
{
"file_name": "/var/log/app.log",
"line_number": 42,
"line": "2023-03-15 12:34:58,789 ERROR django.request: Internal Server Error"
}
]
}
Build code index for semantic search.
Request:
{
"target_dir": "/path/to/code",
"force": false
}
Response:
{
"status": "success",
"message": "Index built successfully",
"index_path": "/path/to/code/.gnaw/index",
"file_count": 1250,
"build_time": "45.2s"
}
Get index status and statistics.
Request:
{
"target_dir": "/path/to/code"
}
Response:
{
"status": "ready",
"index_path": "/path/to/code/.gnaw/index",
"file_count": 1250,
"last_updated": "2023-03-15T12:34:58Z",
"size_mb": 45.2
}
Semantic code search using AI.
Request:
{
"query": "authentication functions",
"target_dir": "/path/to/code",
"options": {
"file_types": ["rs", "go", "js"],
"directory": "src/auth",
"limit": 10,
"json": true
}
}
Response:
{
"query": "authentication functions",
"results": [
{
"file": "src/auth.rs",
"snippet": "pub fn authenticate_user(token: &str) -> Result<User, AuthError>",
"line_range": [15, 25],
"score": 0.95,
"context_before": "// User authentication module",
"context_after": "}",
"semantic_match": "Function definition matches query",
"relevance_factors": ["Function definition matches query", "Contains authentication keywords"]
}
],
"filters": {
"file_types": ["rs"],
"directory": "src/auth"
}
}
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": "Additional error details"
}
}
| Code | Description | HTTP Status |
|------|-------------|-------------|
| INVALID_PATTERN | Invalid regular expression | 400 |
| FILE_NOT_FOUND | File or directory not found | 404 |
| PERMISSION_DENIED | Insufficient permissions | 403 |
| RATE_LIMIT_EXCEEDED | Rate limit exceeded | 429 |
| INTERNAL_ERROR | Internal server error | 500 |
{
"error": {
"code": "INVALID_PATTERN",
"message": "Invalid regular expression pattern",
"details": "Unmatched opening bracket at position 5"
}
}
API requests are rate limited to prevent abuse:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"retry_after": 60
}
}
import requests
import json
class GnawAPI:
def __init__(self, base_url, api_key):
self.base_url = base_url
self.headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
def search(self, pattern, path, options=None):
data = {
'pattern': pattern,
'path': path,
'options': options or {}
}
response = requests.post(
f'{self.base_url}/api/search',
headers=self.headers,
json=data
)
return response.json()
def chat_search(self, query, path, options=None):
data = {
'query': query,
'path': path,
'options': options or {}
}
response = requests.post(
f'{self.base_url}/api/search/chat',
headers=self.headers,
json=data
)
return response.json()
def agent_ask(self, query, target_dir, options=None):
data = {
'query': query,
'target_dir': target_dir,
'options': options or {}
}
response = requests.post(
f'{self.base_url}/api/agent/ask',
headers=self.headers,
json=data
)
return response.json()
# Usage
api = GnawAPI('http://localhost:8080', 'your-api-key')
results = api.search('ERROR', '/var/log/app.log')
class GnawAPI {
constructor(baseUrl, apiKey) {
this.baseUrl = baseUrl;
this.headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
}
async search(pattern, path, options = {}) {
const response = await fetch(`${this.baseUrl}/api/search`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
pattern,
path,
options
})
});
return await response.json();
}
async chatSearch(query, path, options = {}) {
const response = await fetch(`${this.baseUrl}/api/search/chat`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
query,
path,
options
})
});
return await response.json();
}
async agentAsk(query, targetDir, options = {}) {
const response = await fetch(`${this.baseUrl}/api/agent/ask`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
query,
target_dir: targetDir,
options
})
});
return await response.json();
}
}
// Usage
const api = new GnawAPI('http://localhost:8080', 'your-api-key');
const results = await api.search('ERROR', '/var/log/app.log');