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

@hasna/contacts

v0.6.31

Published

Contact management for AI coding agents — CLI + MCP + Web

Readme

@hasna/contacts

Contact management for AI coding agents — CLI + MCP + Web

npm License

Install

npm install -g @hasna/contacts

CLI Usage

contacts --help

Audiences, consent, and suppression

Audience segments implement the hasna.audience.v1 contract (distribution apps plan): predicate definitions over contact tags, attributes (columns or custom fields), and group membership, resolved to per-channel recipient lists that honor consent and suppression.

contacts audience create beta-testers \
  --name "Beta testers" \
  --predicates '[{"kind":"tag","value":"beta"}]' \
  --policy opt_in
contacts audience list
contacts audience show beta-testers          # hasna.audience.v1 document
contacts audience resolve beta-testers --channel email    # email|telegram|sms
contacts consent set CONTACT_ID --channel email --status opt_in
contacts suppression add [email protected] --channel email --reason unsubscribe
contacts suppression sync --dry-run          # push unsubscribes to mailery

Resolution always excludes archived and do_not_contact contacts and suppressed addresses; the audience --policy (opt_in, opt_out, transactional, none) controls how per-channel consent is applied. contacts suppression sync pushes unsynced email suppressions to mailery via @hasna/mailery when it is installed; any other backend can implement the SuppressionSyncAdapter interface exported from the package.

MCP Server

contacts-mcp

HTTP mode

Long-lived Streamable HTTP transport (stateless, bind 127.0.0.1 only):

contacts-mcp --http              # default port 8809
contacts-mcp --http --port 8809
MCP_HTTP=1 contacts-mcp
  • Health: GET http://127.0.0.1:8809/health
  • MCP: http://127.0.0.1:8809/mcp

The REST server (contacts-serve) also exposes /health and /mcp when running.

REST API

contacts-serve

contacts-serve binds to 127.0.0.1 by default. Use --host <host> or CONTACTS_HOST=<host> only when intentionally exposing it beyond loopback. Shared binds still fail closed unless a valid contacts token is configured and sent with the request. The unauthenticated local development fallback is disabled by default and only activates when all of the following are true:

  • no contacts API token environment variable is configured
  • CONTACTS_ALLOW_UNAUTHENTICATED_LOOPBACK=1
  • the server is explicitly bound to a loopback host

The fallback does not trust the HTTP Host header.

Storage

Contacts owns its local SQLite storage directly. It does not depend on shared cloud runtime commands or MCP tools.

contacts storage status
contacts storage status --json
contacts storage push --tables contacts,companies
contacts storage pull --tables contacts,companies
contacts storage sync

Optional cross-machine sync uses contacts-owned PostgreSQL storage. Set one of:

export HASNA_CONTACTS_POSTGRES_URL="postgres://..."
# or OPEN_CONTACTS_POSTGRES_URL / CONTACTS_POSTGRES_URL

Remote PostgreSQL connections require verified TLS for non-local hosts. Local PostgreSQL development URLs can disable TLS explicitly.

By default, remote sync covers contacts, companies, tags, and the other non-sensitive relationship tables. webhooks, contact_documents, and contact_health are excluded until explicitly requested with --tables and HASNA_CONTACTS_ALLOW_SENSITIVE_SYNC=1. Sync inserts or updates rows with timestamp conflict protection. Deletes for contacts, companies, and tags write _contacts_tombstones; push/pull sync carries those tombstones and pull applies them unless the local row has a newer updated_at.

Shared REST/dashboard deployments must set one of HASNA_CONTACTS_API_TOKENS, OPEN_CONTACTS_API_TOKENS, or CONTACTS_API_TOKENS. Values are comma-separated token=scope scope records. Supported scopes include contacts:read, contacts:write, contacts:import, contacts:export, contacts:export:full, documents:read, images:read, images:write, companies:*, tags:*, stats:read, dashboard:read, and mcp:access. Loopback-only development without configured tokens remains allowed; shared hosts fail closed.

Server exports are redacted by default: email addresses, phone numbers, addresses, notes, birthdays, social profiles, and custom fields are withheld. Full exports require both contacts:export and contacts:export:full. Export, import, document file read, image mutation, contact mutation, company mutation, and tag mutation routes write audit entries. Document attachments are served only from the managed contacts documents directory and use private no-store cache headers.

contacts cloud status, contacts cloud push, contacts cloud pull, and contacts cloud sync remain compatibility aliases for the contacts-owned storage commands. They do not load or depend on the deprecated shared cloud runtime. contacts cloud feedback saves feedback locally in the contacts database.

Data Directory

Data is stored in ~/.hasna/contacts/.

License

Apache-2.0 -- see LICENSE