npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@lasercat/claude-code-sdk-ts

v0.3.5

Published

Unofficial TypeScript port of the official Python Claude Code SDK

Downloads

4

Readme

Claude Code SDK for TypeScript

npm version npm downloads License: MIT TypeScript Node.js Version

Unofficial TypeScript SDK for Claude Code - the powerful CLI tool for interacting with Claude.

✨ What's New in v0.3.3:

  • 🎬 Interactive streaming session with working visual typewriter effects
  • 🛡️ Advanced error handling with retry strategies and typed errors
  • 📊 Token streaming analysis with honest documentation about current behavior
  • 🔧 Production-ready examples that actually work as advertised

Note: For the classic async generator API, see Classic API Documentation.

Installation

npm install @instantlyeasy/claude-code-sdk-ts
# or
yarn add @instantlyeasy/claude-code-sdk-ts
# or  
pnpm add @instantlyeasy/claude-code-sdk-ts

Latest Version: v0.3.3 with enhanced features and working visual streaming!

Prerequisites:

  • Node.js 18 or later
  • Claude Code CLI installed (npm install -g @anthropic-ai/claude-code)

Quick Start

import { claude } from '@instantlyeasy/claude-code-sdk-ts';

// Simple query
const response = await claude()
  .query('Say "Hello World!"')
  .asText();

console.log(response); // "Hello World!"

Authentication

This SDK delegates all authentication to the Claude CLI:

# One-time setup - login with your Claude account
claude login

The SDK does not handle authentication directly. If you see authentication errors, authenticate using the Claude CLI first.

Core Features

🎯 Fluent API

Chain methods for clean, readable code:

const result = await claude()
  .withModel('sonnet')              // Choose model
  .allowTools('Read', 'Write')      // Configure permissions
  .skipPermissions()                // Auto-accept edits
  .inDirectory('/path/to/project')  // Set working directory
  .query('Refactor this code')     // Your prompt
  .asText();                       // Get response as text

📊 Response Parsing

Extract exactly what you need:

// Get plain text
const text = await claude()
  .query('Explain this concept')
  .asText();

// Parse JSON response
const data = await claude()
  .query('Return a JSON array of files')
  .asJSON<string[]>();

// Get the final result
const result = await claude()
  .query('Complete this task')
  .asResult();

// Analyze tool usage
const tools = await claude()
  .allowTools('Read', 'Grep')
  .query('Find all TODO comments')
  .asToolExecutions();

for (const execution of tools) {
  console.log(`${execution.tool}: ${execution.isError ? 'Failed' : 'Success'}`);
}

🔧 Tool Management

Fine-grained control over Claude's capabilities:

// Allow specific tools
await claude()
  .allowTools('Read', 'Grep', 'LS')
  .query('Analyze this codebase')
  .asText();

// Deny dangerous tools
await claude()
  .denyTools('Bash', 'Write')
  .query('Review this code')
  .asText();

// Read-only mode (no tools)
await claude()
  .allowTools() // Empty = deny all
  .query('Explain this architecture')
  .asText();

💬 Session Management

Maintain conversation context across queries:

const session = claude()
  .withModel('sonnet')
  .skipPermissions();

// First query
const response1 = await session
  .query('Pick a random number between 1 and 100')
  .asText();

// Continue with context
const sessionId = await session.query('').getSessionId();
const response2 = await session
  .withSessionId(sessionId)
  .query('What number did you pick?')
  .asText();
// Claude remembers the number!

🚦 Cancellation Support

Cancel long-running operations:

const controller = new AbortController();

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);

try {
  const response = await claude()
    .withSignal(controller.signal)
    .query('Long running task')
    .asText();
} catch (error) {
  if (error instanceof AbortError) {
    console.log('Query was cancelled');
  }
}

📝 Logging

Built-in logging with multiple implementations:

import { ConsoleLogger, LogLevel } from '@instantlyeasy/claude-code-sdk-ts';

const logger = new ConsoleLogger(LogLevel.DEBUG);

const response = await claude()
  .withLogger(logger)
  .query('Debug this issue')
  .asText();

// Also available: JSONLogger, MultiLogger, NullLogger

🎭 Event Handlers

React to events during execution:

await claude()
  .onMessage(msg => console.log('Message:', msg.type))
  .onAssistant(msg => console.log('Claude:', msg))
  .onToolUse(tool => console.log(`Using ${tool.name}...`))
  .query('Perform analysis')
  .stream(async (message) => {
    // Handle streaming messages
  });

Environment Variables

The SDK automatically loads safe configuration from environment:

  • DEBUG - Enable debug mode (values: true, 1, yes, on)
  • VERBOSE - Enable verbose output
  • LOG_LEVEL - Set log level (0-4)
  • NODE_ENV - Node environment

⚠️ Important: API keys are NOT automatically loaded from ANTHROPIC_API_KEY for safety. This prevents accidental billing charges. See Environment Variables Documentation.

Error Handling

Enhanced error handling with categories and resolution hints:

import { isEnhancedError, hasResolution } from '@instantlyeasy/claude-code-sdk-ts';

try {
  await claude().query('Task').asText();
} catch (error) {
  if (isEnhancedError(error)) {
    console.error(`${error.category} error: ${error.message}`);
    if (hasResolution(error)) {
      console.error('Try:', error.resolution);
    }
  }
}

Error categories include:

  • network - Connection issues
  • authentication - Auth problems
  • permission - Access denied
  • timeout - Operation timeouts
  • validation - Invalid input
  • cli - Claude CLI issues
  • configuration - Config problems

Advanced Usage

Configuration Files & Roles

Load settings and define reusable roles from YAML or JSON:

// Load configuration with roles
await claude()
  .withConfigFile('./config/claude.yaml')
  .withRole('developer', {
    language: 'TypeScript',
    framework: 'React'
  })
  .query('Generate component')
  .asText();

Role System

Roles provide reusable configurations with:

  • Model preferences
  • Tool permissions
  • Custom prompts with template variables
  • Context settings (temperature, max tokens)
  • Inheritance support

Example YAML config with roles:

version: "1.0"

globalSettings:
  model: opus
  timeout: 60000

# Define reusable roles
roles:
  developer:
    model: sonnet
    tools:
      allowed: [Read, Write, Edit]
      denied: [Delete]
    prompts:
      prefix: "You are an expert ${language} developer using ${framework}."
    
  senior-developer:
    extends: developer  # Inherit from developer role
    model: opus
    permissions:
      mode: acceptEdits
    tools:
      allowed: [TodoRead, TodoWrite]  # Additional tools
// Using roles with template variables
const response = await claude()
  .withRolesFile('./roles.yaml')
  .withRole('senior-developer', {
    language: 'TypeScript',
    framework: 'Next.js',
    specialty: 'performance optimization'
  })
  .query('Optimize this React component')
  .asText();

See Roles Documentation for complete details.

Production Features

Token Usage & Costs

const parser = await claude()
  .query('Complex task')
  .getParser();

const usage = await parser.getUsage();
console.log('Tokens:', usage.totalTokens);
console.log('Cost: $', usage.totalCost);

Streaming

await claude()
  .query('Tell me a story')
  .stream(async (message) => {
    if (message.type === 'assistant') {
      // Stream complete messages (not individual tokens)
      console.log(message.content[0].text);
    }
  });

Custom Models & Endpoints

const response = await claude()
  .withModel('claude-3-opus-20240229')
  .withTimeout(30000)
  .query('Complex analysis')
  .asText();

🚀 Enhanced Features (v0.3.3)

✨ Visual Token Streaming

Create typewriter effects and real-time response display:

import { claude, createTokenStream } from '@instantlyeasy/claude-code-sdk-ts';

// Collect response for controlled display
const messageGenerator = claude()
  .withModel('sonnet')
  .queryRaw('Write a story about AI');

const tokenStream = createTokenStream(messageGenerator);
const allTokens = [];

for await (const chunk of tokenStream.tokens()) {
  allTokens.push(chunk.token);
}

// Display with typewriter effect
const fullText = allTokens.join('');
for (const char of fullText) {
  process.stdout.write(char);
  await new Promise(resolve => setTimeout(resolve, 30));
}

🛡️ Advanced Error Handling

Handle specific error types with smart retry logic:

import { claude, detectErrorType, withRetry } from '@instantlyeasy/claude-code-sdk-ts';

try {
  const result = await withRetry(
    async () => claude().query('Complex task').asText(),
    {
      maxAttempts: 3,
      strategy: 'exponential',
      shouldRetry: (error) => {
        const errorType = detectErrorType(error.message);
        return ['network_error', 'timeout_error'].includes(errorType);
      }
    }
  );
} catch (error) {
  const errorType = detectErrorType(error.message);
  console.log(`Failed with error type: ${errorType}`);
}

🎬 Interactive Streaming Session

NEW! Complete chat interface with visual streaming:

# Try the interactive streaming example
node examples/fluent-api/new-features/interactive-streaming.js

Features working character-by-character display, conversation history, speed control, and model switching!

Examples

Comprehensive examples are available in the examples directory:

Basic Examples

Advanced Features (new-features directory)

Core Examples

  • File Operations - Reading, writing, and analyzing code
  • Web Research - Using Claude's web capabilities
  • Interactive Sessions - Building conversational interfaces

Migration from Classic API

The SDK maintains full backward compatibility. The classic query() function still works:

import { query } from '@instantlyeasy/claude-code-sdk-ts';

for await (const message of query('Hello')) {
  // Classic async generator API
}

However, we recommend the fluent API for new projects. See Migration Guide.

API Reference

claude(): QueryBuilder

Creates a new query builder:

claude()
  .withModel(model: string)
  .allowTools(...tools: ToolName[])
  .denyTools(...tools: ToolName[])
  .skipPermissions()
  .withTimeout(ms: number)
  .inDirectory(path: string)
  .withSessionId(id: string)
  .withSignal(signal: AbortSignal)
  .withLogger(logger: Logger)
  .withConfigFile(path: string)
  .withRole(name: string, vars?: Record<string, string>)
  .onMessage(handler: (msg: Message) => void)
  .onAssistant(handler: (msg: AssistantMessage) => void)
  .onToolUse(handler: (tool: ToolUseBlock) => void)
  .query(prompt: string): ResponseParser

Response Parser Methods

  • asText() - Extract plain text
  • asJSON<T>() - Parse JSON response
  • asResult() - Get final result message
  • asToolExecutions() - Get tool execution details
  • findToolResults(name) - Find specific tool results
  • getUsage() - Get token usage stats
  • getSessionId() - Get session ID
  • stream(callback) - Stream messages

Types

See TypeScript definitions for complete type information.

Changelog

See CHANGELOG.md for version history.

Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

License

MIT © Daniel King & Claude

Links