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

@litpage/cli

v0.6.6

Published

Agent-first CLI for LitPage v2 content publishing

Readme

@litpage/cli

Publish Markdown to LitPage from your terminal.

LitPage CLI is an agent-first CLI for LitPage v2 content publishing. It is designed for LLM agents, CI jobs, scripts, and developers who want a stable way to push Markdown files to LitPage with machine-readable output.

All examples below use npx @litpage/cli ....

For agent and AI workflows, the security baseline is:

  • prepare configuration before the agent starts
  • inject the workspace key through the host environment or secret manager
  • do not put the raw key into prompts, command lines, Markdown files, or checked-in config

Create a post.md file:

---
title: Hello LitPage
slug: hello-litpage
subdomain: docs
type: BLOG
language: EN
excerpt: First post published from Markdown
author:
  name: Codex
updateReason: Initial draft
---

# Hello LitPage

This page was published from a local Markdown file.

Then publish it:

npx @litpage/cli publish ./post.md

If your file includes complete frontmatter such as slug, title, subdomain, type, and language, LitPage CLI can turn that Markdown file into a LitPage page in one command.

Why LitPage CLI

  • Publish Markdown files directly to LitPage
  • Upsert by slug, so retries are safe
  • Use subdomain instead of internal siteId for normal workflows
  • Default to JSON on stdout, which works well for agents and automation
  • Pull remote content back into Markdown when you need to sync locally

Requirements

  • Node.js >= 18
  • A LitPage workspace API key
  • An existing LitPage site created in https://lit.page

If you do not have a workspace API key yet, sign up at https://lit.page, create a site, then create or copy a key from your LitPage account.

At the current stage, the CLI publishes content to an existing LitPage site. It does not create sites or provision domains for you. Create the site first in the LitPage product UI, then use the CLI to publish Markdown into that site.

Before You Start: Create A Site In LitPage

Today the expected setup flow is:

  1. Go to https://lit.page
  2. Create a site in the product UI
  3. Choose or confirm its site address
  4. Create a workspace API key with access to that site
  5. Use LitPage CLI to publish content into that site

If you skip step 2, the CLI has nowhere to publish.

What subdomain Means

For normal workflows, LitPage CLI targets a site by subdomain.

subdomain is the site identifier that comes from the LitPage site you already created. If your site address is:

  • docs.lit.page, then subdomain is docs
  • news.lit.page, then subdomain is news

If you later bind a custom domain, the site still has an underlying LitPage site identity. In CLI usage, prefer the canonical LitPage subdomain unless you intentionally want to resolve by domain.

You can find the value from:

  • the site creation flow in https://lit.page
  • the site settings or dashboard where the LitPage address is shown
  • npx @litpage/cli site list
  • npx @litpage/cli site resolve <domain-or-subdomain>

Example:

npx @litpage/cli site list
npx @litpage/cli site resolve docs
npx @litpage/cli site resolve docs.lit.page

Use With npx

Run commands directly with:

npx @litpage/cli --help

Quick Start

1. Create or confirm the target site

Before using the CLI, make sure the target site already exists in https://lit.page.

If the site address is docs.lit.page, the subdomain you should use in CLI commands and frontmatter is docs.

2. Configure only the workspace key reference

The recommended setup is to save a non-secret reference for the key:

npx @litpage/cli config set workspaceKey env:LITPAGE_WORKSPACE_KEY

Resulting config:

{
  "workspaceKey": "env:LITPAGE_WORKSPACE_KEY",
  "defaultType": "BLOG",
  "defaultLanguage": "EN"
}

Then let the host shell, CI runner, or secret manager inject the real key value:

export LITPAGE_WORKSPACE_KEY=lp_live_xxx

Saving a default subdomain in config is optional. For normal workflows, prefer either:

  • subdomain in Markdown frontmatter
  • --subdomain <name> to override the file target explicitly

litpage.config.json may be prepared by a human, deploy script, or CI bootstrap step. The agent should consume existing config, not create or edit secrets.

For a local one-off manual test, a human can also store the literal key with:

npx @litpage/cli config set workspaceKey lp_live_xxx

Do not use that plaintext pattern for agents, CI, or checked-in repositories.

3. Run doctor first

npx @litpage/cli doctor

doctor is the first setup and diagnosis command:

  • if the workspace key is missing, it explains how to create one and inject it
  • if no sites are accessible, it tells you to create a site in https://lit.page
  • if multiple sites are accessible, it points you to Markdown subdomain, --subdomain, site list, and site resolve

If you are not sure which site values are available to the current key, inspect them with:

npx @litpage/cli site list

4. Create a Markdown file

---
title: Hello LitPage
slug: hello-litpage
subdomain: docs
type: BLOG
language: EN
excerpt: First post published from Markdown
author:
  name: Codex
updateReason: Initial draft
---

# Hello LitPage

This page was published from a local Markdown file.

5. Publish it to LitPage

npx @litpage/cli publish ./post.md --subdomain docs

If subdomain is already in the file frontmatter, this also works:

npx @litpage/cli publish ./post.md

The Main Workflow

For most users, there are only two commands to remember:

  • publish <file>: upsert the Markdown file by slug, then publish it
  • apply <file>: upsert the Markdown file by slug without publishing it

Examples:

npx @litpage/cli publish ./post.md --subdomain docs
npx @litpage/cli apply ./draft.md --subdomain docs

If you need low-level primitives, use the content command group.

To initialize a non-empty Markdown starter file instead of hand-writing frontmatter:

npx @litpage/cli content template ./post.md --title "Hello LitPage" --slug hello-litpage --subdomain docs

How Markdown Maps To LitPage

LitPage CLI reads Markdown with frontmatter and turns it into a LitPage content payload.

Frontmatter:

  • title
  • slug
  • subdomain
  • type
  • language
  • excerpt
  • author
  • updateReason

Rules:

  • title may be omitted if the first Markdown heading exists
  • content body is always required
  • slug is required for apply, publish, and content upsert
  • subdomain should match the existing LitPage site you want to publish into
  • the built-in frontmatter parser supports scalar fields and simple one-level nested objects such as author

Example:

---
title: Shipping Notes
slug: shipping-notes
subdomain: docs
type: BLOG
language: EN
excerpt: Weekly release notes
author:
  name: Team LitPage
---

# Shipping Notes

- Added new onboarding flow
- Fixed content sync edge case

Common Examples

Publish a Markdown file

npx @litpage/cli publish ./post.md --subdomain docs

Publish using frontmatter subdomain

npx @litpage/cli publish ./post.md

Upsert without publishing

npx @litpage/cli apply ./post.md --subdomain docs

Override the slug from the command line

npx @litpage/cli publish ./post.md --subdomain docs --slug launch-post

Use a saved project default subdomain

npx @litpage/cli config set subdomain docs
npx @litpage/cli publish ./post.md

This is optional. For normal content workflows, subdomain in Markdown or --subdomain on the command line is usually clearer.

Use a named profile

npx @litpage/cli --profile prod publish ./post.md

Inspect accessible sites

npx @litpage/cli site list

Resolve a subdomain or domain to a site

npx @litpage/cli site resolve docs
npx @litpage/cli site resolve docs.lit.page

List content in a site

npx @litpage/cli content list --subdomain docs
npx @litpage/cli content list --subdomain docs --status PUBLISHED --limit 20

Get a page by slug

npx @litpage/cli content get --slug hello-litpage --subdomain docs

Get a page by id

npx @litpage/cli content get --id content_uuid --subdomain docs

Create content without a stable slug

npx @litpage/cli content create --file ./post.md --subdomain docs

This is available, but for agent-safe workflows publish, apply, or content upsert is usually better.

Update an existing page by content id

npx @litpage/cli content update --id content_uuid --file ./post.md --subdomain docs

Upsert by slug with the low-level command

npx @litpage/cli content upsert --file ./post.md --subdomain docs

Pull remote content back into Markdown

npx @litpage/cli content pull --slug hello-litpage --subdomain docs --out ./post.md

Publish or unpublish an existing content item

npx @litpage/cli content publish --id content_uuid --subdomain docs
npx @litpage/cli content unpublish --id content_uuid --subdomain docs

Configuration

Configuration is resolved in this order:

  1. CLI flags
  2. Environment variables
  3. The first existing config file in this order: ./litpage.config.json ./.litpagerc ~/.litpagerc

Supported environment variables:

  • LITPAGE_WORKSPACE_KEY
  • LITPAGE_SUBDOMAIN
  • LITPAGE_API_BASE_URL
  • LITPAGE_BASE_URL
  • LITPAGE_PROFILE

Supported config keys:

  • workspaceKey
  • apiBaseUrl
  • baseUrl
  • subdomain
  • defaultType
  • defaultLanguage

Security Guidance

For agent and AI usage, treat the workspace key as a secret with the same handling standard as a deploy token.

Recommended:

  • use a dedicated workspace key for each agent, CI environment, or deployment boundary
  • pre-create litpage.config.json or ~/.litpagerc before the agent runs
  • store workspaceKey as env:LITPAGE_WORKSPACE_KEY, not as a literal key
  • inject LITPAGE_WORKSPACE_KEY from the host environment, CI secret store, or container runtime
  • commit non-secret defaults such as subdomain, defaultType, and defaultLanguage
  • keep secret-bearing config outside the repository when possible
  • rotate or revoke the key when an agent environment is retired or suspected to be exposed

Do not do this in agent workflows:

  • do not paste lp_live_... into the agent prompt
  • do not call npx @litpage/cli --workspace-key lp_live_... ...
  • do not call npx @litpage/cli config set workspaceKey lp_live_...
  • do not commit workspaceKey as plaintext in litpage.config.json
  • do not place the key in Markdown frontmatter, shell scripts, issue comments, or screenshots

Why:

  • command-line flags may be captured by shell history, process inspection, CI logs, or agent transcripts
  • plaintext config may be committed, copied into caches, or exposed in workspace snapshots
  • prompt-injected secrets tend to leak into chat history, tool traces, and debugging output

For local development, a human can still choose to store the key directly, but that is not the recommended model for automation or AI agents.

Example litpage.config.json:

{
  "workspaceKey": "env:LITPAGE_WORKSPACE_KEY",
  "subdomain": "docs",
  "defaultType": "BLOG",
  "defaultLanguage": "EN"
}

Profiles are also supported:

{
  "defaultProfile": "prod",
  "profiles": {
    "prod": {
      "workspaceKey": "env:LITPAGE_WORKSPACE_KEY",
      "subdomain": "docs",
      "defaultType": "BLOG",
      "defaultLanguage": "EN"
    }
  }
}

Site Target Resolution

For normal file publishing workflows, LitPage CLI resolves the target site in this order:

  1. Explicit --subdomain
  2. File frontmatter subdomain
  3. Config or environment subdomain
  4. Automatic fallback when the workspace key can access exactly one site

If the key can access multiple sites and no target is provided, the CLI fails with a structured SITE_CONTEXT_REQUIRED error.

For most workflows, subdomain is the preferred target identifier:

npx @litpage/cli publish ./post.md --subdomain docs

In practice, docs should come from the site you already created in https://lit.page, where the site address is docs.lit.page.

Commands

Top-level commands

npx @litpage/cli doctor
npx @litpage/cli config current
npx @litpage/cli site list
npx @litpage/cli site resolve docs
npx @litpage/cli apply ./post.md --subdomain docs
npx @litpage/cli publish ./post.md --subdomain docs

Content commands

npx @litpage/cli content list --subdomain docs
npx @litpage/cli content get --slug hello --subdomain docs
npx @litpage/cli content create --file ./post.md --subdomain docs
npx @litpage/cli content update --id content_uuid --file ./post.md --subdomain docs
npx @litpage/cli content upsert --file ./post.md --subdomain docs
npx @litpage/cli content pull --slug hello --subdomain docs --out ./post.md
npx @litpage/cli content publish --id content_uuid --subdomain docs
npx @litpage/cli content unpublish --id content_uuid --subdomain docs

Output Contract

Normal command output is JSON on stdout. Errors are JSON on stderr.

Success example:

{
  "ok": true,
  "command": "publish",
  "data": {
    "operation": "created",
    "content": {
      "id": "content_1",
      "status": "PUBLISHED"
    }
  },
  "meta": {
    "siteId": "site_1",
    "subdomain": "docs",
    "requestId": "req_1"
  }
}

Error example:

{
  "ok": false,
  "error": {
    "code": "SITE_CONTEXT_REQUIRED",
    "message": "Target site is ambiguous."
  }
}

Recommended Workflow For Agents

For automation, CI, and coding agents, the recommended path is:

  1. A human or bootstrap process writes non-secret config such as subdomain and defaultType
  2. The host injects LITPAGE_WORKSPACE_KEY from a secret store before the agent starts
  3. The agent runs doctor once to verify access without ever handling the raw key value
  4. The agent publishes Markdown files with stable slug values
  5. The agent uses subdomain as the normal site selector
  6. The agent uses content pull when remote content needs to be synced back to local Markdown

Minimal safe setup:

litpage.config.json

{
  "workspaceKey": "env:LITPAGE_WORKSPACE_KEY",
  "subdomain": "docs"
}

host environment:

export LITPAGE_WORKSPACE_KEY=lp_live_xxx

agent commands:

npx @litpage/cli doctor
npx @litpage/cli publish ./post.md

See Also