claudecode4j

mcp
Security Audit
Warn
Health Warn
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 8 GitHub stars
Code Pass
  • Code scan — Scanned 11 files during light audit, no dangerous patterns found
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Java integration for Claude Code CLI. Features Virtual Thread execution, Spring Boot auto-configuration, Kafka request-reply adapters, and REST/SSE streaming endpoints.

README.md

ClaudeCode4J

Bring the agentic power of Claude Code to Java.

English中文فارسیEspañol


Java 25 Spring Boot 4.0.1 License

CI
Quality Gate Status
Coverage
Bugs


A modern Java library for integrating with Claude Code CLI — Anthropic's agentic coding tool.

Table of Contents


Features

  • Pure Java API - Clean interfaces with sealed types and records
  • Virtual Threads - Efficient concurrent execution using Project Loom
  • Structured Concurrency - Safe parallel process management
  • Spring Boot 4 Integration - Auto-configuration, health checks, and metrics
  • REST API Adapter - HTTP endpoints with SSE streaming support
  • Kafka Adapter - Request-reply pattern with correlation IDs
  • WebSocket Terminal - Interactive sessions with human-in-the-loop support
  • MCP Server - Expose Java methods as Claude tools via Model Context Protocol
  • Smart Context - Token-aware context optimization using JTokkit
  • Resilience - Built-in retry with exponential backoff
  • JPMS Ready - Full Java Platform Module System support
  • Null-Safe - JSpecify annotations throughout

Requirements

  • Java 25+
  • Claude Code CLI installed (npm install -g @anthropic-ai/claude-code)
  • Maven 3.9+

Installation

Maven BOM (Recommended)

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.github.sudoitir</groupId>
            <artifactId>claudecode4j-bom</artifactId>
            <version>2026.1.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Core Library (No Spring)

<dependency>
    <groupId>io.github.sudoitir</groupId>
    <artifactId>claudecode4j-core</artifactId>
</dependency>

Spring Boot Starter

<dependency>
    <groupId>io.github.sudoitir</groupId>
    <artifactId>claudecode4j-spring-boot-starter</artifactId>
</dependency>

REST Adapter

<dependency>
    <groupId>io.github.sudoitir</groupId>
    <artifactId>claudecode4j-rest-adapter</artifactId>
</dependency>

Kafka Adapter

<dependency>
    <groupId>io.github.sudoitir</groupId>
    <artifactId>claudecode4j-kafka-adapter</artifactId>
</dependency>

WebSocket Adapter

<dependency>
    <groupId>io.github.sudoitir</groupId>
    <artifactId>claudecode4j-websocket-adapter</artifactId>
</dependency>

MCP Server

<dependency>
    <groupId>io.github.sudoitir</groupId>
    <artifactId>claudecode4j-mcp-server</artifactId>
</dependency>

Context Module (Token Optimization)

<dependency>
    <groupId>io.github.sudoitir</groupId>
    <artifactId>claudecode4j-context</artifactId>
</dependency>

Quick Start

Standalone Usage (No Spring)

import ir.sudoit.claudecode4j.api.client.ClaudeClient;
import ir.sudoit.claudecode4j.api.model.request.Prompt;
import ir.sudoit.claudecode4j.core.client.DefaultClaudeClientFactory;

// Create client using SPI
ClaudeClient client = new DefaultClaudeClientFactory().create();

// Execute a prompt
Prompt prompt = Prompt.of("Explain what this code does");
ClaudeResponse response = client.execute(prompt);

// Handle response using pattern matching
switch (response) {
    case TextResponse text -> System.out.println(text.content());
    case StreamResponse stream -> stream.events().forEach(System.out::println);
    case ErrorResponse error -> System.err.println(error.message());
}

Async Execution

CompletableFuture<ClaudeResponse> future = client.executeAsync(prompt);
future.thenAccept(response -> {
    if (response instanceof TextResponse text) {
        System.out.println(text.content());
    }
});

Streaming

import ir.sudoit.claudecode4j.api.model.response.StreamEvent;
import java.util.stream.Stream;

Stream<StreamEvent> events = client.stream(prompt);
events.forEach(event -> {
    switch (event) {
        case StreamEvent.Text text -> System.out.print(text.content());
        case StreamEvent.Tool tool -> System.out.println("Tool: " + tool.name());
        case StreamEvent.Result result -> System.out.println("\nDone: " + result.success());
    }
});

Session Management

// Create a conversation session
ClaudeSession session = client.createSession();

// Continue conversation with context
ClaudeResponse response1 = session.send(Prompt.of("Create a Java class for User"));
ClaudeResponse response2 = session.send(Prompt.of("Add validation annotations"));

// Session maintains conversation history
session.close();

Spring Boot Integration

Configuration

claude:
  code:
    binary-path: /usr/local/bin/claude  # Optional: auto-detected
    concurrency-limit: 4                 # Max concurrent executions
    default-timeout: 5m                  # Execution timeout
    dangerously-skip-permissions: false  # Security flag
    health:
      enabled: true                      # Enable health indicator
      cache-duration: 30s                # Health check cache
    metrics:
      enabled: true                      # Enable Micrometer metrics

Auto-wired Usage

@Service
public class CodeAssistantService {

    private final ClaudeClient claudeClient;

    public CodeAssistantService(ClaudeClient claudeClient) {
        this.claudeClient = claudeClient;
    }

    public String analyzeCode(String code) {
        Prompt prompt = Prompt.builder()
            .text("Analyze this code for potential issues:\n" + code)
            .outputFormat(OutputFormat.TEXT)
            .build();

        ClaudeResponse response = claudeClient.execute(prompt);
        return switch (response) {
            case TextResponse text -> text.content();
            case ErrorResponse error -> "Error: " + error.message();
            default -> "Unexpected response";
        };
    }
}

Concurrency Limiting with AOP

@Service
public class RateLimitedService {

    private final ClaudeClient claudeClient;

    @ConcurrencyLimit(permits = 2)  // Max 2 concurrent calls to this method
    public ClaudeResponse processWithLimit(Prompt prompt) {
        return claudeClient.execute(prompt);
    }
}

REST API

Enable the REST adapter to expose Claude functionality via HTTP:

claude:
  code:
    rest:
      enabled: true
      base-path: /api/claude

Endpoints

Method Path Description
POST /api/claude/prompt Execute prompt synchronously
POST /api/claude/prompt/async Execute prompt asynchronously
POST /api/claude/stream Stream response via SSE
GET /api/claude/health Health check

Example Request

curl -X POST http://localhost:8080/api/claude/prompt \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Write a hello world in Rust",
    "outputFormat": "TEXT",
    "timeout": "PT30S"
  }'

SSE Streaming

curl -N http://localhost:8080/api/claude/stream \
  -H "Content-Type: application/json" \
  -d '{"text": "Explain microservices architecture"}'

OpenAI-Compatible API

The REST adapter includes an OpenAI-compatible /v1/chat/completions endpoint, allowing tools and applications designed for OpenAI's API to work with Claude Code CLI.

Configuration

claude:
  code:
    rest:
      openai:
        enabled: true                    # Enable OpenAI-compatible endpoint (default: true)
        base-path: /v1                   # Base path for OpenAI endpoints (default: /v1)

Endpoints

Method Path Description
POST /v1/chat/completions OpenAI-compatible chat completions API

Example Request

curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Write a hello world in Rust"}
    ],
    "max_tokens": 1000,
    "temperature": 0.7,
    "stream": false
  }'

Streaming Example

curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "messages": [
      {"role": "user", "content": "Explain quantum computing"}
    ],
    "stream": true
  }'

Response Format (Non-Streaming)

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1234567890,
  "model": "claude-3-5-sonnet-20241022",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Hello, World! in Rust:\n\nfn main() {\n    println!(\"Hello, World!\");\n}"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 20,
    "completion_tokens": 30,
    "total_tokens": 50
  }
}

Streaming Format

data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1234567890,"model":"claude-3-5-sonnet-20241022","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}

data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1234567890,"model":"claude-3-5-sonnet-20241022","choices":[{"index":0,"delta":{"content": " World!"},"finish_reason":null}]}

data: [DONE]

Anthropic-Compatible API

The REST adapter also includes an Anthropic-compatible /v1/messages endpoint, following Anthropic's Messages API specification.

Configuration

claude:
  code:
    rest:
      anthropic:
        enabled: true                    # Enable Anthropic-compatible endpoint (default: true)
        base-path: /v1                   # Base path for Anthropic endpoints (default: /v1)

Endpoints

Method Path Description
POST /v1/messages Anthropic-compatible Messages API

Example Request

curl -X POST http://localhost:8080/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: not-required" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "max_tokens": 1000,
    "system": "You are a helpful assistant.",
    "messages": [
      {"role": "user", "content": "Write a hello world in Rust"}
    ],
    "stream": false
  }'

Streaming Example

curl -X POST http://localhost:8080/v1/messages \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "max_tokens": 1000,
    "messages": [
      {"role": "user", "content": "Explain reactive programming"}
    ],
    "stream": true
  }'

Response Format (Non-Streaming)

{
  "id": "msg_abc123",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Here is a hello world in Rust:\n\nfn main() {\n    println!(\"Hello, World!\");\n}"
    }
  ],
  "model": "claude-3-5-sonnet-20241022",
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 15,
    "output_tokens": 25
  }
}

Streaming Format

event: message_start
data: {"type":"message_start","message":{"id":"msg_abc123","type":"message","role":"assistant","content":[]}}

event: content_block_start
data: {"type":"content_block_start","index":0}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Here is"}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":25}}

event: message_stop
data: {"type":"message_stop"}

Kafka Integration

Enable request-reply messaging over Kafka:

claude:
  code:
    kafka:
      enabled: true
      request-topic: claude-requests
      reply-topic: claude-replies
      group-id: claude-processor
      reply-timeout: 5m

Producer (Request Side)

@Service
public class KafkaPromptService {

    private final ClaudeKafkaProducer producer;

    public CompletableFuture<String> sendPrompt(String text) {
        return producer.sendRequest(text);
    }
}

Consumer (Processing Side)

The ClaudeKafkaListener automatically:

  1. Consumes messages from request-topic
  2. Executes prompts via ClaudeClient
  3. Sends responses to reply-topic with correlation ID

Module Structure

claudecode4j/
├── claudecode4j-bom/                 # Bill of Materials
├── claudecode4j-api/                 # Interfaces & DTOs
│   ├── client/                       # ClaudeClient, ClaudeSession
│   ├── model/                        # Prompt, Response records
│   ├── exception/                    # Sealed exception hierarchy
│   └── spi/                          # Extension points
├── claudecode4j-core/                # Pure Java implementation
│   ├── client/                       # DefaultClaudeClient
│   ├── process/                      # VirtualThreadExecutor
│   ├── parser/                       # StreamJsonParser
│   └── resolver/                     # Binary resolvers
├── claudecode4j-context/             # Token-aware context optimization
│   ├── spi/                          # TokenCounter, ContextOptimizer
│   ├── model/                        # ContextBudget, ModelTokenLimits
│   ├── tokenizer/                    # JTokkit implementation
│   └── optimizer/                    # DefaultContextOptimizer
├── claudecode4j-spring-boot-starter/ # Spring Boot integration
│   ├── autoconfigure/                # Auto-configuration
│   ├── properties/                   # ConfigurationProperties
│   ├── health/                       # HealthIndicator
│   ├── metrics/                      # Micrometer metrics
│   └── resilience/                   # Retry with backoff
├── claudecode4j-rest-adapter/        # REST API
│   ├── controller/                   # ClaudeController
│   └── dto/                          # Request/Response DTOs
├── claudecode4j-kafka-adapter/       # Kafka messaging
│   ├── listener/                     # Message consumer
│   ├── producer/                     # Request producer
│   └── correlation/                  # Correlation ID manager
├── claudecode4j-websocket-adapter/   # WebSocket terminal
│   ├── handler/                      # WebSocket handler
│   ├── session/                      # Session management
│   └── message/                      # Sealed message types
└── claudecode4j-mcp-server/          # MCP Server support
    ├── annotation/                   # @ClaudeTool, @ToolParam
    ├── registry/                     # Tool discovery
    └── server/                       # Tool invocation

Exception Handling

All exceptions extend the sealed ClaudeException:

try {
    ClaudeResponse response = client.execute(prompt);
} catch (ClaudeException e) {
    switch (e) {
        case ClaudeBinaryNotFoundException ex ->
            log.error("Claude CLI not found: {}", ex.getMessage());
        case ClaudeExecutionException ex ->
            log.error("Execution failed: {}", ex.getMessage());
        case ClaudeTimeoutException ex ->
            log.error("Timeout after: {}", ex.getTimeout());
        case ClaudeConfigurationException ex ->
            log.error("Configuration error: {}", ex.getMessage());
    }
}

Observability

Health Check

{
  "status": "UP",
  "components": {
    "claudeCode": {
      "status": "UP",
      "details": {
        "binaryPath": "/usr/local/bin/claude",
        "version": "1.0.0"
      }
    }
  }
}

Metrics (Micrometer)

Metric Type Description
claude.code.executions Counter Total executions
claude.code.executions.active Gauge Currently running
claude.code.execution.duration Timer Execution time
claude.code.errors Counter Error count by type

Security

The library includes built-in security measures:

  • Input Sanitization - Prevents command injection attacks
  • Concurrency Limiting - Protects against resource exhaustion
  • Permission Control - dangerously-skip-permissions must be explicitly enabled

Building from Source

git clone [https://github.com/sudoit/claudecode4j.git](https://github.com/sudoit/claudecode4j.git)
cd claudecode4j
mvn clean install

Running Tests

Test Profiles

# Unit tests only (default - fast, no external dependencies)
mvn test

# Integration tests (requires Docker for Testcontainers)
mvn verify -Pintegration

# All tests including E2E (requires Claude CLI installation and authentication)
mvn verify -Pall

# Run specific test class
mvn test -Dtest=ClaudeRestIntegrationTest

# Run specific test method
mvn test -Dtest=ClaudeRestIntegrationTest#shouldExecutePromptAndReturnResponse

Test Categories

  • Unit Tests (*Test.java): Fast, isolated tests with mocked dependencies
  • Integration Tests (*IntegrationTest.java): Tests with real containers (Testcontainers)
  • E2E Tests (*E2ETest.java): Full end-to-end tests requiring Claude CLI

Note: E2E tests should only be run manually. They require:

  • Claude CLI installed: npm install -g @anthropic-ai/claude-code
  • Claude CLI authenticated (run claude once to authenticate)

Contributing

Contributions are welcome! Please read our Contributing Guide for details.

License

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

Acknowledgments

Reviews (0)

No results found