
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
@botanicastudios/claude-code-sdk-ts
Advanced tools
Unofficial TypeScript port of the official Python Claude Code SDK
Unofficial TypeScript port of the official Python Claude Code SDK for Claude Code, the CLI tool for interacting with Claude.
Note: This is a community-maintained TypeScript port. For the official Python SDK, see claude-code-sdk.
npm install @instantlyeasy/claude-code-sdk-ts
# or
yarn add @instantlyeasy/claude-code-sdk-ts
# or
pnpm add @instantlyeasy/claude-code-sdk-ts
Prerequisites:
npm install -g @anthropic-ai/claude-code
)The SDK now includes a powerful fluent API that makes common tasks easier:
import { claude } from '@instantlyeasy/claude-code-sdk-ts';
// Simple Hello World
const response = await claude().withModel('sonnet').skipPermissions().query('Say "Hello World!"').asText();
console.log(response); // Outputs: Hello World!
import { claude } from '@instantlyeasy/claude-code-sdk-ts';
// Create a file with automatic result extraction
const result = await claude()
.allowTools('Write')
.skipPermissions()
.query('Create a hello.txt file with "Hello from Claude!"')
.asResult();
console.log('Task completed:', result);
// Read and parse JSON data
const config = await claude().allowTools('Read').query('Read package.json and return its content').asJSON();
console.log('Version:', config.version);
Maintain conversation context across multiple queries with built-in session handling:
import { claude } from '@instantlyeasy/claude-code-sdk-ts';
// Session management with explicit session ID
const builder = claude().withModel('sonnet').skipPermissions();
const parser = builder.query('Pick a random number from 1-100');
const sessionId = await parser.getSessionId();
const firstResponse = await parser.asText();
const secondResponse = await builder.withSessionId(sessionId).query('What number did you pick?').asText();
// Claude remembers the number from the first query
// Manual session management
const builder = claude().withModel('sonnet').skipPermissions();
const parser = builder.query('Tell me a fun fact');
const sessionId = await parser.getSessionId();
const fact = await parser.asText();
// Continue conversation with session ID
const follow = await builder.withSessionId(sessionId).query('Tell me more about that topic').asText();
import { claude, ConsoleLogger, LogLevel } from '@instantlyeasy/claude-code-sdk-ts';
// Full example with logging, event handlers, and response parsing
const logger = new ConsoleLogger(LogLevel.DEBUG);
const analysis = await claude()
.withModel('opus')
.allowTools('Read', 'Grep', 'Glob')
.inDirectory(process.cwd())
.withLogger(logger)
.onToolUse(tool => console.log(`Using ${tool.name}...`))
.query('Find all TODO comments in the codebase')
.asToolExecutions();
// Get detailed tool execution results
for (const execution of analysis) {
console.log(`${execution.tool}: ${execution.isError ? 'Failed' : 'Success'}`);
}
The original async generator API is still fully supported:
import { query } from '@instantlyeasy/claude-code-sdk-ts';
// Simple Hello World
for await (const message of query('Say "Hello World!"')) {
if (message.type === 'assistant') {
for (const block of message.content) {
if (block.type === 'text') {
console.log(block.text); // Outputs: Hello World!
}
}
}
}
This SDK delegates all authentication to the Claude CLI. There are two ways to authenticate:
# One-time setup - login with your Claude account
claude login
The Claude CLI may support API key authentication in some configurations. Check your Claude CLI documentation.
Important: The SDK does not handle authentication directly. If you see authentication errors, you need to authenticate using the Claude CLI first.
claude(): QueryBuilder
Creates a new query builder for the fluent API.
const builder = claude()
.withModel('sonnet') // Set model
.allowTools('Read', 'Write') // Configure tools
.skipPermissions() // Skip permission prompts
.withTimeout(30000) // Set timeout
.inDirectory('/path') // Set working directory
.withLogger(logger) // Add logging
.onMessage(handler) // Add event handlers
.withSessionId('session-id') // Continue existing session
.query('Your prompt'); // Execute query
.asText()
- Extract plain text from assistant messages.asJSON<T>()
- Parse JSON from the response.asResult()
- Get the final result message.asToolExecutions()
- Get all tool executions with results.findToolResults(toolName)
- Find results from specific tool.getUsage()
- Get token usage and cost statistics.stream(callback)
- Stream messages with a callbackquery(prompt: string, options?: ClaudeCodeOptions): AsyncGenerator<Message>
Query Claude Code with a prompt and options.
prompt
(string): The prompt to send to Claude Codeoptions
(ClaudeCodeOptions, optional): Configuration optionsAn async generator that yields Message
objects.
ClaudeCodeOptions
interface ClaudeCodeOptions {
// Model selection
model?: string; // Claude model to use (e.g., 'opus', 'sonnet')
// Tool configuration
allowedTools?: ToolName[]; // Explicitly allowed tools
deniedTools?: ToolName[]; // Explicitly denied tools
// Permission handling
permissionMode?: PermissionMode; // 'default' | 'acceptEdits' | 'bypassPermissions'
// Session management
sessionId?: string; // Existing session ID to continue conversation
// Execution environment
cwd?: string; // Working directory
env?: Record<string, string>; // Environment variables
// MCP (Model Context Protocol) servers
mcpServers?: MCPServer[]; // MCP servers to connect
// SDK options
timeout?: number; // Timeout in milliseconds
debug?: boolean; // Enable debug logging (Note: may interfere with JSON parsing)
// Deprecated options (not used by CLI transport)
apiKey?: string; // Use `claude login` instead
baseUrl?: string; // Not applicable for CLI
maxTokens?: number; // Not configurable via CLI
temperature?: number; // Not configurable via CLI
tools?: ToolName[]; // Use allowedTools/deniedTools instead
context?: string[]; // Not implemented
}
Message
type Message = UserMessage | AssistantMessage | SystemMessage | ResultMessage;
interface UserMessage {
type: 'user';
content: string;
}
interface AssistantMessage {
type: 'assistant';
content: ContentBlock[];
}
interface SystemMessage {
type: 'system';
content: string;
}
interface ResultMessage {
type: 'result';
content: string;
usage?: UsageInfo;
cost?: CostInfo;
}
ContentBlock
type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock;
interface TextBlock {
type: 'text';
text: string;
}
interface ToolUseBlock {
type: 'tool_use';
id: string;
name: string;
input: Record<string, unknown>;
}
interface ToolResultBlock {
type: 'tool_result';
tool_use_id: string;
content: string | Array<TextBlock | unknown>;
is_error?: boolean;
}
A chainable API that reduces boilerplate and improves readability:
Extract exactly what you need from Claude's responses:
.asText()
.asJSON<T>()
Pluggable logging system for better debugging:
Check out the examples directory for complete, runnable examples including:
For detailed documentation on the fluent API, see docs/FLUENT_API.md.
The fluent API dramatically reduces boilerplate code. Here are some common migration patterns:
let fullText = '';
for await (const message of query('Generate a story')) {
if (message.type === 'assistant') {
for (const block of message.content) {
if (block.type === 'text') {
fullText += block.text;
}
}
}
}
console.log(fullText);
const fullText = await claude().query('Generate a story').asText();
console.log(fullText);
More migration examples in docs/FLUENT_API.md#migration-guide.
import { query, ClaudeSDKError, CLINotFoundError } from '@instantlyeasy/claude-code-sdk-ts';
try {
for await (const message of query('Hello')) {
console.log(message);
}
} catch (error) {
if (error instanceof CLINotFoundError) {
console.error('Please install Claude Code CLI first:');
console.error('npm install -g @anthropic-ai/claude-code');
} else if (error instanceof ClaudeSDKError) {
console.error('SDK error:', error.message);
} else if (error.message?.includes('Invalid API key')) {
console.error('Authentication required. Please run: claude login');
} else {
console.error('Unexpected error:', error);
}
}
# Install dependencies
npm install
# Build the SDK
npm run build
# Run tests
npm test
# Type checking
npm run typecheck
# Linting
npm run lint
New Features:
claude()
for improved developer experienceonMessage()
, onAssistant()
, and onToolUse()
callbacks.getUsage()
Improvements:
claude
command--print
flag for non-interactive modeMIT
FAQs
Unofficial TypeScript port of the official Python Claude Code SDK
The npm package @botanicastudios/claude-code-sdk-ts receives a total of 14 weekly downloads. As such, @botanicastudios/claude-code-sdk-ts popularity was classified as not popular.
We found that @botanicastudios/claude-code-sdk-ts demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.