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.0

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 DB_URL="postgres://..." --reads 1 --ttl 1h

CLI

# Push a secret that burns after one read
sirr push DB_URL="postgres://..." --reads 1 --ttl 1h

# Retrieve (burns on read if reads=1)
sirr get DB_URL

# Push entire .env — expires in 24h
sirr push .env --ttl 24h

# Manage
sirr list
sirr delete API_KEY
sirr prune
sirr health

Config via env vars:

export SIRR_SERVER=http://localhost:39999
export SIRR_TOKEN=your-master-key

Programmatic API

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

const sirr = new SirrClient({
  server: process.env.SIRR_SERVER ?? 'http://localhost:39999',
  token: process.env.SIRR_TOKEN!,
})

// Push a one-time secret (burned after first read)
await sirr.push('API_KEY', 'sk-...', { ttl: 3600, reads: 1 })

// Push a persistent secret (survives reads; patchable)
await sirr.push('DB_URL', 'postgres://...', { ttl: 86400, burnOnRead: false })

// Update TTL or value in place (only works if burnOnRead: false)
const meta = await sirr.patch('DB_URL', { ttl: 172800 })

// Retrieve — null if burned, expired, or sealed
const value = await sirr.get('API_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.API_KEY is set here
  await runAgentTask()
})

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

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

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

Multi-Tenant / Org Mode

When working with a multi-tenant Sirr server, pass an org slug to scope all secret, audit, webhook, and prune operations under that org:

const sirr = new SirrClient({
  server: 'http://localhost:39999',
  token: process.env.SIRR_TOKEN!,
  org: 'acme',   // all paths become /orgs/acme/...
})

// These now hit /orgs/acme/secrets, /orgs/acme/audit, etc.
await sirr.push('DB_URL', 'postgres://...', { reads: 1 })
const secrets = await sirr.list()
const events = await sirr.audit()

Without org, the client behaves exactly as before (/secrets, /audit, etc.).

/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 } from '@sirrlock/node'

try {
  await sirr.push('KEY', 'value')
} catch (e) {
  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

await sirr.push('DEPLOY_TOKEN', process.env.PERMANENT_TOKEN!, { reads: 1 })
await execa('sirr', ['run', '--', './deploy.sh'])
// DEPLOY_TOKEN was read once and is now deleted

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 |