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.
Working in Python?
The same wizard ships with the Python SDK. Run pip install spanlens && spanlens init and jump to the Python CLI section below.
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()diffPython CLI
The Python SDK ships the same wizard as a console command. There is no separate package to install: pip install spanlens gives you both the SDK and the spanlens command. It uses only the standard library plus httpx, so it adds no weight to your environment.
pip install spanlens
spanlens initbashIt detects your package manager (poetry, uv, pipenv, or pip), reads which provider libraries you already declare, validates your key, writes .env, and rewrites your client construction. A real run looks like this:
🔭 Spanlens setup
Detected pip project · uses openai, anthropic
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
Created .env with SPANLENS_API_KEY
Installed (pip install spanlens[anthropic,openai])
Found 2 patches to apply
• [openai] app/agent.py
→ import: from openai → from spanlens.integrations.openai import create_openai
→ 1 × constructor → create_openai(...)
• [anthropic] app/summarize.py
→ 1 × constructor → create_anthropic(...)
? Apply these changes? > yes
Patched 2 file(s)
🎉 Spanlens setup completebashEvery patched file is re-parsed before it is written, so the wizard never leaves you with code that will not import. Here is what each provider rewrite looks like:
OpenAI (Python)
- from openai import OpenAI
- client = OpenAI(api_key=os.environ["OPENAI_API_KEY"], timeout=30)
+ from spanlens.integrations.openai import create_openai
+ client = create_openai(timeout=30)diffAnthropic (Python)
- from anthropic import Anthropic
- client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
+ from spanlens.integrations.anthropic import create_anthropic
+ client = create_anthropic()diffGemini (Python)
Gemini uses module-level configuration in Python, so the wizard rewrites the genai.configure(...) call and keeps your GenerativeModel usage untouched:
import google.generativeai as genai
- genai.configure(api_key=os.environ["GEMINI_API_KEY"])
+ from spanlens.integrations.gemini import configure_gemini
+ configure_gemini()diffPreview without writing anything, or check connectivity without running the full wizard:
spanlens init --dry-runbashspanlens testbashFor CI or scripted setup, pass --yes to accept every prompt and --api-key sl_live_... (or set SPANLENS_API_KEY) to skip the interactive key entry. Self-hosting works the same way with --server-url.
What 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.