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

@kingcrab/pi-imessage

v0.0.43

Published

AI-powered iMessage bot using pi coding agent — understands images, quoted replies, and conversation context

Readme

@kingcrab/pi-imessage

A minimal and self-managing iMessage bot — powered by pi.

Features

  • Minimal: No BlueBubble, no webhooks, no extra dependencies
  • Self-managing: Turn the agent into whatever you need. He builds his own tools without pre-built assumptions
  • Transparent: tool calls and reasoning are sent to your iMessage chat, so you can see exactly what it's doing and why
  • iMessage Integration: Responds to DMs, SMS, and group chats; identifies who sent each message; understands quoted/reply-to messages
  • Persistent Reminders: Schedule one-time messages without per-reminder cron jobs; reminders survive restarts and retry transient failures
  • Web UI: browse chat history, toggle replies on/off per chat, live updates — disable with WEB_ENABLED=false and let the agent build your own web UI

Get Started

⚠️ Security note

  • Replies are off for all chats by default (blacklist: ["*"]) — only explicitly whitelisted chats get a response
  • The agent runs with Full Disk Access and can read/write your filesystem as part of its tool use
  • The web UI has no authentication and is accessible to anyone on your local network; set WEB_ENABLED=false if that's a concern

Prerequisites: macOS with Messages.app, Full Disk Access for the terminal, Pi Coding Agent authenticated

npm install -g @kingcrab/pi-imessage

pi-imessage             # run in foreground
pi-imessage install     # install as launchd service (auto-start on boot, restart on crash)

Usage

Web UI

Available at http://localhost:7750 (configurable via WEB_HOST and WEB_PORT).

  • Chat history with live updates
  • Logs (tail -f style)
  • Memory (global & per-chat)

P.S. Disable with WEB_ENABLED=false and let the agent build your own web UI

Structured Memory

Durable memories are stored as namespaced JSONL records under WORKING_DIR/skills/file-memory/namespaces/. Each record includes a stable ID, creation timestamp, factual event date when known, source, kind, subjects, importance, confidence, and status. This keeps every memory traceable without inventing dates for older facts.

The agent uses typed tools to load complete namespaces, search for specific records, and append validated memories. Corrections append a new record that supersedes the old ID, preserving an auditable history instead of silently rewriting it. Legacy global and per-chat MEMORY.md files remain read-only archives. See the structured memory flow for migration, retrieval, and write behavior.

API

The agent is aware of these endpoints via its system prompt and can use them as tools (e.g., scheduling a cron job that calls /prompt).

| Endpoint | Description | Example | |---|---|---| | POST /send | Send text and/or a local file attachment to a chat (bypasses the agent) | curl -X POST localhost:7750/send -d '{"chatGuid": "iMessage;-;+11234567890", "text": "hello"}'{"ok": true} | | POST /prompt | Feed a prompt to the agent asynchronously; replies are sent to the chat when ready | curl -X POST localhost:7750/prompt -d '{"chatGuid": "iMessage;-;+11234567890", "prompt": "say hello"}'{"ok": true} | | POST /reminders | Schedule a persistent one-time reminder; scheduledAt requires an explicit timezone | curl -X POST localhost:7750/reminders -d '{"chatGuid":"iMessage;-;+11234567890","text":"check the oven","scheduledAt":"2026-08-08T21:30:00+08:00"}' | | GET /reminders | List reminders; optionally filter with ?status=pending | curl 'localhost:7750/reminders?status=pending' | | DELETE /reminders/:id | Cancel a pending reminder | curl -X DELETE localhost:7750/reminders/<id> | | GET /health/model | Make a live request to the configured default AI model; returns HTTP 200 when healthy or 503 on failure | curl localhost:7750/health/model{"ok":true,"model":"openai/gpt-5","latencyMs":842,"checkedAt":"..."} |

Commands

Send these as iMessage to interact with the bot:

| Command | Description | Example Reply | |---|---|---| | /help | List available slash commands | Commands:/help — list commands | | /new | Reset the session, starting a fresh conversation | ✓ New session started | | /status | Show session stats: tokens, context, model | 💬 3 msgs - ↑7.2k ↓505 1.1%/128k🤖 anthropic/claude-sonnet-4 • 💭 minimal | | /compact | Compress session context to free up token space | ✓ Compacted: 15.2k → 2.1k tokens | | /stop | Steer the agent to stop after current tool calls finish, then process the next queued message | | | /reload | Reload models and clear all sessions | ✓ Models reloaded |

Settings (WORKING_DIR/settings.json)

All fields are optional.

{
  "chatAllowlist": {
    "whitelist": ["iMessage;-;+11234567890"],
    "blacklist": ["*"]
  },
  "richText": {
    "enabled": false,
    "markdown": true
  }
}

Chat allowlist controls which chats receive replies (messages are always logged). By default, replies are off for all chats (blacklist: ["*"]) — opt in specific chats via the web UI or by adding their guid to whitelist. Resolution priority: blacklist[guid] > whitelist[guid] > blacklist["*"] > whitelist["*"].

Rich text is optional and disabled by default. When enabled, pi-imessage uses a UI automation fallback to open the target conversation, paste an RTF payload, and send it. Currently this is intended for direct-message iMessage chats. With markdown: true, pi-imessage interprets **bold** spans and renders them as actual bold text in Messages.

Environment Variables

| Variable | Required | Default | Description | |---|---|---|---| | WEB_ENABLED | no | true | Set to false to disable the built-in web UI | | WEB_HOST | no | localhost | Web UI host | | WEB_PORT | no | 7750 | Web UI port | | WORKING_DIR | no | ~/.pi/imessage | Workspace directory | | AGENT_IDLE_TIMEOUT_MS | no | 120000 | Abort only after this much continuous agent inactivity; model and tool events reset the timer | | AGENT_MAX_PROMPT_DURATION_MS | no | 1800000 | Absolute ceiling for one prompt, independent of activity |

Development

npm run check        # typecheck + lint (run after code changes)
npm test             # run tests

How It Works

  ~/Library/Messages/chat.db
        │
  (poll every 2s for new rows)
        │
        ▼
┌──────────────────────────────────────────────────┐
│              pi-imessage                         │
│                                                  │
│  Watcher (chat.db polling)                       │
│    │                                             │
│    ├─ Filter: is_from_me=0, no reactions         │
│    ├─ Deduplicate via seenRowIds                 │
│    ├─ Read attachments from local disk           │
│    │                                             │
│    ▼                                             │
│  AsyncQueue<IncomingMessage>                     │
│    │                                             │
│    ▼                                             │
│  SessionManager (pi-coding-agent)                │
│    │  per chatGuid, persistent on disk           │
│    │  └─ data/<chatGuid>/                        │
│    │       ├─ log.jsonl      (full history)      │
│    │       └─ context.jsonl  (LLM context)       │
│    │                                             │
│    ▼                                             │
│  Agent loop (pi-agent-core)                      │
│    │                                             │
│    │  ┌─ outer: follow-up messages ────┐         │
│    │  │  ┌─ inner: tool calls +      ┐ │         │
│    │  │  │  steering messages        │ │         │
│    │  │  └───────────────────────────┘ │         │
│    │  └────────────────────────────────┘         │
│    │                                             │
│    ▼                                             │
│  Collect assistant reply text                    │
│    │                                             │
│    ├─ sendMessage (AppleScript → Messages.app)   │
│    └─ save logs (messages, digests)              │
│                                                  │
└──────────────────────────────────────────────────┘
        │
        ▼
  iMessage (user receives reply via Messages.app)