# claude-agent-sdk-java
**Repository Path**: kensan/claude-agent-sdk-java
## Basic Information
- **Project Name**: claude-agent-sdk-java
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-01-14
- **Last Updated**: 2026-01-14
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Claude Agent SDK for Java
Java SDK for interacting with [Claude Code CLI](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview). This is a pure Java implementation that mirrors the design of the official Python and TypeScript Claude Agent SDKs.
## Features
| Feature | Description |
|---------|-------------|
| **Simple One-Shot API** | `Query.text()` for quick answers in one line |
| **Blocking Client** | `ClaudeSyncClient` for multi-turn conversations with Iterator |
| **Reactive Client** | `ClaudeAsyncClient` with Flux/Mono for Spring WebFlux |
| **Hook System** | Register callbacks for tool use events |
| **MCP Integration** | Support for Model Context Protocol servers |
| **Permission Callbacks** | Programmatic control over tool execution |
## Requirements
- Java 17+
- Claude Code CLI installed and authenticated
- Maven 3.8+
## Installation
> **Note**: This project is currently available as a SNAPSHOT. Releases to Maven Central are coming soon.
### Maven
Add the snapshot repository and dependency to your `pom.xml`:
```xml
central-snapshots
https://central.sonatype.com/repository/maven-snapshots/
true
org.springaicommunity
claude-code-sdk
1.0.0-SNAPSHOT
```
### Gradle
Add the snapshot repository and dependency to your `build.gradle`:
```groovy
repositories {
mavenCentral()
maven {
url 'https://central.sonatype.com/repository/maven-snapshots/'
}
}
dependencies {
implementation 'org.springaicommunity:claude-code-sdk:1.0.0-SNAPSHOT'
}
```
### Building from Source
```bash
git clone https://github.com/spring-ai-community/claude-agent-sdk-java.git
cd claude-agent-sdk-java
./mvnw install
```
## Three API Styles
| API | Class | Programming Style | Best For |
|-----|-------|-------------------|----------|
| **One-shot** | `Query` | Static methods | Simple scripts, CLI tools |
| **Blocking** | `ClaudeSyncClient` | Iterator-based | Traditional applications, synchronous workflows |
| **Reactive** | `ClaudeAsyncClient` | Flux/Mono | Non-blocking applications, high concurrency |
Both `ClaudeSyncClient` and `ClaudeAsyncClient` support the full feature set: multi-turn conversations, hooks, MCP integration, and permission callbacks. They differ only in programming paradigm (blocking vs non-blocking).
**Factory Pattern**: Use `ClaudeClient.sync()` or `ClaudeClient.async()` to create clients.
### Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ YOUR APPLICATION │
└───────────────┬─────────────────────┬─────────────────┬─────────┘
│ │ │
▼ ▼ ▼
┌───────────────────┐ ┌───────────────────┐ ┌─────────────────┐
│ Query │ │ ClaudeSyncClient │ │ ClaudeAsyncClient│
│ (one-shot) │ │ (blocking) │ │ (reactive) │
│ │ │ │ │ │
│ Query.text() │ │ Iterator-based │ │ Flux/Mono │
│ Query.execute() │ │ Multi-turn │ │ Spring WebFlux│
└─────────┬─────────┘ └─────────┬─────────┘ └────────┬────────┘
│ │ │
└───────────────────────┼──────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ StreamingTransport │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ • Subprocess management (Process API) ││
│ │ • JSON-LD streaming via stdin/stdout ││
│ │ • State machine: DISCONNECTED → CONNECTED → CLOSED ││
│ │ • Thread-safe with separate schedulers ││
│ └─────────────────────────────────────────────────────────────┘│
└───────────────────────────────┬─────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ Claude Code CLI │
│ (claude --output-format stream-json) │
└─────────────────────────────────────────────────────────────────┘
```
### Message Flow
```
┌──────────────┐ ┌─────────────────┐ ┌──────────┐
│ Your Code │ │ StreamingTransport│ │ Claude │
└──────┬───────┘ └────────┬────────┘ └────┬─────┘
│ │ │
│ connect("Hello") │ │
│ ─────────────────────────>│ spawn process │
│ │ ──────────────────────>│
│ │ │
│ │ SystemMessage │
│ │<───────────────────────│
│ Iterator/Flux yields │ │
│<──────────────────────────│ AssistantMessage │
│ │<───────────────────────│
│ process message... │ │
│<──────────────────────────│ ResultMessage │
│ │<───────────────────────│
│ (turn complete) │ │
│ │ │
│ query("Follow-up") │ │
│ ─────────────────────────>│ write to stdin │
│ │ ──────────────────────>│
│ │ │
│ Iterator/Flux yields │ AssistantMessage │
│<──────────────────────────│<───────────────────────│
│ │ │
│ close() │ terminate process │
│ ─────────────────────────>│ ──────────────────────>│
│ │ │
▼ ▼ ▼
```
---
## API 1: Query (Simple One-Shot)
The simplest way to use Claude - one line of code:
```java
import org.springaicommunity.claude.agent.sdk.Query;
String answer = Query.text("What is 2+2?");
System.out.println(answer); // "4"
```
### With Options
```java
String answer = Query.text("Explain quantum computing",
QueryOptions.builder()
.model("claude-sonnet-4-20250514")
.appendSystemPrompt("Be concise")
.timeout(Duration.ofMinutes(5))
.build());
```
### Full Result with Metadata
```java
QueryResult result = Query.execute("Write a haiku about Java");
result.text().ifPresent(System.out::println);
System.out.println("Cost: $" + result.metadata().cost().calculateTotal());
System.out.println("Duration: " + result.metadata().getDuration().toMillis() + "ms");
```
---
## API 2: ClaudeSyncClient (Blocking/Iterator)
For multi-turn conversations, hooks, and MCP servers:
```java
import org.springaicommunity.claude.agent.sdk.ClaudeClient;
import org.springaicommunity.claude.agent.sdk.ClaudeSyncClient;
try (ClaudeSyncClient client = ClaudeClient.sync()
.workingDirectory(Path.of("."))
.model("claude-sonnet-4-20250514")
.build()) {
// Simplest: just get the text (80% use case)
String answer = client.connectText("What is 2+2?");
System.out.println(answer); // "4"
// Follow-up with context preserved
String followUp = client.queryText("Multiply that by 10");
System.out.println(followUp); // "40"
}
```
### Full Message Access (20% use case)
When you need message metadata, tool use details, or cost information:
```java
try (ClaudeSyncClient client = ClaudeClient.sync()
.workingDirectory(Path.of("."))
.build()) {
// For-each with good toString() on all message types
for (Message msg : client.connectAndReceive("List files in current directory")) {
System.out.println(msg); // AssistantMessage, ResultMessage, etc.
}
}
```
### With Hooks
```java
HookRegistry hookRegistry = new HookRegistry();
// Block dangerous commands
hookRegistry.registerPreToolUse("Bash", input -> {
if (input instanceof HookInput.PreToolUseInput preToolUse) {
String cmd = preToolUse.getArgument("command", String.class).orElse("");
if (cmd.contains("rm -rf")) {
return HookOutput.block("Dangerous command blocked");
}
}
return HookOutput.allow();
});
try (ClaudeSyncClient client = ClaudeClient.sync()
.workingDirectory(Path.of("."))
.permissionMode(PermissionMode.DEFAULT)
.hookRegistry(hookRegistry)
.build()) {
// Hooks intercept tool calls
}
```
---
## API 3: ClaudeAsyncClient (Reactive)
For reactive applications using Project Reactor:
```java
ClaudeAsyncClient client = ClaudeClient.async()
.workingDirectory(Path.of("."))
.model("claude-sonnet-4-20250514")
.permissionMode(PermissionMode.BYPASS_PERMISSIONS)
.build();
// Stream text as it arrives
client.connect("Explain recursion").textStream()
.doOnNext(System.out::print)
.subscribe();
```
### Multi-Turn with flatMap Chaining
```java
client.connect("My favorite color is blue.").text()
.doOnSuccess(System.out::println)
.flatMap(r1 -> client.query("What is my favorite color?").text())
.doOnSuccess(System.out::println) // Claude remembers: "blue"
.flatMap(r2 -> client.query("Spell it backwards").text())
.doOnSuccess(System.out::println) // "eulb"
.subscribe();
```
### Full Message Access (20% use case)
When you need all message types (tool use, metadata, etc.):
```java
client.query("List files").messages()
.doOnNext(System.out::println) // Good toString() on all types
.subscribe();
```
---
## Configuration Options
```java
// Via ClaudeClient builder
ClaudeSyncClient client = ClaudeClient.sync()
.workingDirectory(Path.of("."))
.model("claude-sonnet-4-20250514")
.systemPrompt("You are a helpful assistant")
.permissionMode(PermissionMode.DEFAULT)
.timeout(Duration.ofMinutes(5))
.hookRegistry(hookRegistry)
.build();
// Or via CLIOptions
CLIOptions options = CLIOptions.builder()
.model("claude-sonnet-4-20250514")
.permissionMode(PermissionMode.DEFAULT)
.systemPrompt("You are a helpful assistant")
.appendSystemPrompt("Be concise")
.maxTurns(10)
.allowedTools(List.of("Read", "Grep"))
.disallowedTools(List.of("Bash"))
.build();
ClaudeSyncClient client = ClaudeClient.sync(options)
.workingDirectory(Path.of("."))
.build();
```
---
## Project Structure
```
claude-agent-sdk-java/
├── claude-code-sdk/ # Core SDK module
│ └── src/
│ ├── main/java/org/springaicommunity/claude/agent/sdk/
│ │ ├── Query.java # Simple one-shot API
│ │ ├── ClaudeClient.java # Factory: sync() / async()
│ │ ├── ClaudeSyncClient.java # Blocking client interface
│ │ ├── ClaudeAsyncClient.java # Reactive client interface
│ │ ├── transport/ # StreamingTransport
│ │ ├── streaming/ # MessageStreamIterator
│ │ ├── hooks/ # HookRegistry, HookCallback
│ │ ├── permission/ # ToolPermissionCallback
│ │ ├── mcp/ # MCP server configuration
│ │ ├── types/ # Message types, content blocks
│ │ └── parsing/ # JSON parsing, control messages
│ └── test/
└── examples/
├── hello-world/ # All three APIs demonstrated
├── email-agent/ # ClaudeAsyncClient with Vaadin UI
├── excel-demo/ # ClaudeAsyncClient streaming
└── research-agent/ # ClaudeSyncClient multi-turn with hooks
```
---
## Python SDK Feature Comparison
The Java SDK mirrors the official [Python Claude Agent SDK](https://github.com/anthropics/claude-code-sdk-python). Current feature parity status:
| Feature | Python | Java | Notes |
|---------|:------:|:----:|-------|
| **Core APIs** | | | |
| One-shot queries | ✓ | ✓ | `Query.text()`, `Query.execute()` |
| Blocking client | ✓ | ✓ | `ClaudeClient.sync()` |
| Async client | ✓ | ✓ | `ClaudeClient.async()` (Reactor) |
| Multi-turn conversations | ✓ | ✓ | Context preserved across turns |
| **Configuration** | | | |
| Model selection | ✓ | ✓ | `.model()` or `CLIOptions` |
| System prompt | ✓ | ✓ | `.systemPrompt()` |
| Append system prompt | ✓ | ✓ | `.appendSystemPrompt()` |
| Permission modes | ✓ | ✓ | `PermissionMode` enum |
| Allowed/disallowed tools | ✓ | ✓ | `.allowedTools()`, `.disallowedTools()` |
| Max turns | ✓ | ✓ | `.maxTurns()` |
| Max tokens | ✓ | ✓ | `.maxTokens()` |
| **Extensibility** | | | |
| Hook system (PreToolUse) | ✓ | ✓ | `HookRegistry.registerPreToolUse()` |
| Hook system (PostToolUse) | ✓ | ✓ | `HookRegistry.registerPostToolUse()` |
| MCP server integration | ✓ | ✓ | External + in-process servers |
| Permission callbacks | ✓ | ✓ | `ToolPermissionCallback` |
| Agent definitions | ✓ | ✓ | `AgentDefinition` for subagents |
| **Advanced** | | | |
| File checkpointing | ✓ | ✗ | Not yet implemented |
| Beta features (`--betas`) | ✓ | ✗ | Not yet implemented |
| Sandbox settings | ✓ | ✗ | Not yet implemented |
### Key Differences
1. **Reactive Streaming**: Java SDK uses [Project Reactor](https://projectreactor.io/) (Flux/Mono) for reactive streams, while Python uses async generators.
2. **Factory Pattern**: Java follows the MCP Java SDK pattern with `ClaudeClient.sync()` / `ClaudeClient.async()` factory methods.
3. **Iterator vs Iterable**: `ClaudeSyncClient.receiveResponse()` returns `Iterator` (not `Iterable`), requiring `while (response.hasNext())` pattern.
4. **Type Safety**: Java SDK leverages sealed interfaces and pattern matching for message type handling.
## License
Apache License 2.0
## Contributing
Contributions are welcome! Please open an issue or submit a pull request.