neosoftware / anthropic-claude-sdk
PHP SDK для Claude Agent (Claude Code). Порт пакета @anthropic-ai/claude-agent-sdk (TypeScript).
Package info
github.com/NEOSoftWare/anthropic-claude-sdk
pkg:composer/neosoftware/anthropic-claude-sdk
Requires
- php: ^8.2
This package is auto-updated.
Last update: 2026-06-05 11:14:28 UTC
README
A PHP 8.2 SDK for working with Claude Agent (Claude Code).
A port of the @anthropic-ai/claude-agent-sdk package (TypeScript).
Requirements
- PHP 8.2+
- Composer
Installation
composer require neosoftware/anthropic-claude-sdk
Claude binary
The SDK runs claude (Claude Code CLI) as a subprocess. Specify the path to it in one of the following ways:
Via QueryOptions — explicitly for a specific agent:
new QueryOptions(claudePathOverride: '/usr/local/bin/claude')
Via an environment variable — globally for the entire application:
CLAUDE_PATH=/usr/local/bin/claude php artisan ...
Installation into vendor/bin — convenient for containers and servers where Claude Code is not installed globally.
The command downloads the binary for your platform from npm and adds the vendor/bin/claude symlink:
vendor/bin/install-claude
allow-plugins permissions are not required.
Quick start
<?php require 'vendor/autoload.php'; use Anthropic\ClaudeAgent\ClaudeAgent; use Anthropic\ClaudeAgent\Types\Options\QueryOptions; $agent = new ClaudeAgent(new QueryOptions( apiKey: $_ENV['ANTHROPIC_API_KEY'], )); $result = $agent->run('Explain what the array_chunk function does in PHP.'); echo $result->result;
Initialization
new ClaudeAgent(QueryOptions $options = new QueryOptions())
Creates the main SDK object. On the first query() / run() call, it automatically finds and starts the claude CLI.
$agent = new ClaudeAgent(new QueryOptions( apiKey: 'sk-ant-...', // Anthropic API key (or ANTHROPIC_API_KEY env) model: 'claude-sonnet-4-6', // model (optional) claudePathOverride: '/usr/local/bin/claude', // custom path to claude (optional) ));
QueryOptions
| Property | Type | Default | Description |
|---|---|---|---|
apiKey |
?string |
null |
Anthropic API key (passed as ANTHROPIC_API_KEY) |
model |
?string |
null |
Claude model (claude-sonnet-4-6, claude-opus-4-7, …) |
cwd |
?string |
null |
Process working directory |
allowedTools |
?string[] |
null |
Tools allowed without confirmation |
disallowedTools |
?string[] |
null |
Disallowed tools |
tools |
?string[] |
null |
Explicit list of available tools |
permissionMode |
?string |
null |
'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'dontAsk' |
maxTurns |
?int |
null |
Maximum number of turns |
maxBudgetUsd |
?float |
null |
Maximum budget in USD |
resume |
?string |
null |
Session ID for resuming a previous conversation |
continue |
bool |
false |
Continue the last conversation in cwd |
sessionId |
?string |
null |
Use a specific session UUID |
additionalDirectories |
?string[] |
null |
Additional directories (--add-dir) |
mcpServers |
?array |
null |
MCP servers: name → configuration |
persistSession |
bool |
true |
Save the session to disk |
maxThinkingTokens |
?int |
null |
Token limit for thinking; deprecated, use thinking |
effort |
?string |
null |
'low' | 'medium' | 'high' | 'xhigh' | 'max' |
thinking |
?array |
null |
{type: 'adaptive'} / {type: 'enabled', budgetTokens: N} / {type: 'disabled'} |
fallbackModel |
?string |
null |
Fallback model |
betas |
?string[] |
null |
Beta features, for example 'context-1m-2025-08-07' |
agent |
?string |
null |
Agent name for the main thread |
allowDangerouslySkipPermissions |
bool |
false |
Skip all permission checks |
permissionPromptToolName |
?string |
null |
MCP tool for permission prompts |
forkSession |
bool |
false |
Fork the session when resuming |
resumeSessionAt |
?string |
null |
Message UUID to resume up to |
includeHookEvents |
bool |
false |
Include hook events in the stream |
includePartialMessages |
bool |
false |
Include partial streaming messages |
verbose |
bool |
false |
Verbose output |
outputFormat |
?array |
null |
Structured output configuration |
settings |
string|array|null |
null |
Settings: JSON path or object |
taskBudget |
?array |
null |
Task budget in tokens, ['total' => N] |
plugins |
?array |
null |
Plugins: [['type' => 'local', 'path' => '...']] |
extraArgs |
?array |
null |
Arbitrary additional CLI arguments |
env |
?array |
null |
Environment variables. If set, the subprocess receives only these variables |
claudePathOverride |
?string |
null |
Absolute path to a custom claude binary |
clientApp |
?string |
null |
Application identifier (→ CLAUDE_AGENT_SDK_CLIENT_APP) |
timeoutSeconds |
?int |
null |
Response timeout in seconds |
Running queries
query() — streaming
Returns Query immediately. Messages are read as they arrive through a generator.
$query = $agent->query('Check all tests and fix the errors'); foreach ($query->messages() as $msg) { match (true) { $msg instanceof SDKSystemMessage => printf("[init] Model: %s\n", $msg->model), $msg instanceof SDKAssistantMessage => printf("%s\n", $msg->getText()), $msg instanceof SDKResultSuccess => printf("Tokens: %d\n", $msg->usage->outputTokens), default => null, }; }
query()->collect() — blocking collection
$result = $agent->query('Task')->collect(); echo $result->result;
run() — shortened blocking call
$result = $agent->run('Explain this code'); echo $result->result;
Query
$query = $agent->query('prompt'); // Streaming through a generator foreach ($query->messages() as $msg) { ... } // Blocking collection of the final response (throws ResultErrorException on error) $result = $query->collect(); // QueryResult
QueryResult
| Property | Type | Description |
|---|---|---|
result |
string |
Final assistant text response |
sessionId |
string |
Session UUID |
resultMessage |
?SDKResultSuccess |
Full object with tokens and cost |
Message types (SDKMessage)
The Query::messages() generator returns objects of the following classes:
SDKSystemMessage (type: 'system', subtype: 'init')
The first message in the stream. Contains session information.
$msg->sessionId; // string — session UUID $msg->model; // string — active model $msg->permissionMode; // string — permission mode $msg->claudeCodeVersion; // string — Claude Code version $msg->tools; // string[] — available tools $msg->cwd; // string — working directory
SDKAssistantMessage (type: 'assistant')
A complete assistant response.
$msg->getText(); // string — text content (convenience method) $msg->message; // array — full BetaMessage object $msg->error; // ?string — API error, if any $msg->uuid; // string $msg->sessionId; // string
SDKUserMessage (type: 'user')
A user message, including replay from history.
$msg->message; // array $msg->isReplay; // bool $msg->isSynthetic; // bool
SDKResultSuccess (type: 'result', subtype: 'success')
Final successful completion message.
$msg->result; // string — final response text $msg->usage; // Usage — tokens $msg->totalCostUsd; // float — cost in USD $msg->numTurns; // int — number of turns $msg->durationMs; // int — execution time $msg->sessionId; // string $msg->structuredOutput; // mixed — if outputFormat was used
SDKResultError (type: 'result', subtype: 'error_*')
Final error message.
$msg->subtype; // 'error_during_execution'|'error_max_turns'|'error_max_budget_usd'|... $msg->errors; // string[] $msg->usage; // Usage
SDKAPIRetryMessage (type: 'system', subtype: 'api_retry')
Notification about retrying an API request.
$msg->attempt; // int $msg->maxRetries; // int $msg->retryDelayMs; // int $msg->errorStatus; // ?int — error HTTP status code
SDKPartialAssistantMessage (type: 'partial_assistant')
A partial streaming response. Only when includePartialMessages: true.
GenericMessage
A fallback for unknown types. Contains raw data in $msg->data.
Usage
$msg->usage->inputTokens; // int $msg->usage->outputTokens; // int $msg->usage->cacheCreationInputTokens; // int $msg->usage->cacheReadInputTokens; // int
Structured output
$result = $agent->run( 'Return project data', new QueryOptions( outputFormat: [ 'type' => 'json_schema', 'schema' => [ 'type' => 'object', 'additionalProperties' => false, 'properties' => [ 'name' => ['type' => 'string'], 'version' => ['type' => 'string'], ], 'required' => ['name', 'version'], ], ], ), ); // With json_schema, data is in structuredOutput; the result field remains empty $data = $result->resultMessage?->structuredOutput; echo $data['name'];
Resuming a session
// First query — save the sessionId $result = $agent->run('First message.'); $sessionId = $result->sessionId; // Resume the session later $result2 = $agent->run('What did you say last time?', new QueryOptions( resume: $sessionId, )); echo $result2->result; // Or continue the last conversation in the current directory $result3 = $agent->run('Continue.', new QueryOptions( continue: true, ));
MCP servers
$result = $agent->run('List files', new QueryOptions( mcpServers: [ 'my-server' => [ 'command' => 'node', 'args' => ['./my-mcp-server.js'], ], ], ));
Error handling
use Anthropic\ClaudeAgent\Exceptions\ClaudeException; use Anthropic\ClaudeAgent\Exceptions\ParseException; use Anthropic\ClaudeAgent\Exceptions\ResultErrorException; use Anthropic\ClaudeAgent\Exceptions\SpawnException; try { $result = $agent->run('...'); } catch (ResultErrorException $e) { // Claude returned an error result (max_turns, max_budget, etc.) echo "Error: {$e->result->subtype}\n"; print_r($e->result->errors); } catch (SpawnException $e) { // claude CLI was not found, did not start, or hung echo "Startup error: " . $e->getMessage(); } catch (ParseException $e) { // claude returned invalid JSON in the JSONL stream echo "Parse error: " . $e->getMessage(); } catch (ClaudeException $e) { // Base class for all SDK exceptions echo "SDK error: " . $e->getMessage(); }
| Exception | When |
|---|---|
ResultErrorException |
Claude returned type=result, is_error=true |
SpawnException |
claude was not found, did not start, hung, or exited with a non-zero code |
ParseException |
claude returned invalid JSON in the JSONL stream |
ClaudeException |
Base class for all SDK exceptions |
Full example
<?php require 'vendor/autoload.php'; use Anthropic\ClaudeAgent\ClaudeAgent; use Anthropic\ClaudeAgent\Exceptions\ResultErrorException; use Anthropic\ClaudeAgent\Exceptions\SpawnException; use Anthropic\ClaudeAgent\Types\Messages\SDKAssistantMessage; use Anthropic\ClaudeAgent\Types\Messages\SDKResultSuccess; use Anthropic\ClaudeAgent\Types\Messages\SDKSystemMessage; use Anthropic\ClaudeAgent\Types\Options\QueryOptions; $agent = new ClaudeAgent(new QueryOptions( apiKey: $_ENV['ANTHROPIC_API_KEY'], model: 'claude-sonnet-4-6', maxTurns: 10, permissionMode: 'acceptEdits', cwd: '/path/to/project', effort: 'high', )); try { // Streaming $query = $agent->query('Find and fix bugs in src/Payment.php'); foreach ($query->messages() as $msg) { match (true) { $msg instanceof SDKSystemMessage => printf("Session: %s\n", $msg->sessionId), $msg instanceof SDKAssistantMessage => print($msg->getText() . "\n"), $msg instanceof SDKResultSuccess => printf( "Done in %dms | $%.4f\n", $msg->durationMs, $msg->totalCostUsd, ), default => null, }; } // Continue the conversation $result = $agent->run('Now write a test for the fixed code.'); echo $result->result; } catch (ResultErrorException $e) { echo "Error: " . $e->getMessage() . PHP_EOL; } catch (SpawnException $e) { echo "Startup error: " . $e->getMessage() . PHP_EOL; }
License
MIT