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

substack-skill

v0.1.5

Published

TypeScript SDK + CLI for Substack API — built for AI agents

Readme

substack-skill

TypeScript SDK + CLI + AI SDK tools for Substack. Built for autonomous agents to publish, manage, and analyze newsletters.

This is not a scraping tool. This SDK is built for agents that create and publish their own content, manage their own publications, and interact with the Substack platform as legitimate users. All usage must comply with Substack's Terms of Use and API Terms of Service.

Features

  • Pure API authentication — Login via email OTP using EigenMail. No browser required.
  • 75+ API methods — Full read/write coverage: posts, drafts, publishing, comments, reactions, restacking, subscriptions, analytics, payments, and more.
  • AI SDK tools — Drop-in tools for Vercel AI SDK compatible agents.
  • PostBuilder — Fluent builder for Substack's TipTap editor: headings, images, embeds, tables, code blocks, paywall dividers, and more.
  • CLI — Command-line access for common auth, reading, and publishing workflows.
  • Authentic requests — Browser-grade headers so requests look like a real user session.

Install

npm install substack-skill

Quick Start

import { login, SubstackClient, PostBuilder } from "substack-skill";

// Login (pure API, no browser)
const { cookies } = await login({
  eigenMailPrivateKey: "0x...",
  cookiesPath: ".substack-cookies.json",
});

// Create client
const client = new SubstackClient();
await client.authenticate({ cookies });

// Write and publish
const body = new PostBuilder()
  .heading("My First Automated Post", 1)
  .paragraph("Published by an autonomous agent.")
  .build();

const draft = await client.createDraft({ title: "My First Automated Post", body });
const post = await client.publishDraft(draft.id);
console.log(post.canonical_url);

AI SDK Integration

Install your model/runtime packages separately when you use the AI SDK layer, for example:

npm install ai @ai-sdk/anthropic
import { createSubstackTools, SubstackClient } from "substack-skill";
import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";

const client = new SubstackClient();
await client.authenticate({ cookiesPath: ".substack-cookies.json" });

const { text } = await generateText({
  model: anthropic("claude-sonnet-4-6"),
  tools: createSubstackTools(client),
  prompt: "Create a draft post about the future of AI agents and list my current drafts",
});

Tools

| Tool | Description | |------|-------------| | getSubstackPosts | Get posts from any newsletter | | getSubstackPost | Get a single post with full content | | searchSubstackPosts | Search within a newsletter | | getSubstackUser | Get user profile | | searchSubstackPublications | Search for newsletters | | getSubstackCategories | List all categories | | getSubstackNewsletterAuthors | Get newsletter authors | | getSubstackSelf | Get the authenticated account profile | | listSubstackDrafts | List current drafts | | createSubstackDraft | Create a draft post | | publishSubstackDraft | Publish a draft | | postSubstackNote | Post a note (short-form) |

Authentication

No browser needed. Uses Substack's email OTP flow with EigenMail:

import { login, generateAgentIdentity } from "substack-skill";

// Generate a new agent identity
const { privateKey, address } = generateAgentIdentity();
// → Whitelist `address` in EigenMail, then:

const { cookies, email } = await login({
  eigenMailPrivateKey: privateKey,
  cookiesPath: ".substack-cookies.json",
});

How it works:

  1. POST /api/v1/email-login triggers an OTP email to the agent's EigenMail address
  2. SDK polls the EigenMail inbox for the 6-digit verification code
  3. POST /api/v1/email-otp-login/complete with the code returns session cookies
  4. Cookies are saved and reused for all subsequent API calls

API Coverage

Reading (no auth)

  • Posts, search, podcasts
  • User profiles and feeds
  • Newsletter discovery, categories, authors
  • Global platform search

Writing (auth required)

  • Create, update, delete, publish drafts
  • Post notes with attachments
  • Upload images
  • Comments: read, read replies, delete
  • Reactions (heart/like)
  • Restack and un-restack posts/notes
  • Subscribe and unsubscribe to publications

Publication Management (auth required)

  • Profile: get and update
  • Publication settings: read and write
  • Category tags, launch checklist
  • Sections, recommendations
  • Subscriber listing

Analytics (auth required)

  • Dashboard summary
  • Traffic: views, timeseries, visitor sources
  • Email: stats, open rates, timeseries
  • Growth: sources, events, timeseries
  • Audience: location, overlap
  • Payments: Stripe, pledges, pledge stats
  • Network attribution

Draft Options

client.createDraft({
  title: "Post Title",
  subtitle: "A subtitle",
  body: postBuilder.build(),
  audience: "everyone",           // "everyone" | "only_paid" | "founding" | "only_free"
  coverImage: "https://...",      // Hero image URL
  description: "Preview text",
  searchEngineTitle: "SEO title",
  searchEngineDescription: "SEO description",
  socialTitle: "Social title",
  shouldSendEmail: true,          // Email subscribers on publish
  postDate: "2026-04-01T00:00:00Z", // Schedule
  sectionId: 123,                 // Assign to section
});

PostBuilder

import { PostBuilder, text, bold, italic, link, code } from "substack-skill";

const body = new PostBuilder()
  .heading("Title", 1)
  .paragraph("Plain paragraph.")
  .richParagraph(text("Mix "), bold("bold"), text(" and "), link("links", "https://..."))
  .divider()
  .image("https://...", "alt text", "caption")
  .bulletList(["Item 1", "Item 2"])
  .orderedList(["Step 1", "Step 2"])
  .blockquote("A quote")
  .pullquote("A styled pullquote")
  .codeBlock("const x = 1;", "typescript")
  .table([["Col A", "Col B"], ["1", "2"], ["3", "4"]])
  .youtube("dQw4w9WgXcQ")
  .embed("https://twitter.com/...")
  .button("CTA", "https://...")
  .paywall()
  .paragraph("Paid content below the paywall.")
  .subscribeWidget()
  .build();

CLI

Covers common workflows. The SDK surface is broader than the CLI.

# Login
substack auth login --eigenmail-key 0x...
substack --cookies ~/.config/substack/work.json auth whoami
substack auth generate-identity

# Read
substack posts list platformer -l 10
substack posts get platformer some-post-slug
substack posts search platformer "search term"
substack newsletter search "technology"
substack categories list
substack user profile someuser

# Write
substack draft create -t "Title" --body "Content" --audience everyone
substack draft create -t "Title" --file article.txt
substack draft publish 12345
substack draft delete 12345
substack note "Hello from the CLI"

Responsible Use

This SDK is for legitimate agent-based publishing and newsletter management. It is NOT for:

  • Scraping or bulk data extraction
  • Accessing paywalled content without authorization
  • Spam, harassment, or unsolicited outreach
  • Surveillance or profiling of users
  • Circumventing rate limits or access controls
  • Competing with or replicating Substack's platform

All usage must comply with Substack's Terms of Use and API Terms of Service. You are responsible for your use of this SDK.

License

MIT with Responsible Use Restriction — see LICENSE.