Agent skill
perplexity-local-dev-loop
Configure Perplexity local development with mocking, testing, and hot reload. Use when setting up a development environment, configuring test workflows, or establishing a fast iteration cycle with Perplexity Sonar API. Trigger with phrases like "perplexity dev setup", "perplexity local development", "perplexity dev environment", "develop with perplexity", "mock perplexity".
Install this agent skill to your Project
npx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/main/plugins/saas-packs/perplexity-pack/skills/perplexity-local-dev-loop
SKILL.md
Perplexity Local Dev Loop
Overview
Set up a fast, cost-effective local development workflow for Perplexity Sonar API. Key challenge: every real API call performs a web search and costs money, so mocking and caching are essential for development.
Prerequisites
- Completed
perplexity-install-authsetup - Node.js 18+ with npm/pnpm
vitestfor testing
Instructions
Step 1: Project Structure
my-perplexity-project/
├── src/
│ ├── perplexity/
│ │ ├── client.ts # OpenAI client wrapper for Perplexity
│ │ ├── search.ts # Search functions with citation handling
│ │ └── types.ts # Response type extensions
│ └── index.ts
├── tests/
│ ├── fixtures/ # Saved API responses for mocking
│ │ └── sonar-response.json
│ ├── perplexity.test.ts
│ └── setup.ts
├── .env.local # API key (git-ignored)
├── .env.example # Template
└── package.json
Step 2: Type-Safe Client Wrapper
// src/perplexity/client.ts
import OpenAI from "openai";
export interface PerplexityResponse extends OpenAI.ChatCompletion {
citations?: string[];
search_results?: Array<{
title: string;
url: string;
snippet: string;
}>;
related_questions?: string[];
}
export type PerplexityModel = "sonar" | "sonar-pro" | "sonar-reasoning-pro" | "sonar-deep-research";
export function createClient(apiKey?: string): OpenAI {
return new OpenAI({
apiKey: apiKey || process.env.PERPLEXITY_API_KEY,
baseURL: "https://api.perplexity.ai",
});
}
export async function search(
client: OpenAI,
query: string,
opts: {
model?: PerplexityModel;
systemPrompt?: string;
maxTokens?: number;
searchRecencyFilter?: "hour" | "day" | "week" | "month";
searchDomainFilter?: string[];
} = {}
): Promise<PerplexityResponse> {
const response = await client.chat.completions.create({
model: opts.model || "sonar",
messages: [
...(opts.systemPrompt
? [{ role: "system" as const, content: opts.systemPrompt }]
: []),
{ role: "user" as const, content: query },
],
max_tokens: opts.maxTokens,
...(opts.searchRecencyFilter && { search_recency_filter: opts.searchRecencyFilter }),
...(opts.searchDomainFilter && { search_domain_filter: opts.searchDomainFilter }),
} as any);
return response as unknown as PerplexityResponse;
}
Step 3: Save Fixtures for Offline Development
// scripts/capture-fixture.ts
import { createClient, search } from "../src/perplexity/client";
import { writeFileSync } from "fs";
async function captureFixture() {
const client = createClient();
const response = await search(client, "What is TypeScript 5.5?");
writeFileSync(
"tests/fixtures/sonar-response.json",
JSON.stringify(response, null, 2)
);
console.log("Fixture saved with", (response.citations || []).length, "citations");
}
captureFixture();
Step 4: Mock Client for Tests
// tests/setup.ts
import { vi } from "vitest";
import fixture from "./fixtures/sonar-response.json";
export function mockPerplexityClient() {
return {
chat: {
completions: {
create: vi.fn().mockResolvedValue(fixture),
},
},
};
}
Step 5: Write Tests
// tests/perplexity.test.ts
import { describe, it, expect } from "vitest";
import { mockPerplexityClient } from "./setup";
import { search } from "../src/perplexity/client";
describe("Perplexity Search", () => {
it("returns answer with citations", async () => {
const client = mockPerplexityClient() as any;
const result = await search(client, "test query");
expect(result.choices[0].message.content).toBeDefined();
expect(result.citations).toBeDefined();
expect(result.citations!.length).toBeGreaterThan(0);
});
it.skipIf(!process.env.PERPLEXITY_API_KEY)(
"live API returns citations",
async () => {
const { createClient, search } = await import("../src/perplexity/client");
const client = createClient();
const result = await search(client, "What is Node.js?", {
model: "sonar",
maxTokens: 100,
});
expect(result.citations!.length).toBeGreaterThan(0);
}
);
});
Step 6: Dev Scripts
{
"scripts": {
"dev": "tsx watch src/index.ts",
"test": "vitest",
"test:watch": "vitest --watch",
"test:live": "PERPLEXITY_API_KEY=$PERPLEXITY_API_KEY vitest --run",
"capture-fixtures": "tsx scripts/capture-fixture.ts"
}
}
Error Handling
| Error | Cause | Solution |
|---|---|---|
| Fixture missing | Never captured | Run npm run capture-fixtures once |
| Tests hit real API | Missing mock | Ensure mock client is injected |
| Stale fixtures | API response format changed | Re-capture fixtures |
| High dev costs | Making live calls in loop | Use fixtures; reserve live calls for CI |
Output
- Type-safe Perplexity client wrapper
- Fixture-based test suite that runs offline
- Live integration test gated on API key presence
- Hot-reload dev server
Resources
Next Steps
See perplexity-sdk-patterns for production-ready code patterns.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
dockerfile-generator
Dockerfile Generator - Auto-activating skill for DevOps Basics. Triggers on: dockerfile generator, dockerfile generator Part of the DevOps Basics skill category.
branch-naming-helper
Branch Naming Helper - Auto-activating skill for DevOps Basics. Triggers on: branch naming helper, branch naming helper Part of the DevOps Basics skill category.
readme-generator
Readme Generator - Auto-activating skill for DevOps Basics. Triggers on: readme generator, readme generator Part of the DevOps Basics skill category.
makefile-generator
Makefile Generator - Auto-activating skill for DevOps Basics. Triggers on: makefile generator, makefile generator Part of the DevOps Basics skill category.
gitignore-generator
Gitignore Generator - Auto-activating skill for DevOps Basics. Triggers on: gitignore generator, gitignore generator Part of the DevOps Basics skill category.
pre-commit-hook-setup
Pre Commit Hook Setup - Auto-activating skill for DevOps Basics. Triggers on: pre commit hook setup, pre commit hook setup Part of the DevOps Basics skill category.
Didn't find tool you were looking for?