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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@secemp/elwood

v0.1.2

Published

Programmatically import and instrument the locally installed Claude Code CLI via Babel AST

Readme

elwood

Programmatically import and instrument the locally installed Claude Code CLI via Babel AST. Drop-in replacement for @anthropic-ai/claude-agent-sdk that runs in-process -- zero subprocess spawning.

How it works

Instead of spawning claude -p as a subprocess (like the official SDK), elwood:

  1. Locates the installed Claude Code CLI (cli.js)
  2. Parses the 13MB bundle with Babel AST
  3. Fingerprints internal functions via evidence-based pattern matching
  4. Injects instrumentation hooks
  5. Calls agentLoop() directly in-process

This gives you the same API as @anthropic-ai/claude-agent-sdk with lower latency and direct access to internals.

Install

npm install @secemp/elwood

Requires Claude Code to be installed:

npm install -g @anthropic-ai/claude-code

Quick start

import { query } from '@secemp/elwood';

for await (const message of query({
  prompt: 'What files are in this directory?',
  options: { maxTurns: 3 },
})) {
  if (message.type === 'result') {
    console.log(message.result);
  }
}

No API key needed if logged in via claude login (Pro/Max subscription).

API

query({ prompt, options })

Returns an async generator yielding messages. Options include:

  • model -- model to use
  • systemPrompt -- string or {type: 'preset', append: '...'}
  • maxTurns -- maximum conversation turns
  • allowedTools -- auto-approve these tools
  • hooks -- {PreToolUse: [...], PostToolUse: [...], ...}
  • mcpServers -- MCP server configs
  • permissionMode -- 'default' | 'acceptEdits' | 'bypassPermissions'
  • continue / resume / resumeSessionAt / forkSession -- session management
  • env / stderr -- environment and output control
  • ...and all other official SDK options

Query control methods

const conversation = query({ prompt: '...' });
conversation.interrupt();          // soft interrupt
conversation.setModel('...');      // change model mid-conversation
conversation.setPermissionMode('acceptEdits');
await conversation.supportedModels();
await conversation.supportedCommands();
conversation.close();              // cleanup

tool(name, description, schema, handler)

import { tool, createSdkMcpServer, query } from '@secemp/elwood';

const weather = tool('get_weather', 'Get weather',
  { type: 'object', properties: { city: { type: 'string' } } },
  ({ city }) => `72F in ${city}`
);

const server = await createSdkMcpServer({ tools: [weather] });

for await (const msg of query({
  prompt: 'Weather in NYC?',
  options: { mcpServers: [server] },
})) { /* ... */ }

Session utilities

import { listSessions, getSessionMessages, getSessionInfo } from '@secemp/elwood';

const sessions = await listSessions();
const messages = await getSessionMessages(sessions[0].id);

V2 Session API

import { unstable_v2_createSession, unstable_v2_prompt } from '@secemp/elwood';

const result = await unstable_v2_prompt('Explain recursion');

Low-level AST access

import { locate, load, instrument, parseBundle } from '@secemp/elwood';

const { cliPath, version } = await locate();
const ast = parseBundle(cliPath);

Auth

Works with all Claude Code auth methods:

  • Claude Pro/Max subscription (claude login)
  • ANTHROPIC_API_KEY environment variable
  • OAuth tokens
  • Bedrock/Vertex/Foundry

Examples

See the examples/ directory for 24 working examples covering queries, hooks, MCP, custom tools, sessions, and more.

License

MIT