api-reference / rest-api

REST API

HTTP API for integrating gnaw with web applications and services.

Base URL

http://localhost:8080/api

Authentication

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

Endpoints

Search

POST /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)

POST /api/search/chat

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"
    }
  ]
}

Agent Mode

POST /api/agent/index/build

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"
}

POST /api/agent/index/status

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
}

POST /api/agent/ask

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 Responses

Standard Error Format

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": "Additional error details"
  }
}

Common Error Codes

| 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 |

Example Error Response

{
  "error": {
    "code": "INVALID_PATTERN",
    "message": "Invalid regular expression pattern",
    "details": "Unmatched opening bracket at position 5"
  }
}

Rate Limiting

API requests are rate limited to prevent abuse:

  • Default: 100 requests per minute per API key
  • Burst: 10 requests per second
  • Headers: Rate limit information included in response headers

Rate Limit Headers

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200

Rate Limit Exceeded Response

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded",
    "retry_after": 60
  }
}

SDK Examples

Python

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')

JavaScript

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');

Best Practices

- Store API keys securely - Use environment variables - Rotate keys regularly - Monitor key usage - Check response status codes - Handle rate limiting - Implement retry logic - Log errors appropriately - Use appropriate timeouts - Implement connection pooling - Cache results when possible - Monitor API usage The REST API is designed for integration with web applications and services. For interactive use, consider using the CLI interface instead.