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

@anaralabs/sdk

v0.9.0

Published

Official TypeScript SDK for the Anara public API — research, library search, documents, notes, and chat over your authenticated Anara workspace.

Readme

@anaralabs/sdk

Official TypeScript SDK and CLI for the Anara API. It mirrors Anara's in-product code-agent SDK — the anara.* surface (library entities, retrieval, documents, spreadsheets, notes, images, chats, workspace, sandbox) — as a typed HTTP client. Give a coding agent (Claude Code, Codex, …) the same tools the Anara agent has, over a single API key.

One runtime dependency (zod, for the method schemas). Works in Node 18+, Deno, Bun, edge runtimes, and the browser (anywhere fetch exists). The CLI needs Node.

Install

npm install @anaralabs/sdk

Custom citation styles

Use anara.citations.listStyles({ query: 'APA' }) and anara.citations.getStyle({ id: 'apa' }) to read a base CSL style. After editing its XML, call previewStyle({ xml, samples }) to check both inline citations and references, then saveStyle({ name, xml }) to save it in the selected workspace. Identical saves reuse the same style ID.

Saving does not apply the style. setFormat({ format: saved.id }) changes the user's default for chats, notes and exports; getFormat() reads that default. Save and apply require anara:write. Preview and discovery require anara:read. Saved styles remain scoped to their workspace.

The CLI exposes the same methods: anara methods citations lists them and anara citations.previewStyle --help shows the preview input schema.

Authenticate

Mint an API key (Better Auth) from your signed-in browser session:

curl -X POST https://anara.com/api/better-auth/api-key/create \
  -H 'content-type: application/json' \
  -H 'cookie: <signed-in-browser-cookie>' \
  -d '{"name":"CLI","permissions":{"anara":["read","write"]}}'

Keys look like anara_…. Reads need anara:read; library writes need anara:write; the sandbox.* methods need the opt-in anara:sandbox permission (and sandbox.fetchDocument also needs anara:read). Keep keys secret; never commit them.

Use

import { createAnaraClient } from '@anaralabs/sdk';

// `apiKey` defaults to the ANARA_API_KEY environment variable.
const anara = createAnaraClient();

// Retrieval — compose it from the raw primitives: recall, rerank, read.
const candidates = await anara.retrieval.vectorSearch({
  queries: ['wooden pallet recycling drop-off', 'where to recycle pallets'],
});
const winners = await anara.retrieval.rerank({
  query: 'wooden pallet recycling drop-off',
  candidates,
  topK: 6,
});

// Read a winner's full page when snippets aren't enough.
const page = await anara.documents.getPages(
  winners[0].documentId,
  winners[0].pageNumber != null ? [winners[0].pageNumber] : undefined,
);

// Library entities (CRUD). Writes need an `anara:write` key.
const drafts = await anara.entities.query({
  type: 'NOTE',
  nameContains: 'draft',
});
const folder = await anara.entities.create({ type: 'GROUP', name: 'Drafts' });
for (const d of drafts) await anara.entities.move(d.id, folder.id);

// Add files. `uploadFile` presigns and PUTs the bytes straight to storage, so
// it is not bound by the API request-body limit; `import` fetches a URL.
await anara.documents.uploadFile({ filename: 'paper.pdf', bytes: pdfBytes });
await anara.documents.import({ url: 'https://arxiv.org/pdf/1706.03762' });

CLI

The package ships an anara binary. Every registry method is callable with a JSON argument (or JSON on stdin):

export ANARA_API_KEY=anara_…

anara methods                    # list methods with the scopes they need
anara methods retrieval          # filter by prefix
anara me                         # the user + workspace the key resolves to
anara --version

anara retrieval.vectorSearch '{"queries":["pallet recycling"]}'
echo '{"type":"DOCUMENT"}' | anara entities.query

Without a global install: npx -p @anaralabs/sdk anara methods.

| Variable | Meaning | | ----------------------- | ---------------------------------- | | ANARA_API_KEY | required | | ANARA_BASE_URL | default https://anara.com | | ANARA_ORGANIZATION_ID | optional workspace pin (see below) |

Exit codes: 0 success, 1 the API returned an error (message on stderr), 2 usage error (unknown method, bad JSON, missing key).

How it works

The package is a thin client: every anara.* method is one POST /api/v1/sdk/{method} call whose JSON body is the method's arguments, dispatched server-side against your authenticated workspace. anara.me() hits GET /api/v1/me. There is no Anara logic in the package itself — just typed calls over your key.

Surface

  • entities.query / get / create / update / move / delete
  • retrieval.vectorSearch / keywordSearch / rerank
  • documents.getPages / expandContext / readToc / readMedia / extract
  • documents.import / upload / createUpload / uploadFile / uploadAll / importAll
  • spreadsheets.query / export / applyEdits
  • views.list / create / addColumn / updateColumn / rename / run / deleteColumn / delete
  • notes.read / edit · images.create · chats.search
  • organizations.list · me · forOrganization(id)
  • sandbox.create / runShell / writeFile / editFile / readFile / listDir / attachFiles / fetchDocument / stop (requires anara:sandbox)

invoke(method, args) is the escape hatch for any registry method not wrapped above. ANARA_METHODS exports the registry itself (zod input/output schemas, scopes, summaries), and buildOpenApiDocument() renders it as OpenAPI.

Errors are thrown as AnaraApiError (.status, .code, .details) for API responses and AnaraError for client-side failures (missing key, no fetch, failed storage PUT); isAnaraApiError(e) / isAnaraError(e) are type guards.

Workspaces

A key targets your default workspace. To aim at another one you belong to, list them with anara.organizations.list() and pass organizationId (sent as X-Anara-Organization-Id) or derive a scoped client with anara.forOrganization(id).

Drop-in agent guide

ANARA_AGENT_GUIDE is a ready-made system-prompt block teaching an agent when and how to call the SDK:

import { ANARA_AGENT_GUIDE } from '@anaralabs/sdk';

Configuration

createAnaraClient({
  apiKey: '…', // or ANARA_API_KEY
  baseUrl: 'https://anara.com', // override for self-hosted / preview
  organizationId: 'org_…', // pin a workspace you belong to
  fetch: customFetch, // override the fetch implementation (used for every request, including storage PUTs)
  headers: { 'x-trace': '…' }, // extra headers on every request
});

Browser sign-in from the CLI (0.6.1)

On macOS or Linux, run anara login --url https://your-preview.example.com to authorize Anara in your browser. Authorization uses PKCE and a temporary loopback callback; credentials are bound to that environment. macOS uses Keychain; Linux uses owner-only token files under $XDG_CONFIG_HOME/anara/oauth (default ~/.config/anara/oauth). Linux token files are not encrypted. Then run commands with the same ANARA_BASE_URL. An explicit ANARA_API_KEY takes priority. anara logout --url https://your-preview.example.com revokes tokens and removes local credentials. Login requires the environment's existing public OAuth client registration endpoint; it does not configure a provider or grant staff access.

Node applications can import login, getAccessToken, and logout directly from @anaralabs/sdk/oauth. These native helpers are separate from the browser-safe SDK entry point. getAccessToken({ baseUrl }) refreshes expired credentials before returning a bearer token. An absent or revoked login returns undefined; network failures throw without deleting credentials. Other platforms can supply their own CredentialStore from @anaralabs/sdk/oauth-types; no plaintext file fallback is enabled. Automated QA can inject a store and use login({ baseUrl, store, openBrowser: false, onAuthorizationUrl: async url => ... }).

Upload a file from the shell

npx -y @anaralabs/sdk documents.uploadFile "/path/to/paper.pdf"

The command reads a local or sandbox file, reserves an upload through the API, and sends its bytes directly to storage. It prints the document ID; ingestion continues asynchronously. An optional second argument selects a folder. ANARA_API_KEY, ANARA_BASE_URL, and ANARA_ORGANIZATION_ID select the credentials, server, and workspace. No JavaScript installation setup is needed.

Use npx -y @anaralabs/sdk documents.upload --help to inspect a method's input schema before calling it. documents.upload takes base64 bytes, not a file path. Keep upload commands free of | head, which can hide a failing exit status.

Sandbox commands keep generated files in the sandbox by default. Pass attachFiles: ["report.pdf"] to sandbox.runShell to publish selected files, or call sandbox.attachFiles after inspecting the result. Callers that previously relied on automatic file URLs must now select the files explicitly.

Saved extraction views

A view persists the same extraction columns across an explicit set of source documents in a folder. Creating or editing columns does not run extraction automatically; compose the operations in one script:

const view = await anara.views.create({
  folderId: 'folder-id',
  name: 'Study comparison',
  sourceIds: ['paper-1', 'paper-2'],
  columns: [
    {
      name: 'Sample size',
      instruction: 'Report the study sample size.',
      type: 'number',
    },
  ],
});
await anara.views.run({ viewId: view.id });
const views = await anara.views.list({ folderId: 'folder-id' });

The sandbox CLI exposes the same methods: anara views --help and anara views.create --help. Reads require source access; mutations require write access to the owning folder and an anara:write credential. Runs use the existing extraction billing and cell limits. Delete operations permanently remove the view or column and its cells, never the source documents. External SDK callers must obtain any required user confirmation before invoking them.