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

@onta/cli

v0.1.53

Published

Onta SDK and CLI — context graph platform for structured data

Readme

@onta/cli

Node.js SDK and CLI for Onta — turn raw data into a queryable context graph (a knowledge graph you query in natural language).

Quickstart

npx @onta/cli

That's it. The first run opens your browser to sign in, saves a key to ~/.onta/config.json, and drops you into the interactive shell:

  /ingest <file>      Ingest a CSV/JSON/text file
  /ask <question>     Ask in natural language
  /kg list|switch|create|delete <name>
  /types [query]      Types in the active KG, with entity counts
  /type <name>        Drill into one type — attributes & relationships
  /enrich <Type> <attrs...>   Plan + run an enrichment job (interactive)
  /enrich watch <job_id>      Live progress for a running job
  /enrich jobs                List recent enrichment jobs
  /enrich review <job_id>     Walk through conflicts and accept/reject
  /status             Graph stats
  /login              Re-authenticate
  /quit

Bare lines (no leading /) auto-route to /ask. Full walkthrough at getonta.com/docs/quickstart.

Self-hosted mode

Pointing the CLI at your own backend skips the browser sign-in:

onta --local                          # defaults to http://localhost:8000
onta --no-login                       # uses ONTA_API_URL env var
ONTA_API_URL=http://my-host:8000 onta

When self-hosted, the prompt shows the host suffix: onta@localhost:8000 (kg) ▸. Bare onta still triggers the hosted-version login flow.

Auto-enrichment

Fill and verify attributes on entities of a given type by looking them up in external sources, with a human review step before any write:

> /enrich LineItem brand manufacturer
Plan: enrich LineItem.brand, .manufacturer · tier: lite · policy: stage
Job queued: enr_xxxxxxxx · 12,450 entities
[████████████████████] filled 6,200 · verified 1,400 · conflicts 320
Status: review · 320 conflicts pending. Run /enrich review enr_xxxxxxxx

Use /enrich watch <job_id> for live progress, /enrich jobs to list recent jobs, and /enrich review <job_id> to walk through conflicts and accept/reject each one. The lite tier uses Wikidata only (free, no API key).

Install

npm install @onta/cli        # or: npm install -g @onta/cli

Requires Node 20+. The global install exposes the onta command.

Browsing what got ingested

After ingest, look around before asking questions:

onta (mentors) [37,715] ▸ /types
  Type           Entities
  Mentor              988
  Skill               412
  Industry             38

onta (mentors) [37,715] ▸ /type Mentor
  Mentor  1,000 entities

  Attributes (6)
    .name           string      988  ( 99%)
    .level          string      714  ( 71%)
    ...

  Relationships (6)
    .title         → JobTitle    988  ( 99%) (+775 string)
    .skills        → Skill       987  ( 99%)
    ...

/types <query> filters by substring; /type <name> accepts case-insensitive prefix. Auto-attached system metadata (rdfs:label, ingested_at, source) is hidden by default — pass --system to see it. The (+775 string) annotation appears when the resolver produced both a literal value and a typed-entity link for the same column.

SDK

import { Client, OntaError } from "@onta/cli";

const client = new Client({ apiKey: process.env.ONTA_API_KEY });

await client.ingest("sales.csv", { kg: "sales" });
const result = await client.ask("What's the average deal size by region?", { kg: "sales" });
console.log(result.answer);

Constructor

new Client({
  apiKey?: string,    // env: ONTA_API_KEY
  baseUrl?: string,   // env: ONTA_API_URL (default: https://api.onta.sh)
  tenant?: string,    // env: ONTA_TENANT (default: demo-tenant)
})

Methods

  • ingest(pathOrText, { kg?, contentType? }) — auto-detects CSV by extension and uses the two-step schema/rows flow; otherwise sends raw content.
  • ask(question, { kg? }) — returns { answer, sparql?, ... }.
  • listKgs(), createKg(name, description?), deleteKg(name) — context-graph CRUD.
  • ontologyTypes() — list every type in the tenant ontology with attributes and parents.
  • ontologyResolve(ask, { knowledge_graph? }) — resolve a fuzzy natural-language ontology-evolution ask (no exact type/attribute/relationship names needed) against the current schema. Returns { applied, proposals, summary }; high-confidence changes land automatically, ambiguous/new-type ones come back as proposals.
  • ontologyApply(proposal) — confirm and commit a single ResolvedChange from ontologyResolve's proposals. Pass the object through unchanged; returns { applied, operations, summary }.
  • typeCounts(kg)[{ name, entity_count }] for the given KG, sorted desc. Powers /types.
  • typeUsage(kg, name, { includeSystem? }) — full breakdown for one type: attributes (with usage counts), relationships, and 3 sample entities. Powers /type. System predicates filtered by default.
  • exploreRecords(kg, type, { limit?, cursor? }) — one keyset-paginated page of entity instances ({ columns, rows, total, next_cursor }).
  • exploreTypeEdges(kg) — undirected type→type edges for an overview graph ([{ source, target, weight }]).
  • normalizeSuggest(kg, type), normalizeRules({ kg?, status? }), normalizeConfirmRule(id), normalizeRejectRule(id), normalizeApplyRule(id) — inferred-normalization rule lifecycle.
  • ontologyRecommend(body?) — recommend ontology relationships/changes for a KG.

All errors throw OntaError.

Raw / passthrough API (client.raw.*)

Every method above throws on a non-2xx status and some reshape the payload (e.g. listKgs() unwraps { kgs: [] }). When you instead want the backend Response verbatim — to forward it 1:1 (e.g. from a web proxy route) or to branch on status without a try/catch — use the raw namespace. Each raw method maps to one canonical operation with the path encoded inside the SDK, so callers pass no path string:

const client = new Client({ apiKey, tenant });

// Forward the backend response unchanged from a proxy:
const res = await client.raw.enrichJobs();          // GET …/enrich/jobs
return new Response(res.body, { status: res.status, headers: res.headers });

// A non-2xx is a Response, not a throw — and the body is never reshaped:
const r = await client.raw.enrichJob("missing");
if (r.status === 404) { /* … */ }

client.raw covers agent, ask, ingest (+ csv schema/rows), enrich jobs (create/list/get/conflicts/apply/cancel), ontology (types/resolve/recommend/apply), kgs (list/create/delete), explore (summary/records/type-edges/type-counts/search), normalize (suggest/rules GET+POST/confirm/reject/apply) and tenants (list/create/delete). Each returns Promise<Response> and only ever rejects on a network error or timeout (i.e. when there is no HTTP response to return).

One-shot CLI

For scripts and CI — every command is a single HTTP round-trip:

# List / create / delete context graphs
npx @onta/cli kg list
npx @onta/cli kg create my-data --description "demo"
npx @onta/cli kg delete my-data

# Ingest data
npx @onta/cli ingest data.csv --kg my-data
npx @onta/cli ingest --text "Alice works at Acme" --kg my-data

# Ask questions
npx @onta/cli ask "How many companies?" --kg my-data
npx @onta/cli ask "Top 5 deals" --kg my-data --debug

# Ontology + clear
npx @onta/cli ontology types
npx @onta/cli clear --kg my-data --yes

Environment

  • ONTA_API_KEY — required for headless / CI use; interactive onta login writes one to ~/.onta/config.json automatically.
  • ONTA_API_URL — default https://api.onta.sh.
  • ONTA_TENANT — default demo-tenant. The login flow sets this to your user ID.

PDF ingestion is not yet supported in the Node CLI. Use the Python CLI or POST raw bytes to the API.

License

Apache-2.0. See LICENSE.