Claude-code-plugins cohere-local-dev-loop
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/cohere-pack/skills/cohere-local-dev-loop" ~/.claude/skills/jeremylongshore-claude-code-plugins-cohere-local-dev-loop && rm -rf "$T"
manifest:
plugins/saas-packs/cohere-pack/skills/cohere-local-dev-loop/SKILL.mdsource content
Cohere Local Dev Loop
Overview
Set up a fast, reproducible local development workflow with Cohere API v2 mocking, vitest testing, and hot reload.
Prerequisites
- Completed
setupcohere-install-auth - Node.js 18+ with npm/pnpm
- TypeScript project with
ortsxts-node
Instructions
Step 1: Project Structure
my-cohere-project/ ├── src/ │ ├── cohere/ │ │ ├── client.ts # CohereClientV2 wrapper │ │ ├── chat.ts # Chat completions │ │ ├── embed.ts # Embedding operations │ │ └── rerank.ts # Reranking operations │ └── index.ts ├── tests/ │ ├── chat.test.ts │ ├── embed.test.ts │ └── fixtures/ │ └── responses.ts # Mock API responses ├── .env.local # Local secrets (git-ignored) ├── .env.example # Template for team └── package.json
Step 2: Package Setup
{ "scripts": { "dev": "tsx watch src/index.ts", "test": "vitest", "test:watch": "vitest --watch", "test:integration": "COHERE_INTEGRATION=1 vitest --run" }, "dependencies": { "cohere-ai": "^7.0.0" }, "devDependencies": { "tsx": "^4.0.0", "vitest": "^2.0.0", "typescript": "^5.5.0" } }
Step 3: Client Wrapper
// src/cohere/client.ts import { CohereClientV2 } from 'cohere-ai'; let instance: CohereClientV2 | null = null; export function getCohere(): CohereClientV2 { if (!instance) { instance = new CohereClientV2({ token: process.env.CO_API_KEY, }); } return instance; } // Reset for testing export function resetClient(): void { instance = null; }
Step 4: Mock Fixtures
// tests/fixtures/responses.ts export const mockChatResponse = { id: 'test-chat-id', message: { role: 'assistant' as const, content: [{ type: 'text' as const, text: 'Mocked response' }], }, finishReason: 'COMPLETE' as const, usage: { billedUnits: { inputTokens: 10, outputTokens: 5 } }, }; export const mockEmbedResponse = { id: 'test-embed-id', embeddings: { float: [[0.1, 0.2, 0.3, 0.4]], // truncated for dev }, meta: { billedUnits: { inputTokens: 4 } }, }; export const mockRerankResponse = { id: 'test-rerank-id', results: [ { index: 0, relevanceScore: 0.95 }, { index: 2, relevanceScore: 0.72 }, ], meta: { billedUnits: { searchUnits: 1 } }, };
Step 5: Test with Mocks
// tests/chat.test.ts import { describe, it, expect, vi, beforeEach } from 'vitest'; import { mockChatResponse } from './fixtures/responses'; vi.mock('cohere-ai', () => ({ CohereClientV2: vi.fn().mockImplementation(() => ({ chat: vi.fn().mockResolvedValue(mockChatResponse), chatStream: vi.fn().mockReturnValue({ [Symbol.asyncIterator]: async function* () { yield { type: 'content-delta', delta: { message: { content: { text: 'Hi' } } } }; }, }), embed: vi.fn().mockResolvedValue({ embeddings: { float: [[0.1, 0.2]] } }), rerank: vi.fn().mockResolvedValue({ results: [{ index: 0, relevanceScore: 0.9 }], }), })), })); describe('Cohere Chat', () => { it('should return a chat completion', async () => { const { CohereClientV2 } = await import('cohere-ai'); const cohere = new CohereClientV2(); const result = await cohere.chat({ model: 'command-a-03-2025', messages: [{ role: 'user', content: 'test' }], }); expect(result.message?.content?.[0]?.text).toBe('Mocked response'); expect(result.finishReason).toBe('COMPLETE'); }); });
Step 6: Integration Tests (Optional, Hits Real API)
// tests/integration.test.ts import { describe, it, expect } from 'vitest'; import { CohereClientV2 } from 'cohere-ai'; const shouldRun = process.env.COHERE_INTEGRATION === '1'; describe.skipIf(!shouldRun)('Cohere Integration', () => { const cohere = new CohereClientV2(); it('chat endpoint responds', async () => { const res = await cohere.chat({ model: 'command-r7b-12-2024', // cheapest model for tests messages: [{ role: 'user', content: 'Say OK' }], maxTokens: 5, }); expect(res.message?.content?.[0]?.text).toBeTruthy(); }, 15_000); it('embed endpoint responds', async () => { const res = await cohere.embed({ model: 'embed-v4.0', texts: ['test'], inputType: 'search_document', embeddingTypes: ['float'], }); expect(res.embeddings.float[0].length).toBeGreaterThan(0); }, 15_000); });
Environment Management
# .env.example (commit this) CO_API_KEY=your-trial-key-here # .env.local (git-ignored, used by tsx/vitest) CO_API_KEY=actual-key # .gitignore entries .env.local .env.*.local
Output
- Working dev environment with hot reload via
tsx watch - Unit tests with mocked Cohere responses (no API calls)
- Optional integration tests gated by
COHERE_INTEGRATION=1 - Mock fixtures matching real API v2 response shapes
Error Handling
| Error | Cause | Solution |
|---|---|---|
| Wrong import order | Mock before importing modules |
| .env not loaded | Use or tsx env support |
| Integration test timeout | Slow network | Increase timeout to 15s+ |
| Type mismatch on mock | API shape changed | Update fixtures to match SDK types |
Resources
Next Steps
See
cohere-sdk-patterns for production-ready code patterns.