codeapi

module
v0.0.0-...-6320ad3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 8, 2026 License: MIT

README

CodeAPI

A multi-language code analysis and indexing platform that builds semantic code graphs and enables intelligent code search. CodeAPI parses source code using tree-sitter, constructs a knowledge graph in Neo4j, and optionally generates vector embeddings for semantic similarity search.

Features

  • Multi-Language Support: Go, Python, Java, TypeScript, and JavaScript
  • Code Graph Construction: Builds a comprehensive knowledge graph capturing functions, classes, variables, call relationships, inheritance, and data flow
  • Semantic Code Search: Vector embeddings enable similarity-based code search
  • Hierarchical Code Summarization: LLM-powered summaries at function, class, file, folder, and project levels with on-demand generation support
  • Rich Query API: REST endpoints for code exploration, call graph analysis, and impact assessment
  • Flexible Indexing: Server mode for on-demand analysis or CLI mode for batch processing
  • Git Integration: Optional git HEAD mode to index only committed versions

Prerequisites

  • Go 1.23+
  • Neo4j 4.x or 5.x (for code graph storage)
  • MySQL 8.x (for file version tracking)
  • Qdrant (optional, for vector embeddings)
  • Ollama (optional, for embedding generation)

Quick Start

1. Clone and Build
git clone https://github.com/armchr/codeapi.git
cd codeapi
make build
2. Configure
# Copy example configuration files
cp config/app.yaml.example config/app.yaml
cp config/source.yaml.example config/source.yaml

# Edit config/app.yaml with your database credentials
# Edit config/source.yaml with your repositories
3. Start Dependencies
# Using Docker Compose (recommended)
docker-compose up -d neo4j mysql

# Or start services manually
# Neo4j: http://localhost:7474 (bolt://localhost:7687)
# MySQL: localhost:3306
4. Run
# Server mode
make run

# Or directly
./bin/codeapi -app=config/app.yaml -source=config/source.yaml

The API will be available at http://localhost:8181.

5. Access DB
# Maria DB
docker exec -it $(docker ps --filter "publish=3306" --format "{{.Names}}") mariadb -u root -parmchair armchair

# QDrant viewer
git clone https://github.com/qdrant/qdrant-web-ui.git
npm start

Building

# Build main binary
make build

# Build with all dependencies
make deps && make build

# Run tests
make test

# Clean build artifacts
make clean

Testing

CodeAPI includes unit tests for core parsing and utility functionality.

Running Tests
# Run all tests
make test

# Run tests with verbose output
make test-verbose

# Run tests with coverage summary
make test-coverage

# Generate HTML coverage report
make test-coverage-report

# Run unit tests only (parsing, utilities, LSP)
make test-unit
Test Coverage

The test suite covers:

  • LSP Utilities (pkg/lsp/base/) - Symbol matching, range comparison, Java method name extraction
  • Concurrent Data Structures (internal/util/) - Thread-safe map operations
  • Scope Management (internal/parse/) - Symbol resolution, scope hierarchy, variable tracking
  • Java Parser (internal/parse/) - Annotation extraction from Java AST nodes

Configuration

Application Configuration (config/app.yaml)
app:
  port: 8181                    # HTTP server port
  codegraph: true               # Enable Neo4j code graph
  num_file_threads: 5           # Parallel file processing threads
  max_concurrent_file_processing: 5

neo4j:
  uri: "bolt://localhost:7687"
  username: "neo4j"
  password: "your-password"

mysql:
  host: "localhost"
  port: 3306
  username: "root"
  password: "your-password"
  database: "codeapi"

qdrant:                         # Optional: for vector embeddings
  host: "localhost"
  port: 6334

ollama:                         # Optional: for embedding generation
  url: "http://localhost:11434"
  model: "nomic-embed-text"
  dimension: 768

index_building:
  enable_code_graph: true       # Build code graph
  enable_embeddings: false      # Generate embeddings
  enable_summary: false         # Generate LLM code summaries

summary:                        # Required when enable_summary is true
  llm_provider: "ollama"        # ollama, claude, or openai
  llm_model: "qwen2.5-coder"    # Model name
  prompts_file: "config/summary_prompts.yaml"  # Prompt templates
  worker_count: 4               # Parallel summarization workers
  batch_size: 50                # Batch size for DB writes
  skip_if_exists: true          # Skip unchanged entities

code_graph:
  enable_batch_writes: false    # Batch writes (faster for large repos)
  batch_size: 10
Repository Configuration (config/source.yaml)
source:
  repositories:
    - name: my-project
      path: /path/to/your/project
      language: go              # go, python, java, typescript, javascript
      disabled: false
      skip_other_languages: false

CLI Commands

Server Mode (Default)
./bin/codeapi -app=config/app.yaml -source=config/source.yaml
Build Index (CLI Mode)
# Index a single repository
./bin/codeapi -app=config/app.yaml -source=config/source.yaml -build-index=my-repo

# Index multiple repositories
./bin/codeapi -build-index=repo1 -build-index=repo2 -build-index=repo3

# Index using git HEAD (committed versions only)
./bin/codeapi -build-index=my-repo -head

# Dump code graph after indexing (for debugging)
./bin/codeapi -build-index=my-repo -test-dump=output.json

# Clean up database entries after indexing
./bin/codeapi -build-index=my-repo -clean
Using Make
# Build index for a repository
make build-index REPO=my-repo

# Build index using git HEAD
make build-index-head REPO=my-repo

# Index multiple repos
make build-index REPO="repo1 repo2 repo3"
Command-Line Flags
Flag Description
-app Path to application config file (default: app.yaml)
-source Path to source/repository config file (default: source.yaml)
-workdir Working directory for temporary files
-build-index Repository name to index (repeatable for multiple repos)
-head Use git HEAD version instead of working directory
-test-dump Output file path for dumping code graph (debugging)
-clean Clean up all DB entries for the repository after processing
-test Run in LSP test mode

Architecture

┌─────────────────────────────────────────────────────────────┐
│                    HTTP REST API (Gin)                       │
│                    Port 8181 (default)                       │
├─────────────────────────────────────────────────────────────┤
│     RepoController      │      CodeAPIController            │
│  (Indexing & Search)    │   (Graph Queries & Analysis)      │
├─────────────────────────────────────────────────────────────┤
│                   IndexBuilder                               │
│           (Parallel File Processing Pipeline)                │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Tree-Sitter Parsers                     │   │
│  │    Go │ Python │ Java │ TypeScript │ JavaScript     │   │
│  └─────────────────────────────────────────────────────┘   │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐   │
│  │     Neo4j       │ │     Qdrant      │ │    MySQL    │   │
│  │   Code Graph    │ │   Embeddings    │ │  File IDs   │   │
│  └─────────────────┘ └─────────────────┘ └─────────────┘   │
└─────────────────────────────────────────────────────────────┘
Components
Component Responsibility
RepoController Handles indexing requests and code search
CodeAPIController Provides code graph query and analysis APIs
SummaryController Provides code summary query APIs
IndexBuilder Orchestrates parallel file processing
CodeGraphProcessor Parses files and builds Neo4j graph
EmbeddingProcessor Generates vector embeddings for code chunks
SummaryProcessor Generates LLM-powered hierarchical code summaries
CodeGraph Neo4j interface for storing code structure
FileVersionRepository MySQL-based file tracking with unique IDs
SummaryStore MySQL storage for code summaries
Code Graph Model

Node Types (Neo4j Labels):

Label Description
ModuleScope Module or package scope
FileScope Source file
Class Class, struct, or interface
Function Function or method
Field Class field or property
Variable Local variable
Conditional If statements, switch statements
Loop For, while, foreach loops
Block Generic code blocks (not control flow)
Expression Expressions
FunctionCall Function/method invocation site
Import Import statement

Control Flow Node Metadata:

  • Loop nodes contain:

    • condition - ID of the loop condition expression
    • body - ID of the loop body block
    • init - (optional) ID of initialization expression (e.g., for loops)
  • Conditional nodes have BRANCH relationships to each branch with:

    • position - Branch index (0 = if, 1 = first else-if, etc.)
    • condition - ID of the condition expression for that branch

Relationship Types:

  • CONTAINS - Hierarchical containment
  • CALLS - Function invocation
  • USES - Variable/field usage
  • DEFINES - Variable definition
  • INHERITS_FROM - Class inheritance
  • IMPLEMENTS - Interface implementation
  • BRANCH - Conditional branch (from Conditional to branch block)

API Reference

Base URLs
  • Indexing & Search API: /api/v1/
  • Code Analysis API: /codeapi/v1/
API Endpoint Summary
Method Endpoint Description
GET /api/v1/health Health check
POST /api/v1/buildIndex Build repository index
POST /api/v1/indexFile Index specific files
POST /api/v1/searchSimilarCode Semantic code search
POST /api/v1/functionDependencies Get function call dependencies
POST /api/v1/processDirectory Process directory for embeddings
GET /codeapi/v1/repos List indexed repositories
POST /codeapi/v1/files List files in repository
POST /codeapi/v1/classes List classes
POST /codeapi/v1/methods List methods
POST /codeapi/v1/functions List functions
POST /codeapi/v1/classes/find Find classes by pattern
POST /codeapi/v1/methods/find Find methods by pattern
POST /codeapi/v1/class Get class details
POST /codeapi/v1/method Get method details
POST /codeapi/v1/class/methods Get methods of a class
POST /codeapi/v1/class/fields Get fields of a class
POST /codeapi/v1/callgraph Get call graph
POST /codeapi/v1/callers Get callers of a function
POST /codeapi/v1/callees Get callees of a function
POST /codeapi/v1/data/dependents Get data dependents
POST /codeapi/v1/data/sources Get data sources
POST /codeapi/v1/impact Impact analysis
POST /codeapi/v1/inheritance Get inheritance tree
POST /codeapi/v1/field/accessors Get field accessors
POST /codeapi/v1/cypher Execute read Cypher query
POST /codeapi/v1/cypher/write Execute write Cypher query
POST /codeapi/v1/snippet Get code snippet by line range
GET /codeapi/v1/health CodeAPI health check
POST /codeapi/v1/summaries/file Get all summaries for a file
POST /codeapi/v1/summaries/file/summary Get file-level summary
POST /codeapi/v1/summaries/entity Get specific function/class summary
POST /codeapi/v1/summaries/stats Get summary statistics

Indexing & Search Endpoints
Health Check
GET /api/v1/health

Response:

{
  "status": "healthy"
}

Build Index

Build code graph index for a repository.

POST /api/v1/buildIndex

Request:

{
  "repo_name": "my-project",
  "use_head": false
}

Response:

{
  "repo_name": "my-project",
  "status": "completed",
  "message": "Repository indexed successfully"
}

Index File

Index specific files through all processors.

POST /api/v1/indexFile

Request:

{
  "repo_name": "my-project",
  "relative_paths": [
    "src/main.go",
    "src/utils/helper.go"
  ]
}

Response:

{
  "repo_name": "my-project",
  "files": [
    {
      "relative_path": "src/main.go",
      "file_id": 123,
      "file_sha": "abc123...",
      "processors_run": ["CodeGraph", "Embedding"],
      "success": true
    }
  ],
  "message": "Processed 2 file(s): 2 succeeded, 0 failed"
}

Search Similar Code

Find semantically similar code using vector embeddings.

POST /api/v1/searchSimilarCode

Request:

{
  "repo_name": "my-project",
  "code_snippet": "func calculateSum(a, b int) int {\n  return a + b\n}",
  "language": "go",
  "limit": 10,
  "include_code": true
}

Response:

{
  "repo_name": "my-project",
  "collection_name": "my-project",
  "query": {
    "code_snippet": "func calculateSum...",
    "language": "go",
    "chunks_found": 1
  },
  "results": [
    {
      "chunk": {
        "file_path": "/path/to/math.go",
        "start_line": 10,
        "end_line": 15,
        "chunk_type": "function",
        "name": "add"
      },
      "score": 0.95,
      "code": "func add(x, y int) int {\n  return x + y\n}"
    }
  ],
  "success": true
}

Get Function Dependencies

Get call graph for a function.

POST /api/v1/functionDependencies

Request:

{
  "repo_name": "my-project",
  "relative_path": "src/main.go",
  "function_name": "main",
  "depth": 2
}

Response:

{
  "repo_name": "my-project",
  "file_path": "src/main.go",
  "function_name": "main",
  "dependencies": [
    {
      "name": "initialize",
      "call_locations": [...],
      "definition": {
        "name": "initialize",
        "location": {...}
      }
    }
  ]
}

Process Directory

Process a directory and generate embeddings.

POST /api/v1/processDirectory

Request:

{
  "repo_name": "my-project",
  "collection_name": "my-project-embeddings"
}

Response:

{
  "repo_name": "my-project",
  "collection_name": "my-project-embeddings",
  "total_chunks": 150,
  "success": true,
  "message": "Directory processed successfully"
}

Code Analysis API Endpoints
List Repositories
GET /codeapi/v1/repos

Response:

{
  "repos": ["my-project", "another-project"]
}

List Files
POST /codeapi/v1/files

Request:

{
  "repo_name": "my-project",
  "limit": 100,
  "offset": 0
}

Response:

{
  "files": [
    {
      "id": "file-123",
      "path": "src/main.go",
      "language": "go"
    }
  ],
  "total": 50
}

List Classes
POST /codeapi/v1/classes

Request:

{
  "repo_name": "my-project",
  "limit": 50
}

Response:

{
  "classes": [
    {
      "id": "class-456",
      "name": "UserService",
      "file_path": "src/service/user.go",
      "start_line": 10,
      "end_line": 100
    }
  ]
}

List Methods
POST /codeapi/v1/methods

Request:

{
  "repo_name": "my-project",
  "class_id": "class-456"
}

Response:

{
  "methods": [
    {
      "id": "method-123",
      "name": "GetUser",
      "signature": "func (s *UserService) GetUser(id string) (*User, error)",
      "start_line": 15,
      "end_line": 25
    }
  ]
}

List Functions
POST /codeapi/v1/functions

Request:

{
  "repo_name": "my-project",
  "file_path": "src/main.go"
}

Response:

{
  "functions": [
    {
      "id": "func-789",
      "name": "main",
      "signature": "func main()",
      "start_line": 5,
      "end_line": 20
    }
  ]
}

Find Classes by Pattern
POST /codeapi/v1/classes/find

Request:

{
  "repo_name": "my-project",
  "pattern": ".*Service$"
}

Response:

{
  "classes": [
    {
      "id": "class-456",
      "name": "UserService",
      "file_path": "src/service/user.go"
    },
    {
      "id": "class-457",
      "name": "OrderService",
      "file_path": "src/service/order.go"
    }
  ]
}

Find Methods by Pattern
POST /codeapi/v1/methods/find

Request:

{
  "repo_name": "my-project",
  "pattern": "Get.*"
}

Response:

{
  "methods": [
    {
      "id": "method-123",
      "name": "GetUser",
      "class_name": "UserService"
    },
    {
      "id": "method-124",
      "name": "GetOrder",
      "class_name": "OrderService"
    }
  ]
}

Get Class
POST /codeapi/v1/class

Request:

{
  "repo_name": "my-project",
  "class_id": "class-456"
}

Response:

{
  "class": {
    "id": "class-456",
    "name": "UserService",
    "file_path": "src/service/user.go",
    "start_line": 10,
    "end_line": 100,
    "methods": [...],
    "fields": [...]
  }
}

Get Method
POST /codeapi/v1/method

Request:

{
  "repo_name": "my-project",
  "method_id": "method-123"
}

Response:

{
  "method": {
    "id": "method-123",
    "name": "GetUser",
    "signature": "func (s *UserService) GetUser(id string) (*User, error)",
    "start_line": 15,
    "end_line": 25,
    "class_id": "class-456"
  }
}

Get Class Methods
POST /codeapi/v1/class/methods

Request:

{
  "repo_name": "my-project",
  "class_id": "class-456"
}

Response:

{
  "methods": [
    {
      "id": "method-123",
      "name": "GetUser",
      "signature": "func (s *UserService) GetUser(id string) (*User, error)"
    },
    {
      "id": "method-124",
      "name": "CreateUser",
      "signature": "func (s *UserService) CreateUser(user *User) error"
    }
  ]
}

Get Class Fields
POST /codeapi/v1/class/fields

Request:

{
  "repo_name": "my-project",
  "class_id": "class-456"
}

Response:

{
  "fields": [
    {
      "id": "field-001",
      "name": "db",
      "type": "*sql.DB"
    },
    {
      "id": "field-002",
      "name": "logger",
      "type": "*zap.Logger"
    }
  ]
}

Get Call Graph
POST /codeapi/v1/callgraph

Request:

{
  "repo_name": "my-project",
  "function_id": "func-789",
  "direction": "both",
  "max_depth": 3
}

Response:

{
  "nodes": [
    {
      "id": "func-789",
      "name": "processRequest",
      "type": "function"
    }
  ],
  "edges": [
    {
      "from": "func-789",
      "to": "func-790",
      "type": "CALLS"
    }
  ]
}

Get Callers

Get functions that call a specific function. The function_id field is flexible and accepts:

  • A numeric ID: 21474836481
  • A qualified name: "ClassName.methodName"
  • A simple function name: "main"
POST /codeapi/v1/callers

Request (by numeric ID):

{
  "repo_name": "my-project",
  "function_id": 21474836481
}

Request (by qualified name):

{
  "repo_name": "jgnash",
  "function_id": "XStreamAccountDAO.addRootAccount"
}

Request (using separate fields):

{
  "repo_name": "my-project",
  "function_name": "processRequest",
  "class_name": "RequestHandler",
  "file_path": "/path/to/handler.go"
}
Field Type Required Description
repo_name string Yes Repository name
function_id int64/string No* Numeric ID or qualified name (e.g., "Class.method")
function_name string No* Function/method name
class_name string No Class name (for methods)
file_path string No File path to narrow search
max_depth int No Max traversal depth (default: 3)

*Either function_id or function_name is required.

Response:

{
  "call_graph": {
    "nodes": [...],
    "edges": [...],
    "root_id": 21474836481
  }
}

Get Callees

Get functions called by a specific function. The function_id field is flexible and accepts:

  • A numeric ID: 21474836481
  • A qualified name: "ClassName.methodName"
  • A simple function name: "main"
POST /codeapi/v1/callees

Request (by numeric ID):

{
  "repo_name": "my-project",
  "function_id": 21474836481
}

Request (by qualified name):

{
  "repo_name": "jgnash",
  "function_id": "Workbook.addTableSection"
}

Request (using separate fields):

{
  "repo_name": "my-project",
  "function_name": "main",
  "file_path": "/path/to/main.go"
}
Field Type Required Description
repo_name string Yes Repository name
function_id int64/string No* Numeric ID or qualified name (e.g., "Class.method")
function_name string No* Function/method name
class_name string No Class name (for methods)
file_path string No File path to narrow search
max_depth int No Max traversal depth (default: 3)

*Either function_id or function_name is required.

Response:

{
  "call_graph": {
    "nodes": [...],
    "edges": [...],
    "root_id": 21474836481
  }
}

Get Data Dependents

Get entities that depend on a variable or field's data.

POST /codeapi/v1/data/dependents

Request:

{
  "repo_name": "my-project",
  "variable_id": "var-123"
}

Response:

{
  "dependents": [
    {
      "id": "func-300",
      "name": "processData",
      "type": "function"
    }
  ]
}

Get Data Sources

Get the sources of data for a variable or field.

POST /codeapi/v1/data/sources

Request:

{
  "repo_name": "my-project",
  "variable_id": "var-123"
}

Response:

{
  "sources": [
    {
      "id": "func-400",
      "name": "fetchData",
      "type": "function"
    }
  ]
}

Get Impact Analysis

Analyze the impact of changes to a function.

POST /codeapi/v1/impact

Request:

{
  "repo_name": "my-project",
  "function_id": "func-789",
  "max_depth": 5
}

Response:

{
  "impacted": [
    {
      "id": "func-100",
      "name": "main",
      "depth": 1,
      "impact_type": "direct_caller"
    },
    {
      "id": "func-101",
      "name": "runServer",
      "depth": 2,
      "impact_type": "indirect_caller"
    }
  ],
  "total_impacted": 15
}

Get Inheritance Tree
POST /codeapi/v1/inheritance

Request:

{
  "repo_name": "my-project",
  "class_id": "class-456"
}

Response:

{
  "class": {
    "id": "class-456",
    "name": "UserService"
  },
  "parents": [
    {
      "id": "class-100",
      "name": "BaseService"
    }
  ],
  "children": [
    {
      "id": "class-500",
      "name": "AdminUserService"
    }
  ],
  "interfaces": [
    {
      "id": "interface-001",
      "name": "Service"
    }
  ]
}

Get Field Accessors

Get functions that read or write a specific field.

POST /codeapi/v1/field/accessors

Request:

{
  "repo_name": "my-project",
  "field_id": "field-001"
}

Response:

{
  "readers": [
    {
      "id": "func-500",
      "name": "GetConnection",
      "access_type": "read"
    }
  ],
  "writers": [
    {
      "id": "func-501",
      "name": "SetConnection",
      "access_type": "write"
    }
  ]
}

Execute Cypher Query (Read)

Execute custom read-only Cypher queries against the code graph.

POST /codeapi/v1/cypher

Request:

{
  "repo_name": "my-project",
  "query": "MATCH (f:Function)-[:CALLS]->(g:Function) WHERE f.name = 'main' RETURN g.name"
}

Response:

{
  "results": [
    {"g.name": "initialize"},
    {"g.name": "run"}
  ]
}

Execute Cypher Query (Write)

Execute write Cypher queries (use with caution).

POST /codeapi/v1/cypher/write

Request:

{
  "repo_name": "my-project",
  "query": "MATCH (f:Function {name: 'deprecated'}) SET f.deprecated = true"
}

Response:

{
  "success": true,
  "nodes_affected": 3
}

Get Code Snippet

Fetch a code snippet from a file in a repository by specifying a line range.

POST /codeapi/v1/snippet

Request:

{
  "repo_name": "my-project",
  "file_path": "src/main/java/App.java",
  "start_line": 10,
  "end_line": 25
}
Field Type Required Description
repo_name string Yes Repository name (must be configured in source.yaml)
file_path string Yes Relative path to the file within the repository
start_line int Yes Starting line number (1-indexed, inclusive)
end_line int Yes Ending line number (1-indexed, inclusive)

Response:

{
  "repo_name": "my-project",
  "file_path": "src/main/java/App.java",
  "start_line": 10,
  "end_line": 25,
  "code": "public class App {\n    public static void main(String[] args) {\n        System.out.println(\"Hello\");\n    }\n}",
  "total_lines": 16
}
Field Type Description
repo_name string Repository name
file_path string Relative file path
start_line int Requested start line
end_line int Requested end line
code string The extracted code snippet
total_lines int Actual number of lines returned

Error Responses:

  • 400 Bad Request: Invalid parameters (e.g., start_line > end_line, invalid file path)
  • 404 Not Found: Repository not found or file not found

Security:

  • File paths are validated to prevent path traversal attacks
  • Symlinks are resolved and validated to stay within repository bounds

CodeAPI Health Check
GET /codeapi/v1/health

Response:

{
  "status": "healthy"
}

Code Summary Query Endpoints

These endpoints query LLM-generated code summaries. Summaries can be generated in two ways:

  1. Batch Generation: During index building when index_building.enable_summary is set to true
  2. On-Demand Generation: When querying via /summaries/entity, /summaries/file, or /summaries/file/summary, if a summary doesn't exist, it will be automatically generated using the configured LLM (requires summary processor to be enabled)

On-demand generation may take a few seconds for the first request as it calls the LLM to generate the summary.

Get File Summaries

Get all function, class, and file-level summaries for a file. Optionally filter by entity type.

POST /codeapi/v1/summaries/file

Request:

{
  "repo_name": "my-project",
  "file_path": "/path/to/UserService.java",
  "entity_type": "function"
}
Field Type Required Description
repo_name string Yes Repository name
file_path string Yes Absolute path to the file
entity_type string No Filter by type: "function", "class", or omit for all

Response:

{
  "file_path": "/path/to/UserService.java",
  "summaries": [
    {
      "id": 123,
      "entity_id": "func-456",
      "entity_type": "function",
      "entity_name": "getUser",
      "file_path": "/path/to/UserService.java",
      "summary": "ONE_LINE: Retrieves a user by ID from the database.\nDESCRIPTION: This method queries the user repository to find a user matching the provided ID. Returns null if no user is found.\nSIDE_EFFECTS: Database read operation.",
      "llm_provider": "ollama",
      "llm_model": "qwen2.5-coder",
      "prompt_tokens": 450,
      "output_tokens": 85,
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T10:30:00Z"
    }
  ],
  "count": 5
}

Get File-Level Summary

Get the file-level summary for a source file. Supports on-demand generation - if the summary doesn't exist, it will be generated automatically.

POST /codeapi/v1/summaries/file/summary

Request:

{
  "repo_name": "my-project",
  "file_path": "/path/to/UserService.java"
}

Response:

{
  "id": 789,
  "entity_id": "file:/path/to/UserService.java",
  "entity_type": "file",
  "entity_name": "UserService.java",
  "file_path": "/path/to/UserService.java",
  "summary": "This file provides the UserService class which handles user management operations including CRUD operations, authentication, and user profile management. It depends on UserRepository for data persistence.",
  "llm_provider": "ollama",
  "llm_model": "qwen2.5-coder",
  "prompt_tokens": 1200,
  "output_tokens": 150,
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z"
}

Get Entity Summary

Get a specific function or class summary by name. Supports on-demand generation - if the summary doesn't exist, it will be generated automatically.

POST /codeapi/v1/summaries/entity

Request:

{
  "repo_name": "my-project",
  "file_path": "/path/to/UserService.java",
  "entity_type": "function",
  "entity_name": "getUser"
}
Field Type Required Description
repo_name string Yes Repository name
file_path string Yes Absolute path to the file
entity_type string Yes Type: "function" or "class"
entity_name string Yes Name of the function or class

Response:

{
  "id": 123,
  "entity_id": "func-456",
  "entity_type": "function",
  "entity_name": "getUser",
  "file_path": "/path/to/UserService.java",
  "summary": "ONE_LINE: Retrieves a user by ID from the database.\nDESCRIPTION: This method queries the user repository to find a user matching the provided ID. Returns null if no user is found.\nSIDE_EFFECTS: Database read operation.",
  "llm_provider": "ollama",
  "llm_model": "qwen2.5-coder",
  "prompt_tokens": 450,
  "output_tokens": 85,
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z"
}

Error Response (404):

{
  "error": "summary not found"
}

Get Summary Statistics

Get statistics about code summaries for a repository.

POST /codeapi/v1/summaries/stats

Request:

{
  "repo_name": "my-project"
}

Response:

{
  "repo_name": "my-project",
  "stats": {
    "total": 250,
    "functions": 180,
    "classes": 45,
    "files": 25,
    "folders": 0,
    "projects": 0,
    "total_prompt_tokens": 125000,
    "total_output_tokens": 35000
  }
}

Docker

Build Image
make docker-build
Run Container
# Interactive mode
make docker-run

# Detached mode
make docker-run-detached

# With custom work directory
make docker-run-with-workdir WORKDIR=/path/to/code
Docker Compose (Full Stack)
# Start all services (Neo4j, MySQL, Qdrant, CodeAPI)
make docker-compose-up

# View logs
make docker-compose-logs

# Stop all services
make docker-compose-down

Supported Languages

Language Parser LSP Server Key Features
Go tree-sitter-go gopls Generics, interfaces, goroutines, channels
Python tree-sitter-python pyright Async/await, decorators, type hints, comprehensions
Java tree-sitter-java Eclipse JDT.LS Records, sealed classes, pattern matching, lambdas, annotations
TypeScript tree-sitter-typescript typescript-language-server Generics, advanced types, decorators
JavaScript tree-sitter-javascript typescript-language-server ES6+, async/await, classes, arrow functions
C# tree-sitter-c-sharp csharp-ls Classes, interfaces, LINQ, async/await
Java Support

Java support includes full LSP integration via Eclipse JDT Language Server for semantic analysis (call hierarchies, symbol resolution) combined with tree-sitter for fast syntax parsing.

Chained Method Calls:

CodeAPI correctly parses and tracks chained method calls common in Java (fluent APIs, Stream API, repository pattern):

// All method calls in the chain are captured:
return repository.findByVetId(id)   // FunctionCall → findByVetId
    .stream()                        // FunctionCall → stream
    .map(this::toDto)                // FunctionCall → map
    .collect(Collectors.toList());   // FunctionCall → collect

This enables accurate CALLS_FUNCTION relationship tracking for Spring Data repositories, Stream operations, and builder patterns.

Setup:

Eclipse JDT.LS is bundled in the assets/ folder as a tar.gz archive. Extract it before first use:

cd assets
tar -xzf jdt-language-server-*.tar.gz

This creates the bin/jdtls launcher and plugins/ directory needed by the language server.

Configuration:

language_servers:
  java: "${CODEAPI_ROOT}/scripts/javalsp.sh"

External Module Detection: Java LSP client automatically detects external dependencies from:

  • Maven local repository (.m2/repository/)
  • Gradle cache (.gradle/caches/)
  • Build output directories (target/, build/, out/)
  • JDK/JRE locations
Java Annotations in Metadata

Java annotations are automatically extracted and stored in the metadata field of Class and Function nodes. This enables querying code by framework-specific annotations (e.g., Spring Boot @RestController, @GetMapping).

API Access:

Metadata is exposed in all Code Graph API responses (/codeapi/v1/classes, /codeapi/v1/methods, etc.). See API.md for complete documentation.

How Annotations Are Captured:

Annotations are extracted from classes, interfaces, records, enums, methods, and constructors. Each annotation is serialized as a JSON string containing:

  • name: The annotation name (e.g., "RestController", "GetMapping")
  • arguments: Optional key-value pairs for annotation arguments

Example: Spring Boot Controller

For a class like:

@RestController
@RequestMapping("/api/owners")
public class OwnerController {

    @GetMapping("/{id}")
    public Owner getOwner(@PathVariable Long id) { ... }
}

The metadata stored in Neo4j:

// Class node metadata
{
  "annotations": [
    "{\"name\":\"RestController\"}",
    "{\"name\":\"RequestMapping\",\"arguments\":{\"value\":\"/api/owners\"}}"
  ]
}

// Method node metadata
{
  "annotations": [
    "{\"name\":\"GetMapping\",\"arguments\":{\"value\":\"/{id}\"}}"
  ]
}

Querying Annotations via Cypher:

Find all REST controllers:

MATCH (c:Class)
WHERE ANY(a IN c.annotations WHERE a CONTAINS '"name":"RestController"')
RETURN c.name, c.file_path

Find all methods with @GetMapping:

MATCH (f:Function)
WHERE ANY(a IN f.annotations WHERE a CONTAINS '"name":"GetMapping"')
RETURN f.name, f.annotations

Supported Annotation Types:

  • Marker annotations: @Override, @Repository, @Service
  • Single-value annotations: @GetMapping("/path"), @Query("SELECT ...")
  • Multi-value annotations: @Size(min = 1, max = 50), @Column(name = "id", nullable = false)

Project Structure

codeapi/
├── cmd/                    # Entry points
│   └── main.go            # Main server and CLI
├── internal/
│   ├── handler/           # HTTP route handlers
│   ├── controller/        # Business logic
│   ├── service/           # Domain services
│   │   ├── codegraph/    # Neo4j code graph
│   │   └── vector/       # Vector DB & embeddings
│   ├── codeapi/          # CodeAPI facade
│   ├── parse/            # Language parsers
│   ├── model/            # Data models
│   ├── config/           # Configuration
│   ├── db/               # Database layer
│   └── util/             # Utilities
├── pkg/
│   └── lsp/              # LSP integration
├── config/               # Configuration files
├── tests/                # Test repositories
├── Makefile
├── Dockerfile
└── docker-compose.yml

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Directories

Path Synopsis
internal
codeapi
Package codeapi provides a clean read interface for querying the code graph.
Package codeapi provides a clean read interface for querying the code graph.
db
pkg
lsp

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL