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

@sirrlock/node

v1.0.16

Published

Sirr (سر) — Node.js client and npx CLI for the ephemeral secret vault

Readme

@sirrlock/node

npm version npm downloads CI TypeScript Node.js GitHub stars Last commit License: MIT

Node.js client and npx CLI for Sirr — ephemeral secret management.

Give AI agents exactly the credentials they need, for exactly as long as they need them. Read once and it's gone. Expired by time and you never have to clean anything up.

Install

npm install @sirrlock/node

Or use without installing:

npx @sirrlock/node push "postgres://..." --reads 1 --ttl 1h

CLI

# Push a public dead drop — returns a one-time URL
sirr push "postgres://..." --reads 1 --ttl 1h
# → https://sirr.sirrlock.com/s/abc123

# Set an org-scoped named secret
sirr set DB_URL "postgres://..." --org acme --reads 3 --ttl 24h

# Retrieve by ID (dead drop) or key (org-scoped)
sirr get abc123
sirr get DB_URL --org acme

# Manage
sirr list
sirr delete API_KEY
sirr prune
sirr health

Config via env vars:

export SIRR_SERVER=https://sirr.sirrlock.com
export SIRR_TOKEN=your-master-key

Programmatic API

import { SirrClient, SirrError, SecretExistsError } from '@sirrlock/node'

const sirr = new SirrClient({
  server: process.env.SIRR_SERVER ?? 'https://sirr.sirrlock.com',
  token: process.env.SIRR_TOKEN!,
})

// Push a public dead drop — returns { id, url }
const { id, url } = await sirr.push('sk-...', { ttl: 3600, reads: 1 })
console.log(url)  // → https://sirr.sirrlock.com/s/abc123

// Set an org-scoped named secret — throws SecretExistsError on conflict
await sirr.set('DB_URL', 'postgres://...', { org: 'acme', ttl: 86400, reads: 3 })

// Retrieve — routes by org presence
const value = await sirr.get(id)                              // dead drop by ID
const dbUrl = await sirr.get('DB_URL', { org: 'acme' })      // org-scoped by key

// Pull all secrets into a plain object
const secrets = await sirr.pullAll()

// Inject all secrets as env vars for the duration of a callback
await sirr.withSecrets(async () => {
  // process.env.DB_URL is set here
  await runAgentTask()
})

// Inspect metadata without consuming a read (HEAD request)
const status = await sirr.check('DB_URL')
// { status: 'active', readCount: 0, readsRemaining: 3, ... }

// Delete immediately
await sirr.delete('DB_URL')

// List active secrets (metadata only — no values)
const list = await sirr.list()

Multi-Tenant / Org Mode

Org scoping is now per-call via the org option on set() and get():

// Set an org-scoped secret
await sirr.set('DB_URL', 'postgres://...', { org: 'acme', reads: 1 })

// Retrieve an org-scoped secret
const value = await sirr.get('DB_URL', { org: 'acme' })

// Audit, list, and webhook calls still support org at the client level
const sirr = new SirrClient({
  server: 'https://sirr.sirrlock.com',
  token: process.env.SIRR_TOKEN!,
  org: 'acme',
})
const events = await sirr.audit()

/me endpoints

Manage the current principal's profile and API keys:

const profile = await sirr.me()                                // GET /me
await sirr.updateMe({ metadata: { team: 'platform' } })       // PATCH /me
const key = await sirr.createKey({ name: 'ci' })              // POST /me/keys
const revoked = await sirr.deleteKey(key.id)                   // DELETE /me/keys/{id} → boolean

Admin endpoints (master key only)

Manage orgs, principals, and roles. Available both as flat methods and through namespaced sub-clients (sirr.orgs.*, sirr.principals.*, sirr.webhooks.*):

// Orgs
const org = await sirr.orgs.create({ name: 'acme' })  // or sirr.createOrg(...)
const orgs = await sirr.orgs.list()                    // returns Org[]
await sirr.orgs.delete(org.id)

// Principals
const p = await sirr.principals.create(org.id, { name: 'alice', role: 'writer' })
const principals = await sirr.principals.list(org.id)  // returns Principal[]
await sirr.principals.delete(org.id, p.id)

// Roles — permissions is a letter string, not an array
await sirr.createRole(org.id, { name: 'reader', permissions: 'rRlL' })
await sirr.listRoles(org.id)
await sirr.deleteRole(org.id, 'reader')

// Webhooks
const wh = await sirr.webhooks.create('https://example.com/hook')
const webhooks = await sirr.webhooks.list()
await sirr.webhooks.delete(wh.id)

// Audit log
const events = await sirr.audit({ action: 'secret.read', limit: 50 })

Error Handling

import { SirrError, SecretExistsError } from '@sirrlock/node'

try {
  await sirr.set('DB_URL', 'postgres://...', { org: 'acme' })
} catch (e) {
  if (e instanceof SecretExistsError) {
    // 409 — secret with this key already exists in the org
    console.error('Secret already exists, use a different key or delete first')
  } else if (e instanceof SirrError) {
    console.error(`API error ${e.status}: ${e.message}`)
  }
}

AI Workflows

LangChain.js tool with scoped credential

import { DynamicTool } from 'langchain/tools'

const dbTool = new DynamicTool({
  name: 'query_database',
  description: 'Run a SQL query against the production database',
  func: async (query) => {
    const connStr = await sirr.get('AGENT_DB')
    if (!connStr) throw new Error('DB credential expired or burned')
    return runQuery(connStr, query)
  },
})

Inject secrets into a subprocess

await sirr.withSecrets(async () => {
  await execa('python', ['agent.py'])
})

CI/CD: one-time deploy credential

const { url } = await sirr.push(process.env.PERMANENT_TOKEN!, { reads: 1 })
// Share the URL with the deploy script — burned after one read

pytest-style fixture for Node.js tests

beforeAll(async () => {
  await sirr.withSecrets(async () => {
    // All vault secrets set as process.env for the test suite
    await runTestSuite()
  })
})

Related

| Package | Description | |---------|-------------| | sirr | Rust monorepo: sirrd server + sirr CLI | | @sirrlock/mcp | MCP server for AI assistants | | sirr (PyPI) | Python SDK | | Sirr.Client (NuGet) | .NET SDK | | sirr.dev | Documentation | | sirrlock.com | Managed cloud + license keys |