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/attachments

v1.1.9

Published

Open-source attachment transfer with local or private S3 storage, app-hosted share links, CLI, MCP, and REST API

Readme

@hasna/attachments

Open-source attachment transfer for agents and teams with local or private S3 object storage, share links, a CLI, an MCP server, and local and hosted REST APIs.

npm License

Install

npm install -g @hasna/attachments

The package installs three binaries:

  • attachments — local-first CLI and REST server
  • attachments-mcp — MCP server over Streamable HTTP or stdio
  • attachments-serve — self-hosted Postgres + S3 service

Quick Start

Fresh installs need no S3 configuration. Files are stored under ~/.hasna/attachments/objects, metadata is stored in SQLite, and public links use the local server.

attachments upload report.pdf
attachments list
attachments serve

The server listens on http://localhost:3459 by default. Open the URL returned by attachments upload, or download by attachment ID:

attachments download att_xxx --output ./downloads/

CLI

Run attachments <command> --help for complete options.

| Area | Commands | |------|----------| | Transfer | upload, download, list, delete, remove, link | | Direct S3 upload | presign-upload, presign-complete | | Configuration | config show, config set, config test, domain | | Service and diagnostics | serve, status, whoami, doctor, health-check, clean, report | | Agent integrations | mcp, init, heartbeat, focus, link-task, complete-task, resolve-evidence, snapshot-session, task-journal, watch |

Common upload controls include expiry, tags, passwords, encrypted storage, download limits, email gates, JSON output, stdin input, and internal-network links:

attachments upload report.pdf --expiry 24h --tag task:TASK-042
attachments upload archive.zip --password "$ATTACHMENT_PASSWORD" --encrypt --max-downloads 1
printf 'hello\n' | attachments upload --stdin --filename greeting.txt --format json

Storage and Links

Storage defaults to auto: it uses S3 when a bucket and region are configured, and local object storage otherwise.

attachments config set --storage-backend local
attachments config set --storage-backend s3 --bucket my-bucket --region us-east-1
attachments config set --max-size 10737418240 # 10 GiB

The configured default link type is presigned. A request automatically uses an app-hosted server link when a presigned S3 URL cannot represent it, including local storage, expiry beyond seven days, non-expiring links, passwords, encryption, download limits, and email gates. The S3 bucket can remain private in both modes.

Use --link-type presigned|server on uploads, or change the default:

attachments config set --link-type server --expiry 7d

Local REST API

attachments serve starts the local SQLite-backed API on port 3459. GET /api/health is public. Other /api/* routes require a bearer token only when ATTACHMENTS_API_TOKEN or HASNA_ATTACHMENTS_API_TOKEN is set.

| Surface | Path | |---------|------| | Attachments API | /api/attachments | | Health, context, report | /api/health, /api/context, /api/report | | Public share page | /a/<token> | | Legacy public download | /d/<attachment-id> |

The attachment API supports JSON/base64, raw-body, multipart form, multipart S3 upload, presigned upload completion, listing, metadata, deletion, downloads, and link regeneration.

Self-Hosted Service

attachments-serve is the hosted API. It reads and writes Postgres and object storage directly; there is no local/cloud sync engine or cache mode.

export HASNA_ATTACHMENTS_STORAGE_MODE=cloud
export HASNA_ATTACHMENTS_DATABASE_URL=postgres://...
export HASNA_ATTACHMENTS_API_SIGNING_KEY=replace-me
export ATTACHMENTS_S3_BUCKET=my-bucket
export ATTACHMENTS_PUBLIC_BASE_URL=https://files.example.com

attachments-serve

It runs migrations before serving unless --no-migrate or ATTACHMENTS_SKIP_MIGRATE=1 is set. Use attachments-serve migrate for a one-shot migration. The hosted surface exposes public /health, /ready, /version, and /openapi.json endpoints plus the authenticated /v1 API.

Public Domains

Domain support is declarative and does not depend on @hasna/domains at runtime. domain configure only stores local metadata; it does not deploy DNS, Cloudflare Workers, or provider routes. Configure public routing, export a credential-free plan, deploy it with your DNS/CDN provider, then probe the deployed attachment prefix:

attachments domain configure \
  --hostname files.example.com \
  --attachments-origin https://attachments-origin.example.com \
  --fallback-origin https://shortlinks-origin.example.com \
  --provider cloudflare

attachments domain plan --format cloudflare
attachments domain verify --format json

On a shared hostname, route /a/* to attachments before a generic /* shortlink or redirect route.

MCP Server

attachments-mcp defaults to Streamable HTTP on 127.0.0.1:8850. Use --stdio for clients that launch one MCP process per session.

attachments-mcp                       # http://127.0.0.1:8850/mcp
attachments-mcp --port 9000           # HTTP port override
attachments-mcp --stdio               # stdio transport
MCP_STDIO=1 attachments-mcp           # stdio transport via environment
  • Health: GET http://127.0.0.1:8850/health
  • MCP: http://127.0.0.1:8850/mcp
  • Port environment override: MCP_HTTP_PORT

ATTACHMENTS_PROFILE controls the lean schemas returned by tools/list:

| Profile | Tools | Intended use | |---------|------:|--------------| | minimal | 3 | Upload, download, and link retrieval | | standard | 13 | Default transfer, reporting, task, context, and agent workflow | | full | 22 | Every tool, including S3 setup, presigned upload, health, search, and feedback |

Install MCP configuration for supported clients with:

attachments mcp --claude
attachments mcp --codex
attachments mcp --gemini
attachments mcp --all
attachments mcp --uninstall --all

Configuration and Data

Configuration is stored in ~/.hasna/attachments/config.json; secrets are masked by attachments config show. SQLite metadata defaults to ~/.hasna/attachments/db.sqlite and can be overridden with HASNA_ATTACHMENTS_DB_PATH.

On first use, missing files from the retired legacy ~/.open-attachments/ and ~/.attachments/ directories are copied into the canonical directory without overwriting existing files.

Development

Requires Bun.

bun install --frozen-lockfile
bun run typecheck
bun run test
bun run build

Documentation

License

Apache-2.0 — see LICENSE.