Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Configure Algolia local development with separate dev index, mocking, and testing. Use when setting up a development environment, configuring test workflows, or establishing a fast iteration cycle with Algolia. Trigger: "algolia dev setup", "algolia local development", "algolia dev environment", "test algolia locally".
.claude/skills/jeremylongshore-algolia-local-dev-loop/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 43% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 24% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 42% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 122% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 44% | 0% |
Set up a fast, reproducible local development workflow for Algolia. Use separate dev indices, mock the client in tests, and iterate without touching production data.
algolia-install-auth setuptypescript// src/algolia/config.ts import { algoliasearch } from 'algoliasearch'; const ENV = process.env.NODE_ENV || 'development'; // Each environment gets its own index prefix export function indexName(base: string): string { if (ENV === 'production') return base; return `${ENV}_${base}`; // e.g., "development_products" } export const client = algoliasearch( process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY! );
typescript// scripts/seed-algolia.ts import { client, indexName } from '../src/algolia/config'; const SEED_DATA = [ { objectID: 'prod-1', name: 'Widget A', category: 'tools', price: 29.99 }, { objectID: 'prod-2', name: 'Widget B', category: 'tools', price: 49.99 }, { objectID: 'prod-3', name: 'Gadget C', category: 'electronics', price: 199.99 }, ]; async function seed() { const idx = indexName('products'); // replaceAllObjects atomically swaps index content const { taskID } = await client.replaceAllObjects({ indexName: idx, objects: SEED_DATA, }); await client.waitForTask({ indexName: idx, taskID }); // Configure settings for the dev index await client.setSettings({ indexName: idx, indexSettings: { searchableAttributes: ['name', 'category'], attributesForFaceting: ['category', 'filterOnly(price)'], customRanking: ['asc(price)'], }, }); console.log(`Seeded ${SEED_DATA.length} records into ${idx}`); } seed().catch(console.error);
json{ "scripts": { "seed:algolia": "npx tsx scripts/seed-algolia.ts", "dev": "tsx watch src/index.ts", "test": "vitest", "test:watch": "vitest --watch" } }
typescript// tests/algolia.test.ts import { describe, it, expect, vi, beforeEach } from 'vitest'; // Mock the entire algoliasearch module vi.mock('algoliasearch', () => ({ algoliasearch: vi.fn(() => ({ searchSingleIndex: vi.fn().mockResolvedValue({ hits: [ { objectID: '1', name: 'Widget A', _highlightResult: {} }, ], nbHits: 1, page: 0, nbPages: 1, }), saveObjects: vi.fn().mockResolvedValue({ taskID: 123 }), waitForTask: vi.fn().mockResolvedValue({}), })), })); import { algoliasearch } from 'algoliasearch'; describe('Product Search', () => { const client = algoliasearch('test-app-id', 'test-api-key'); it('returns matching products', async () => { const { hits } = await client.searchSingleIndex({ indexName: 'development_products', searchParams: { query: 'widget' }, }); expect(hits).toHaveLength(1); expect(hits[0].name).toBe('Widget A'); }); });
typescript// tests/integration/algolia.integration.test.ts import { describe, it, expect } from 'vitest'; import { algoliasearch } from 'algoliasearch'; describe.skipIf(!process.env.ALGOLIA_APP_ID)('Algolia Integration', () => { const client = algoliasearch( process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY! ); const testIndex = `test_${Date.now()}_products`; it('indexes and searches records', async () => { // Index const { taskID } = await client.saveObjects({ indexName: testIndex, objects: [{ objectID: '1', name: 'Test Product' }], }); await client.waitForTask({ indexName: testIndex, taskID }); // Search const { hits } = await client.searchSingleIndex({ indexName: testIndex, searchParams: { query: 'test' }, }); expect(hits.length).toBeGreaterThan(0); // Cleanup await client.deleteIndex({ indexName: testIndex }); }); });
The local loop provides an isolated development index, repeatable seed data, and a fast verification path for search and indexing changes. Production data and credentials remain outside the local development workflow.
| Error | Cause | Solution | |-------|-------|----------| | Index does not exist | Dev index not seeded | Run npm run seed:algolia | | Test pollution | Shared index between tests | Use unique timestamped index names | | Stale search results | Indexing not waited | Always await client.waitForTask() after writes | | Mock not applied | Wrong import order | Ensure vi.mock() is before imports |
typescript// scripts/reset-dev-algolia.ts import { client, indexName } from '../src/algolia/config'; async function reset() { const idx = indexName('products'); try { await client.deleteIndex({ indexName: idx }); console.log(`Deleted ${idx}`); } catch (e) { // Index may not exist yet — that's fine } } reset().catch(console.error);
See algolia-sdk-patterns for production-ready code patterns.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 54,572 | 41,956 | -23% | 1 | 1 | 0% | 3,819 | 4,211 | +10% | 0 | 0 | — |
case-02 | fail→pass | 13,652 | 12,647 | -7% | 1 | 1 | 0% | 2,896 | 4,140 | +43% | 0 | 0 | — |
case-03 | fail→fail | 18,161 | 9,264 | -49% | 1 | 1 | 0% | 3,360 | 3,404 | +1% | 0 | 0 | — |
case-04 | pass→pass | 8,961 | 7,875 | -12% | 1 | 1 | 0% | 1,624 | 2,948 | +82% | 0 | 0 | — |
case-05 | pass→pass | 5,520 | 2,536 | -54% | 1 | 1 | 0% | 915 | 2,047 | +124% | 0 | 0 | — |
case-06 | fail→pass | 9,188 | 32,596 | +255% | 1 | 1 | 0% | 1,646 | 2,043 | +24% | 0 | 0 | — |
case-07 | pass→pass | 6,603 | 2,664 | -60% | 1 | 1 | 0% | 1,133 | 2,056 | +81% | 0 | 0 | — |
case-08 | pass→pass | 12,663 | 7,096 | -44% | 1 | 1 | 0% | 2,229 | 2,824 | +27% | 0 | 0 | — |
case-09 | pass→pass | 13,637 | 9,729 | -29% | 1 | 1 | 0% | 2,192 | 3,331 | +52% | 0 | 0 | — |
case-10 | fail→pass | 9,880 | 4,186 | -58% | 1 | 1 | 0% | 1,656 | 2,350 | +42% | 0 | 0 | — |
case-11 | pass→pass | 14,211 | 10,098 | -29% | 1 | 1 | 0% | 2,231 | 3,416 | +53% | 0 | 0 | — |
case-12 | pass→pass | 8,889 | 4,296 | -52% | 1 | 1 | 0% | 1,505 | 2,317 | +54% | 0 | 0 | — |
case-13 | fail→pass | 5,085 | 2,159 | -58% | 1 | 1 | 0% | 902 | 2,005 | +122% | 0 | 0 | — |
case-14 | pass→pass | 8,257 | 2,534 | -69% | 1 | 1 | 0% | 1,424 | 2,058 | +45% | 0 | 0 | — |
case-15 | pass→pass | 4,473 | 1,987 | -56% | 1 | 1 | 0% | 770 | 1,950 | +153% | 0 | 0 | — |
case-16 | fail→pass | 45,742 | 7,722 | -83% | 1 | 1 | 0% | 2,181 | 3,151 | +44% | 0 | 0 | — |
case-17 | pass→pass | 13,228 | 6,954 | -47% | 1 | 1 | 0% | 2,348 | 2,814 | +20% | 0 | 0 | — |
case-18 | pass→pass | 11,162 | 5,821 | -48% | 1 | 1 | 0% | 1,976 | 2,511 | +27% | 0 | 0 | — |
case-19 | pass→pass | 12,433 | 13,206 | +6% | 1 | 1 | 0% | 2,539 | 4,333 | +71% | 0 | 0 | — |
case-20 | pass→pass | 7,177 | 6,507 | -9% | 1 | 1 | 0% | 1,456 | 2,801 | +92% | 0 | 0 | — |
case-21 | pass→pass | 12,525 | 13,005 | +4% | 1 | 1 | 0% | 2,539 | 4,228 | +67% | 0 | 0 | — |
case-22 | pass→pass | 7,895 | 5,839 | -26% | 1 | 1 | 0% | 1,413 | 2,715 | +92% | 0 | 0 | — |
case-23 | pass→pass | 11,383 | 10,303 | -9% | 1 | 1 | 0% | 1,943 | 3,475 | +79% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +22 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/13/2026 | +27% |
Other measured skills in the registry, with their headline benchmark lift.