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

@khotan/cli

v0.12.0

Published

Khotan CLI: a human- and agent-facing adapter over the Khotan /api/v1 surface.

Readme

Khotan CLI

@khotan/cli is the first-party command-line interface for the Khotan API. It is a thin adapter over the public /api/v1 HTTP API, driven by the shared capability catalog in @khotan/core. It adds nothing the API cannot do — it makes the same operations ergonomic for humans and agents alike.

Install & run

The published CLI is a self-contained Node.js binary (no Bun required). Install or invoke it with standard npm tooling:

npx @khotan/cli --help     # zero-install
npm i -g @khotan/cli       # global `khotan` binary
# or: bun add -g @khotan/cli / pnpm add -g @khotan/cli
khotan --help

From this repository (contributors), run it from source on Bun:

bun run khotan -- --help          # via the root script
bun packages/khotan-cli/src/bin/khotan.ts --help   # directly

Scaffold a workspace

khotan init writes Khotan agent integration into the current directory so your own agents (Cursor, Devin, …) can drive setup. It is non-destructive and re-runnable, and never writes secrets.

khotan init                 # Cursor: .cursor/rules/khotan.mdc
khotan init --client generic   # khotan-agents.md
khotan init --force         # regenerate managed assets, overwriting edits
khotan init --json          # machine-readable summary on stdout

It writes agent guidance for using the CLI. Authenticate separately with khotan auth set-key or environment variables — never commit a key.

init also installs catalog-derived agent skills for using the CLI into .cursor/skills/, .agents/skills/, and .claude/skills/ (regardless of --client): an overview khotan skill plus one per command domain (khotan-apps, khotan-databases, …). The skills are generated from the same capability catalog that drives the commands and khotan help, so they can never drift. They are managed assets: every khotan init run regenerates them in place (no --force needed), so re-running init is how a workspace picks up new CLI commands — like the databases branches group. Your hand-authored rule/guide stays non-destructive (preserved unless --force).

Authentication & profiles

The CLI authenticates with an organization-scoped API key. Credentials are stored in an owner-only file at ${XDG_CONFIG_HOME:-~/.config}/khotan/profiles.json (0600, in a 0700 directory). You can keep several named profiles.

Store an existing API key

Create a key in the dashboard, then:

khotan auth set-key --api-url https://app.example.com --api-key khk_live_...
khotan whoami        # verifies the key via GET /api/v1/me

Exchange credentials for a key

khotan login \
  --api-url https://app.example.com \
  --email [email protected] \
  --password '••••••' \
  --organization-id org_123

login calls POST /api/v1/api-keys, stores the minted key once, and verifies it. The key itself is never printed to stdout.

Profiles

khotan auth set-key --profile staging --api-url https://staging.example.com --api-key ...
khotan auth use staging      # switch the active profile
khotan auth list             # list profiles (never prints keys)
khotan apps list --profile staging   # one-off override

Environment variables (CI & agents)

Environment variables take precedence over stored profile values, so no on-disk state is needed in CI or sandboxes:

| Variable | Purpose | | ----------------- | ----------------------------------------- | | KHOTAN_API_URL | API origin (e.g. https://app.example.com) | | KHOTAN_API_KEY | Organization-scoped API key | | KHOTAN_PROFILE | Select a stored profile by name | | KHOTAN_ORG_ID | Expected org id; the CLI asserts whoami.organizationId matches it and fails closed otherwise |

export KHOTAN_API_URL=https://app.example.com
export KHOTAN_API_KEY=khk_live_...
khotan apps list --json | jq '.apps[].id'

Repo-local org isolation (env.khotan.local)

When an env.khotan.local file sits at (or above) the working directory, the CLI auto-loads its KHOTAN_* values so every command is scoped to that repo's organization — never a stray machine-global profile from another customer. The file is authoritative: its values win over shell-exported KHOTAN_*, which win over the stored profile, and CLI flags win over everything (flag > env.khotan.local > shell env > profile).

# env.khotan.local (git-ignored; never commit secrets)
KHOTAN_API_URL='https://<customer>.khotan.com'
KHOTAN_API_KEY='<org-scoped key>'
KHOTAN_ORG_ID='<org id>'

When KHOTAN_ORG_ID (or --assert-org <id>) is set, every operation verifies whoami.organizationId matches before trusting output and fails closed on mismatch (error [org_mismatch]). With no expected org id set, behavior is unchanged.

Command surface

Commands are grouped by domain and derived from the capability catalog, so the documented surface and the executable surface cannot drift. Run khotan help or khotan <command> --help for details.

| Domain | Examples | | --------- | -------- | | Apps | apps list, apps get <id>, apps create --name web --env KEY=VALUE, apps delete <id>, apps redeploy <id> | | App env | apps env list <id>, apps env set <id> <KEY> --value V, apps env reveal <id> <KEY>, apps env unset <id> <KEY>, apps env bulk-set <id> --var A=1 --var B=2 | | Pipelines | same shape as apps under pipelines … | | Databases | databases list, databases create --name db, databases connection <id>, databases rotate-credentials <id>, databases delete <id> | | Files | files list, files get <id>, files upload <path>, files download <id> --output <path>, files download-url <id>, files preview-url <id>, files update <id> --name new.txt, files delete <id> | | Folders | folders list, folders create --name docs, folders rename <id> --name new, folders delete <id> | | Context | context list, context get <slug>, context raw <slug>, context create --title T --kind knowledge --content '...' --folder-id <id>, context update <slug> --expected-revision 3 --content '...' --folder-id <id>, context delete <slug> | | Context folders | context folders list, context folders create --name docs --parent-id <id>, context folders update <id> --name new --parent-id <id>, context folders delete <id> --recursive | | Context revisions | context revisions list <slug>, context revisions get <slug> <revision>, context revisions restore <slug> <revision> |

Output modes

  • Human-readable tables/detail by default.
  • --json emits the API-shaped JSON to stdout.
  • Results go to stdout; diagnostics, prompts, and progress go to stderr, so khotan ... --json | jq stays clean.

Safety

Each capability has a safety class (read, write, destructive, secret):

  • Destructive commands (delete, env unset) prompt for confirmation in a terminal and refuse in non-interactive sessions unless you pass --yes.
  • Secret values (env reveal, databases connection, databases rotate-credentials) are only available via explicit commands and are never included in list/table output.

File transfer

Uploads and downloads move bytes directly between your machine and object storage using presigned URLs:

khotan files upload ./report.pdf --folder-path /reports/2026
khotan files download file_123 --output ./report.pdf

To hand a file to a browser instead of saving it locally, mint a short-lived presigned URL and load it directly (no API key on the URL; expires in ~5 minutes):

khotan files preview-url file_123     # inline disposition, images and PDFs only
khotan files download-url file_123    # attachment disposition, any file type

See Serving file attachments for the full preview/download flow and the receiver wiring guidance.

Catalog ↔ OpenAPI consistency

@khotan/core validates that every catalog operation maps to a real /api/v1 operation (method, path, operationId) using a snapshot of the OpenAPI document at packages/khotan-core/src/catalog/__fixtures__/openapi.snapshot.json.

Because that snapshot is committed, the catalog can validate green against a stale contract. Guard against it by regenerating the live operation index in-process and diffing it against the snapshot (no running server needed):

bun run khotan:snapshot:check   # exit 1 on any added/removed/renamed operation

Wire this into CI (it only needs build-minimum env) so a route added, removed, or renamed without updating the snapshot fails the build.

Regenerate the snapshot when the API surface changes:

curl -s "$KHOTAN_API_URL/api/v1/openapi.json" \
  | jq '{openapi, info, paths: (.paths | map_values(map_values({operationId})))}' \
  > packages/khotan-core/src/catalog/__fixtures__/openapi.snapshot.json

Development

bun run khotan:typecheck   # typecheck both packages
bun run khotan:test        # run all Khotan tests
bun run khotan -- <args>   # run the CLI from source
bun run khotan:build       # bundle the publishable dist/khotan.js (Node target)

The build bundles @khotan/core into a single Node-executable ESM file at packages/khotan-cli/dist/khotan.js. @khotan/core stays a private workspace package; only the bundled @khotan/cli is published, so the published manifest has no workspace:* dependencies.

Release

Versioning and publishing use changesets:

bun run changeset          # author a changeset describing the change
bun run release:version    # apply changesets: bump version + update changelog
bun run release:publish    # build, then publish @khotan/cli to npm (public)

prepublishOnly rebuilds the bundle, so the published bin always matches source. Publishing requires the @khotan npm org and a publish token.