Ploy
Ploy

AI Skills

Agent skills for AI coding assistants to build Ploy applications

AI Skills

Ploy provides agent skills that give AI coding assistants the knowledge to scaffold and build applications on Ploy. These skills work with Claude Code, Cursor, Windsurf, Codex, Aider, Cline, and other AI coding tools.

Available Skills

SkillDescriptionUse When
worker-basicBasic Cloudflare WorkerBuilding APIs, webhooks, serverless functions
nextjs-appNext.js applicationFull-stack web apps with SSR
db-drizzleD1 database with DrizzleAdding persistence to workers
nextjs-dbNext.js with databaseFull-stack apps with data
queue-handlerMessage queuesBackground jobs, async processing
workflowDurable workflowsMulti-step processes, sagas
start-frameworkPloy Start frameworkType-safe REST APIs

Quick Install

The easiest way to install skills is using add-skill, which works with any AI coding tool:

npx add-skill polarlightsllc/ploy

This will prompt you to:

  1. Select which skills to install
  2. Choose your AI tool (Claude Code, Cursor, Windsurf, etc.)
  3. Automatically install to the correct location

Install specific skills

# Install only the skills you need
npx add-skill polarlightsllc/ploy/worker-basic
npx add-skill polarlightsllc/ploy/start-framework
npx add-skill polarlightsllc/ploy/db-drizzle

Manual Installation

Usage Examples

Once skills are installed, ask your AI assistant:

Create a Worker

"Create a new Ploy worker with health check and JSON API endpoints"

The AI will use the worker-basic skill to scaffold:

import type { Ploy } from "@meetploy/types";

export default {
	async fetch(request: Request, env: Env): Promise<Response> {
		const url = new URL(request.url);

		if (url.pathname === "/health") {
			return Response.json({ status: "ok" });
		}

		if (url.pathname === "/api/data") {
			return Response.json({ message: "Hello!" });
		}

		return new Response("Not Found", { status: 404 });
	},
} satisfies Ploy<Env>;

Add Database

"Add a users table with CRUD operations"

The AI will use the db-drizzle skill to add:

# ploy.yaml
db:
  DB: default
// schema.ts
export const users = sqliteTable("users", {
	id: integer("id").primaryKey({ autoIncrement: true }),
	name: text("name").notNull(),
	email: text("email").notNull().unique(),
});

Build a REST API

"Create a REST API for managing products with Ploy Start"

The AI will use the start-framework skill:

import { ploy, withDrizzle, z } from "@meetploy/start";

const worker = ploy<Env>()
	.state(withDrizzle("DB", schema))
	.openapi({ path: "/docs", info: { title: "Products API", version: "1.0.0" } })

	.get(
		"/products",
		{
			response: z.object({ products: z.array(productSchema) }),
		},
		async (ctx) => {
			const products = await ctx.state.db.select().from(schema.products);
			return { products };
		},
	)

	.post(
		"/products",
		{
			body: z.object({ name: z.string(), price: z.number() }),
			response: z.object({ product: productSchema }),
		},
		async (ctx) => {
			const [product] = await ctx.state.db
				.insert(schema.products)
				.values(ctx.body)
				.returning();
			return { product };
		},
	)

	.build();

Add Background Processing

"Add a queue for processing image uploads"

The AI will use the queue-handler skill:

# ploy.yaml
queue:
  UPLOADS: image-uploads
export default {
	async fetch(request, env) {
		const { messageId } = await env.UPLOADS.send({
			type: "process-image",
			imageUrl: "...",
		});
		return Response.json({ queued: true, messageId });
	},

	async message(event) {
		await processImage(event.payload);
	},
} satisfies Ploy<Env>;

Create a Workflow

"Build an order processing workflow with payment and shipping"

The AI will use the workflow skill:

workflows: {
  async order_processing({ input, step, log }) {
    log("Processing order", { orderId: input.orderId });

    const payment = await step.run("charge", async () => {
      return await chargeCustomer(input.amount);
    });

    const shipment = await step.run("ship", async () => {
      return await createShipment(input.address);
    });

    await step.sleep(24 * 60 * 60 * 1000); // 24 hours

    await step.run("followup", async () => {
      await sendFollowupEmail(input.email);
    });

    return { paymentId: payment.id, trackingNumber: shipment.tracking };
  },
}

Skill Architecture

Each skill is a markdown file with:

---
name: skill-name
description: Brief description for selection
---
# Skill Name

Instructions for the AI on how to implement this pattern...

Skills include:

  • Project structure
  • Configuration files (ploy.yaml, package.json, tsconfig.json)
  • Code examples with TypeScript
  • Best practices and patterns
  • Common use cases

Creating Custom Skills

Add your own skills by creating markdown files in skills/your-skill/SKILL.md:

---
name: my-custom-skill
description: Custom pattern for my project
---
# My Custom Skill

When asked to implement [pattern], follow these steps...

Repository

Skills are maintained in the Ploy repository: github.com/polarlightsllc/ploy

ploy/
└── skills/
    ├── README.md
    ├── worker-basic/
    │   └── SKILL.md
    ├── nextjs-app/
    │   └── SKILL.md
    ├── db-drizzle/
    │   └── SKILL.md
    ├── nextjs-db/
    │   └── SKILL.md
    ├── queue-handler/
    │   └── SKILL.md
    ├── workflow/
    │   └── SKILL.md
    └── start-framework/
        └── SKILL.md

Troubleshooting

Skill Not Recognized

Ensure the skill files are in the correct location for your tool:

  • Claude Code: ~/.claude/skills/ or .claude/skills/ in project
  • Cursor: ~/.cursor/skills/ or referenced in .cursorrules

AI Not Following Instructions

Try being more specific in your request:

  • "Use the worker-basic skill to create a new API"
  • "Following the db-drizzle skill, add a users table"

Missing Dependencies

After scaffolding, run:

pnpm install
pnpm types  # Generate env.d.ts

How is this guide?

Last updated on