Available on npm — v0.4.8

Claude Code
In your code

Claude Connector
Claude Connector

The entire power of Claude Code — reading files, editing code, running commands, browsing the web — available as a simple Node.js API. No terminal. No copy-paste. Just import and go.

Copied! $ npm install @scottwalker/claude-connector
1
Dependency
214
Tests
45+
CLI flags
75kb
Size
app.ts
import { Claude, EVENT_TEXT } from '@scottwalker/claude-connector'

const claude = new Claude({ model: 'sonnet' })
await claude.init()

// Ask anything, get answers instantly
const result = await claude.query('Find and fix all bugs in auth.ts')
console.log(result.text)

// Or stream the response in real time
await claude.stream('Find bugs')
  .on(EVENT_TEXT, t => process.stdout.write(t))
  .done()

45+ CLI flags. One typed API.

Everything Claude Code can do — now from your code.

Persistent SDK sessions
Real-time streaming
Bidirectional streaming (chat)
Multi-turn sessions
Fork & resume sessions
Parallel agents
Recurring tasks (loop)
Structured JSON output
Permission modes (plan/edit/bypass)
Tool allow/deny with globs
MCP server connections
Custom subagents
Git worktree isolation
Piped input (files, images, logs)
Model selection (opus/sonnet/haiku)
Effort level (low/medium/high/max)
Fallback model on failure
System prompt override/append
Max turns & budget limits
Additional working directories
Lifecycle hooks (pre/post tool use)
Custom env variables
Swappable executor backends
Typed error hierarchy
Single runtime dependency (Agent SDK)

From terminal to API

Before — manual CLI

# Run Claude, copy output, parse it,
# somehow feed it into your pipeline...

$ claude -p "find bugs" --output-format json \
    | jq '.result' \
    | your-script.sh

# No sessions. No streaming. No types.
# Good luck with error handling.

After — claude-connector

import { Claude, EVENT_TEXT } from '@scottwalker/claude-connector'

const claude = new Claude()
await claude.init()

// Stream with fluent callbacks
await claude.stream('Find bugs')
  .on(EVENT_TEXT, t => process.stdout.write(t))
  .done()

// Multi-turn sessions with memory
const session = claude.session()
const bugs = await session.query('Find bugs')
const fixes = await session.query('Fix them')

claude.loop()

Schedule Claude to run on intervals — like cron, but with AI. Monitor, review, report — hands-free.

monitor.ts
import { SCHED_RESULT, SCHED_ERROR } from '@scottwalker/claude-connector'

// Check CI pipeline every 5 minutes
const job = claude.loop('5m', 'Check CI status and report failures')

job.on(SCHED_RESULT, (result) => {
  console.log(`[${new Date().toISOString()}]`, result.text)
})

job.on(SCHED_ERROR, (err) => {
  console.error('Check failed:', err.message)
})

// Stop when done
job.stop()
review-bot.ts
import { PERMISSION_PLAN } from '@scottwalker/claude-connector'

// Periodic code review every 2 hours
const reviewer = claude.loop('2h', 'Review recent commits for bugs and security issues', {
  permissionMode: PERMISSION_PLAN,  // read-only, safe
})

// Supported intervals: '30s', '5m', '2h', '1d', or raw ms

Real-time responses

Watch Claude think word-by-word. React to tool calls, errors, and results as they happen.

stream.ts
import { Claude, EVENT_TEXT, EVENT_TOOL_USE, EVENT_RESULT } from '@scottwalker/claude-connector'

// Fluent API — register callbacks, await completion
const result = await claude.stream('Refactor the auth module')
  .on(EVENT_TEXT, t => process.stdout.write(t))
  .on(EVENT_TOOL_USE, e => console.log(`[tool: ${e.toolName}]`))
  .done()

console.log(`Done in ${result.durationMs}ms`)

// Or collect all text at once
const text = await claude.stream('Summarize').text()

// Or pipe to stdout
await claude.stream('Explain').pipe(process.stdout)
stream-for-await.ts
import { Claude, EVENT_TEXT, EVENT_TOOL_USE, EVENT_RESULT } from '@scottwalker/claude-connector'

// for-await works too — full control over each event
for await (const event of claude.stream('Analyze this project')) {
  switch (event.type) {
    case EVENT_TEXT:
      process.stdout.write(event.text)
      break
    case EVENT_TOOL_USE:
      console.log(`[tool: ${event.toolName}]`)
      break
    case EVENT_RESULT:
      console.log(`Tokens: ${event.usage.inputTokens}in / ${event.usage.outputTokens}out`)
      break
  }
}

Native stream integration

StreamHandle converts to a Node.js Readable. Pipe to files, compress with gzip, stream to HTTP responses — the full Node.js ecosystem just works.

readable.ts
import { createWriteStream } from 'node:fs'
import { pipeline } from 'node:stream/promises'
import { createGzip } from 'node:zlib'

// Pipe to file
claude.stream('Generate a report').toReadable()
  .pipe(createWriteStream('report.txt'))

// Pipeline with gzip compression
await pipeline(
  claude.stream('Generate docs').toReadable(),
  createGzip(),
  createWriteStream('docs.txt.gz'),
)
http-stream.ts
import express from 'express'

// Stream Claude's response directly to HTTP client
app.get('/ai/stream', (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' })
  claude.stream(req.query.prompt).toReadable().pipe(res)
})
sugar.ts
// Collect all text — one liner
const text = await claude.stream('Summarize README.md').text()

// Pipe to stdout, get result metadata back
const result = await claude.stream('Explain the auth flow').pipe(process.stdout)
console.log(`\nCost: $${result.cost}`)

claude.chat()

One persistent process, unlimited turns. Send prompts, get responses — real-time conversation over a single CLI connection.

chat.ts
import { Claude, EVENT_TEXT } from '@scottwalker/claude-connector'

const chat = claude.chat()
  .on(EVENT_TEXT, t => process.stdout.write(t))

const r1 = await chat.send('What files are in src/?')
console.log(`\n[${r1.durationMs}ms]`)

const r2 = await chat.send('Refactor the largest file')
console.log(`\n[${r2.durationMs}ms]`)

chat.end()  // graceful close
duplex.ts
import { pipeline } from 'node:stream/promises'
import { createReadStream, createWriteStream } from 'node:fs'

// Full Node.js Duplex — write prompts in, read text out
const duplex = claude.chat().toDuplex()

await pipeline(
  createReadStream('prompts.txt'),  // one prompt per line
  duplex,
  createWriteStream('responses.txt'),
)
websocket.ts
import { WebSocketServer } from 'ws'
import { Claude, EVENT_TEXT, EVENT_RESULT } from '@scottwalker/claude-connector'

wss.on('connection', (ws) => {
  const chat = claude.chat()
    .on(EVENT_TEXT, t => ws.send(JSON.stringify({ type: 'text', t })))
    .on(EVENT_RESULT, r => ws.send(JSON.stringify({ type: 'done', usage: r.usage })))

  ws.on('message', async (data) => {
    await chat.send(JSON.parse(data).prompt)
  })
  ws.on('close', () => chat.end())
})

Connect any MCP server

Extend Claude with external tools via Model Context Protocol — databases, browsers, APIs, and more.

mcp-inline.ts
// Define MCP servers inline
const claude = new Claude({
  mcpServers: {
    playwright: {
      command: 'npx',
      args: ['@playwright/mcp@latest'],
    },
    database: {
      type: 'http',
      url: 'http://localhost:3001/mcp',
    },
    github: {
      command: 'npx',
      args: ['@modelcontextprotocol/server-github'],
      env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN },
    },
  },
})
mcp-config.ts
// Or load from a config file
const claude = new Claude({
  mcpConfig: './mcp.json',
})

// Now Claude can browse the web, query your DB,
// create GitHub issues — all from your code
const result = await claude.query('Open the login page and test the auth flow')

Control what Claude can do

Allow or deny specific tools. Use glob patterns for fine-grained control over Bash commands.

tools-allow.ts
import { Claude, PERMISSION_PLAN } from '@scottwalker/claude-connector'

// Only allow reading and searching — no edits, no bash
const claude = new Claude({
  allowedTools: ['Read', 'Glob', 'Grep'],
  permissionMode: PERMISSION_PLAN,
})
tools-bash.ts
// Allow Bash but only for specific commands
const claude = new Claude({
  allowedTools: [
    'Read', 'Edit', 'Write',
    'Bash(npm run *)',       // only npm scripts
    'Bash(git status)',      // only git status
    'Bash(npx prettier *)',  // only prettier
  ],
})
tools-deny.ts
import { Claude, PERMISSION_ACCEPT_EDITS } from '@scottwalker/claude-connector'

// Allow everything except web access and file deletion
const claude = new Claude({
  disallowedTools: ['WebFetch', 'WebSearch'],
  permissionMode: PERMISSION_ACCEPT_EDITS,
})

Isolated git worktrees

Run risky refactors in an isolated copy of the repo. Your working tree stays untouched.

worktree.ts
// Run in an isolated worktree — auto-generated branch name
const result = await claude.query('Refactor the entire auth module', {
  worktree: true,
})

// Or specify a branch name
const result2 = await claude.query('Migrate from Express to Fastify', {
  worktree: 'migration/fastify',
})
parallel-worktrees.ts
// Run multiple experiments in parallel — each in its own worktree
const [approach1, approach2] = await claude.parallel([
  {
    prompt: 'Rewrite auth using JWT tokens',
    options: { worktree: 'experiment/jwt' },
  },
  {
    prompt: 'Rewrite auth using session cookies',
    options: { worktree: 'experiment/sessions' },
  },
])

// Compare results, pick the best approach, merge it

Attach files to your prompt

Pass images, logs, configs, or any data alongside your prompt — just like piping in the terminal.

analyze-image.ts
import { readFileSync } from 'node:fs'

// Attach an image for analysis
const screenshot = readFileSync('./bug-screenshot.png', 'base64')
const result = await claude.query('What bug do you see in this screenshot?', {
  input: screenshot,
})
analyze-logs.ts
// Attach error logs
const logs = readFileSync('./error.log', 'utf-8')
const result = await claude.query('Analyze these errors and suggest fixes', {
  input: logs,
})
review-config.ts
// Attach any document — configs, CSVs, JSON, etc.
const config = readFileSync('./docker-compose.yml', 'utf-8')
const result = await claude.query('Review this config for security issues', {
  input: config,
})

Three lines to your first query!

Install the package, import it, and go. Works with your existing Claude Code subscription.

terminal
# Install from npm
$ npm install @scottwalker/claude-connector

# or with other package managers
$ yarn add @scottwalker/claude-connector
$ pnpm add @scottwalker/claude-connector
index.ts
import { Claude, EVENT_TEXT } from '@scottwalker/claude-connector'

const claude = new Claude({ model: 'sonnet' })
await claude.init()

// That's it. Ask anything.
const result = await claude.query('What does this project do?')
console.log(result.text)

// Or stream it live
await claude.stream('Explain the architecture')
  .on(EVENT_TEXT, t => process.stdout.write(t))
  .done()

Available on npm

@scottwalker/claude-connector@0.3.0 — MIT License

npmjs.com