@kingcrab/pi-imessage
v1.0.0
Published
A minimal, self-managing iMessage bot powered by Pi Durable
Readme
pi-imessage
A minimal, self-managing iMessage bot powered by Pi Durable.
Features
- Minimal: No BlueBubbles or webhook setup. Runs directly on your Mac alongside Messages.app.
- Messages: DMs, SMS, and group chats, with sender identification and reply context.
- Self-managing: The agent builds its own tools, with native web search, page fetch, and a conversation-owned browser.
- Web UI: Chat history, native task state, scheduled jobs with their latest ten executions, logs, memory, and configuration.
- Memory: Searchable, traceable records; corrections preserve history. See structured memory.
Quick Start
Just point your Pi coding agent at this README and ask it to set up pi-imessage.
Prerequisites: macOS with Messages.app, Node.js 22.22.2 or newer, Python 3 (shared memory writer), Full Disk Access for the terminal, and an authenticated Pi Coding Agent.
npm install -g @kingcrab/pi-imessage
pi-imessage # run in foreground
pi-imessage install # write a launchd job; loading it is a separate operator actionEnable replies for your chats by adding their GUIDs to the settings allowlist. For installation and service operations, see ops/README.md.
Commands
Send these commands as iMessages:
| Command | Description |
|---|---|
| /help | List commands |
| /new | Cancel current work and start a fresh conversation |
| /status | Show tokens, context usage, and model |
| /thinking <level\|default> | Set thinking for this chat or follow the default |
| /compact | Compress context without replaying prior work |
| /run <duration> [task] | Keep working for up to the given time, e.g. /run 1h; /stop ends it early |
| /stop | Abort current work and stop /run; later messages are still answered |
| /reload | Refresh models/auth, AGENTS, skills and extensions without cancelling work |
Configuration
Settings
Edit WORKING_DIR/settings.json. All fields are optional.
{
"chatAllowlist": {
"whitelist": ["iMessage;-;+11234567890"],
"blacklist": ["*"]
},
"richText": {
"enabled": false,
"markdown": true
}
}Add chat GUIDs to whitelist to enable replies; blacklist: ["*"] blocks replies
elsewhere. An explicit blacklist entry takes priority. Messages are always logged.
Rich text is optional; markdown: true renders bold spans in direct iMessage chats.
Workspace extensions and scheduler
Context compaction runs every six hours as a native Durable background task.
Personal tools, tasks and optional daily/interval schedules live in
WORKING_DIR/extensions/<name>/index.ts with config.json, not framework
settings. Startup and /reload load them; the assistant can use
reload_extensions to apply its own changes.
See workspace extensions for the factory contract
and scheduling rules.
One-off runs use the same scheduler: declare a stable runRequests ID, target
schedule and at: "now" (or epoch milliseconds) in the extension configuration,
then call reload_extensions. No restart or separate execution API is needed.
Times use the service machine's local timezone. Saved deadlines survive reload
and restart; view schedules and latest-ten execution history at /scheduled.
Model policy
Optional settings.json fields, applied at startup and /reload:
{
"modelPolicy": {
"fallback": { "provider": "your-provider", "modelId": "your-model" },
"codexServiceTier": "default"
}
}Without a fallback, an unavailable default fails explicitly. Without a tier,
provider requests are unchanged. codexServiceTier accepts default or
priority; priority may have a different cost. Existing deployments migrate
their previous choices into explicit configuration rather than silently changing
behavior.
Environment Variables
All variables are optional.
| Variable | Default | Description |
|---|---|---|
| WEB_ENABLED | true | Set to false to disable the built-in web UI |
| WEB_HOST | localhost | Web UI host |
| WEB_PORT | 7750 | Web UI port |
| WORKING_DIR | ~/.pi/imessage | Workspace directory |
Web and API
See the HTTP API for read-only state and model health checks.
The agent sends files and extra messages with send_message. The scheduler
provides daily/interval cadence and one-off triggers for workspace tasks, plus built-in six-hour compaction.
It does not revive legacy cron files or HTTP prompt/send endpoints.
How It Works
Messages chat.db → Watcher → Pi Durable → Messages.appEach chat has its own conversation, persisted under WORKING_DIR/durable/.
Durable resumes pending work after a crash. Agent replies are sent at most once;
uncertain send results are flagged, never automatically resent.
Context is compacted silently every 6 hours and near the model's limit. Failed
compaction keeps the old context. /new starts fresh without deleting searchable
history.
Development
See AGENTS.md for development rules, architecture for the module layout and execution flow, and ADRs for design decisions.
