Plot Twist Creator - Build intelligent extensions that integrate and automate
npm install @plotday/twister
The official package for building Plot Twists -
smart automations that connect, organize, and prioritize your work.
Choose your path:
- No Code - Write natural language, deploy in minutes
- TypeScript - Full control with code
Describe your twist and Plot will do the rest.
1. Create plot-twist.md:
``markdownMy Calendar Twist
I want a twist that:
- Syncs my Google Calendar events into Plot
- Creates tasks for upcoming meetings
- Sends reminders 10 minutes before meetings
`
2. Deploy:
`bash`
npx @plotday/twister login
npx @plotday/twister deploy
That's it! Learn more →
Build twists with TypeScript for maximum flexibility.
1. Create a new twist:
`bash`
npx @plotday/twister create
2. Implement your twist:
`typescript
import {
ActivityType,
type Priority,
type ToolBuilder,
Twist,
} from "@plotday/twister";
import { Plot } from "@plotday/twister/tools/plot";
export default class MyTwist extends Twist
build(build: ToolBuilder) {
return {
plot: build(Plot),
};
}
async activate(priority: Pick
await this.tools.plot.createActivity({
type: ActivityType.Note,
title: "Welcome! Your twist is now active.",
notes:
{
content: "Your twist is ready to use. Check out the [documentation to learn more.",
},
],
});
}
}
`
3. Deploy:
`bash`
npm run plot login
npm run deploy
---
Twists are smart automations that connect, organize, and prioritize your work. They implement opinionated workflows and respond to lifecycle events.
`typescript`
// Lifecycle methods
async activate(priority) // When twist is added to a priority
async deactivate() // When twist is removed
async upgrade() // When new version is deployed
Twist tools provide capabilities to twists. They are usually unopinionated and do nothing on their own. Use built-in tools or create your own.
Built-in Tools:
- Plot - Manage activities and priorities
- Store - Persistent key-value storage
- AI - Language models with structured output
- Integrations - OAuth authentication
- Network - HTTP access and webhooks
- Tasks - Background task execution
- Callbacks - Persistent function references
Activity represents something done or to be done (a task, event, or conversation).
Notes represent updates and details on that activity.
Think of an Activity as a thread and Notes as messages in that thread. Always create activities with an initial note, and add notes for updates rather than creating new activities.
Data sync: When syncing from external systems, use Activity.source (canonical URL) and Note.key for automatic upserts without manual ID tracking. See the Sync Strategies guide for detailed patterns.
Action scheduling: When creating Actions (tasks), omitting the start field defaults to "Do Now" (current time). For most integrations, explicitly set start: null to create backlog items ("Do Someday"), only using "Do Now" for urgent or in-progress tasks.
`typescript
// Create an activity with source for automatic deduplication
await this.tools.plot.createActivity({
source: "https://github.com/org/repo/pull/123", // Enables automatic upserts
type: ActivityType.Action,
title: "Review pull request",
start: null, // "Do Someday" - backlog item (recommended default)
notes: [
{
activity: { source: "https://github.com/org/repo/pull/123" },
key: "description", // Use key for upsertable notes
content: "New PR ready for review",
links: [
{
type: ActivityLinkType.external,
title: "View PR",
url: "https://github.com/org/repo/pull/123",
},
],
},
],
});
// Add or update a note using key (upserts if key exists)
await this.tools.plot.createNote({
activity: { source: "https://github.com/org/repo/pull/123" },
key: "approval", // Using key enables upserts
content: "LGTM! Approved ✅",
});
`
---
`bashAuthentication
plot login
---
Documentation
📚 Full Documentation at twist.plot.day
$3
- Getting Started - Complete walkthrough
- Core Concepts - Twists, tools, and architecture
- Sync Strategies - Data synchronization patterns (upserts, deduplication, ID management)
- Built-in Tools - Plot, Store, AI, and more
- Building Custom Tools - Create reusable twist tools
- Runtime Environment - Execution constraints and optimization
- Advanced Topics - Complex patterns and techniques
$3
- CLI Reference - Complete command documentation
- API Reference - TypeDoc-generated API docs
---
Examples
$3
`typescript
export default class WelcomeTwist extends Twist {
build(build: ToolBuilder) {
return { plot: build(Plot) };
} async activate(priority: Pick) {
await this.tools.plot.createActivity({
type: ActivityType.Note,
title: "Welcome to Plot! 👋",
notes: [
{
content: "This twist will help you get started with Plot.",
},
],
});
}
}
`$3
`typescript
export default class GitHubTwist extends Twist {
build(build: ToolBuilder) {
return {
plot: build(Plot),
network: build(Network, {
urls: ["https://api.github.com/*"],
}),
};
} async activate(priority: Pick) {
// Set up webhook for issue updates
const webhookUrl = await this.tools.network.createWebhook("onIssueUpdate");
await this.set("webhook_url", webhookUrl);
}
async onIssueUpdate(request: WebhookRequest) {
// Sync GitHub issues to Plot activities
}
}
`---
TypeScript Configuration
Extend the Twist Creator's base configuration in your
tsconfig.json:`json
{
"extends": "@plotday/twister/tsconfig.base.json",
"include": ["src/*.ts"]
}
``---
- Documentation: twist.plot.day
- Issues: github.com/plotday/plot/issues
- Website: plot.day
---
MIT © Plot Technologies Inc.