Spanlens CLI
One command rewrites every new OpenAI(...), new Anthropic(...), and new GoogleGenerativeAI(...) in your codebase into the matching @spanlens/sdk factory. The wizard validates your key against the dashboard, picks up which providers are registered on your project, and runs tsc --noEmit before committing so you do not ship a broken build.
Two-line manual integration still works
If the wizard does not fit your stack, skip it and use the @spanlens/sdk factories directly. Same end result, same proxy, same dashboard.
Install & run
npx @spanlens/cli initbashNo global install needed. npx fetches the latest release on each run, so the patch rules stay current with new framework releases. The wizard expects:
- A Spanlens account with a project at /projects
- At least one provider key (OpenAI / Anthropic / Gemini) registered on that project
- A Spanlens API key issued for the project (
sl_live_*) - Node.js 18 or newer in the project you are patching
Walkthrough
Here is a real run against a Next.js project with three direct provider SDK call sites:
Spanlens setup
Detected Next.js (TypeScript)
Before continuing, make sure you have:
1. A Spanlens account at https://www.spanlens.io
2. A Project at https://www.spanlens.io/projects
3. Provider keys (OpenAI / Anthropic / Gemini) added to that project
4. A Spanlens key issued for that project (sl_live_...)
? Paste your Spanlens key > sl_live_*************
Key valid - project chatbot-prod - providers: openai, anthropic, gemini
Updated SPANLENS_API_KEY in .env.local
Installed @spanlens/sdk (pnpm add @spanlens/sdk)
Found 3 patches to apply
- [openai] app/api/chat/route.ts
import: "OpenAI" from 'openai' -> { createOpenAI } from '@spanlens/sdk/openai'
1 x new OpenAI(...) -> createOpenAI(...)
- [anthropic] app/api/summary/route.ts
1 x new Anthropic(...) -> createAnthropic(...)
- [gemini] app/api/translate/route.ts
1 x new GoogleGenerativeAI(...) -> createGemini(...)
? Apply these changes? > yes
Patched 3 files
TypeScript check passed
Spanlens setup completebashThe wizard never writes to disk until you answer yes on the confirmation prompt. The tsc --noEmit check after patching is mandatory; if any rewrite breaks a type, the wizard refuses to complete and reports which file failed.
Before / after
Each provider follows the same pattern: drop the import, drop the explicit apiKey, keep every other option (timeout, organization, defaultHeaders, etc.).
OpenAI
- import OpenAI from 'openai'
- const openai = new OpenAI({
- apiKey: process.env.OPENAI_API_KEY,
- timeout: 30_000,
- })
+ import { createOpenAI } from '@spanlens/sdk/openai'
+ const openai = createOpenAI({
+ timeout: 30_000,
+ })diffAnthropic
- import Anthropic from '@anthropic-ai/sdk'
- const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY })
+ import { createAnthropic } from '@spanlens/sdk/anthropic'
+ const anthropic = createAnthropic()diffGemini
- import { GoogleGenerativeAI } from '@google/generative-ai'
- const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY ?? '')
+ import { createGemini } from '@spanlens/sdk/gemini'
+ const genAI = createGemini()diffWhat is supported today
| Area | Status |
|---|---|
| OpenAI / Anthropic / Gemini SDK rewrites | Stable. Auto-detected from your registered provider keys. |
| Next.js (TypeScript & JavaScript) | Stable. |
| Vite / Express / Fastify / standalone Node | Detection-only today, full rewrite path is on the roadmap. |
| Python (FastAPI / Flask) | Planned. Use the manual @spanlens/sdk for now. |
| Package managers | npm, pnpm, yarn, bun all detected automatically. |
| Env-file writes | Preserves comments and surrounding keys; confirms before overwriting. |
Flags
| Flag | Use it for |
|---|---|
--dry-run | Preview the patch list without writing or installing anything. Safe to run on a clean tree to see what the wizard would do.bash |
--server-url <url> | Point at a self-hosted Spanlens instance. Validation, dashboard links, and the generated SPANLENS_BASE_URL all use your URL instead of spanlens.io.bash |
Manual integration
Prefer to skip the wizard? The same factories work standalone. Add @spanlens/sdk as a dependency, replace your provider SDK constructor with the matching factory, and you are done:
import { createOpenAI } from '@spanlens/sdk/openai'
import { createAnthropic } from '@spanlens/sdk/anthropic'
import { createGemini } from '@spanlens/sdk/gemini'
// Each factory reads SPANLENS_API_KEY from env and routes the
// underlying provider SDK through the Spanlens proxy. The response
// types and method signatures are identical to the upstream SDKs.tsSee the SDK reference for the full option list, streaming details, and agent-tracing primitives.
Troubleshooting
The wizard says my key is invalid
The CLI calls POST /api/v1/keys/validate on the Spanlens server before writing anything. Common causes:
- The key is for a different project than the one you intended.
- The key was revoked from /projects.
- A self-hosted deployment without
--server-urlpoints atspanlens.ioby default.
TypeScript check fails after patching
The wizard aborts with the file that failed. Almost always this is a custom field on the original constructor that we did not migrate (for example, a private adapter wrapping new OpenAI). Open the file, finish the migration by hand, and re-run with --dry-run to confirm there is nothing left to patch.
Wizard does not detect my framework
Today the rewrite path is Next.js only. For Vite, Express, Fastify, or standalone Node projects, run the manual integration shown above. Open an issue on spanlens/spanlens with the framework you would like detected.
I want to roll back what the wizard did
Every change is a regular file edit and an env write. git diff shows the rewrite; git restore . reverses it. The wizard never touches anything outside the patched source files and your env file, so a single revert is enough.
Source: packages/cli on GitHub. MIT licensed.