A Claude Code-style terminal interface for Poke AI - tools execute locally, responses stream back via iMessage.
Quick Start · Usage · Report a Bug
Tip
Companions — Your terminal has a new resident. Hatch a persistent island-tech creature that lives beside your input, evolves with usage, and reacts to your coding sessions. /companion hatch Sparky to get started.
¥/=~\
(◉=◉) ── "nice refactor!"
=/|≡|\=
(_/ \_)
Sparky
Cron Scheduling — Schedule prompts to run on a timer with natural language (/cron every 30 minutes check build status) or standard cron expressions. Runs in-session or as a background daemon with optional macOS launchd integration for auto-start on boot.
AutoDream — Automatic memory consolidation. After enough sessions, poke-code summarizes your recent conversations into long-term memory files so it gets smarter over time — no manual effort required. Trigger manually anytime with /dream.
- Execute tools locally - read, write, edit files, run shell commands, search the web, all from your terminal with syntax highlighting and diff previews
- Stream responses via iMessage - polls macOS
chat.dbfor Poke's replies with sub-second latency, or uses theimsgCLI for event-driven streaming - Parse three response formats - tries XML tool calls first, falls back to bracket commands, then natural language intent detection as a last resort
- Discover and inject skills - automatically finds skills from
~/.claude/skills/and marketplace plugins, matches them to your message by keyword relevance, and injects them into context - Load project context - reads
POKE.md/CLAUDE.md, memory files from multiple directories, project rules, and working directory listings to give Poke full codebase awareness - Manage permissions - three-tier system (default, trusted, readonly) with per-tool approval prompts and "always allow" for trusted tools
- Schedule prompts with cron - run prompts on a recurring or one-shot basis using natural language or cron expressions, with a background daemon and launchd support
- Auto-consolidate memory - after enough sessions, automatically summarize recent conversations into long-term memory files that enrich future context
- Persist sessions - JSONL-based session history with resume, context compaction, and session browsing
- Hatch a companion - a persistent island-tech creature that evolves with your usage, reacts to your coding via
[emote]tags, and unlocks accessories over time - Guard against partial writes - detects when iMessage splits a file write across multiple bubbles and refuses to overwrite with incomplete content
- Render markdown - assistant messages render with full terminal markdown (bold, code blocks, lists) via
marked-terminal
# install globally
npm install -g poke-code
# or from source
git clone https://github.com/hummusonrails/poke-code
cd poke-code
npm install && npm run build && npm link
# run the setup wizard
poke-code --initThe wizard walks you through:
- Importing existing
~/.claude/rules and memory into~/.poke/(renamesCLAUDE.mdtoPOKE.md) - Setting your Poke API key
- Selecting your Poke iMessage contact from recent conversations
| Layer | Tool | Notes |
|---|---|---|
| Runtime | Node.js 20+ | ES modules, strict TypeScript |
| UI | React + Ink | Full component model in the terminal |
| Database | better-sqlite3 | Readonly access to macOS chat.db with WAL mode |
| Messaging | imsg CLI | Direct iMessage send, bypasses API for large payloads |
| Parsing | 3-tier fallback | XML <tool_call>, bracket [read], natural language intent |
| Highlighting | cli-highlight + chalk | Syntax coloring for 20+ languages on file reads |
| Diffing | diff | Colored inline diffs on every file edit |
| Markdown | marked + marked-terminal | Rich terminal rendering for assistant messages |
Prerequisites
- Node.js 20+ - install via nvm
- macOS - required for iMessage integration
- Full Disk Access - grant to your terminal app in System Settings > Privacy & Security > Full Disk Access
- Poke account - get an API key from poke.com/kitchen
- imsg CLI (optional) -
brew install steipete/tap/imsgfor faster message delivery
# interactive mode
poke-code
# one-shot message
poke-code "explain what this codebase does"
# resume last session
poke-code --continue
# resume specific session
poke-code --resume <session-id>
# trusted mode (no permission prompts)
poke-code --permission-mode trusted
# readonly mode (no writes allowed)
poke-code --permission-mode readonly
# background cron daemon
poke-code --daemon start
poke-code --daemon stop
poke-code --daemon statusSchedule prompts to run on a timer using natural language or standard cron expressions:
# natural language
/cron every 30 minutes check if the build is passing
/cron every weekday at 5pm remind me to push my branch
/cron at 9am summarize overnight git activity
# standard cron syntax
/cron add */30 * * * * check build status
/cron once 0 9 * * * run morning report
# manage tasks
/cron list
/cron remove <id>
/cron resultsBackground daemon — run cron jobs even when the CLI is closed:
# start/stop the daemon
poke-code --daemon start
poke-code --daemon stop
poke-code --daemon status
# auto-start on macOS login (launchd)
/cron install
/cron uninstallResults are always written to ~/.poke/cron-results/. When running in daemon mode, results are also sent to you via iMessage.
poke-code automatically consolidates your session history into long-term memory. After 5+ sessions over 24+ hours, it summarizes recent conversations and writes memory files to .poke/memory/autodream/. These memories are loaded into future sessions automatically.
Run /dream to trigger consolidation manually at any time.
Configure thresholds in ~/.poke/config.json:
{
"autoDream": {
"enabled": true,
"minHours": 24,
"minSessions": 5
}
}Every poke-code user gets a unique island-tech companion — a hybrid creature that's part tropical, part circuitry. Your companion is deterministically generated from your identity, so it's uniquely yours.
/~\ ¥/=~\ ¥¥/≡=~\
(·_·) → (◉=◉)~ → (✦≡=✦)~≈
_/| |\_ =/|≡|\= *=/|≡≡|\=*
(_/ \_) (_/ \_) (≈/ \≈)
Spark Powered Overclocked
10 species — Clicklaw, Synthray, Drifter, Shellbyte, Flickbug, Reefnode, Zapgecko, Coilpod, Wattpalm, Neoncoil
3 evolution stages — Companions earn XP from your activity (sessions, messages, tool use, cron jobs, /dream) and evolve from Spark → Powered → Overclocked, gaining visual detail at each stage.
Accessory unlocks — Between stages, companions unlock cosmetics: Signal Spark, Coral Crown, Tide Trail, Solar Shell, Copper Coil, Biolume Glow, and Storm Aura.
AI-powered reactions — Poke can include [emote] tags in responses, giving your companion contextual speech bubbles and animations. Local events (tool success, failures, idle) also trigger reactions without any API call.
/companion # show your companion's card
/companion hatch Sparky # hatch a new companion
/companion pet # give it a pat
/companion mute # hide companion
/companion unmute # bring it back
/companion name Ziggy # renameAll tools execute locally in your terminal. Results are sent back to Poke for context.
| Tool | Permission | Description |
|---|---|---|
read_file |
Auto | Read files with line numbers and syntax highlighting |
write_file |
Ask | Create or overwrite files with partial-write guard |
edit_file |
Ask | Inline string replacement with diff preview |
bash |
Ask | Execute shell commands with configurable timeout |
glob |
Auto | Find files by glob pattern |
grep |
Auto | Search file contents with regex and file type filtering |
list_dir |
Auto | List directory contents |
web_search |
Auto | Search the web via DuckDuckGo |
web_fetch |
Auto | Fetch and extract text from web pages |
Read-only tools run in parallel (up to 5 concurrent). Write and bash tools run sequentially with permission prompts.
| Command | Description |
|---|---|
/help |
Show all commands |
/clear |
Clear message history |
/history |
Show conversation history |
/sessions |
List or resume sessions |
/compact |
Summarize and compress context |
/permissions |
Switch permission mode |
/status |
Show connection status |
/model |
Show current configuration |
/init |
Re-run setup wizard |
/apikey |
Update your API key |
/verbose |
Toggle verbose tool output |
/memory |
List or view memory files |
/doctor |
Run setup diagnostics |
/bug |
Report a bug or issue |
/copy |
Copy last response to clipboard |
/companion |
Manage your island-tech companion (hatch, pet, mute, unmute, name) |
/cron |
Manage scheduled prompts (add, once, list, remove, results, install, uninstall) |
/dream |
Manually trigger memory consolidation |
/quit |
Exit |
| Key | Action |
|---|---|
Enter |
Send message |
Ctrl+E |
Toggle multi-line input mode |
Ctrl+D |
Submit in multi-line mode |
Ctrl+C |
Exit |
| Mode | Read tools | Write / bash |
|---|---|---|
default |
Auto | Ask (y/n/a to always allow) |
trusted |
Auto | Auto |
readonly |
Auto | Denied |
poke-code automatically discovers and loads skills from:
~/.claude/skills/- user custom skills~/.claude/plugins/marketplaces/.../skills/- marketplace plugin skills (scanned recursively)- Custom directories configured in
~/.poke/config.jsonviaskillsDirs
Each skill is a directory containing a SKILL.md with YAML frontmatter:
---
name: my-skill
description: what this skill does
---
skill content and instructions hereWhen you send a message, poke-code matches your message against skill names, descriptions, and content by keyword relevance. The top 3 matching skills are injected into the context sent to Poke, giving it specialized knowledge for your task.
Every message sent to Poke is enriched with:
- System prompt - tool format instructions, bracket command syntax, and rules
- Working directory listing - files and folders in your project root
- Tool schemas - auto-generated from the tool registry with examples
- Project context -
POKE.mdorCLAUDE.mdfrom your project root - Memory - markdown files from
.poke/memory/,.claude/memory/, or~/.poke/memory/ - Rules - markdown files from
.poke/rules/,.claude/rules/, or~/.poke/rules/ - Relevant skills - top 3 keyword-matched skills from discovered skill directories
┌──────────────┐ ┌───────────┐ ┌────────────┐
│ You type a │────>│ Poke API │────>│ Poke AI │
│ message │ │ (send) │ │ (responds) │
└──────────────┘ └───────────┘ └──────┬─────┘
│
v
┌──────────────┐ ┌───────────┐ ┌────────────┐
│ Execute │<────│ Parse │<────│ chat.db │
│ tools │ │ response │ │ (poll) │
└──────┬───────┘ └───────────┘ └────────────┘
│
v
┌──────────────┐
│ Send results│────> (back to Poke via imsg or API)
│ loop again │
└──────────────┘
- Your message is enriched with context (system prompt, skills, memory, project files) and sent to Poke via their REST API
- Poke's response arrives via iMessage - the CLI polls
chat.dbevery 1.5s (or usesimsg watchfor ~500ms event-driven latency) - The response is parsed for tool calls using a 3-tier fallback: XML
<tool_call>> bracket commands[read]> natural language intent - Tools execute locally with permission checks, read tools in parallel, writes sequentially
- Results (capped at 8KB per tool) are sent back to Poke via
imsg send(or the API as fallback) and the loop continues - If a response has unclosed bracket blocks (split across iMessage bubbles), the poller waits for more messages before parsing
poke-code/
├── bin/
│ └── poke.ts # cli entry point and setup wizard
├── src/
│ ├── api/
│ │ ├── client.ts # poke rest client with retry and backoff
│ │ └── conversation.ts # async generator conversation loop
│ ├── config/
│ │ ├── store.ts # ~/.poke/config.json persistence
│ │ └── wizard.ts # claude-to-poke config migration
│ ├── context/
│ │ ├── builder.ts # system prompt, tools, skills, memory assembly
│ │ ├── memory.ts # memory file discovery and loading
│ │ └── skills.ts # skill discovery, matching, and injection
│ ├── db/
│ │ ├── poller.ts # chat.db polling with fast/normal modes
│ │ ├── attributed-body.ts # NSAttributedString binary extraction
│ │ ├── imsg-sender.ts # direct imessage send via imsg cli
│ │ └── imsg-watcher.ts # event-driven imsg watch streaming
│ ├── parser/
│ │ ├── response-parser.ts # xml <tool_call> extraction
│ │ ├── bracket-parser.ts # [read] [write] [edit] bracket parsing
│ │ ├── intent-parser.ts # natural language "read the file" detection
│ │ ├── strip-commands.ts # strip all tool markup from display text
│ │ └── incomplete-check.ts # detect mid-stream unclosed blocks
│ ├── tools/
│ │ ├── registry.ts # 9 tool definitions with permission levels
│ │ ├── executor.ts # parallel reads, sequential writes
│ │ ├── read-file.ts # syntax highlighted reads with line numbers
│ │ ├── write-file.ts # writes with partial-content guard
│ │ ├── edit-file.ts # string replacement with diff preview
│ │ ├── bash.ts # shell execution with timeout
│ │ ├── glob.ts # file pattern matching
│ │ ├── grep.ts # regex content search
│ │ ├── list-dir.ts # directory listing
│ │ ├── web-search.ts # duckduckgo html scraping
│ │ └── web-fetch.ts # html-to-text extraction
│ ├── session/
│ │ ├── manager.ts # jsonl session files with index
│ │ └── compactor.ts # conversation summary for context compression
│ ├── cron/
│ │ ├── scheduler.ts # cron tick loop, execution, logging
│ │ ├── storage.ts # CRUD for scheduled_tasks.json
│ │ ├── natural-schedule.ts # natural language → cron expression parser
│ │ └── launchd.ts # macOS plist generation and management
│ ├── services/
│ │ └── autodream.ts # memory consolidation engine
│ ├── entrypoints/
│ │ └── daemon.ts # headless daemon bootstrap
│ ├── companion/
│ │ ├── types.ts # species, stages, accessories, xp types
│ │ ├── roll.ts # deterministic prng from user identity
│ │ ├── xp.ts # xp tracking and milestone computation
│ │ ├── sprites.ts # ascii art: 10 species × 3 stages × 3 frames
│ │ ├── companion.ts # core api: get, hatch, evolve, rename
│ │ ├── prompt.ts # system prompt companion context injection
│ │ ├── emote-parser.ts # [emote] tag extraction from responses
│ │ ├── local-events.ts # event emitter for tool/session reactions
│ │ └── CompanionSprite.tsx # animated terminal sprite component
│ ├── commands/
│ │ └── router.ts # slash commands with diagnostics
│ ├── ui/
│ │ ├── welcome.tsx # poke-branded welcome with palm tree ascii art
│ │ ├── message.tsx # markdown-rendered message bubbles
│ │ ├── spinner.tsx # animated loading indicator
│ │ ├── permission.tsx # y/n/a tool approval prompt
│ │ ├── tool-call.tsx # compact tool result summaries
│ │ ├── status-line.tsx # footer with mode and shortcuts
│ │ └── diff-view.tsx # colored unified diff display
│ ├── app.tsx # main react app with state management
│ └── types.ts # shared type definitions
└── test/ # vitest test suites for all modules
Config lives at ~/.poke/config.json. The setup wizard creates it, or edit manually:
{
"apiKey": "$YOUR_API_KEY",
"chatId": 123,
"handleId": 456,
"permissionMode": "default"
}Add a POKE.md (or CLAUDE.md) to your project root for persistent codebase instructions. Memory and rules directories are also supported:
your-project/
├── POKE.md # project-level instructions for Poke
├── .poke/
│ ├── memory/ # project-scoped memory files
│ └── rules/ # project-scoped rules
~/.poke/
├── config.json # api key, chat settings, permissions, autodream config
├── sessions/ # jsonl session files + index
├── memory/ # global memory files
├── rules/ # global rules
├── scheduled_tasks.json # cron task definitions
├── cron-results/ # execution result logs
├── daemon.pid # daemon process ID (when running)
├── daemon.log # daemon output log
├── consolidation.lock # autodream file lock
└── consolidation-state.json # last consolidation timestamp
Found a bug or have an idea? Open an issue or send a PR.
