This guide helps AI assistants build Plot sources and twists correctly.
Connectors are packages that connect to external services (Linear, Slack, Google Calendar, etc.). They extend Connector and save data directly via integrations.saveThread().
Start here: connectors/AGENTS.md — Complete connector development guide with scaffold, patterns, and checklist.
Twists are the entry point that users install. They declare which tools to use and implement domain logic.
Start here: twister/cli/templates/AGENTS.template.md — Twist implementation guide.
All types in twister/src/ with full JSDoc:
- Connector base:
twister/src/connector.ts - Tool base:
twister/src/tool.ts - Twist base:
twister/src/twist.ts - Built-in tools:
twister/src/tools/*.tscallbacks.ts,store.ts,tasks.ts,plot.ts,ai.ts,network.ts,integrations.ts,twists.ts
- Core types:
twister/src/plot.ts,twister/src/tag.ts
- Full Documentation: https://twist.plot.day
- Building Connectors Guide:
connectors/AGENTS.md - Runtime Environment:
twister/docs/RUNTIME.md - Tools Guide:
twister/docs/TOOLS_GUIDE.md - Multi-User Auth:
twister/docs/MULTI_USER_AUTH.md - Sync Strategies:
twister/docs/SYNC_STRATEGIES.md - Working Connector Examples:
connectors/linear/,connectors/google-calendar/,connectors/slack/,connectors/jira/
- ❌ Using instance variables for state — Use
this.set()/this.get()(state doesn't persist between executions) - ❌ Long-running operations without batching — Break into chunks with
runTask()(~1000 requests per execution) - ❌ Passing functions to
this.callback()— Seeconnectors/AGENTS.mdfor callback serialization pattern - ❌ Forgetting sync metadata — Always inject
syncProviderandchannelIdintothread.meta - ❌ Not handling initial vs incremental sync — Propagate
initialSyncflag from entry point (onChannelEnabled→true, webhook →false) through all batch callbacks. Setunread: falseandarchived: falsefor initial, omit for incremental - ❌ Missing localhost guard in webhooks — Skip webhook registration when URL contains "localhost"
- ❌ Stripping HTML tags locally — Pass raw HTML with
contentType: "html"for server-side markdown conversion
Remember: When in doubt, check the type definitions in twister/src/ and study the working examples in connectors/.